New feature : add Anime
-add trackers support for anime
12
.metadata
|
|
@ -4,7 +4,7 @@
|
||||||
# This file should be version controlled.
|
# This file should be version controlled.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||||
channel: stable
|
channel: stable
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
|
|
@ -13,11 +13,11 @@ project_type: app
|
||||||
migration:
|
migration:
|
||||||
platforms:
|
platforms:
|
||||||
- platform: root
|
- platform: root
|
||||||
create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||||
base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||||
- platform: windows
|
- platform: macos
|
||||||
create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||||
base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ Features include:
|
||||||
* Local reading of downloaded content
|
* Local reading of downloaded content
|
||||||
* Read and manage local archives (.cbz, .zip)
|
* Read and manage local archives (.cbz, .zip)
|
||||||
* A configurable reader with multiple viewers, reading directions.
|
* A configurable reader with multiple viewers, reading directions.
|
||||||
|
* Tracker support: [MyAnimeList](https://myanimelist.net/) and [AniList](https://anilist.co/) support
|
||||||
* Categories to organize your library
|
* Categories to organize your library
|
||||||
* Light and dark themes
|
* Light and dark themes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
|
|
||||||
44
ios/Podfile
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Uncomment this line to define a global platform for your project
|
||||||
|
platform :ios, '13.0'
|
||||||
|
|
||||||
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
||||||
|
project 'Runner', {
|
||||||
|
'Debug' => :debug,
|
||||||
|
'Profile' => :release,
|
||||||
|
'Release' => :release,
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutter_root
|
||||||
|
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||||
|
unless File.exist?(generated_xcode_build_settings_path)
|
||||||
|
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||||
|
end
|
||||||
|
|
||||||
|
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||||
|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||||
|
return matches[1].strip if matches
|
||||||
|
end
|
||||||
|
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||||
|
|
||||||
|
flutter_ios_podfile_setup
|
||||||
|
|
||||||
|
target 'Runner' do
|
||||||
|
use_frameworks!
|
||||||
|
use_modular_headers!
|
||||||
|
|
||||||
|
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
target 'RunnerTests' do
|
||||||
|
inherit! :search_paths
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_ios_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
150
ios/Podfile.lock
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
PODS:
|
||||||
|
- background_downloader (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- DKImagePickerController/Core (4.3.4):
|
||||||
|
- DKImagePickerController/ImageDataManager
|
||||||
|
- DKImagePickerController/Resource
|
||||||
|
- DKImagePickerController/ImageDataManager (4.3.4)
|
||||||
|
- DKImagePickerController/PhotoGallery (4.3.4):
|
||||||
|
- DKImagePickerController/Core
|
||||||
|
- DKPhotoGallery
|
||||||
|
- DKImagePickerController/Resource (4.3.4)
|
||||||
|
- DKPhotoGallery (0.0.17):
|
||||||
|
- DKPhotoGallery/Core (= 0.0.17)
|
||||||
|
- DKPhotoGallery/Model (= 0.0.17)
|
||||||
|
- DKPhotoGallery/Preview (= 0.0.17)
|
||||||
|
- DKPhotoGallery/Resource (= 0.0.17)
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Core (0.0.17):
|
||||||
|
- DKPhotoGallery/Model
|
||||||
|
- DKPhotoGallery/Preview
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Model (0.0.17):
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Preview (0.0.17):
|
||||||
|
- DKPhotoGallery/Model
|
||||||
|
- DKPhotoGallery/Resource
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Resource (0.0.17):
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- file_picker (0.0.1):
|
||||||
|
- DKImagePickerController/PhotoGallery
|
||||||
|
- Flutter
|
||||||
|
- Flutter (1.0.0)
|
||||||
|
- flutter_inappwebview (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- flutter_inappwebview/Core (= 0.0.1)
|
||||||
|
- OrderedSet (~> 5.0)
|
||||||
|
- flutter_inappwebview/Core (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- OrderedSet (~> 5.0)
|
||||||
|
- flutter_js (0.1.0):
|
||||||
|
- Flutter
|
||||||
|
- flutter_web_auth_2 (1.1.1):
|
||||||
|
- Flutter
|
||||||
|
- FMDB (2.7.5):
|
||||||
|
- FMDB/standard (= 2.7.5)
|
||||||
|
- FMDB/standard (2.7.5)
|
||||||
|
- isar_flutter_libs (1.0.0):
|
||||||
|
- Flutter
|
||||||
|
- OrderedSet (5.0.0)
|
||||||
|
- package_info_plus (0.4.5):
|
||||||
|
- Flutter
|
||||||
|
- path_provider_foundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
- permission_handler_apple (9.0.4):
|
||||||
|
- Flutter
|
||||||
|
- SDWebImage (5.17.0):
|
||||||
|
- SDWebImage/Core (= 5.17.0)
|
||||||
|
- SDWebImage/Core (5.17.0)
|
||||||
|
- share_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- sqflite (0.0.3):
|
||||||
|
- Flutter
|
||||||
|
- FMDB (>= 2.7.5)
|
||||||
|
- SwiftyGif (5.4.4)
|
||||||
|
- url_launcher_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- background_downloader (from `.symlinks/plugins/background_downloader/ios`)
|
||||||
|
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||||
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`)
|
||||||
|
- flutter_js (from `.symlinks/plugins/flutter_js/ios`)
|
||||||
|
- flutter_web_auth_2 (from `.symlinks/plugins/flutter_web_auth_2/ios`)
|
||||||
|
- isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`)
|
||||||
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
|
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||||
|
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||||
|
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||||
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
trunk:
|
||||||
|
- DKImagePickerController
|
||||||
|
- DKPhotoGallery
|
||||||
|
- FMDB
|
||||||
|
- OrderedSet
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
background_downloader:
|
||||||
|
:path: ".symlinks/plugins/background_downloader/ios"
|
||||||
|
file_picker:
|
||||||
|
:path: ".symlinks/plugins/file_picker/ios"
|
||||||
|
Flutter:
|
||||||
|
:path: Flutter
|
||||||
|
flutter_inappwebview:
|
||||||
|
:path: ".symlinks/plugins/flutter_inappwebview/ios"
|
||||||
|
flutter_js:
|
||||||
|
:path: ".symlinks/plugins/flutter_js/ios"
|
||||||
|
flutter_web_auth_2:
|
||||||
|
:path: ".symlinks/plugins/flutter_web_auth_2/ios"
|
||||||
|
isar_flutter_libs:
|
||||||
|
:path: ".symlinks/plugins/isar_flutter_libs/ios"
|
||||||
|
package_info_plus:
|
||||||
|
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||||
|
path_provider_foundation:
|
||||||
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
|
permission_handler_apple:
|
||||||
|
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||||
|
share_plus:
|
||||||
|
:path: ".symlinks/plugins/share_plus/ios"
|
||||||
|
sqflite:
|
||||||
|
:path: ".symlinks/plugins/sqflite/ios"
|
||||||
|
url_launcher_ios:
|
||||||
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
background_downloader: 6f55e5548875be2ad4bb91b542558b5be22f339a
|
||||||
|
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
|
||||||
|
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
|
||||||
|
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
|
||||||
|
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||||
|
flutter_inappwebview: 50b55a88f5dddadc9e741a7caf72f378116e2156
|
||||||
|
flutter_js: 95929d4e146e8ceb1c8e1889d8c2065c5d840076
|
||||||
|
flutter_web_auth_2: a1bc00762c408a8f80b72a538cd7ff5b601c3e71
|
||||||
|
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||||
|
isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073
|
||||||
|
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
||||||
|
package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7
|
||||||
|
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
|
||||||
|
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
|
||||||
|
SDWebImage: 750adf017a315a280c60fde706ab1e552a3ae4e9
|
||||||
|
share_plus: 599aa54e4ea31d4b4c0e9c911bcc26c55e791028
|
||||||
|
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
|
||||||
|
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
|
||||||
|
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
||||||
|
|
||||||
|
PODFILE CHECKSUM: 351dbda8241c6ae667acbc7bc0353a0d9978d7f1
|
||||||
|
|
||||||
|
COCOAPODS: 1.12.1
|
||||||
|
|
@ -8,13 +8,26 @@
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
|
2E161ED88D6088BA04182D24 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 87B3D97401D2090714EBD2ED /* Pods_Runner.framework */; };
|
||||||
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||||
|
A83607D399EF885A7879ED92 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F944C966F0D3C46230816475 /* Pods_RunnerTests.framework */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
||||||
|
remoteInfo = Runner;
|
||||||
|
};
|
||||||
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
|
@ -31,10 +44,15 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
|
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||||
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
|
48F414924F0EBD7233D9B3FB /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
|
87B3D97401D2090714EBD2ED /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
8FEFB82C0F5EBF076D246DED /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
|
@ -42,19 +60,55 @@
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
9D7FF371C06E43EB2821A307 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
E3DBD23DF4F6477DD1B2D619 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
F2F655C8A844E54BF4806B9E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
F6B35AE9FD7580BD87744873 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
F944C966F0D3C46230816475 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
856C729112305BC7D8FE80C9 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
A83607D399EF885A7879ED92 /* Pods_RunnerTests.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
2E161ED88D6088BA04182D24 /* Pods_Runner.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
331C807B294A618700263BE5 /* RunnerTests.swift */,
|
||||||
|
);
|
||||||
|
path = RunnerTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
6CD41D1121E5C42BF1E41F31 /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9D7FF371C06E43EB2821A307 /* Pods-Runner.debug.xcconfig */,
|
||||||
|
F6B35AE9FD7580BD87744873 /* Pods-Runner.release.xcconfig */,
|
||||||
|
F2F655C8A844E54BF4806B9E /* Pods-Runner.profile.xcconfig */,
|
||||||
|
E3DBD23DF4F6477DD1B2D619 /* Pods-RunnerTests.debug.xcconfig */,
|
||||||
|
48F414924F0EBD7233D9B3FB /* Pods-RunnerTests.release.xcconfig */,
|
||||||
|
8FEFB82C0F5EBF076D246DED /* Pods-RunnerTests.profile.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Pods;
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
|
@ -72,6 +126,9 @@
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
|
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||||
|
6CD41D1121E5C42BF1E41F31 /* Pods */,
|
||||||
|
BCA59FF3AA594C41BF8ADD28 /* Frameworks */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
|
@ -79,6 +136,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||||
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -98,19 +156,49 @@
|
||||||
path = Runner;
|
path = Runner;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
BCA59FF3AA594C41BF8ADD28 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
87B3D97401D2090714EBD2ED /* Pods_Runner.framework */,
|
||||||
|
F944C966F0D3C46230816475 /* Pods_RunnerTests.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
331C8080294A63A400263BE5 /* RunnerTests */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||||
|
buildPhases = (
|
||||||
|
EF1F895BD02D12F0BC740A9E /* [CP] Check Pods Manifest.lock */,
|
||||||
|
331C807D294A63A400263BE5 /* Sources */,
|
||||||
|
331C807F294A63A400263BE5 /* Resources */,
|
||||||
|
856C729112305BC7D8FE80C9 /* Frameworks */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
331C8086294A63A400263BE5 /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
name = RunnerTests;
|
||||||
|
productName = RunnerTests;
|
||||||
|
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||||
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
|
};
|
||||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
F7E3AB66492405CCCAB00559 /* [CP] Check Pods Manifest.lock */,
|
||||||
9740EEB61CF901F6004384FC /* Run Script */,
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
DC786BE6A6336FF08B227C10 /* [CP] Embed Pods Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
|
@ -127,9 +215,14 @@
|
||||||
97C146E61CF9000F007C117D /* Project object */ = {
|
97C146E61CF9000F007C117D /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
|
BuildIndependentTargetsInParallel = YES;
|
||||||
LastUpgradeCheck = 1300;
|
LastUpgradeCheck = 1300;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
331C8080294A63A400263BE5 = {
|
||||||
|
CreatedOnToolsVersion = 14.0;
|
||||||
|
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||||
|
};
|
||||||
97C146ED1CF9000F007C117D = {
|
97C146ED1CF9000F007C117D = {
|
||||||
CreatedOnToolsVersion = 7.3.1;
|
CreatedOnToolsVersion = 7.3.1;
|
||||||
LastSwiftMigration = 1100;
|
LastSwiftMigration = 1100;
|
||||||
|
|
@ -150,11 +243,19 @@
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
97C146ED1CF9000F007C117D /* Runner */,
|
97C146ED1CF9000F007C117D /* Runner */,
|
||||||
|
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
331C807F294A63A400263BE5 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
|
@ -176,6 +277,7 @@
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
|
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||||
);
|
);
|
||||||
name = "Thin Binary";
|
name = "Thin Binary";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
|
|
@ -199,9 +301,78 @@
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
};
|
};
|
||||||
|
DC786BE6A6336FF08B227C10 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
EF1F895BD02D12F0BC740A9E /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
F7E3AB66492405CCCAB00559 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
331C807D294A63A400263BE5 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
|
@ -213,6 +384,14 @@
|
||||||
};
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||||
|
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
|
|
@ -256,6 +435,7 @@
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
|
@ -274,7 +454,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
|
@ -292,6 +472,7 @@
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
|
@ -304,6 +485,56 @@
|
||||||
};
|
};
|
||||||
name = Profile;
|
name = Profile;
|
||||||
};
|
};
|
||||||
|
331C8088294A63A400263BE5 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = E3DBD23DF4F6477DD1B2D619 /* Pods-RunnerTests.debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.kodjodevf.mangayomi.RunnerTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
331C8089294A63A400263BE5 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 48F414924F0EBD7233D9B3FB /* Pods-RunnerTests.release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.kodjodevf.mangayomi.RunnerTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
331C808A294A63A400263BE5 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 8FEFB82C0F5EBF076D246DED /* Pods-RunnerTests.profile.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.kodjodevf.mangayomi.RunnerTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
97C147031CF9000F007C117D /* Debug */ = {
|
97C147031CF9000F007C117D /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
|
@ -327,6 +558,7 @@
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
|
@ -351,7 +583,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
|
@ -382,6 +614,7 @@
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
|
@ -400,7 +633,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
|
@ -420,6 +653,7 @@
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
|
@ -442,6 +676,7 @@
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
|
@ -457,6 +692,16 @@
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
331C8088294A63A400263BE5 /* Debug */,
|
||||||
|
331C8089294A63A400263BE5 /* Release */,
|
||||||
|
331C808A294A63A400263BE5 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,17 @@
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</MacroExpansion>
|
</MacroExpansion>
|
||||||
<Testables>
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO"
|
||||||
|
parallelizable = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "331C8080294A63A400263BE5"
|
||||||
|
BuildableName = "RunnerTests.xctest"
|
||||||
|
BlueprintName = "RunnerTests"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
</Testables>
|
</Testables>
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
|
|
|
||||||
3
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
|
|
@ -4,4 +4,7 @@
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "group:Runner.xcodeproj">
|
location = "group:Runner.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
</Workspace>
|
</Workspace>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 723 B After Width: | Height: | Size: 295 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 406 B |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 450 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 282 B |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 462 B |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 704 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 406 B |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 586 B |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 862 B |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 862 B |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 8 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 762 B |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 1.4 KiB |
|
|
@ -2,6 +2,8 @@
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
<true/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
|
|
@ -13,7 +15,7 @@
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>Mangayomi</string>
|
<string>mangayomi</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
|
|
@ -24,6 +26,12 @@
|
||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
|
<true/>
|
||||||
|
<key>UIBackgroundModes</key>
|
||||||
|
<array>
|
||||||
|
<string>fetch</string>
|
||||||
|
</array>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
|
|
@ -43,9 +51,5 @@
|
||||||
</array>
|
</array>
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
|
||||||
<true/>
|
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
||||||
12
ios/RunnerTests/RunnerTests.swift
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import Flutter
|
||||||
|
import UIKit
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class RunnerTests: XCTestCase {
|
||||||
|
|
||||||
|
func testExample() {
|
||||||
|
// If you add code to the Runner application, consider adding tests here.
|
||||||
|
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -65,3 +65,12 @@ class MangaModel {
|
||||||
this.images,
|
this.images,
|
||||||
this.statusList});
|
this.statusList});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VideoModel {
|
||||||
|
String? url;
|
||||||
|
String? quality;
|
||||||
|
String? originalUrl;
|
||||||
|
Map<dynamic, dynamic>? headers;
|
||||||
|
|
||||||
|
VideoModel({this.url, this.quality, this.originalUrl, this.headers});
|
||||||
|
}
|
||||||
|
|
|
||||||
134
lib/eval/bridge_class/video_model.dart
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
import 'package:dart_eval/dart_eval.dart';
|
||||||
|
import 'package:dart_eval/dart_eval_bridge.dart';
|
||||||
|
import 'package:dart_eval/stdlib/core.dart';
|
||||||
|
import 'package:mangayomi/eval/bridge_class/model.dart';
|
||||||
|
|
||||||
|
class $VideoModel implements VideoModel, $Instance {
|
||||||
|
$VideoModel.wrap(this.$value) : _superclass = $Object($value);
|
||||||
|
|
||||||
|
static const $type = BridgeTypeRef(
|
||||||
|
BridgeTypeSpec('package:bridge_lib/bridge_lib.dart', 'VideoModel'));
|
||||||
|
|
||||||
|
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||||
|
constructors: {
|
||||||
|
'': BridgeConstructorDef(BridgeFunctionDef(
|
||||||
|
returns: BridgeTypeAnnotation($type),
|
||||||
|
params: [],
|
||||||
|
namedParams: [
|
||||||
|
BridgeParameter(
|
||||||
|
'url',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
false),
|
||||||
|
BridgeParameter(
|
||||||
|
'quality',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
false),
|
||||||
|
BridgeParameter(
|
||||||
|
'originalUrl',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
false),
|
||||||
|
BridgeParameter(
|
||||||
|
'headers',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.mapType)),
|
||||||
|
false),
|
||||||
|
]))
|
||||||
|
},
|
||||||
|
// Specify class fields
|
||||||
|
fields: {
|
||||||
|
'url': BridgeFieldDef(
|
||||||
|
BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.stringType))),
|
||||||
|
'quality': BridgeFieldDef(
|
||||||
|
BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.stringType))),
|
||||||
|
'originalUrl': BridgeFieldDef(
|
||||||
|
BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.stringType))),
|
||||||
|
'headers': BridgeFieldDef(
|
||||||
|
BridgeTypeAnnotation(BridgeTypeRef.type(RuntimeTypes.mapType))),
|
||||||
|
},
|
||||||
|
wrap: true);
|
||||||
|
|
||||||
|
static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||||
|
return $VideoModel.wrap(VideoModel());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
final VideoModel $value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
VideoModel get $reified => $value;
|
||||||
|
|
||||||
|
final $Instance _superclass;
|
||||||
|
|
||||||
|
@override
|
||||||
|
$Value? $getProperty(Runtime runtime, String identifier) {
|
||||||
|
switch (identifier) {
|
||||||
|
case 'url':
|
||||||
|
return $String($value.url!);
|
||||||
|
case 'quality':
|
||||||
|
return $String($value.quality!);
|
||||||
|
case 'originalUrl':
|
||||||
|
return $String($value.originalUrl!);
|
||||||
|
|
||||||
|
case 'headers':
|
||||||
|
return $Map.wrap($value.headers!);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return _superclass.$getProperty(runtime, identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void $setProperty(Runtime runtime, String identifier, $Value value) {
|
||||||
|
switch (identifier) {
|
||||||
|
case 'url':
|
||||||
|
$value.url = value.$reified;
|
||||||
|
case 'quality':
|
||||||
|
$value.quality = value.$reified;
|
||||||
|
case 'originalUrl':
|
||||||
|
$value.originalUrl = value.$reified;
|
||||||
|
case 'headers':
|
||||||
|
$value.headers = value.$reified as Map;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_superclass.$setProperty(runtime, identifier, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get url => $value.url;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get quality => $value.quality;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map? get headers => $value.headers;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get originalUrl => $value.originalUrl;
|
||||||
|
|
||||||
|
@override
|
||||||
|
set url(String? url) {
|
||||||
|
// implement apiUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
set quality(String? quality) {
|
||||||
|
// implement baseUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
set headers(Map? headers) {
|
||||||
|
// implement dateFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
set originalUrl(String? originalUrl) {
|
||||||
|
// implement dateFormatLocale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:dart_eval/dart_eval.dart';
|
import 'package:dart_eval/dart_eval.dart';
|
||||||
import 'package:mangayomi/eval/bridge_class/manga_model.dart';
|
import 'package:mangayomi/eval/bridge_class/manga_model.dart';
|
||||||
|
import 'package:mangayomi/eval/bridge_class/video_model.dart';
|
||||||
import 'package:mangayomi/eval/m_bridge.dart';
|
import 'package:mangayomi/eval/m_bridge.dart';
|
||||||
|
|
||||||
Uint8List compilerEval(String sourceCode) {
|
Uint8List compilerEval(String sourceCode) {
|
||||||
|
|
@ -8,6 +9,7 @@ Uint8List compilerEval(String sourceCode) {
|
||||||
compiler.defineBridgeClasses([
|
compiler.defineBridgeClasses([
|
||||||
$MBridge.$declaration,
|
$MBridge.$declaration,
|
||||||
$MangaModel.$declaration,
|
$MangaModel.$declaration,
|
||||||
|
$VideoModel.$declaration
|
||||||
]);
|
]);
|
||||||
final program = compiler.compile({
|
final program = compiler.compile({
|
||||||
'package:mangayomi': {'main.dart': sourceCode}
|
'package:mangayomi': {'main.dart': sourceCode}
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,16 @@ import 'package:flutter_js/flutter_js.dart';
|
||||||
import 'package:intl/date_symbol_data_local.dart';
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:json_path/json_path.dart';
|
import 'package:json_path/json_path.dart';
|
||||||
|
import 'package:mangayomi/eval/bridge_class/model.dart';
|
||||||
|
import 'package:mangayomi/eval/bridge_class/video_model.dart';
|
||||||
|
import 'package:mangayomi/services/anime_servers/dood_extractor.dart';
|
||||||
|
import 'package:mangayomi/services/anime_servers/gogo_cdn_extractor.dart';
|
||||||
import 'package:mangayomi/main.dart';
|
import 'package:mangayomi/main.dart';
|
||||||
import 'package:mangayomi/models/source.dart';
|
import 'package:mangayomi/models/source.dart';
|
||||||
|
import 'package:mangayomi/models/video.dart';
|
||||||
import 'package:mangayomi/modules/webview/webview.dart';
|
import 'package:mangayomi/modules/webview/webview.dart';
|
||||||
|
import 'package:mangayomi/services/anime_servers/mp4_upload_extractor.dart';
|
||||||
|
import 'package:mangayomi/services/anime_servers/stream_tape_extractor.dart';
|
||||||
import 'package:mangayomi/services/http_service/cloudflare/cloudflare_bypass.dart';
|
import 'package:mangayomi/services/http_service/cloudflare/cloudflare_bypass.dart';
|
||||||
import 'package:mangayomi/utils/constant.dart';
|
import 'package:mangayomi/utils/constant.dart';
|
||||||
import 'package:mangayomi/utils/reg_exp_matcher.dart';
|
import 'package:mangayomi/utils/reg_exp_matcher.dart';
|
||||||
|
|
@ -499,6 +506,45 @@ class MBridge {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<List<Video>> gogoCdnExtractor(String url) async {
|
||||||
|
return await GogoCdnExtractor().videosFromUrl(
|
||||||
|
url,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<List<Video>> doodExtractor(String url) async {
|
||||||
|
return await DoodExtractor().videosFromUrl(
|
||||||
|
url,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<List<Video>> mp4UploadExtractor(String url,
|
||||||
|
Map<String, String>? headers, String prefix, String suffix) async {
|
||||||
|
return await Mp4uploadExtractor()
|
||||||
|
.videosFromUrl(url, headers ?? {}, prefix: prefix, suffix: suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<List<Video>> streamTapeExtractor(String url) async {
|
||||||
|
return await StreamTapeExtractor().videosFromUrl(
|
||||||
|
url,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String subString(String text, String pattern, int type) {
|
||||||
|
String result = "";
|
||||||
|
//substring before
|
||||||
|
if (type == 0) {
|
||||||
|
result = text.split(pattern).first;
|
||||||
|
} else
|
||||||
|
// substring after last
|
||||||
|
if (type == 1) {
|
||||||
|
result = text.split(pattern).last;
|
||||||
|
} else if (type == 2) {
|
||||||
|
result = text.substring(text.lastIndexOf(pattern) + 1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static String parseChapterDate(
|
static String parseChapterDate(
|
||||||
String date, String dateFormat, String dateFormatLocale) {
|
String date, String dateFormat, String dateFormatLocale) {
|
||||||
int parseRelativeDate(String date) {
|
int parseRelativeDate(String date) {
|
||||||
|
|
@ -686,6 +732,29 @@ class $MBridge extends MBridge with $Bridge {
|
||||||
returns: BridgeTypeAnnotation($type), params: [], namedParams: []))
|
returns: BridgeTypeAnnotation($type), params: [], namedParams: []))
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
'subString': BridgeMethodDef(
|
||||||
|
BridgeFunctionDef(
|
||||||
|
returns: BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
params: [
|
||||||
|
BridgeParameter(
|
||||||
|
'text',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
false),
|
||||||
|
BridgeParameter(
|
||||||
|
'pattern',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
false),
|
||||||
|
BridgeParameter(
|
||||||
|
'type',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.intType)),
|
||||||
|
false),
|
||||||
|
],
|
||||||
|
namedParams: []),
|
||||||
|
isStatic: true),
|
||||||
'listParse': BridgeMethodDef(
|
'listParse': BridgeMethodDef(
|
||||||
BridgeFunctionDef(
|
BridgeFunctionDef(
|
||||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list,
|
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list,
|
||||||
|
|
@ -988,6 +1057,74 @@ class $MBridge extends MBridge with $Bridge {
|
||||||
],
|
],
|
||||||
namedParams: []),
|
namedParams: []),
|
||||||
isStatic: true),
|
isStatic: true),
|
||||||
|
'gogoCdnExtractor': BridgeMethodDef(
|
||||||
|
BridgeFunctionDef(
|
||||||
|
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future,
|
||||||
|
[BridgeTypeRef.type(RuntimeTypes.dynamicType)])),
|
||||||
|
params: [
|
||||||
|
BridgeParameter(
|
||||||
|
'url',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
false),
|
||||||
|
],
|
||||||
|
namedParams: []),
|
||||||
|
isStatic: true),
|
||||||
|
'doodExtractor': BridgeMethodDef(
|
||||||
|
BridgeFunctionDef(
|
||||||
|
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future,
|
||||||
|
[BridgeTypeRef.type(RuntimeTypes.dynamicType)])),
|
||||||
|
params: [
|
||||||
|
BridgeParameter(
|
||||||
|
'url',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
false),
|
||||||
|
],
|
||||||
|
namedParams: []),
|
||||||
|
isStatic: true),
|
||||||
|
'streamTapeExtractor': BridgeMethodDef(
|
||||||
|
BridgeFunctionDef(
|
||||||
|
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future,
|
||||||
|
[BridgeTypeRef.type(RuntimeTypes.dynamicType)])),
|
||||||
|
params: [
|
||||||
|
BridgeParameter(
|
||||||
|
'url',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
false),
|
||||||
|
],
|
||||||
|
namedParams: []),
|
||||||
|
isStatic: true),
|
||||||
|
'mp4UploadExtractor': BridgeMethodDef(
|
||||||
|
BridgeFunctionDef(
|
||||||
|
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future,
|
||||||
|
[BridgeTypeRef.type(RuntimeTypes.dynamicType)])),
|
||||||
|
params: [
|
||||||
|
BridgeParameter(
|
||||||
|
'url',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
false),
|
||||||
|
BridgeParameter(
|
||||||
|
'headers',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.mapType),
|
||||||
|
nullable: true),
|
||||||
|
false),
|
||||||
|
BridgeParameter(
|
||||||
|
'prefix',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
false),
|
||||||
|
BridgeParameter(
|
||||||
|
'suffix',
|
||||||
|
BridgeTypeAnnotation(
|
||||||
|
BridgeTypeRef.type(RuntimeTypes.stringType)),
|
||||||
|
false),
|
||||||
|
],
|
||||||
|
namedParams: []),
|
||||||
|
isStatic: true),
|
||||||
'getHtmlViaWebview': BridgeMethodDef(
|
'getHtmlViaWebview': BridgeMethodDef(
|
||||||
BridgeFunctionDef(
|
BridgeFunctionDef(
|
||||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future,
|
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future,
|
||||||
|
|
@ -1140,6 +1277,15 @@ class $MBridge extends MBridge with $Bridge {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static $String $subString(
|
||||||
|
Runtime runtime, $Value? target, List<$Value?> args) {
|
||||||
|
return $String(MBridge.subString(
|
||||||
|
args[0]!.$value,
|
||||||
|
args[1]!.$value,
|
||||||
|
args[2]!.$value,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
static $String $getMapValue(
|
static $String $getMapValue(
|
||||||
Runtime runtime, $Value? target, List<$Value?> args) {
|
Runtime runtime, $Value? target, List<$Value?> args) {
|
||||||
return $String(MBridge.getMapValue(
|
return $String(MBridge.getMapValue(
|
||||||
|
|
@ -1220,11 +1366,54 @@ class $MBridge extends MBridge with $Bridge {
|
||||||
static $Future $http(Runtime runtime, $Value? target, List<$Value?> args) =>
|
static $Future $http(Runtime runtime, $Value? target, List<$Value?> args) =>
|
||||||
$Future.wrap(MBridge.http(args[0]!.$value, args[1]!.$value)
|
$Future.wrap(MBridge.http(args[0]!.$value, args[1]!.$value)
|
||||||
.then((value) => $String(value)));
|
.then((value) => $String(value)));
|
||||||
|
|
||||||
static $Future $getHtmlViaWebview(
|
static $Future $getHtmlViaWebview(
|
||||||
Runtime runtime, $Value? target, List<$Value?> args) =>
|
Runtime runtime, $Value? target, List<$Value?> args) =>
|
||||||
$Future.wrap(MBridge.getHtmlViaWebview(args[0]!.$value, args[1]!.$value)
|
$Future.wrap(MBridge.getHtmlViaWebview(args[0]!.$value, args[1]!.$value)
|
||||||
.then((value) => $String(value)));
|
.then((value) => $String(value)));
|
||||||
|
|
||||||
|
static $Future $gogoCdnExtractor(
|
||||||
|
Runtime runtime, $Value? target, List<$Value?> args) =>
|
||||||
|
$Future.wrap(MBridge.gogoCdnExtractor(args[0]!.$value)
|
||||||
|
.then((value) => $List.wrap(value
|
||||||
|
.map((e) => $VideoModel.wrap(VideoModel()
|
||||||
|
..headers = e.headers
|
||||||
|
..originalUrl = e.originalUrl
|
||||||
|
..quality = e.quality
|
||||||
|
..url = e.url))
|
||||||
|
.toList())));
|
||||||
|
|
||||||
|
static $Future $doodExtractor(
|
||||||
|
Runtime runtime, $Value? target, List<$Value?> args) =>
|
||||||
|
$Future.wrap(MBridge.doodExtractor(args[0]!.$value)
|
||||||
|
.then((value) => $List.wrap(value
|
||||||
|
.map((e) => $VideoModel.wrap(VideoModel()
|
||||||
|
..headers = e.headers
|
||||||
|
..originalUrl = e.originalUrl
|
||||||
|
..quality = e.quality
|
||||||
|
..url = e.url))
|
||||||
|
.toList())));
|
||||||
|
static $Future $streamTapeExtractor(
|
||||||
|
Runtime runtime, $Value? target, List<$Value?> args) =>
|
||||||
|
$Future.wrap(MBridge.streamTapeExtractor(args[0]!.$value)
|
||||||
|
.then((value) => $List.wrap(value
|
||||||
|
.map((e) => $VideoModel.wrap(VideoModel()
|
||||||
|
..headers = e.headers
|
||||||
|
..originalUrl = e.originalUrl
|
||||||
|
..quality = e.quality
|
||||||
|
..url = e.url))
|
||||||
|
.toList())));
|
||||||
|
static $Future $mp4UploadExtractor(
|
||||||
|
Runtime runtime, $Value? target, List<$Value?> args) =>
|
||||||
|
$Future.wrap(MBridge.mp4UploadExtractor(args[0]!.$value, args[1]!.$value,
|
||||||
|
args[2]!.$value, args[3]!.$value)
|
||||||
|
.then((value) => $List.wrap(value
|
||||||
|
.map((e) => $VideoModel.wrap(VideoModel()
|
||||||
|
..headers = e.headers
|
||||||
|
..originalUrl = e.originalUrl
|
||||||
|
..quality = e.quality
|
||||||
|
..url = e.url))
|
||||||
|
.toList())));
|
||||||
@override
|
@override
|
||||||
$Value? $bridgeGet(String identifier) {
|
$Value? $bridgeGet(String identifier) {
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:dart_eval/dart_eval.dart';
|
import 'package:dart_eval/dart_eval.dart';
|
||||||
|
import 'package:mangayomi/eval/bridge_class/video_model.dart';
|
||||||
import 'package:mangayomi/eval/m_bridge.dart';
|
import 'package:mangayomi/eval/m_bridge.dart';
|
||||||
import 'package:mangayomi/eval/bridge_class/manga_model.dart';
|
import 'package:mangayomi/eval/bridge_class/manga_model.dart';
|
||||||
|
|
||||||
|
|
@ -11,10 +12,20 @@ Runtime runtimeEval(Uint8List bytecode) {
|
||||||
isBridge: true);
|
isBridge: true);
|
||||||
runtime.registerBridgeFunc(
|
runtime.registerBridgeFunc(
|
||||||
'package:bridge_lib/bridge_lib.dart', 'MangaModel.', $MangaModel.$new);
|
'package:bridge_lib/bridge_lib.dart', 'MangaModel.', $MangaModel.$new);
|
||||||
|
runtime.registerBridgeFunc(
|
||||||
|
'package:bridge_lib/bridge_lib.dart', 'VideoModel.', $VideoModel.$new);
|
||||||
runtime.registerBridgeFunc(
|
runtime.registerBridgeFunc(
|
||||||
'package:bridge_lib/bridge_lib.dart', 'MBridge.http', $MBridge.$http);
|
'package:bridge_lib/bridge_lib.dart', 'MBridge.http', $MBridge.$http);
|
||||||
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
||||||
'MBridge.listParseDateTime', $MBridge.$listParseDateTime);
|
'MBridge.listParseDateTime', $MBridge.$listParseDateTime);
|
||||||
|
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
||||||
|
'MBridge.gogoCdnExtractor', $MBridge.$gogoCdnExtractor);
|
||||||
|
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
||||||
|
'MBridge.doodExtractor', $MBridge.$doodExtractor);
|
||||||
|
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
||||||
|
'MBridge.streamTapeExtractor', $MBridge.$streamTapeExtractor);
|
||||||
|
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
||||||
|
'MBridge.mp4UploadExtractor', $MBridge.$mp4UploadExtractor);
|
||||||
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
||||||
'MBridge.jsonPathToString', $MBridge.$jsonPathToString);
|
'MBridge.jsonPathToString', $MBridge.$jsonPathToString);
|
||||||
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
||||||
|
|
@ -35,6 +46,8 @@ Runtime runtimeEval(Uint8List bytecode) {
|
||||||
'MBridge.parseChapterDate', $MBridge.$parseChapterDate);
|
'MBridge.parseChapterDate', $MBridge.$parseChapterDate);
|
||||||
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
||||||
'MBridge.stringParse', $MBridge.$stringParse);
|
'MBridge.stringParse', $MBridge.$stringParse);
|
||||||
|
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
||||||
|
'MBridge.subString', $MBridge.$subString);
|
||||||
runtime.registerBridgeFunc(
|
runtime.registerBridgeFunc(
|
||||||
'package:bridge_lib/bridge_lib.dart', 'MBridge.evalJs', $MBridge.$evalJs);
|
'package:bridge_lib/bridge_lib.dart', 'MBridge.evalJs', $MBridge.$evalJs);
|
||||||
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
|
||||||
|
|
|
||||||
|
|
@ -181,5 +181,18 @@
|
||||||
"one_tracker":"1 tracker",
|
"one_tracker":"1 tracker",
|
||||||
"n_tracker":"{n} trackers",
|
"n_tracker":"{n} trackers",
|
||||||
"tracking": "Tracking",
|
"tracking": "Tracking",
|
||||||
"description": "Description"
|
"description": "Description",
|
||||||
|
"episode_progress": "Progress: {n}",
|
||||||
|
"n_episodes": "{n} episodes",
|
||||||
|
"manga_sources":"Manga Sources",
|
||||||
|
"anime_sources":"Anime Sources",
|
||||||
|
"anime_extensions":"Anime Extensions",
|
||||||
|
"manga_extensions":"Manga Extensions",
|
||||||
|
"anime":"Anime",
|
||||||
|
"manga":"Manga",
|
||||||
|
"library_no_category_exist":"You don't have any categories yet",
|
||||||
|
"watching":"Watching",
|
||||||
|
"plan_to_watch":"Plan to watch",
|
||||||
|
"re_watching":"Rewatching"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -181,5 +181,17 @@
|
||||||
"one_tracker":"Suivi par 1 service",
|
"one_tracker":"Suivi par 1 service",
|
||||||
"n_tracker":"Suivi par {n} services",
|
"n_tracker":"Suivi par {n} services",
|
||||||
"tracking": "Suivi",
|
"tracking": "Suivi",
|
||||||
"description": "Description"
|
"description": "Description",
|
||||||
|
"episode_progress": "Progression: {n}",
|
||||||
|
"n_episodes": "{n} épisodes",
|
||||||
|
"manga_sources":"Sources d'animés",
|
||||||
|
"anime_sources":"Sources des mangas",
|
||||||
|
"anime_extensions":"Extensions d'animés",
|
||||||
|
"manga_extensions":"Extensions des mangas",
|
||||||
|
"anime":"Animé",
|
||||||
|
"manga":"Manga",
|
||||||
|
"library_no_category_exist":"Vous n'avez pas encore de catégories",
|
||||||
|
"watching":"En lecture",
|
||||||
|
"plan_to_watch":"À regarder",
|
||||||
|
"re_watching":"Revisionnage"
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ import 'package:bot_toast/bot_toast.dart';
|
||||||
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
||||||
import 'package:flex_color_scheme/flex_color_scheme.dart';
|
import 'package:flex_color_scheme/flex_color_scheme.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_meedu_videoplayer/init_meedu_player.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:intl/date_symbol_data_local.dart';
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
|
|
@ -29,6 +30,10 @@ class MyHttpoverrides extends HttpOverrides {
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
|
initMeeduPlayer(
|
||||||
|
androidUseMediaKit: true,
|
||||||
|
iosUseMediaKit: true,
|
||||||
|
);
|
||||||
HttpOverrides.global = MyHttpoverrides();
|
HttpOverrides.global = MyHttpoverrides();
|
||||||
if (Platform.isLinux || Platform.isWindows) {
|
if (Platform.isLinux || Platform.isWindows) {
|
||||||
if (runWebViewTitleBarWidget(args)) {
|
if (runWebViewTitleBarWidget(args)) {
|
||||||
|
|
@ -125,4 +130,3 @@ class _MyAppState extends ConsumerState<MyApp> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@ part 'category.g.dart';
|
||||||
class Category {
|
class Category {
|
||||||
Id? id;
|
Id? id;
|
||||||
String? name;
|
String? name;
|
||||||
|
bool? forManga;
|
||||||
Category({
|
Category({
|
||||||
this.id = Isar.autoIncrement,
|
this.id = Isar.autoIncrement,
|
||||||
required this.name,
|
required this.name,
|
||||||
|
required this.forManga
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,13 @@ const CategorySchema = CollectionSchema(
|
||||||
name: r'Category',
|
name: r'Category',
|
||||||
id: 5751694338128944171,
|
id: 5751694338128944171,
|
||||||
properties: {
|
properties: {
|
||||||
r'name': PropertySchema(
|
r'forManga': PropertySchema(
|
||||||
id: 0,
|
id: 0,
|
||||||
|
name: r'forManga',
|
||||||
|
type: IsarType.bool,
|
||||||
|
),
|
||||||
|
r'name': PropertySchema(
|
||||||
|
id: 1,
|
||||||
name: r'name',
|
name: r'name',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
)
|
)
|
||||||
|
|
@ -58,7 +63,8 @@ void _categorySerialize(
|
||||||
List<int> offsets,
|
List<int> offsets,
|
||||||
Map<Type, List<int>> allOffsets,
|
Map<Type, List<int>> allOffsets,
|
||||||
) {
|
) {
|
||||||
writer.writeString(offsets[0], object.name);
|
writer.writeBool(offsets[0], object.forManga);
|
||||||
|
writer.writeString(offsets[1], object.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Category _categoryDeserialize(
|
Category _categoryDeserialize(
|
||||||
|
|
@ -68,8 +74,9 @@ Category _categoryDeserialize(
|
||||||
Map<Type, List<int>> allOffsets,
|
Map<Type, List<int>> allOffsets,
|
||||||
) {
|
) {
|
||||||
final object = Category(
|
final object = Category(
|
||||||
|
forManga: reader.readBoolOrNull(offsets[0]),
|
||||||
id: id,
|
id: id,
|
||||||
name: reader.readStringOrNull(offsets[0]),
|
name: reader.readStringOrNull(offsets[1]),
|
||||||
);
|
);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
@ -82,6 +89,8 @@ P _categoryDeserializeProp<P>(
|
||||||
) {
|
) {
|
||||||
switch (propertyId) {
|
switch (propertyId) {
|
||||||
case 0:
|
case 0:
|
||||||
|
return (reader.readBoolOrNull(offset)) as P;
|
||||||
|
case 1:
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
default:
|
default:
|
||||||
throw IsarError('Unknown property with id $propertyId');
|
throw IsarError('Unknown property with id $propertyId');
|
||||||
|
|
@ -177,6 +186,32 @@ extension CategoryQueryWhere on QueryBuilder<Category, Category, QWhereClause> {
|
||||||
|
|
||||||
extension CategoryQueryFilter
|
extension CategoryQueryFilter
|
||||||
on QueryBuilder<Category, Category, QFilterCondition> {
|
on QueryBuilder<Category, Category, QFilterCondition> {
|
||||||
|
QueryBuilder<Category, Category, QAfterFilterCondition> forMangaIsNull() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(const FilterCondition.isNull(
|
||||||
|
property: r'forManga',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Category, Category, QAfterFilterCondition> forMangaIsNotNull() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||||
|
property: r'forManga',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Category, Category, QAfterFilterCondition> forMangaEqualTo(
|
||||||
|
bool? value) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.equalTo(
|
||||||
|
property: r'forManga',
|
||||||
|
value: value,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Category, Category, QAfterFilterCondition> idIsNull() {
|
QueryBuilder<Category, Category, QAfterFilterCondition> idIsNull() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addFilterCondition(const FilterCondition.isNull(
|
return query.addFilterCondition(const FilterCondition.isNull(
|
||||||
|
|
@ -399,6 +434,18 @@ extension CategoryQueryLinks
|
||||||
on QueryBuilder<Category, Category, QFilterCondition> {}
|
on QueryBuilder<Category, Category, QFilterCondition> {}
|
||||||
|
|
||||||
extension CategoryQuerySortBy on QueryBuilder<Category, Category, QSortBy> {
|
extension CategoryQuerySortBy on QueryBuilder<Category, Category, QSortBy> {
|
||||||
|
QueryBuilder<Category, Category, QAfterSortBy> sortByForManga() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'forManga', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Category, Category, QAfterSortBy> sortByForMangaDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'forManga', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Category, Category, QAfterSortBy> sortByName() {
|
QueryBuilder<Category, Category, QAfterSortBy> sortByName() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addSortBy(r'name', Sort.asc);
|
return query.addSortBy(r'name', Sort.asc);
|
||||||
|
|
@ -414,6 +461,18 @@ extension CategoryQuerySortBy on QueryBuilder<Category, Category, QSortBy> {
|
||||||
|
|
||||||
extension CategoryQuerySortThenBy
|
extension CategoryQuerySortThenBy
|
||||||
on QueryBuilder<Category, Category, QSortThenBy> {
|
on QueryBuilder<Category, Category, QSortThenBy> {
|
||||||
|
QueryBuilder<Category, Category, QAfterSortBy> thenByForManga() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'forManga', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Category, Category, QAfterSortBy> thenByForMangaDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'forManga', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Category, Category, QAfterSortBy> thenById() {
|
QueryBuilder<Category, Category, QAfterSortBy> thenById() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addSortBy(r'id', Sort.asc);
|
return query.addSortBy(r'id', Sort.asc);
|
||||||
|
|
@ -441,6 +500,12 @@ extension CategoryQuerySortThenBy
|
||||||
|
|
||||||
extension CategoryQueryWhereDistinct
|
extension CategoryQueryWhereDistinct
|
||||||
on QueryBuilder<Category, Category, QDistinct> {
|
on QueryBuilder<Category, Category, QDistinct> {
|
||||||
|
QueryBuilder<Category, Category, QDistinct> distinctByForManga() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addDistinctBy(r'forManga');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Category, Category, QDistinct> distinctByName(
|
QueryBuilder<Category, Category, QDistinct> distinctByName(
|
||||||
{bool caseSensitive = true}) {
|
{bool caseSensitive = true}) {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
|
@ -457,6 +522,12 @@ extension CategoryQueryProperty
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Category, bool?, QQueryOperations> forMangaProperty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addPropertyName(r'forManga');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Category, String?, QQueryOperations> nameProperty() {
|
QueryBuilder<Category, String?, QQueryOperations> nameProperty() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addPropertyName(r'name');
|
return query.addPropertyName(r'name');
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ class Manga {
|
||||||
@enumerated
|
@enumerated
|
||||||
Status status;
|
Status status;
|
||||||
|
|
||||||
|
bool? isManga;
|
||||||
|
|
||||||
List<String>? genre;
|
List<String>? genre;
|
||||||
|
|
||||||
bool favorite;
|
bool favorite;
|
||||||
|
|
@ -55,6 +57,7 @@ class Manga {
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.status,
|
required this.status,
|
||||||
required this.description,
|
required this.description,
|
||||||
|
this.isManga = true,
|
||||||
this.dateAdded,
|
this.dateAdded,
|
||||||
this.lastUpdate,
|
this.lastUpdate,
|
||||||
this.categories,
|
this.categories,
|
||||||
|
|
@ -71,3 +74,4 @@ enum Status {
|
||||||
onHiatus,
|
onHiatus,
|
||||||
publishingFinished
|
publishingFinished
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,38 +62,43 @@ const MangaSchema = CollectionSchema(
|
||||||
name: r'isLocalArchive',
|
name: r'isLocalArchive',
|
||||||
type: IsarType.bool,
|
type: IsarType.bool,
|
||||||
),
|
),
|
||||||
r'lang': PropertySchema(
|
r'isManga': PropertySchema(
|
||||||
id: 9,
|
id: 9,
|
||||||
|
name: r'isManga',
|
||||||
|
type: IsarType.bool,
|
||||||
|
),
|
||||||
|
r'lang': PropertySchema(
|
||||||
|
id: 10,
|
||||||
name: r'lang',
|
name: r'lang',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'lastRead': PropertySchema(
|
r'lastRead': PropertySchema(
|
||||||
id: 10,
|
id: 11,
|
||||||
name: r'lastRead',
|
name: r'lastRead',
|
||||||
type: IsarType.long,
|
type: IsarType.long,
|
||||||
),
|
),
|
||||||
r'lastUpdate': PropertySchema(
|
r'lastUpdate': PropertySchema(
|
||||||
id: 11,
|
id: 12,
|
||||||
name: r'lastUpdate',
|
name: r'lastUpdate',
|
||||||
type: IsarType.long,
|
type: IsarType.long,
|
||||||
),
|
),
|
||||||
r'link': PropertySchema(
|
r'link': PropertySchema(
|
||||||
id: 12,
|
id: 13,
|
||||||
name: r'link',
|
name: r'link',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'name': PropertySchema(
|
r'name': PropertySchema(
|
||||||
id: 13,
|
id: 14,
|
||||||
name: r'name',
|
name: r'name',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'source': PropertySchema(
|
r'source': PropertySchema(
|
||||||
id: 14,
|
id: 15,
|
||||||
name: r'source',
|
name: r'source',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'status': PropertySchema(
|
r'status': PropertySchema(
|
||||||
id: 15,
|
id: 16,
|
||||||
name: r'status',
|
name: r'status',
|
||||||
type: IsarType.byte,
|
type: IsarType.byte,
|
||||||
enumMap: _MangastatusEnumValueMap,
|
enumMap: _MangastatusEnumValueMap,
|
||||||
|
|
@ -211,13 +216,14 @@ void _mangaSerialize(
|
||||||
writer.writeStringList(offsets[6], object.genre);
|
writer.writeStringList(offsets[6], object.genre);
|
||||||
writer.writeString(offsets[7], object.imageUrl);
|
writer.writeString(offsets[7], object.imageUrl);
|
||||||
writer.writeBool(offsets[8], object.isLocalArchive);
|
writer.writeBool(offsets[8], object.isLocalArchive);
|
||||||
writer.writeString(offsets[9], object.lang);
|
writer.writeBool(offsets[9], object.isManga);
|
||||||
writer.writeLong(offsets[10], object.lastRead);
|
writer.writeString(offsets[10], object.lang);
|
||||||
writer.writeLong(offsets[11], object.lastUpdate);
|
writer.writeLong(offsets[11], object.lastRead);
|
||||||
writer.writeString(offsets[12], object.link);
|
writer.writeLong(offsets[12], object.lastUpdate);
|
||||||
writer.writeString(offsets[13], object.name);
|
writer.writeString(offsets[13], object.link);
|
||||||
writer.writeString(offsets[14], object.source);
|
writer.writeString(offsets[14], object.name);
|
||||||
writer.writeByte(offsets[15], object.status.index);
|
writer.writeString(offsets[15], object.source);
|
||||||
|
writer.writeByte(offsets[16], object.status.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Manga _mangaDeserialize(
|
Manga _mangaDeserialize(
|
||||||
|
|
@ -237,13 +243,14 @@ Manga _mangaDeserialize(
|
||||||
id: id,
|
id: id,
|
||||||
imageUrl: reader.readStringOrNull(offsets[7]),
|
imageUrl: reader.readStringOrNull(offsets[7]),
|
||||||
isLocalArchive: reader.readBoolOrNull(offsets[8]),
|
isLocalArchive: reader.readBoolOrNull(offsets[8]),
|
||||||
lang: reader.readStringOrNull(offsets[9]),
|
isManga: reader.readBoolOrNull(offsets[9]),
|
||||||
lastRead: reader.readLongOrNull(offsets[10]),
|
lang: reader.readStringOrNull(offsets[10]),
|
||||||
lastUpdate: reader.readLongOrNull(offsets[11]),
|
lastRead: reader.readLongOrNull(offsets[11]),
|
||||||
link: reader.readStringOrNull(offsets[12]),
|
lastUpdate: reader.readLongOrNull(offsets[12]),
|
||||||
name: reader.readStringOrNull(offsets[13]),
|
link: reader.readStringOrNull(offsets[13]),
|
||||||
source: reader.readStringOrNull(offsets[14]),
|
name: reader.readStringOrNull(offsets[14]),
|
||||||
status: _MangastatusValueEnumMap[reader.readByteOrNull(offsets[15])] ??
|
source: reader.readStringOrNull(offsets[15]),
|
||||||
|
status: _MangastatusValueEnumMap[reader.readByteOrNull(offsets[16])] ??
|
||||||
Status.ongoing,
|
Status.ongoing,
|
||||||
);
|
);
|
||||||
return object;
|
return object;
|
||||||
|
|
@ -275,18 +282,20 @@ P _mangaDeserializeProp<P>(
|
||||||
case 8:
|
case 8:
|
||||||
return (reader.readBoolOrNull(offset)) as P;
|
return (reader.readBoolOrNull(offset)) as P;
|
||||||
case 9:
|
case 9:
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
return (reader.readBoolOrNull(offset)) as P;
|
||||||
case 10:
|
case 10:
|
||||||
return (reader.readLongOrNull(offset)) as P;
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
case 11:
|
case 11:
|
||||||
return (reader.readLongOrNull(offset)) as P;
|
return (reader.readLongOrNull(offset)) as P;
|
||||||
case 12:
|
case 12:
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
return (reader.readLongOrNull(offset)) as P;
|
||||||
case 13:
|
case 13:
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
case 14:
|
case 14:
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
case 15:
|
case 15:
|
||||||
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
|
case 16:
|
||||||
return (_MangastatusValueEnumMap[reader.readByteOrNull(offset)] ??
|
return (_MangastatusValueEnumMap[reader.readByteOrNull(offset)] ??
|
||||||
Status.ongoing) as P;
|
Status.ongoing) as P;
|
||||||
default:
|
default:
|
||||||
|
|
@ -1555,6 +1564,32 @@ extension MangaQueryFilter on QueryBuilder<Manga, Manga, QFilterCondition> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Manga, Manga, QAfterFilterCondition> isMangaIsNull() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(const FilterCondition.isNull(
|
||||||
|
property: r'isManga',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Manga, Manga, QAfterFilterCondition> isMangaIsNotNull() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||||
|
property: r'isManga',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Manga, Manga, QAfterFilterCondition> isMangaEqualTo(
|
||||||
|
bool? value) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.equalTo(
|
||||||
|
property: r'isManga',
|
||||||
|
value: value,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Manga, Manga, QAfterFilterCondition> langIsNull() {
|
QueryBuilder<Manga, Manga, QAfterFilterCondition> langIsNull() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addFilterCondition(const FilterCondition.isNull(
|
return query.addFilterCondition(const FilterCondition.isNull(
|
||||||
|
|
@ -2457,6 +2492,18 @@ extension MangaQuerySortBy on QueryBuilder<Manga, Manga, QSortBy> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Manga, Manga, QAfterSortBy> sortByIsManga() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'isManga', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Manga, Manga, QAfterSortBy> sortByIsMangaDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'isManga', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Manga, Manga, QAfterSortBy> sortByLang() {
|
QueryBuilder<Manga, Manga, QAfterSortBy> sortByLang() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addSortBy(r'lang', Sort.asc);
|
return query.addSortBy(r'lang', Sort.asc);
|
||||||
|
|
@ -2627,6 +2674,18 @@ extension MangaQuerySortThenBy on QueryBuilder<Manga, Manga, QSortThenBy> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Manga, Manga, QAfterSortBy> thenByIsManga() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'isManga', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Manga, Manga, QAfterSortBy> thenByIsMangaDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'isManga', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Manga, Manga, QAfterSortBy> thenByLang() {
|
QueryBuilder<Manga, Manga, QAfterSortBy> thenByLang() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addSortBy(r'lang', Sort.asc);
|
return query.addSortBy(r'lang', Sort.asc);
|
||||||
|
|
@ -2770,6 +2829,12 @@ extension MangaQueryWhereDistinct on QueryBuilder<Manga, Manga, QDistinct> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Manga, Manga, QDistinct> distinctByIsManga() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addDistinctBy(r'isManga');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Manga, Manga, QDistinct> distinctByLang(
|
QueryBuilder<Manga, Manga, QDistinct> distinctByLang(
|
||||||
{bool caseSensitive = true}) {
|
{bool caseSensitive = true}) {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
|
@ -2878,6 +2943,12 @@ extension MangaQueryProperty on QueryBuilder<Manga, Manga, QQueryProperty> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Manga, bool?, QQueryOperations> isMangaProperty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addPropertyName(r'isManga');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Manga, String?, QQueryOperations> langProperty() {
|
QueryBuilder<Manga, String?, QQueryOperations> langProperty() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addPropertyName(r'lang');
|
return query.addPropertyName(r'lang');
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,31 @@ class Settings {
|
||||||
|
|
||||||
L10nLocale? locale;
|
L10nLocale? locale;
|
||||||
|
|
||||||
|
@enumerated
|
||||||
|
DisplayType animeDisplayType;
|
||||||
|
|
||||||
|
int? libraryFilterAnimeDownloadType;
|
||||||
|
|
||||||
|
int? libraryFilterAnimeUnreadType;
|
||||||
|
|
||||||
|
int? libraryFilterAnimeStartedType;
|
||||||
|
|
||||||
|
int? libraryFilterAnimeBookMarkedType;
|
||||||
|
|
||||||
|
bool? animeLibraryShowCategoryTabs;
|
||||||
|
|
||||||
|
bool? animeLibraryDownloadedChapters;
|
||||||
|
|
||||||
|
bool? animeLibraryShowLanguage;
|
||||||
|
|
||||||
|
bool? animeLibraryShowNumbersOfItems;
|
||||||
|
|
||||||
|
bool? animeLibraryShowContinueReadingButton;
|
||||||
|
|
||||||
|
bool? animeLibraryLocalSource;
|
||||||
|
|
||||||
|
SortLibraryManga? sortLibraryAnime;
|
||||||
|
|
||||||
Settings(
|
Settings(
|
||||||
{this.id = 227,
|
{this.id = 227,
|
||||||
this.displayType = DisplayType.compactGrid,
|
this.displayType = DisplayType.compactGrid,
|
||||||
|
|
@ -132,7 +157,19 @@ class Settings {
|
||||||
this.downloadLocation = "",
|
this.downloadLocation = "",
|
||||||
this.cropBorders = false,
|
this.cropBorders = false,
|
||||||
this.libraryLocalSource,
|
this.libraryLocalSource,
|
||||||
this.autoUpdateExtensions = false});
|
this.autoUpdateExtensions = false,
|
||||||
|
this.animeDisplayType = DisplayType.compactGrid,
|
||||||
|
this.libraryFilterAnimeDownloadType = 0,
|
||||||
|
this.libraryFilterAnimeUnreadType = 0,
|
||||||
|
this.libraryFilterAnimeStartedType = 0,
|
||||||
|
this.libraryFilterAnimeBookMarkedType = 0,
|
||||||
|
this.animeLibraryShowCategoryTabs = false,
|
||||||
|
this.animeLibraryDownloadedChapters = false,
|
||||||
|
this.animeLibraryShowLanguage = false,
|
||||||
|
this.animeLibraryShowNumbersOfItems = false,
|
||||||
|
this.animeLibraryShowContinueReadingButton = false,
|
||||||
|
this.animeLibraryLocalSource,
|
||||||
|
this.sortLibraryAnime});
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DisplayType {
|
enum DisplayType {
|
||||||
|
|
@ -216,5 +253,5 @@ class FilterScanlator {
|
||||||
class L10nLocale {
|
class L10nLocale {
|
||||||
String? languageCode;
|
String? languageCode;
|
||||||
String? countryCode;
|
String? countryCode;
|
||||||
L10nLocale({this.languageCode,this.countryCode});
|
L10nLocale({this.languageCode, this.countryCode});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ class Source {
|
||||||
|
|
||||||
String? headers;
|
String? headers;
|
||||||
|
|
||||||
|
bool? isManga;
|
||||||
|
|
||||||
Source({
|
Source({
|
||||||
this.id = 0,
|
this.id = 0,
|
||||||
this.name = '',
|
this.name = '',
|
||||||
|
|
@ -68,6 +70,7 @@ class Source {
|
||||||
this.versionLast = "",
|
this.versionLast = "",
|
||||||
this.sourceCode = '',
|
this.sourceCode = '',
|
||||||
this.headers = '',
|
this.headers = '',
|
||||||
|
this.isManga = true,
|
||||||
});
|
});
|
||||||
Source.fromJson(Map<String, dynamic> json) {
|
Source.fromJson(Map<String, dynamic> json) {
|
||||||
name = json['name'];
|
name = json['name'];
|
||||||
|
|
@ -83,93 +86,6 @@ class Source {
|
||||||
sourceCodeUrl = json['sourceCodeUrl'];
|
sourceCodeUrl = json['sourceCodeUrl'];
|
||||||
apiUrl = json['apiUrl'];
|
apiUrl = json['apiUrl'];
|
||||||
version = json['version'];
|
version = json['version'];
|
||||||
|
isManga = json['isManga'] ?? true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// enum TypeSource {
|
|
||||||
// single,
|
|
||||||
|
|
||||||
// mangathemesia,
|
|
||||||
|
|
||||||
// comick,
|
|
||||||
|
|
||||||
// mmrcms,
|
|
||||||
|
|
||||||
// heancms,
|
|
||||||
|
|
||||||
// madara,
|
|
||||||
|
|
||||||
// mangadex
|
|
||||||
// }
|
|
||||||
|
|
||||||
// class Source {
|
|
||||||
// String? name;
|
|
||||||
|
|
||||||
// String? baseUrl;
|
|
||||||
|
|
||||||
// String? lang;
|
|
||||||
|
|
||||||
// bool? isActive;
|
|
||||||
|
|
||||||
// bool? isAdded;
|
|
||||||
|
|
||||||
// bool? isPinned;
|
|
||||||
|
|
||||||
// bool? lastUsed;
|
|
||||||
|
|
||||||
// bool? isFullData;
|
|
||||||
|
|
||||||
// bool? isNsfw;
|
|
||||||
|
|
||||||
// String? sourceCodeUrl;
|
|
||||||
|
|
||||||
// String? typeSource;
|
|
||||||
|
|
||||||
// String? iconUrl;
|
|
||||||
|
|
||||||
// bool? hasCloudflare;
|
|
||||||
|
|
||||||
// String? dateFormat;
|
|
||||||
|
|
||||||
// String? dateFormatLocale;
|
|
||||||
|
|
||||||
// String? apiUrl;
|
|
||||||
|
|
||||||
// String? version;
|
|
||||||
|
|
||||||
// Source({
|
|
||||||
// this.name = "",
|
|
||||||
// this.baseUrl = "",
|
|
||||||
// this.lang = "",
|
|
||||||
// this.typeSource = "",
|
|
||||||
// this.iconUrl = "",
|
|
||||||
// this.dateFormat,
|
|
||||||
// this.dateFormatLocale,
|
|
||||||
// this.isActive = true,
|
|
||||||
// this.isAdded = false,
|
|
||||||
// this.isNsfw = false,
|
|
||||||
// this.isFullData = false,
|
|
||||||
// this.hasCloudflare = false,
|
|
||||||
// this.isPinned = false,
|
|
||||||
// this.lastUsed = false,
|
|
||||||
// this.sourceCodeUrl = "",
|
|
||||||
// this.apiUrl = "",
|
|
||||||
// this.version = "",
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Source.fromJson(Map<String, dynamic> json) {
|
|
||||||
// name = json['name'];
|
|
||||||
// id = json['id'];
|
|
||||||
// baseUrl = json['baseUrl'];
|
|
||||||
// lang = json['lang'];
|
|
||||||
// typeSource = json['typeSource'];
|
|
||||||
// iconUrl = json['iconUrl'];
|
|
||||||
// dateFormat = json['dateFormat'];
|
|
||||||
// dateFormatLocale = json['dateFormatLocale'];
|
|
||||||
// isNsfw = json['isNsfw'];
|
|
||||||
// hasCloudflare = json['hasCloudflare'];
|
|
||||||
// sourceCodeUrl = json['sourceCodeUrl'];
|
|
||||||
// apiUrl = json['apiUrl'];
|
|
||||||
// version = json['version'];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
|
||||||
|
|
@ -67,53 +67,58 @@ const SourceSchema = CollectionSchema(
|
||||||
name: r'isFullData',
|
name: r'isFullData',
|
||||||
type: IsarType.bool,
|
type: IsarType.bool,
|
||||||
),
|
),
|
||||||
r'isNsfw': PropertySchema(
|
r'isManga': PropertySchema(
|
||||||
id: 10,
|
id: 10,
|
||||||
|
name: r'isManga',
|
||||||
|
type: IsarType.bool,
|
||||||
|
),
|
||||||
|
r'isNsfw': PropertySchema(
|
||||||
|
id: 11,
|
||||||
name: r'isNsfw',
|
name: r'isNsfw',
|
||||||
type: IsarType.bool,
|
type: IsarType.bool,
|
||||||
),
|
),
|
||||||
r'isPinned': PropertySchema(
|
r'isPinned': PropertySchema(
|
||||||
id: 11,
|
id: 12,
|
||||||
name: r'isPinned',
|
name: r'isPinned',
|
||||||
type: IsarType.bool,
|
type: IsarType.bool,
|
||||||
),
|
),
|
||||||
r'lang': PropertySchema(
|
r'lang': PropertySchema(
|
||||||
id: 12,
|
id: 13,
|
||||||
name: r'lang',
|
name: r'lang',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'lastUsed': PropertySchema(
|
r'lastUsed': PropertySchema(
|
||||||
id: 13,
|
id: 14,
|
||||||
name: r'lastUsed',
|
name: r'lastUsed',
|
||||||
type: IsarType.bool,
|
type: IsarType.bool,
|
||||||
),
|
),
|
||||||
r'name': PropertySchema(
|
r'name': PropertySchema(
|
||||||
id: 14,
|
id: 15,
|
||||||
name: r'name',
|
name: r'name',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'sourceCode': PropertySchema(
|
r'sourceCode': PropertySchema(
|
||||||
id: 15,
|
id: 16,
|
||||||
name: r'sourceCode',
|
name: r'sourceCode',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'sourceCodeUrl': PropertySchema(
|
r'sourceCodeUrl': PropertySchema(
|
||||||
id: 16,
|
id: 17,
|
||||||
name: r'sourceCodeUrl',
|
name: r'sourceCodeUrl',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'typeSource': PropertySchema(
|
r'typeSource': PropertySchema(
|
||||||
id: 17,
|
id: 18,
|
||||||
name: r'typeSource',
|
name: r'typeSource',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'version': PropertySchema(
|
r'version': PropertySchema(
|
||||||
id: 18,
|
id: 19,
|
||||||
name: r'version',
|
name: r'version',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
),
|
),
|
||||||
r'versionLast': PropertySchema(
|
r'versionLast': PropertySchema(
|
||||||
id: 19,
|
id: 20,
|
||||||
name: r'versionLast',
|
name: r'versionLast',
|
||||||
type: IsarType.string,
|
type: IsarType.string,
|
||||||
)
|
)
|
||||||
|
|
@ -235,16 +240,17 @@ void _sourceSerialize(
|
||||||
writer.writeBool(offsets[7], object.isActive);
|
writer.writeBool(offsets[7], object.isActive);
|
||||||
writer.writeBool(offsets[8], object.isAdded);
|
writer.writeBool(offsets[8], object.isAdded);
|
||||||
writer.writeBool(offsets[9], object.isFullData);
|
writer.writeBool(offsets[9], object.isFullData);
|
||||||
writer.writeBool(offsets[10], object.isNsfw);
|
writer.writeBool(offsets[10], object.isManga);
|
||||||
writer.writeBool(offsets[11], object.isPinned);
|
writer.writeBool(offsets[11], object.isNsfw);
|
||||||
writer.writeString(offsets[12], object.lang);
|
writer.writeBool(offsets[12], object.isPinned);
|
||||||
writer.writeBool(offsets[13], object.lastUsed);
|
writer.writeString(offsets[13], object.lang);
|
||||||
writer.writeString(offsets[14], object.name);
|
writer.writeBool(offsets[14], object.lastUsed);
|
||||||
writer.writeString(offsets[15], object.sourceCode);
|
writer.writeString(offsets[15], object.name);
|
||||||
writer.writeString(offsets[16], object.sourceCodeUrl);
|
writer.writeString(offsets[16], object.sourceCode);
|
||||||
writer.writeString(offsets[17], object.typeSource);
|
writer.writeString(offsets[17], object.sourceCodeUrl);
|
||||||
writer.writeString(offsets[18], object.version);
|
writer.writeString(offsets[18], object.typeSource);
|
||||||
writer.writeString(offsets[19], object.versionLast);
|
writer.writeString(offsets[19], object.version);
|
||||||
|
writer.writeString(offsets[20], object.versionLast);
|
||||||
}
|
}
|
||||||
|
|
||||||
Source _sourceDeserialize(
|
Source _sourceDeserialize(
|
||||||
|
|
@ -265,16 +271,17 @@ Source _sourceDeserialize(
|
||||||
isActive: reader.readBoolOrNull(offsets[7]),
|
isActive: reader.readBoolOrNull(offsets[7]),
|
||||||
isAdded: reader.readBoolOrNull(offsets[8]),
|
isAdded: reader.readBoolOrNull(offsets[8]),
|
||||||
isFullData: reader.readBoolOrNull(offsets[9]),
|
isFullData: reader.readBoolOrNull(offsets[9]),
|
||||||
isNsfw: reader.readBoolOrNull(offsets[10]),
|
isManga: reader.readBoolOrNull(offsets[10]),
|
||||||
isPinned: reader.readBoolOrNull(offsets[11]),
|
isNsfw: reader.readBoolOrNull(offsets[11]),
|
||||||
lang: reader.readStringOrNull(offsets[12]),
|
isPinned: reader.readBoolOrNull(offsets[12]),
|
||||||
lastUsed: reader.readBoolOrNull(offsets[13]),
|
lang: reader.readStringOrNull(offsets[13]),
|
||||||
name: reader.readStringOrNull(offsets[14]),
|
lastUsed: reader.readBoolOrNull(offsets[14]),
|
||||||
sourceCode: reader.readStringOrNull(offsets[15]),
|
name: reader.readStringOrNull(offsets[15]),
|
||||||
sourceCodeUrl: reader.readStringOrNull(offsets[16]),
|
sourceCode: reader.readStringOrNull(offsets[16]),
|
||||||
typeSource: reader.readStringOrNull(offsets[17]),
|
sourceCodeUrl: reader.readStringOrNull(offsets[17]),
|
||||||
version: reader.readStringOrNull(offsets[18]),
|
typeSource: reader.readStringOrNull(offsets[18]),
|
||||||
versionLast: reader.readStringOrNull(offsets[19]),
|
version: reader.readStringOrNull(offsets[19]),
|
||||||
|
versionLast: reader.readStringOrNull(offsets[20]),
|
||||||
);
|
);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
@ -311,11 +318,11 @@ P _sourceDeserializeProp<P>(
|
||||||
case 11:
|
case 11:
|
||||||
return (reader.readBoolOrNull(offset)) as P;
|
return (reader.readBoolOrNull(offset)) as P;
|
||||||
case 12:
|
case 12:
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
|
||||||
case 13:
|
|
||||||
return (reader.readBoolOrNull(offset)) as P;
|
return (reader.readBoolOrNull(offset)) as P;
|
||||||
case 14:
|
case 13:
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
|
case 14:
|
||||||
|
return (reader.readBoolOrNull(offset)) as P;
|
||||||
case 15:
|
case 15:
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
case 16:
|
case 16:
|
||||||
|
|
@ -326,6 +333,8 @@ P _sourceDeserializeProp<P>(
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
case 19:
|
case 19:
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
|
case 20:
|
||||||
|
return (reader.readStringOrNull(offset)) as P;
|
||||||
default:
|
default:
|
||||||
throw IsarError('Unknown property with id $propertyId');
|
throw IsarError('Unknown property with id $propertyId');
|
||||||
}
|
}
|
||||||
|
|
@ -1472,6 +1481,32 @@ extension SourceQueryFilter on QueryBuilder<Source, Source, QFilterCondition> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Source, Source, QAfterFilterCondition> isMangaIsNull() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(const FilterCondition.isNull(
|
||||||
|
property: r'isManga',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Source, Source, QAfterFilterCondition> isMangaIsNotNull() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||||
|
property: r'isManga',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Source, Source, QAfterFilterCondition> isMangaEqualTo(
|
||||||
|
bool? value) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.equalTo(
|
||||||
|
property: r'isManga',
|
||||||
|
value: value,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Source, Source, QAfterFilterCondition> isNsfwIsNull() {
|
QueryBuilder<Source, Source, QAfterFilterCondition> isNsfwIsNull() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addFilterCondition(const FilterCondition.isNull(
|
return query.addFilterCondition(const FilterCondition.isNull(
|
||||||
|
|
@ -2697,6 +2732,18 @@ extension SourceQuerySortBy on QueryBuilder<Source, Source, QSortBy> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Source, Source, QAfterSortBy> sortByIsManga() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'isManga', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Source, Source, QAfterSortBy> sortByIsMangaDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'isManga', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Source, Source, QAfterSortBy> sortByIsNsfw() {
|
QueryBuilder<Source, Source, QAfterSortBy> sortByIsNsfw() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addSortBy(r'isNsfw', Sort.asc);
|
return query.addSortBy(r'isNsfw', Sort.asc);
|
||||||
|
|
@ -2951,6 +2998,18 @@ extension SourceQuerySortThenBy on QueryBuilder<Source, Source, QSortThenBy> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Source, Source, QAfterSortBy> thenByIsManga() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'isManga', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Source, Source, QAfterSortBy> thenByIsMangaDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'isManga', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Source, Source, QAfterSortBy> thenByIsNsfw() {
|
QueryBuilder<Source, Source, QAfterSortBy> thenByIsNsfw() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addSortBy(r'isNsfw', Sort.asc);
|
return query.addSortBy(r'isNsfw', Sort.asc);
|
||||||
|
|
@ -3140,6 +3199,12 @@ extension SourceQueryWhereDistinct on QueryBuilder<Source, Source, QDistinct> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Source, Source, QDistinct> distinctByIsManga() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addDistinctBy(r'isManga');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Source, Source, QDistinct> distinctByIsNsfw() {
|
QueryBuilder<Source, Source, QDistinct> distinctByIsNsfw() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addDistinctBy(r'isNsfw');
|
return query.addDistinctBy(r'isNsfw');
|
||||||
|
|
@ -3276,6 +3341,12 @@ extension SourceQueryProperty on QueryBuilder<Source, Source, QQueryProperty> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryBuilder<Source, bool?, QQueryOperations> isMangaProperty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addPropertyName(r'isManga');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QueryBuilder<Source, bool?, QQueryOperations> isNsfwProperty() {
|
QueryBuilder<Source, bool?, QQueryOperations> isNsfwProperty() {
|
||||||
return QueryBuilder.apply(this, (query) {
|
return QueryBuilder.apply(this, (query) {
|
||||||
return query.addPropertyName(r'isNsfw');
|
return query.addPropertyName(r'isNsfw');
|
||||||
|
|
|
||||||
|
|
@ -47,4 +47,14 @@ class Track {
|
||||||
this.trackingUrl});
|
this.trackingUrl});
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TrackStatus { reading, completed, onHold, dropped, planToRead, rereading }
|
enum TrackStatus {
|
||||||
|
reading,
|
||||||
|
completed,
|
||||||
|
onHold,
|
||||||
|
dropped,
|
||||||
|
planToRead,
|
||||||
|
rereading,
|
||||||
|
watching,
|
||||||
|
planToWatch,
|
||||||
|
reWatching
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -203,6 +203,9 @@ const _TrackstatusEnumValueMap = {
|
||||||
'dropped': 3,
|
'dropped': 3,
|
||||||
'planToRead': 4,
|
'planToRead': 4,
|
||||||
'rereading': 5,
|
'rereading': 5,
|
||||||
|
'watching': 6,
|
||||||
|
'planToWatch': 7,
|
||||||
|
'reWatching': 8,
|
||||||
};
|
};
|
||||||
const _TrackstatusValueEnumMap = {
|
const _TrackstatusValueEnumMap = {
|
||||||
0: TrackStatus.reading,
|
0: TrackStatus.reading,
|
||||||
|
|
@ -211,6 +214,9 @@ const _TrackstatusValueEnumMap = {
|
||||||
3: TrackStatus.dropped,
|
3: TrackStatus.dropped,
|
||||||
4: TrackStatus.planToRead,
|
4: TrackStatus.planToRead,
|
||||||
5: TrackStatus.rereading,
|
5: TrackStatus.rereading,
|
||||||
|
6: TrackStatus.watching,
|
||||||
|
7: TrackStatus.planToWatch,
|
||||||
|
8: TrackStatus.reWatching,
|
||||||
};
|
};
|
||||||
|
|
||||||
Id _trackGetId(Track object) {
|
Id _trackGetId(Track object) {
|
||||||
|
|
|
||||||
8
lib/models/video.dart
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
class Video {
|
||||||
|
final String url;
|
||||||
|
final String quality;
|
||||||
|
final String originalUrl;
|
||||||
|
final Map<String, String>? headers;
|
||||||
|
|
||||||
|
Video(this.url, this.quality, this.originalUrl, {this.headers});
|
||||||
|
}
|
||||||
296
lib/modules/anime/anime_stream_view.dart
Normal file
|
|
@ -0,0 +1,296 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_meedu_videoplayer/meedu_player.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart' as riv;
|
||||||
|
import 'package:mangayomi/models/chapter.dart';
|
||||||
|
import 'package:mangayomi/models/video.dart';
|
||||||
|
import 'package:mangayomi/modules/anime/providers/stream_controller_provider.dart';
|
||||||
|
import 'package:mangayomi/modules/widgets/progress_center.dart';
|
||||||
|
import 'package:mangayomi/services/get_anime_servers.dart';
|
||||||
|
import 'package:mangayomi/utils/media_query.dart';
|
||||||
|
|
||||||
|
class AnimeStreamView extends riv.ConsumerWidget {
|
||||||
|
final Chapter episode;
|
||||||
|
const AnimeStreamView({
|
||||||
|
super.key,
|
||||||
|
required this.episode,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky,
|
||||||
|
overlays: []);
|
||||||
|
final serversData = ref.watch(getAnimeServersProvider(
|
||||||
|
chapter: episode,
|
||||||
|
));
|
||||||
|
return serversData.when(
|
||||||
|
data: (data) {
|
||||||
|
if (data.isEmpty &&
|
||||||
|
(episode.manga.value!.isLocalArchive ?? false) == false) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text(''),
|
||||||
|
leading: BackButton(
|
||||||
|
onPressed: () {
|
||||||
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||||
|
overlays: SystemUiOverlay.values);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: WillPopScope(
|
||||||
|
onWillPop: () async {
|
||||||
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||||
|
overlays: SystemUiOverlay.values);
|
||||||
|
Navigator.pop(context);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
child: const Center(
|
||||||
|
child: Text("Error"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return AnimeStreamPage(
|
||||||
|
episode: episode,
|
||||||
|
videos: data,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
error: (error, stackTrace) => Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text(''),
|
||||||
|
leading: BackButton(
|
||||||
|
onPressed: () {
|
||||||
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||||
|
overlays: SystemUiOverlay.values);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: WillPopScope(
|
||||||
|
onWillPop: () async {
|
||||||
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||||
|
overlays: SystemUiOverlay.values);
|
||||||
|
Navigator.pop(context);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: Text(error.toString()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
loading: () {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
body: WillPopScope(
|
||||||
|
onWillPop: () async {
|
||||||
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||||
|
overlays: SystemUiOverlay.values);
|
||||||
|
Navigator.pop(context);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
MeeduVideoPlayer(
|
||||||
|
header: (context, controller, responsive) => AppBar(
|
||||||
|
leading: BackButton(
|
||||||
|
color: Colors.white,
|
||||||
|
onPressed: () {
|
||||||
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||||
|
overlays: SystemUiOverlay.values);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
controller: MeeduPlayerController(
|
||||||
|
autoHideControls: false,
|
||||||
|
enabledButtons:
|
||||||
|
const EnabledButtons(playPauseAndRepeat: false),
|
||||||
|
screenManager: const ScreenManager(
|
||||||
|
forceLandScapeInFullscreen: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const ProgressCenter(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnimeStreamPage extends StatefulWidget {
|
||||||
|
final List<Video> videos;
|
||||||
|
final Chapter episode;
|
||||||
|
const AnimeStreamPage({Key? key, required this.videos, required this.episode})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AnimeStreamPage> createState() => _AnimeStreamPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AnimeStreamPageState extends State<AnimeStreamPage> {
|
||||||
|
final _controller = MeeduPlayerController(
|
||||||
|
screenManager: const ScreenManager(
|
||||||
|
forceLandScapeInFullscreen: false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
late final streamController = AnimeStreamController(episode: widget.episode);
|
||||||
|
|
||||||
|
/// listener for the video quality
|
||||||
|
final ValueNotifier<Video?> _video = ValueNotifier(null);
|
||||||
|
|
||||||
|
late Duration _currentPosition =
|
||||||
|
streamController.geTCurrentPosition(); // to save the video position
|
||||||
|
|
||||||
|
/// subscription to listen the video position changes
|
||||||
|
StreamSubscription? _currentPositionSubs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_video.value = widget.videos[0]; // set the default video quality (480p)
|
||||||
|
|
||||||
|
// listen the video position
|
||||||
|
_currentPositionSubs = _controller.onPositionChanged.listen(
|
||||||
|
(Duration position) {
|
||||||
|
_currentPosition = position; // save the video position
|
||||||
|
|
||||||
|
streamController.setCurrentPosition(position.inMilliseconds);
|
||||||
|
streamController.setAnimeHistoryUpdate();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
_setDataSource();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_currentPositionSubs?.cancel(); // cancel the subscription
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onChangeVideoQuality() {
|
||||||
|
showCupertinoModalPopup(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => CupertinoActionSheet(
|
||||||
|
actions: List.generate(
|
||||||
|
widget.videos.length,
|
||||||
|
(index) {
|
||||||
|
final quality = widget.videos[index];
|
||||||
|
return CupertinoActionSheetAction(
|
||||||
|
child: Text(quality.quality),
|
||||||
|
onPressed: () {
|
||||||
|
_video.value = quality; // change the video quality
|
||||||
|
_setDataSource(); // update the datasource
|
||||||
|
Navigator.maybePop(_);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
cancelButton: CupertinoActionSheetAction(
|
||||||
|
onPressed: () => Navigator.maybePop(_),
|
||||||
|
isDestructiveAction: true,
|
||||||
|
child: const Text("Cancel"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _setDataSource() async {
|
||||||
|
// set the data source and play the video in the last video position
|
||||||
|
await _controller.setDataSource(
|
||||||
|
DataSource(
|
||||||
|
type: DataSourceType.network,
|
||||||
|
source: _video.value!.url,
|
||||||
|
httpHeaders: _video.value!.headers),
|
||||||
|
autoplay: true,
|
||||||
|
seekTo: _currentPosition,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: WillPopScope(
|
||||||
|
onWillPop: () async {
|
||||||
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||||
|
overlays: SystemUiOverlay.values);
|
||||||
|
Navigator.pop(context);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
child: MeeduVideoPlayer(
|
||||||
|
controller: _controller,
|
||||||
|
header: (ctx, controller, responsive) {
|
||||||
|
// creates a responsive fontSize using the size of video container
|
||||||
|
final double fontSize = responsive.ip(3);
|
||||||
|
|
||||||
|
return AppBar(
|
||||||
|
title: ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: SizedBox(
|
||||||
|
width: mediaWidth(context, 0.8),
|
||||||
|
child: Text(
|
||||||
|
widget.episode.manga.value!.name!,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold, color: Colors.white),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: SizedBox(
|
||||||
|
width: mediaWidth(context, 0.8),
|
||||||
|
child: Text(
|
||||||
|
widget.episode.name!,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Colors.white),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
leading: BackButton(
|
||||||
|
color: Colors.white,
|
||||||
|
onPressed: () {
|
||||||
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||||
|
overlays: SystemUiOverlay.values);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: CupertinoButton(
|
||||||
|
padding: const EdgeInsets.all(5),
|
||||||
|
onPressed: _onChangeVideoQuality,
|
||||||
|
child: ValueListenableBuilder<Video?>(
|
||||||
|
valueListenable: _video,
|
||||||
|
builder: (context, Video? video, child) {
|
||||||
|
return Text(
|
||||||
|
video!.quality,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: fontSize > 18 ? 18 : fontSize,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
124
lib/modules/anime/providers/stream_controller_provider.dart
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
import 'package:isar/isar.dart';
|
||||||
|
import 'package:mangayomi/main.dart';
|
||||||
|
import 'package:mangayomi/models/chapter.dart';
|
||||||
|
import 'package:mangayomi/models/history.dart';
|
||||||
|
import 'package:mangayomi/models/manga.dart';
|
||||||
|
import 'package:mangayomi/models/settings.dart';
|
||||||
|
|
||||||
|
class AnimeStreamController {
|
||||||
|
final Chapter episode;
|
||||||
|
AnimeStreamController({required this.episode});
|
||||||
|
|
||||||
|
Manga getAnime() {
|
||||||
|
return episode.manga.value!;
|
||||||
|
}
|
||||||
|
|
||||||
|
Chapter geAnime() {
|
||||||
|
return episode;
|
||||||
|
}
|
||||||
|
|
||||||
|
final incognitoMode = isar.settings.getSync(227)!.incognitoMode!;
|
||||||
|
|
||||||
|
Settings getIsarSetting() {
|
||||||
|
return isar.settings.getSync(227)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getPrevEpisodeIndex() {
|
||||||
|
final episodes = getAnime().chapters.toList();
|
||||||
|
int? index;
|
||||||
|
for (var i = 0; i < episodes.length; i++) {
|
||||||
|
if (episodes[i].id == episode.id) {
|
||||||
|
index = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index!;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getNextEpisodeIndex() {
|
||||||
|
final episodes = getAnime().chapters.toList();
|
||||||
|
int? index;
|
||||||
|
for (var i = 0; i < episodes.length; i++) {
|
||||||
|
if (episodes[i].id == episode.id) {
|
||||||
|
index = i - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index!;
|
||||||
|
}
|
||||||
|
|
||||||
|
Chapter getPrevEpisode() {
|
||||||
|
return getAnime().chapters.toList()[getPrevEpisodeIndex()];
|
||||||
|
}
|
||||||
|
|
||||||
|
Chapter getNextEpisode() {
|
||||||
|
return getAnime().chapters.toList()[getNextEpisodeIndex()];
|
||||||
|
}
|
||||||
|
|
||||||
|
int getChaptersLength() {
|
||||||
|
return getAnime().chapters.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
Duration geTCurrentPosition() {
|
||||||
|
if (!incognitoMode) {
|
||||||
|
String position = episode.lastPageRead ?? "0";
|
||||||
|
return Duration(
|
||||||
|
milliseconds: episode.isRead!
|
||||||
|
? 0
|
||||||
|
: int.parse(position.isEmpty ? "0" : position));
|
||||||
|
}
|
||||||
|
return Duration.zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAnimeHistoryUpdate() {
|
||||||
|
if (!incognitoMode) {
|
||||||
|
isar.writeTxnSync(() {
|
||||||
|
Manga? manga = episode.manga.value;
|
||||||
|
manga!.lastRead = DateTime.now().millisecondsSinceEpoch;
|
||||||
|
isar.mangas.putSync(manga);
|
||||||
|
});
|
||||||
|
History? history;
|
||||||
|
|
||||||
|
final empty =
|
||||||
|
isar.historys.filter().mangaIdEqualTo(getAnime().id).isEmptySync();
|
||||||
|
|
||||||
|
if (empty) {
|
||||||
|
history = History(
|
||||||
|
mangaId: getAnime().id,
|
||||||
|
date: DateTime.now().millisecondsSinceEpoch.toString())
|
||||||
|
..chapter.value = episode;
|
||||||
|
} else {
|
||||||
|
history = (isar.historys
|
||||||
|
.filter()
|
||||||
|
.mangaIdEqualTo(getAnime().id)
|
||||||
|
.findFirstSync())!
|
||||||
|
..chapter.value = episode
|
||||||
|
..date = DateTime.now().millisecondsSinceEpoch.toString();
|
||||||
|
}
|
||||||
|
isar.writeTxnSync(() {
|
||||||
|
isar.historys.putSync(history!);
|
||||||
|
history.chapter.saveSync();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCurrentPosition(int duration) {
|
||||||
|
if (!incognitoMode) {
|
||||||
|
final chap = episode;
|
||||||
|
isar.writeTxnSync(() {
|
||||||
|
chap.lastPageRead = (duration).toString();
|
||||||
|
isar.chapters.putSync(chap);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getAnimeName() {
|
||||||
|
return getAnime().name!;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getSourceName() {
|
||||||
|
return getAnime().source!;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getChapterTitle() {
|
||||||
|
return episode.name!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -370,4 +370,5 @@ class GetArchiveDataFromFileProvider
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_tabBarController = TabController(length: 3, vsync: this);
|
_tabBarController = TabController(length: 5, vsync: this);
|
||||||
_tabBarController.animateTo(0);
|
_tabBarController.animateTo(0);
|
||||||
_tabBarController.addListener(() {
|
_tabBarController.addListener(() {
|
||||||
_chekPermission();
|
_chekPermission();
|
||||||
|
|
@ -44,7 +44,7 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
|
||||||
final l10n = l10nLocalizations(context)!;
|
final l10n = l10nLocalizations(context)!;
|
||||||
return DefaultTabController(
|
return DefaultTabController(
|
||||||
animationDuration: Duration.zero,
|
animationDuration: Duration.zero,
|
||||||
length: 3,
|
length: 5,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
|
|
@ -70,22 +70,25 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
|
||||||
},
|
},
|
||||||
controller: _textEditingController,
|
controller: _textEditingController,
|
||||||
)
|
)
|
||||||
: _tabBarController.index != 2
|
: _tabBarController.index != 4
|
||||||
? IconButton(
|
? IconButton(
|
||||||
splashRadius: 20,
|
splashRadius: 20,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_tabBarController.index == 1) {
|
if (_tabBarController.index != 1 &&
|
||||||
|
_tabBarController.index != 0) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isSearch = true;
|
_isSearch = true;
|
||||||
});
|
});
|
||||||
} else if (_tabBarController.index == 0) {
|
} else {
|
||||||
context.push(
|
context.push('/globalSearch',
|
||||||
'/globalSearch',
|
extra: _tabBarController.index == 0
|
||||||
);
|
? true
|
||||||
|
: false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
_tabBarController.index == 0
|
_tabBarController.index == 0 ||
|
||||||
|
_tabBarController.index == 1
|
||||||
? Icons.travel_explore_rounded
|
? Icons.travel_explore_rounded
|
||||||
: Icons.search_rounded,
|
: Icons.search_rounded,
|
||||||
color: Theme.of(context).hintColor))
|
color: Theme.of(context).hintColor))
|
||||||
|
|
@ -94,34 +97,53 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
|
||||||
splashRadius: 20,
|
splashRadius: 20,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_tabBarController.index == 0) {
|
if (_tabBarController.index == 0) {
|
||||||
context.push('/sourceFilter');
|
context.push('/sourceFilter', extra: true);
|
||||||
} else if (_tabBarController.index == 1) {
|
} else if (_tabBarController.index == 1) {
|
||||||
|
context.push('/sourceFilter', extra: false);
|
||||||
|
} else if (_tabBarController.index == 2) {
|
||||||
_textEditingController.clear();
|
_textEditingController.clear();
|
||||||
context.push('/extensionLang');
|
context.push('/ExtensionLang', extra: true);
|
||||||
|
} else if (_tabBarController.index == 3) {
|
||||||
|
_textEditingController.clear();
|
||||||
|
context.push('/ExtensionLang', extra: false);
|
||||||
} else {}
|
} else {}
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
_tabBarController.index == 0
|
_tabBarController.index == 0 || _tabBarController.index == 1
|
||||||
? Icons.filter_list_sharp
|
? Icons.filter_list_sharp
|
||||||
: _tabBarController.index == 1
|
: _tabBarController.index == 2 ||
|
||||||
|
_tabBarController.index == 3
|
||||||
? Icons.translate_rounded
|
? Icons.translate_rounded
|
||||||
: Icons.help_outline_outlined,
|
: Icons.help_outline_outlined,
|
||||||
color: Theme.of(context).hintColor)),
|
color: Theme.of(context).hintColor)),
|
||||||
],
|
],
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
indicatorSize: TabBarIndicatorSize.tab,
|
indicatorSize: TabBarIndicatorSize.label,
|
||||||
|
isScrollable: true,
|
||||||
controller: _tabBarController,
|
controller: _tabBarController,
|
||||||
tabs: [
|
tabs: [
|
||||||
Tab(text: l10n.sources),
|
Tab(text: l10n.manga_sources),
|
||||||
Tab(text: l10n.extensions),
|
Tab(text: l10n.anime_sources),
|
||||||
|
Tab(text: l10n.manga_extensions),
|
||||||
|
Tab(text: l10n.anime_extensions),
|
||||||
Tab(text: l10n.migrate),
|
Tab(text: l10n.migrate),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: TabBarView(controller: _tabBarController, children: [
|
body: TabBarView(controller: _tabBarController, children: [
|
||||||
const SourcesScreen(),
|
const SourcesScreen(
|
||||||
|
isManga: true,
|
||||||
|
),
|
||||||
|
const SourcesScreen(
|
||||||
|
isManga: false,
|
||||||
|
),
|
||||||
ExtensionScreen(
|
ExtensionScreen(
|
||||||
query: _textEditingController.text,
|
query: _textEditingController.text,
|
||||||
|
isManga: true,
|
||||||
|
),
|
||||||
|
ExtensionScreen(
|
||||||
|
query: _textEditingController.text,
|
||||||
|
isManga: false,
|
||||||
),
|
),
|
||||||
const MigrateScreen()
|
const MigrateScreen()
|
||||||
]),
|
]),
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ import 'package:mangayomi/utils/language.dart';
|
||||||
import 'package:mangayomi/modules/browse/extension/widgets/extension_lang_list_tile_widget.dart';
|
import 'package:mangayomi/modules/browse/extension/widgets/extension_lang_list_tile_widget.dart';
|
||||||
|
|
||||||
class ExtensionsLang extends ConsumerWidget {
|
class ExtensionsLang extends ConsumerWidget {
|
||||||
const ExtensionsLang({super.key});
|
final bool isManga;
|
||||||
|
const ExtensionsLang({required this.isManga, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -20,8 +21,12 @@ class ExtensionsLang extends ConsumerWidget {
|
||||||
title: Text(l10n.extensions),
|
title: Text(l10n.extensions),
|
||||||
),
|
),
|
||||||
body: StreamBuilder(
|
body: StreamBuilder(
|
||||||
stream:
|
stream: isar.sources
|
||||||
isar.sources.filter().idIsNotNull().watch(fireImmediately: true),
|
.filter()
|
||||||
|
.idIsNotNull()
|
||||||
|
.and()
|
||||||
|
.isMangaEqualTo(isManga)
|
||||||
|
.watch(fireImmediately: true),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
List<Source>? entries = snapshot.hasData ? snapshot.data : [];
|
List<Source>? entries = snapshot.hasData ? snapshot.data : [];
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
|
|
@ -33,15 +38,16 @@ class ExtensionsLang extends ConsumerWidget {
|
||||||
onChanged: (val) {
|
onChanged: (val) {
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
for (var source in entries) {
|
for (var source in entries) {
|
||||||
if (source.lang!.toLowerCase() == lang) {
|
if (source.lang!.toLowerCase() == lang.toLowerCase()) {
|
||||||
isar.sources.putSync(source..isActive = val == true);
|
isar.sources.putSync(source..isActive = val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
value: entries!
|
value: entries!
|
||||||
.where((element) => element.lang!.toLowerCase() == lang)
|
.where((element) =>
|
||||||
.where((element) => element.isActive!)
|
element.lang!.toLowerCase() == lang.toLowerCase() &&
|
||||||
|
element.isActive!)
|
||||||
.isNotEmpty,
|
.isNotEmpty,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,30 @@ import 'package:grouped_list/grouped_list.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:mangayomi/main.dart';
|
import 'package:mangayomi/main.dart';
|
||||||
import 'package:mangayomi/models/source.dart';
|
import 'package:mangayomi/models/source.dart';
|
||||||
import 'package:mangayomi/modules/browse/extension/providers/fetch_sources.dart';
|
import 'package:mangayomi/modules/browse/extension/providers/fetch_anime_sources.dart';
|
||||||
|
import 'package:mangayomi/modules/browse/extension/providers/fetch_manga_sources.dart';
|
||||||
import 'package:mangayomi/utils/language.dart';
|
import 'package:mangayomi/utils/language.dart';
|
||||||
import 'package:mangayomi/modules/browse/extension/widgets/extension_list_tile_widget.dart';
|
import 'package:mangayomi/modules/browse/extension/widgets/extension_list_tile_widget.dart';
|
||||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
||||||
|
|
||||||
class ExtensionScreen extends ConsumerWidget {
|
class ExtensionScreen extends ConsumerWidget {
|
||||||
|
final bool isManga;
|
||||||
final String query;
|
final String query;
|
||||||
const ExtensionScreen({required this.query, super.key});
|
const ExtensionScreen(
|
||||||
|
{required this.query, required this.isManga, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
ref.watch(fetchSourcesListProvider(id: null));
|
if (isManga) {
|
||||||
|
ref.watch(fetchMangaSourcesListProvider(id: null));
|
||||||
|
} else {
|
||||||
|
ref.watch(fetchAnimeSourcesListProvider(id: null));
|
||||||
|
}
|
||||||
|
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () => ref.refresh(fetchSourcesListProvider(id: null).future),
|
onRefresh: () => isManga
|
||||||
|
? ref.refresh(fetchMangaSourcesListProvider(id: null).future)
|
||||||
|
: ref.refresh(fetchAnimeSourcesListProvider(id: null).future),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(top: 10),
|
padding: const EdgeInsets.only(top: 10),
|
||||||
child: StreamBuilder(
|
child: StreamBuilder(
|
||||||
|
|
@ -28,12 +38,14 @@ class ExtensionScreen extends ConsumerWidget {
|
||||||
.idIsNotNull()
|
.idIsNotNull()
|
||||||
.and()
|
.and()
|
||||||
.isActiveEqualTo(true)
|
.isActiveEqualTo(true)
|
||||||
|
.isMangaEqualTo(isManga)
|
||||||
.watch(fireImmediately: true)
|
.watch(fireImmediately: true)
|
||||||
: isar.sources
|
: isar.sources
|
||||||
.filter()
|
.filter()
|
||||||
.idIsNotNull()
|
.idIsNotNull()
|
||||||
.and()
|
.and()
|
||||||
.isActiveEqualTo(true)
|
.isActiveEqualTo(true)
|
||||||
|
.isMangaEqualTo(isManga)
|
||||||
.watch(fireImmediately: true),
|
.watch(fireImmediately: true),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||||
|
|
|
||||||
106
lib/modules/browse/extension/providers/fetch_anime_sources.dart
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'package:mangayomi/main.dart';
|
||||||
|
import 'package:mangayomi/models/settings.dart';
|
||||||
|
import 'package:mangayomi/models/source.dart';
|
||||||
|
import 'package:mangayomi/modules/browse/extension/providers/fetch_manga_sources.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
part 'fetch_anime_sources.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future fetchAnimeSourcesList(FetchAnimeSourcesListRef ref, {int? id}) async {
|
||||||
|
final req = await http.get(Uri.parse(
|
||||||
|
"https://kodjodevf.github.io/mangayomi-extensions/anime_index.json"));
|
||||||
|
final res = jsonDecode(req.body) as List;
|
||||||
|
|
||||||
|
final sourceList = res.map((e) => Source.fromJson(e)).toList();
|
||||||
|
|
||||||
|
isar.writeTxnSync(() async {
|
||||||
|
for (var source in sourceList) {
|
||||||
|
if (!source.isManga!) {
|
||||||
|
if (id != null) {
|
||||||
|
if (id == source.id) {
|
||||||
|
final sourc = isar.sources.getSync(id)!;
|
||||||
|
final req = await http.get(Uri.parse(source.sourceCodeUrl!));
|
||||||
|
final headers = await getHeaders(req.body, source.baseUrl!);
|
||||||
|
isar.writeTxnSync(() {
|
||||||
|
isar.sources.putSync(sourc
|
||||||
|
..headers = headers ?? ""
|
||||||
|
..isAdded = true
|
||||||
|
..sourceCode = req.body
|
||||||
|
..sourceCodeUrl = source.sourceCodeUrl
|
||||||
|
..id = id
|
||||||
|
..apiUrl = source.apiUrl
|
||||||
|
..baseUrl = source.baseUrl
|
||||||
|
..dateFormat = source.dateFormat
|
||||||
|
..dateFormatLocale = source.dateFormatLocale
|
||||||
|
..hasCloudflare = source.hasCloudflare
|
||||||
|
..iconUrl = source.iconUrl
|
||||||
|
..typeSource = source.typeSource
|
||||||
|
..lang = source.lang
|
||||||
|
..isNsfw = source.isNsfw
|
||||||
|
..name = source.name
|
||||||
|
..version = source.version
|
||||||
|
..versionLast = source.version
|
||||||
|
..isManga = source.isManga);
|
||||||
|
});
|
||||||
|
// log("successfully installed");
|
||||||
|
}
|
||||||
|
} else if (isar.sources.getSync(source.id!) != null) {
|
||||||
|
// log("exist");
|
||||||
|
final sourc = isar.sources.getSync(source.id!)!;
|
||||||
|
if (compareVersions(sourc.version!, source.version!) < 0) {
|
||||||
|
// log("update aivalable auto update");
|
||||||
|
if (isar.settings.getSync(227)!.autoUpdateExtensions ?? false) {
|
||||||
|
final req = await http.get(Uri.parse(source.sourceCodeUrl!));
|
||||||
|
final headers = await getHeaders(req.body, source.baseUrl!);
|
||||||
|
isar.writeTxnSync(() {
|
||||||
|
isar.sources.putSync(sourc
|
||||||
|
..headers = headers
|
||||||
|
..sourceCode = req.body
|
||||||
|
..sourceCodeUrl = source.sourceCodeUrl
|
||||||
|
..id = source.id
|
||||||
|
..apiUrl = source.apiUrl
|
||||||
|
..baseUrl = source.baseUrl
|
||||||
|
..dateFormat = source.dateFormat
|
||||||
|
..dateFormatLocale = source.dateFormatLocale
|
||||||
|
..hasCloudflare = source.hasCloudflare
|
||||||
|
..iconUrl = source.iconUrl
|
||||||
|
..typeSource = source.typeSource
|
||||||
|
..isFullData = source.isFullData
|
||||||
|
..lang = source.lang
|
||||||
|
..isNsfw = source.isNsfw
|
||||||
|
..name = source.name
|
||||||
|
..version = source.version
|
||||||
|
..versionLast = source.version
|
||||||
|
..isManga = source.isManga);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// log("update aivalable");
|
||||||
|
isar.sources.putSync(sourc..versionLast = source.version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isar.sources.putSync(Source()
|
||||||
|
..sourceCodeUrl = source.sourceCodeUrl
|
||||||
|
..id = source.id
|
||||||
|
..sourceCode = source.sourceCode
|
||||||
|
..apiUrl = source.apiUrl
|
||||||
|
..baseUrl = source.baseUrl
|
||||||
|
..dateFormat = source.dateFormat
|
||||||
|
..dateFormatLocale = source.dateFormatLocale
|
||||||
|
..hasCloudflare = source.hasCloudflare
|
||||||
|
..iconUrl = source.iconUrl
|
||||||
|
..typeSource = source.typeSource
|
||||||
|
..lang = source.lang
|
||||||
|
..isNsfw = source.isNsfw
|
||||||
|
..name = source.name
|
||||||
|
..version = source.version
|
||||||
|
..versionLast = source.version
|
||||||
|
..isManga = source.isManga);
|
||||||
|
// log("new source");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
part of 'fetch_sources.dart';
|
part of 'fetch_anime_sources.dart';
|
||||||
|
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$fetchSourcesListHash() => r'151bfddc9daf2cde079bf0f98f523d92b7e6ab00';
|
String _$fetchAnimeSourcesListHash() =>
|
||||||
|
r'1b16436684b132a5dc6db2159e38200f1dc9b11e';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|
@ -29,29 +30,29 @@ class _SystemHash {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef FetchSourcesListRef = AutoDisposeFutureProviderRef<dynamic>;
|
typedef FetchAnimeSourcesListRef = AutoDisposeFutureProviderRef<dynamic>;
|
||||||
|
|
||||||
/// See also [fetchSourcesList].
|
/// See also [fetchAnimeSourcesList].
|
||||||
@ProviderFor(fetchSourcesList)
|
@ProviderFor(fetchAnimeSourcesList)
|
||||||
const fetchSourcesListProvider = FetchSourcesListFamily();
|
const fetchAnimeSourcesListProvider = FetchAnimeSourcesListFamily();
|
||||||
|
|
||||||
/// See also [fetchSourcesList].
|
/// See also [fetchAnimeSourcesList].
|
||||||
class FetchSourcesListFamily extends Family<AsyncValue<dynamic>> {
|
class FetchAnimeSourcesListFamily extends Family<AsyncValue<dynamic>> {
|
||||||
/// See also [fetchSourcesList].
|
/// See also [fetchAnimeSourcesList].
|
||||||
const FetchSourcesListFamily();
|
const FetchAnimeSourcesListFamily();
|
||||||
|
|
||||||
/// See also [fetchSourcesList].
|
/// See also [fetchAnimeSourcesList].
|
||||||
FetchSourcesListProvider call({
|
FetchAnimeSourcesListProvider call({
|
||||||
int? id,
|
int? id,
|
||||||
}) {
|
}) {
|
||||||
return FetchSourcesListProvider(
|
return FetchAnimeSourcesListProvider(
|
||||||
id: id,
|
id: id,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FetchSourcesListProvider getProviderOverride(
|
FetchAnimeSourcesListProvider getProviderOverride(
|
||||||
covariant FetchSourcesListProvider provider,
|
covariant FetchAnimeSourcesListProvider provider,
|
||||||
) {
|
) {
|
||||||
return call(
|
return call(
|
||||||
id: provider.id,
|
id: provider.id,
|
||||||
|
|
@ -70,35 +71,35 @@ class FetchSourcesListFamily extends Family<AsyncValue<dynamic>> {
|
||||||
_allTransitiveDependencies;
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? get name => r'fetchSourcesListProvider';
|
String? get name => r'fetchAnimeSourcesListProvider';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See also [fetchSourcesList].
|
/// See also [fetchAnimeSourcesList].
|
||||||
class FetchSourcesListProvider extends AutoDisposeFutureProvider<dynamic> {
|
class FetchAnimeSourcesListProvider extends AutoDisposeFutureProvider<dynamic> {
|
||||||
/// See also [fetchSourcesList].
|
/// See also [fetchAnimeSourcesList].
|
||||||
FetchSourcesListProvider({
|
FetchAnimeSourcesListProvider({
|
||||||
this.id,
|
this.id,
|
||||||
}) : super.internal(
|
}) : super.internal(
|
||||||
(ref) => fetchSourcesList(
|
(ref) => fetchAnimeSourcesList(
|
||||||
ref,
|
ref,
|
||||||
id: id,
|
id: id,
|
||||||
),
|
),
|
||||||
from: fetchSourcesListProvider,
|
from: fetchAnimeSourcesListProvider,
|
||||||
name: r'fetchSourcesListProvider',
|
name: r'fetchAnimeSourcesListProvider',
|
||||||
debugGetCreateSourceHash:
|
debugGetCreateSourceHash:
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
? null
|
? null
|
||||||
: _$fetchSourcesListHash,
|
: _$fetchAnimeSourcesListHash,
|
||||||
dependencies: FetchSourcesListFamily._dependencies,
|
dependencies: FetchAnimeSourcesListFamily._dependencies,
|
||||||
allTransitiveDependencies:
|
allTransitiveDependencies:
|
||||||
FetchSourcesListFamily._allTransitiveDependencies,
|
FetchAnimeSourcesListFamily._allTransitiveDependencies,
|
||||||
);
|
);
|
||||||
|
|
||||||
final int? id;
|
final int? id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is FetchSourcesListProvider && other.id == id;
|
return other is FetchAnimeSourcesListProvider && other.id == id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -109,4 +110,5 @@ class FetchSourcesListProvider extends AutoDisposeFutureProvider<dynamic> {
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
152
lib/modules/browse/extension/providers/fetch_manga_sources.dart
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'package:dart_eval/stdlib/core.dart';
|
||||||
|
import 'package:mangayomi/eval/compiler/compiler.dart';
|
||||||
|
import 'package:mangayomi/eval/runtime/runtime.dart';
|
||||||
|
import 'package:mangayomi/main.dart';
|
||||||
|
import 'package:mangayomi/models/settings.dart';
|
||||||
|
import 'package:mangayomi/models/source.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
part 'fetch_manga_sources.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future fetchMangaSourcesList(FetchMangaSourcesListRef ref, {int? id}) async {
|
||||||
|
final req = await http.get(
|
||||||
|
Uri.parse("https://kodjodevf.github.io/mangayomi-extensions/index.json"));
|
||||||
|
final res = jsonDecode(req.body) as List;
|
||||||
|
|
||||||
|
final sourceList = res.map((e) => Source.fromJson(e)).toList();
|
||||||
|
|
||||||
|
isar.writeTxnSync(() async {
|
||||||
|
for (var source in sourceList) {
|
||||||
|
if (source.isManga!) {
|
||||||
|
if (id != null) {
|
||||||
|
if (id == source.id) {
|
||||||
|
final sourc = isar.sources.getSync(id)!;
|
||||||
|
final req = await http.get(Uri.parse(source.sourceCodeUrl!));
|
||||||
|
final headers = await getHeaders(req.body, source.baseUrl!);
|
||||||
|
isar.writeTxnSync(() {
|
||||||
|
isar.sources.putSync(sourc
|
||||||
|
..headers = headers ?? ""
|
||||||
|
..isAdded = true
|
||||||
|
..sourceCode = req.body
|
||||||
|
..sourceCodeUrl = source.sourceCodeUrl
|
||||||
|
..id = id
|
||||||
|
..apiUrl = source.apiUrl
|
||||||
|
..baseUrl = source.baseUrl
|
||||||
|
..dateFormat = source.dateFormat
|
||||||
|
..dateFormatLocale = source.dateFormatLocale
|
||||||
|
..hasCloudflare = source.hasCloudflare
|
||||||
|
..iconUrl = source.iconUrl
|
||||||
|
..typeSource = source.typeSource
|
||||||
|
..lang = source.lang
|
||||||
|
..isNsfw = source.isNsfw
|
||||||
|
..name = source.name
|
||||||
|
..version = source.version
|
||||||
|
..versionLast = source.version
|
||||||
|
..isManga = source.isManga);
|
||||||
|
});
|
||||||
|
// log("successfully installed");
|
||||||
|
}
|
||||||
|
} else if (isar.sources.getSync(source.id!) != null) {
|
||||||
|
// log("exist");
|
||||||
|
final sourc = isar.sources.getSync(source.id!)!;
|
||||||
|
if (compareVersions(sourc.version!, source.version!) < 0) {
|
||||||
|
// log("update aivalable auto update");
|
||||||
|
if (isar.settings.getSync(227)!.autoUpdateExtensions ?? false) {
|
||||||
|
final req = await http.get(Uri.parse(source.sourceCodeUrl!));
|
||||||
|
final headers = await getHeaders(req.body, source.baseUrl!);
|
||||||
|
isar.writeTxnSync(() {
|
||||||
|
isar.sources.putSync(sourc
|
||||||
|
..headers = headers
|
||||||
|
..sourceCode = req.body
|
||||||
|
..sourceCodeUrl = source.sourceCodeUrl
|
||||||
|
..id = source.id
|
||||||
|
..apiUrl = source.apiUrl
|
||||||
|
..baseUrl = source.baseUrl
|
||||||
|
..dateFormat = source.dateFormat
|
||||||
|
..dateFormatLocale = source.dateFormatLocale
|
||||||
|
..hasCloudflare = source.hasCloudflare
|
||||||
|
..iconUrl = source.iconUrl
|
||||||
|
..typeSource = source.typeSource
|
||||||
|
..isFullData = source.isFullData
|
||||||
|
..lang = source.lang
|
||||||
|
..isNsfw = source.isNsfw
|
||||||
|
..name = source.name
|
||||||
|
..version = source.version
|
||||||
|
..versionLast = source.version
|
||||||
|
..isManga = source.isManga);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// log("update aivalable");
|
||||||
|
isar.sources.putSync(sourc..versionLast = source.version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isar.sources.putSync(Source()
|
||||||
|
..sourceCodeUrl = source.sourceCodeUrl
|
||||||
|
..id = source.id
|
||||||
|
..sourceCode = source.sourceCode
|
||||||
|
..apiUrl = source.apiUrl
|
||||||
|
..baseUrl = source.baseUrl
|
||||||
|
..dateFormat = source.dateFormat
|
||||||
|
..dateFormatLocale = source.dateFormatLocale
|
||||||
|
..hasCloudflare = source.hasCloudflare
|
||||||
|
..iconUrl = source.iconUrl
|
||||||
|
..typeSource = source.typeSource
|
||||||
|
..lang = source.lang
|
||||||
|
..isNsfw = source.isNsfw
|
||||||
|
..name = source.name
|
||||||
|
..version = source.version
|
||||||
|
..versionLast = source.version
|
||||||
|
..isManga = source.isManga);
|
||||||
|
// log("new source");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int compareVersions(String version1, String version2) {
|
||||||
|
List<String> v1Components = version1.split('.');
|
||||||
|
List<String> v2Components = version2.split('.');
|
||||||
|
|
||||||
|
for (int i = 0; i < v1Components.length && i < v2Components.length; i++) {
|
||||||
|
int v1Value = int.parse(v1Components[i]);
|
||||||
|
int v2Value = int.parse(v2Components[i]);
|
||||||
|
|
||||||
|
if (v1Value < v2Value) {
|
||||||
|
return -1;
|
||||||
|
} else if (v1Value > v2Value) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v1Components.length < v2Components.length) {
|
||||||
|
return -1;
|
||||||
|
} else if (v1Components.length > v2Components.length) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> getHeaders(String codeSource, String baseUrl) async {
|
||||||
|
try {
|
||||||
|
final bytecode = compilerEval(codeSource);
|
||||||
|
final runtime = runtimeEval(bytecode);
|
||||||
|
runtime.args = [$String(baseUrl)];
|
||||||
|
var res = await runtime.executeLib(
|
||||||
|
'package:mangayomi/main.dart',
|
||||||
|
'getHeader',
|
||||||
|
);
|
||||||
|
Map<String, String> headers = {};
|
||||||
|
if (res is $Map) {
|
||||||
|
headers = res.$reified
|
||||||
|
.map((key, value) => MapEntry(key.toString(), value.toString()));
|
||||||
|
}
|
||||||
|
return jsonEncode(headers);
|
||||||
|
} catch (_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'fetch_manga_sources.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$fetchMangaSourcesListHash() =>
|
||||||
|
r'82665771175f4fea39c0dee77d06d568737ea989';
|
||||||
|
|
||||||
|
/// 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef FetchMangaSourcesListRef = AutoDisposeFutureProviderRef<dynamic>;
|
||||||
|
|
||||||
|
/// See also [fetchMangaSourcesList].
|
||||||
|
@ProviderFor(fetchMangaSourcesList)
|
||||||
|
const fetchMangaSourcesListProvider = FetchMangaSourcesListFamily();
|
||||||
|
|
||||||
|
/// See also [fetchMangaSourcesList].
|
||||||
|
class FetchMangaSourcesListFamily extends Family<AsyncValue<dynamic>> {
|
||||||
|
/// See also [fetchMangaSourcesList].
|
||||||
|
const FetchMangaSourcesListFamily();
|
||||||
|
|
||||||
|
/// See also [fetchMangaSourcesList].
|
||||||
|
FetchMangaSourcesListProvider call({
|
||||||
|
int? id,
|
||||||
|
}) {
|
||||||
|
return FetchMangaSourcesListProvider(
|
||||||
|
id: id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
FetchMangaSourcesListProvider getProviderOverride(
|
||||||
|
covariant FetchMangaSourcesListProvider provider,
|
||||||
|
) {
|
||||||
|
return call(
|
||||||
|
id: provider.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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'fetchMangaSourcesListProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [fetchMangaSourcesList].
|
||||||
|
class FetchMangaSourcesListProvider extends AutoDisposeFutureProvider<dynamic> {
|
||||||
|
/// See also [fetchMangaSourcesList].
|
||||||
|
FetchMangaSourcesListProvider({
|
||||||
|
this.id,
|
||||||
|
}) : super.internal(
|
||||||
|
(ref) => fetchMangaSourcesList(
|
||||||
|
ref,
|
||||||
|
id: id,
|
||||||
|
),
|
||||||
|
from: fetchMangaSourcesListProvider,
|
||||||
|
name: r'fetchMangaSourcesListProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$fetchMangaSourcesListHash,
|
||||||
|
dependencies: FetchMangaSourcesListFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
FetchMangaSourcesListFamily._allTransitiveDependencies,
|
||||||
|
);
|
||||||
|
|
||||||
|
final int? id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is FetchMangaSourcesListProvider && other.id == id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, id.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
@ -1,147 +0,0 @@
|
||||||
import 'dart:convert';
|
|
||||||
import 'package:dart_eval/stdlib/core.dart';
|
|
||||||
import 'package:mangayomi/eval/compiler/compiler.dart';
|
|
||||||
import 'package:mangayomi/eval/runtime/runtime.dart';
|
|
||||||
import 'package:mangayomi/main.dart';
|
|
||||||
import 'package:mangayomi/models/settings.dart';
|
|
||||||
import 'package:mangayomi/models/source.dart';
|
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
||||||
import 'package:http/http.dart' as http;
|
|
||||||
part 'fetch_sources.g.dart';
|
|
||||||
|
|
||||||
@riverpod
|
|
||||||
Future fetchSourcesList(FetchSourcesListRef ref, {int? id}) async {
|
|
||||||
final req = await http
|
|
||||||
.get(Uri.parse("https://kodjodevf.github.io/mangayomi-extensions/index.json"));
|
|
||||||
final res = jsonDecode(req.body) as List;
|
|
||||||
|
|
||||||
final sourceList = res.map((e) => Source.fromJson(e)).toList();
|
|
||||||
|
|
||||||
isar.writeTxnSync(() async {
|
|
||||||
for (var source in sourceList) {
|
|
||||||
if (id != null) {
|
|
||||||
if (id == source.id) {
|
|
||||||
final sourc = isar.sources.getSync(id)!;
|
|
||||||
final req = await http.get(Uri.parse(source.sourceCodeUrl!));
|
|
||||||
final headers = await getHeaders(req.body, source.baseUrl!);
|
|
||||||
isar.writeTxnSync(() {
|
|
||||||
isar.sources.putSync(sourc
|
|
||||||
..headers = headers ?? ""
|
|
||||||
..isAdded = true
|
|
||||||
..sourceCode = req.body
|
|
||||||
..sourceCodeUrl = source.sourceCodeUrl
|
|
||||||
..id = id
|
|
||||||
..apiUrl = source.apiUrl
|
|
||||||
..baseUrl = source.baseUrl
|
|
||||||
..dateFormat = source.dateFormat
|
|
||||||
..dateFormatLocale = source.dateFormatLocale
|
|
||||||
..hasCloudflare = source.hasCloudflare
|
|
||||||
..iconUrl = source.iconUrl
|
|
||||||
..typeSource = source.typeSource
|
|
||||||
..lang = source.lang
|
|
||||||
..isNsfw = source.isNsfw
|
|
||||||
..name = source.name
|
|
||||||
..version = source.version
|
|
||||||
..versionLast = source.version);
|
|
||||||
});
|
|
||||||
// log("successfully installed");
|
|
||||||
}
|
|
||||||
} else if (isar.sources.getSync(source.id!) != null) {
|
|
||||||
// log("exist");
|
|
||||||
final sourc = isar.sources.getSync(source.id!)!;
|
|
||||||
if (compareVersions(sourc.version!, source.version!) < 0) {
|
|
||||||
// log("update aivalable auto update");
|
|
||||||
if (isar.settings.getSync(227)!.autoUpdateExtensions ?? false) {
|
|
||||||
final req = await http.get(Uri.parse(source.sourceCodeUrl!));
|
|
||||||
final headers = await getHeaders(req.body, source.baseUrl!);
|
|
||||||
isar.writeTxnSync(() {
|
|
||||||
isar.sources.putSync(sourc
|
|
||||||
..headers = headers
|
|
||||||
..sourceCode = req.body
|
|
||||||
..sourceCodeUrl = source.sourceCodeUrl
|
|
||||||
..id = source.id
|
|
||||||
..apiUrl = source.apiUrl
|
|
||||||
..baseUrl = source.baseUrl
|
|
||||||
..dateFormat = source.dateFormat
|
|
||||||
..dateFormatLocale = source.dateFormatLocale
|
|
||||||
..hasCloudflare = source.hasCloudflare
|
|
||||||
..iconUrl = source.iconUrl
|
|
||||||
..typeSource = source.typeSource
|
|
||||||
..isFullData = source.isFullData
|
|
||||||
..lang = source.lang
|
|
||||||
..isNsfw = source.isNsfw
|
|
||||||
..name = source.name
|
|
||||||
..version = source.version
|
|
||||||
..versionLast = source.version);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// log("update aivalable");
|
|
||||||
isar.sources.putSync(sourc..versionLast = source.version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
isar.sources.putSync(Source()
|
|
||||||
..sourceCodeUrl = source.sourceCodeUrl
|
|
||||||
..id = source.id
|
|
||||||
..sourceCode = source.sourceCode
|
|
||||||
..apiUrl = source.apiUrl
|
|
||||||
..baseUrl = source.baseUrl
|
|
||||||
..dateFormat = source.dateFormat
|
|
||||||
..dateFormatLocale = source.dateFormatLocale
|
|
||||||
..hasCloudflare = source.hasCloudflare
|
|
||||||
..iconUrl = source.iconUrl
|
|
||||||
..typeSource = source.typeSource
|
|
||||||
..lang = source.lang
|
|
||||||
..isNsfw = source.isNsfw
|
|
||||||
..name = source.name
|
|
||||||
..version = source.version
|
|
||||||
..versionLast = source.version);
|
|
||||||
// log("new source");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
int compareVersions(String version1, String version2) {
|
|
||||||
List<String> v1Components = version1.split('.');
|
|
||||||
List<String> v2Components = version2.split('.');
|
|
||||||
|
|
||||||
for (int i = 0; i < v1Components.length && i < v2Components.length; i++) {
|
|
||||||
int v1Value = int.parse(v1Components[i]);
|
|
||||||
int v2Value = int.parse(v2Components[i]);
|
|
||||||
|
|
||||||
if (v1Value < v2Value) {
|
|
||||||
return -1;
|
|
||||||
} else if (v1Value > v2Value) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v1Components.length < v2Components.length) {
|
|
||||||
return -1;
|
|
||||||
} else if (v1Components.length > v2Components.length) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> getHeaders(String codeSource, String baseUrl) async {
|
|
||||||
try {
|
|
||||||
final bytecode = compilerEval(codeSource);
|
|
||||||
final runtime = runtimeEval(bytecode);
|
|
||||||
runtime.args = [$String(baseUrl)];
|
|
||||||
var result2 = await runtime.executeLib(
|
|
||||||
'package:package:mangayomi/main.dart',
|
|
||||||
'getHeader',
|
|
||||||
);
|
|
||||||
Map<String, String> headers = {};
|
|
||||||
if (result2 is $Map) {
|
|
||||||
headers = result2.$reified
|
|
||||||
.map((key, value) => MapEntry(key.toString(), value.toString()));
|
|
||||||
}
|
|
||||||
return jsonEncode(headers);
|
|
||||||
} catch (_) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:mangayomi/models/source.dart';
|
import 'package:mangayomi/models/source.dart';
|
||||||
import 'package:mangayomi/modules/browse/extension/providers/fetch_sources.dart';
|
import 'package:mangayomi/modules/browse/extension/providers/fetch_anime_sources.dart';
|
||||||
|
import 'package:mangayomi/modules/browse/extension/providers/fetch_manga_sources.dart';
|
||||||
import 'package:mangayomi/utils/language.dart';
|
import 'package:mangayomi/utils/language.dart';
|
||||||
|
|
||||||
class ExtensionListTileWidget extends ConsumerStatefulWidget {
|
class ExtensionListTileWidget extends ConsumerStatefulWidget {
|
||||||
|
|
@ -90,8 +91,13 @@ class _ExtensionListTileWidgetState
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
await ref.watch(
|
widget.source.isManga!
|
||||||
fetchSourcesListProvider(id: widget.source.id).future);
|
? await ref.watch(
|
||||||
|
fetchMangaSourcesListProvider(id: widget.source.id)
|
||||||
|
.future)
|
||||||
|
: await ref.watch(
|
||||||
|
fetchAnimeSourcesListProvider(id: widget.source.id)
|
||||||
|
.future);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,9 @@ import 'package:mangayomi/modules/widgets/bottom_text_widget.dart';
|
||||||
import 'package:mangayomi/modules/widgets/manga_image_card_widget.dart';
|
import 'package:mangayomi/modules/widgets/manga_image_card_widget.dart';
|
||||||
|
|
||||||
class GlobalSearchScreen extends ConsumerStatefulWidget {
|
class GlobalSearchScreen extends ConsumerStatefulWidget {
|
||||||
|
final bool isManga;
|
||||||
const GlobalSearchScreen({
|
const GlobalSearchScreen({
|
||||||
|
required this.isManga,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -35,12 +37,19 @@ class _GlobalSearchScreenState extends ConsumerState<GlobalSearchScreen> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final sourceList = ref.watch(onlyIncludePinnedSourceStateProvider)
|
final sourceList = ref.watch(onlyIncludePinnedSourceStateProvider)
|
||||||
? isar.sources.filter().isPinnedEqualTo(true).findAllSync()
|
? isar.sources
|
||||||
|
.filter()
|
||||||
|
.isPinnedEqualTo(true)
|
||||||
|
.and()
|
||||||
|
.isMangaEqualTo(widget.isManga)
|
||||||
|
.findAllSync()
|
||||||
: isar.sources
|
: isar.sources
|
||||||
.filter()
|
.filter()
|
||||||
.idIsNotNull()
|
.idIsNotNull()
|
||||||
.and()
|
.and()
|
||||||
.isAddedEqualTo(true)
|
.isAddedEqualTo(true)
|
||||||
|
.and()
|
||||||
|
.isMangaEqualTo(widget.isManga)
|
||||||
.findAllSync();
|
.findAllSync();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
|
|
@ -186,7 +195,10 @@ class _MangaGlobalImageCardState extends ConsumerState<MangaGlobalImageCard>
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
pushToMangaReaderDetail(
|
pushToMangaReaderDetail(
|
||||||
context: context, getManga: data, lang: widget.source.lang!);
|
context: context,
|
||||||
|
getManga: data,
|
||||||
|
lang: widget.source.lang!,
|
||||||
|
isManga: widget.source.isManga ?? true);
|
||||||
},
|
},
|
||||||
child: StreamBuilder(
|
child: StreamBuilder(
|
||||||
stream: isar.mangas
|
stream: isar.mangas
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ import 'package:mangayomi/providers/l10n_providers.dart';
|
||||||
import 'package:mangayomi/utils/language.dart';
|
import 'package:mangayomi/utils/language.dart';
|
||||||
|
|
||||||
class SourcesFilterScreen extends ConsumerWidget {
|
class SourcesFilterScreen extends ConsumerWidget {
|
||||||
const SourcesFilterScreen({super.key});
|
final bool isManga;
|
||||||
|
const SourcesFilterScreen({required this.isManga, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -26,6 +27,8 @@ class SourcesFilterScreen extends ConsumerWidget {
|
||||||
.idIsNotNull()
|
.idIsNotNull()
|
||||||
.and()
|
.and()
|
||||||
.sourceCodeIsNotEmpty()
|
.sourceCodeIsNotEmpty()
|
||||||
|
.and()
|
||||||
|
.isMangaEqualTo(isManga)
|
||||||
.watch(fireImmediately: true),
|
.watch(fireImmediately: true),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||||
|
|
@ -43,7 +46,8 @@ class SourcesFilterScreen extends ConsumerWidget {
|
||||||
value: entries
|
value: entries
|
||||||
.where((element) =>
|
.where((element) =>
|
||||||
element.lang!.toLowerCase() == groupByValue &&
|
element.lang!.toLowerCase() == groupByValue &&
|
||||||
element.isActive!)
|
element.isActive! &&
|
||||||
|
element.isManga == isManga)
|
||||||
.isNotEmpty,
|
.isNotEmpty,
|
||||||
onChanged: (val) {
|
onChanged: (val) {
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
|
|
@ -65,7 +69,8 @@ class SourcesFilterScreen extends ConsumerWidget {
|
||||||
if (entries
|
if (entries
|
||||||
.where((s) =>
|
.where((s) =>
|
||||||
s.lang!.toLowerCase() == element.lang &&
|
s.lang!.toLowerCase() == element.lang &&
|
||||||
s.isActive!)
|
s.isActive! &&
|
||||||
|
s.isManga == isManga)
|
||||||
.isEmpty) {
|
.isEmpty) {
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ import 'package:mangayomi/utils/language.dart';
|
||||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
||||||
|
|
||||||
class SourcesScreen extends ConsumerWidget {
|
class SourcesScreen extends ConsumerWidget {
|
||||||
const SourcesScreen({super.key});
|
final bool isManga;
|
||||||
|
const SourcesScreen({required this.isManga, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -29,6 +30,8 @@ class SourcesScreen extends ConsumerWidget {
|
||||||
.isActiveEqualTo(true)
|
.isActiveEqualTo(true)
|
||||||
.and()
|
.and()
|
||||||
.lastUsedEqualTo(true)
|
.lastUsedEqualTo(true)
|
||||||
|
.and()
|
||||||
|
.isMangaEqualTo(isManga)
|
||||||
.watch(fireImmediately: true),
|
.watch(fireImmediately: true),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
|
|
@ -76,6 +79,8 @@ class SourcesScreen extends ConsumerWidget {
|
||||||
.isActiveEqualTo(true)
|
.isActiveEqualTo(true)
|
||||||
.and()
|
.and()
|
||||||
.isPinnedEqualTo(true)
|
.isPinnedEqualTo(true)
|
||||||
|
.and()
|
||||||
|
.isMangaEqualTo(isManga)
|
||||||
.watch(fireImmediately: true),
|
.watch(fireImmediately: true),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
|
|
@ -123,6 +128,8 @@ class SourcesScreen extends ConsumerWidget {
|
||||||
.isActiveEqualTo(true)
|
.isActiveEqualTo(true)
|
||||||
.and()
|
.and()
|
||||||
.isPinnedEqualTo(false)
|
.isPinnedEqualTo(false)
|
||||||
|
.and()
|
||||||
|
.isMangaEqualTo(isManga)
|
||||||
.watch(fireImmediately: true),
|
.watch(fireImmediately: true),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,11 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:grouped_list/grouped_list.dart';
|
import 'package:grouped_list/grouped_list.dart';
|
||||||
|
import 'package:isar/isar.dart';
|
||||||
import 'package:mangayomi/main.dart';
|
import 'package:mangayomi/main.dart';
|
||||||
|
import 'package:mangayomi/models/chapter.dart';
|
||||||
import 'package:mangayomi/models/history.dart';
|
import 'package:mangayomi/models/history.dart';
|
||||||
|
import 'package:mangayomi/models/manga.dart';
|
||||||
import 'package:mangayomi/modules/history/providers/isar_providers.dart';
|
import 'package:mangayomi/modules/history/providers/isar_providers.dart';
|
||||||
import 'package:mangayomi/modules/manga/reader/providers/push_router.dart';
|
import 'package:mangayomi/modules/manga/reader/providers/push_router.dart';
|
||||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||||
|
|
@ -22,15 +25,33 @@ class HistoryScreen extends ConsumerStatefulWidget {
|
||||||
ConsumerState<HistoryScreen> createState() => _HistoryScreenState();
|
ConsumerState<HistoryScreen> createState() => _HistoryScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HistoryScreenState extends ConsumerState<HistoryScreen> {
|
class _HistoryScreenState extends ConsumerState<HistoryScreen>
|
||||||
|
with TickerProviderStateMixin {
|
||||||
|
late TabController _tabBarController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_tabBarController = TabController(length: 2, vsync: this);
|
||||||
|
_tabBarController.animateTo(0);
|
||||||
|
_tabBarController.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
_textEditingController.clear();
|
||||||
|
_isSearch = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
final _textEditingController = TextEditingController();
|
final _textEditingController = TextEditingController();
|
||||||
bool _isSearch = false;
|
bool _isSearch = false;
|
||||||
List<History> entriesData = [];
|
List<History> entriesData = [];
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final l10n = l10nLocalizations(context)!;
|
final l10n = l10nLocalizations(context)!;
|
||||||
final history = ref.watch(getAllHistoryStreamProvider);
|
return DefaultTabController(
|
||||||
return Scaffold(
|
animationDuration: Duration.zero,
|
||||||
|
length: 2,
|
||||||
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
|
|
@ -92,8 +113,21 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen> {
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
List<History> histories = isar.historys
|
||||||
|
.filter()
|
||||||
|
.idIsNotNull()
|
||||||
|
.chapter((q) => q.manga((q) =>
|
||||||
|
q.isMangaEqualTo(
|
||||||
|
_tabBarController.index ==
|
||||||
|
0)))
|
||||||
|
.findAllSync()
|
||||||
|
.toList();
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.historys.clearSync();
|
// _tabBarController.index != 1
|
||||||
|
|
||||||
|
for (var history in histories) {
|
||||||
|
isar.historys.deleteSync(history.id!);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
|
@ -109,226 +143,262 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen> {
|
||||||
icon: Icon(Icons.delete_sweep_outlined,
|
icon: Icon(Icons.delete_sweep_outlined,
|
||||||
color: Theme.of(context).hintColor)),
|
color: Theme.of(context).hintColor)),
|
||||||
],
|
],
|
||||||
|
bottom: TabBar(
|
||||||
|
indicatorSize: TabBarIndicatorSize.tab,
|
||||||
|
controller: _tabBarController,
|
||||||
|
tabs: [
|
||||||
|
Tab(text: l10n.manga),
|
||||||
|
Tab(text: l10n.anime),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: history.when(
|
body: Padding(
|
||||||
data: (data) {
|
padding: const EdgeInsets.only(top: 10),
|
||||||
final entries = data
|
child: TabBarView(controller: _tabBarController, children: [
|
||||||
.where((element) => _textEditingController.text.isNotEmpty
|
HistoryTab(
|
||||||
? element.chapter.value!.manga.value!.name!
|
isManga: true,
|
||||||
.toLowerCase()
|
query: _textEditingController.text,
|
||||||
.contains(_textEditingController.text.toLowerCase())
|
),
|
||||||
: true)
|
HistoryTab(
|
||||||
.toList();
|
isManga: false,
|
||||||
|
query: _textEditingController.text,
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (entries.isNotEmpty) {
|
class HistoryTab extends ConsumerStatefulWidget {
|
||||||
return GroupedListView<History, String>(
|
final String query;
|
||||||
elements: entries,
|
final bool isManga;
|
||||||
groupBy: (element) => dateFormat(element.date!,
|
const HistoryTab({required this.isManga, required this.query, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<HistoryTab> createState() => _HistoryTabState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HistoryTabState extends ConsumerState<HistoryTab> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final l10n = l10nLocalizations(context)!;
|
||||||
|
final history =
|
||||||
|
ref.watch(getAllHistoryStreamProvider(isManga: widget.isManga));
|
||||||
|
return Scaffold(
|
||||||
|
body: history.when(
|
||||||
|
data: (data) {
|
||||||
|
final entries = data
|
||||||
|
.where((element) => widget.query.isNotEmpty
|
||||||
|
? element.chapter.value!.manga.value!.name!
|
||||||
|
.toLowerCase()
|
||||||
|
.contains(widget.query.toLowerCase())
|
||||||
|
: true)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (entries.isNotEmpty) {
|
||||||
|
return GroupedListView<History, String>(
|
||||||
|
elements: entries,
|
||||||
|
groupBy: (element) => dateFormat(element.date!,
|
||||||
|
context: context,
|
||||||
|
ref: ref,
|
||||||
|
forHistoryValue: true,
|
||||||
|
useRelativeTimesTamps: false),
|
||||||
|
groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8, left: 12),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(dateFormat(
|
||||||
|
null,
|
||||||
context: context,
|
context: context,
|
||||||
|
stringDate: groupByValue,
|
||||||
ref: ref,
|
ref: ref,
|
||||||
forHistoryValue: true,
|
)),
|
||||||
useRelativeTimesTamps: false),
|
],
|
||||||
groupSeparatorBuilder: (String groupByValue) => Padding(
|
),
|
||||||
padding: const EdgeInsets.only(bottom: 8, left: 12),
|
),
|
||||||
child: Row(
|
itemBuilder: (context, History element) {
|
||||||
children: [
|
final manga = element.chapter.value!.manga.value!;
|
||||||
Text(dateFormat(
|
final chapter = element.chapter.value!;
|
||||||
null,
|
return ElevatedButton(
|
||||||
context: context,
|
style: ElevatedButton.styleFrom(
|
||||||
stringDate: groupByValue,
|
padding: const EdgeInsets.all(0),
|
||||||
ref: ref,
|
backgroundColor: Colors.transparent,
|
||||||
)),
|
shape: RoundedRectangleBorder(
|
||||||
],
|
borderRadius: BorderRadius.circular(0)),
|
||||||
),
|
elevation: 0,
|
||||||
),
|
shadowColor: Colors.transparent),
|
||||||
itemBuilder: (context, History element) {
|
onPressed: () {
|
||||||
final manga = element.chapter.value!.manga.value!;
|
pushMangaReaderView(context: context, chapter: chapter);
|
||||||
final chapter = element.chapter.value!;
|
},
|
||||||
return ElevatedButton(
|
child: Padding(
|
||||||
style: ElevatedButton.styleFrom(
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
padding: const EdgeInsets.all(0),
|
child: SizedBox(
|
||||||
backgroundColor: Colors.transparent,
|
height: 105,
|
||||||
shape: RoundedRectangleBorder(
|
child: Row(
|
||||||
borderRadius: BorderRadius.circular(0)),
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
elevation: 0,
|
children: [
|
||||||
shadowColor: Colors.transparent),
|
SizedBox(
|
||||||
onPressed: () {
|
width: 60,
|
||||||
pushMangaReaderView(context: context, chapter: chapter);
|
height: 90,
|
||||||
},
|
child: ElevatedButton(
|
||||||
child: Padding(
|
style: ElevatedButton.styleFrom(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
padding: const EdgeInsets.all(0),
|
||||||
child: SizedBox(
|
shape: RoundedRectangleBorder(
|
||||||
height: 105,
|
borderRadius: BorderRadius.circular(7)),
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: 60,
|
|
||||||
height: 90,
|
|
||||||
child: ElevatedButton(
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
padding: const EdgeInsets.all(0),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(7)),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
context.push('/manga-reader/detail',
|
|
||||||
extra: manga.id);
|
|
||||||
},
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(7),
|
|
||||||
child: manga.customCoverImage != null
|
|
||||||
? Image.memory(
|
|
||||||
manga.customCoverImage as Uint8List)
|
|
||||||
: cachedNetworkImage(
|
|
||||||
headers: ref.watch(headersProvider(
|
|
||||||
source: manga.source!,
|
|
||||||
lang: manga.lang!)),
|
|
||||||
imageUrl: manga.imageUrl!,
|
|
||||||
width: 60,
|
|
||||||
height: 90,
|
|
||||||
fit: BoxFit.cover),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Flexible(
|
onPressed: () {
|
||||||
child: Row(
|
context.push('/manga-reader/detail',
|
||||||
children: [
|
extra: manga.id);
|
||||||
Expanded(
|
},
|
||||||
child: Container(
|
child: ClipRRect(
|
||||||
color: Colors.transparent,
|
borderRadius: BorderRadius.circular(7),
|
||||||
child: Padding(
|
child: manga.customCoverImage != null
|
||||||
padding: const EdgeInsets.all(8.0),
|
? Image.memory(
|
||||||
child: Column(
|
manga.customCoverImage as Uint8List)
|
||||||
mainAxisAlignment:
|
: cachedNetworkImage(
|
||||||
MainAxisAlignment.center,
|
headers: ref.watch(headersProvider(
|
||||||
|
source: manga.source!,
|
||||||
|
lang: manga.lang!)),
|
||||||
|
imageUrl: manga.imageUrl!,
|
||||||
|
width: 60,
|
||||||
|
height: 90,
|
||||||
|
fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
manga.name!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyLarge!
|
||||||
|
.color,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
),
|
||||||
|
Wrap(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
CrossAxisAlignment.start,
|
WrapCrossAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
manga.name!,
|
chapter.name!,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 11,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyLarge!
|
||||||
|
.color,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
" - ${dateFormatHour(element.date!, context)}",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.bodyLarge!
|
.bodyLarge!
|
||||||
.color,
|
.color,
|
||||||
fontWeight: FontWeight.bold),
|
fontWeight: FontWeight.w400),
|
||||||
textAlign: TextAlign.start,
|
|
||||||
),
|
|
||||||
Wrap(
|
|
||||||
crossAxisAlignment:
|
|
||||||
WrapCrossAlignment.end,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
chapter.name!,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 11,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyLarge!
|
|
||||||
.color,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
" - ${dateFormatHour(element.date!, context)}",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 11,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyLarge!
|
|
||||||
.color,
|
|
||||||
fontWeight:
|
|
||||||
FontWeight.w400),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
),
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: Text(
|
|
||||||
l10n.remove,
|
|
||||||
),
|
|
||||||
content: Text(
|
|
||||||
l10n.remove_history_msg),
|
|
||||||
actions: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pop(
|
|
||||||
context);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
l10n.cancel)),
|
|
||||||
const SizedBox(
|
|
||||||
width: 15,
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
await isar.writeTxn(
|
|
||||||
() async {
|
|
||||||
await isar
|
|
||||||
.historys
|
|
||||||
.delete(
|
|
||||||
element
|
|
||||||
.id!);
|
|
||||||
});
|
|
||||||
if (mounted) {
|
|
||||||
Navigator.pop(
|
|
||||||
context);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
l10n.remove)),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
icon: Icon(
|
|
||||||
Icons.delete_outline,
|
|
||||||
size: 25,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyLarge!
|
|
||||||
.color,
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
)
|
IconButton(
|
||||||
],
|
onPressed: () {
|
||||||
),
|
showDialog(
|
||||||
),
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text(
|
||||||
|
l10n.remove,
|
||||||
|
),
|
||||||
|
content:
|
||||||
|
Text(l10n.remove_history_msg),
|
||||||
|
actions: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Text(l10n.cancel)),
|
||||||
|
const SizedBox(
|
||||||
|
width: 15,
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await isar
|
||||||
|
.writeTxn(() async {
|
||||||
|
await isar.historys
|
||||||
|
.delete(
|
||||||
|
element.id!);
|
||||||
|
});
|
||||||
|
if (mounted) {
|
||||||
|
Navigator.pop(
|
||||||
|
context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(l10n.remove)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.delete_outline,
|
||||||
|
size: 25,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyLarge!
|
||||||
|
.color,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
),
|
||||||
itemComparator: (item1, item2) =>
|
|
||||||
item1.date!.compareTo(item2.date!),
|
|
||||||
order: GroupedListOrder.DESC,
|
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
return Center(
|
itemComparator: (item1, item2) =>
|
||||||
child: Text(l10n.nothing_read_recently),
|
item1.date!.compareTo(item2.date!),
|
||||||
);
|
order: GroupedListOrder.DESC,
|
||||||
},
|
);
|
||||||
error: (Object error, StackTrace stackTrace) {
|
}
|
||||||
return ErrorText(error);
|
return Center(
|
||||||
},
|
child: Text(l10n.nothing_read_recently),
|
||||||
loading: () {
|
);
|
||||||
return const ProgressCenter();
|
},
|
||||||
},
|
error: (Object error, StackTrace stackTrace) {
|
||||||
));
|
return ErrorText(error);
|
||||||
|
},
|
||||||
|
loading: () {
|
||||||
|
return const ProgressCenter();
|
||||||
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,18 @@
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:mangayomi/main.dart';
|
import 'package:mangayomi/main.dart';
|
||||||
|
import 'package:mangayomi/models/chapter.dart';
|
||||||
import 'package:mangayomi/models/history.dart';
|
import 'package:mangayomi/models/history.dart';
|
||||||
|
import 'package:mangayomi/models/manga.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
part 'isar_providers.g.dart';
|
part 'isar_providers.g.dart';
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Stream<List<History>> getAllHistoryStream(
|
Stream<List<History>> getAllHistoryStream(GetAllHistoryStreamRef ref,
|
||||||
GetAllHistoryStreamRef ref,
|
{required bool isManga}) async* {
|
||||||
) async* {
|
yield* isar.historys
|
||||||
yield* isar.historys.filter().idIsNotNull().watch(fireImmediately: true);
|
.filter()
|
||||||
|
.idIsNotNull()
|
||||||
|
.and()
|
||||||
|
.chapter((q) => q.manga((q) => q.isMangaEqualTo(isManga)))
|
||||||
|
.watch(fireImmediately: true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,20 +7,109 @@ part of 'isar_providers.dart';
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$getAllHistoryStreamHash() =>
|
String _$getAllHistoryStreamHash() =>
|
||||||
r'361f085ba7b3269583a09cd7b2e2629d8f3282aa';
|
r'32dc5fa16315f199a5c86ee99cf59b7190c4d28e';
|
||||||
|
|
||||||
|
/// 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef GetAllHistoryStreamRef = AutoDisposeStreamProviderRef<List<History>>;
|
||||||
|
|
||||||
/// See also [getAllHistoryStream].
|
/// See also [getAllHistoryStream].
|
||||||
@ProviderFor(getAllHistoryStream)
|
@ProviderFor(getAllHistoryStream)
|
||||||
final getAllHistoryStreamProvider =
|
const getAllHistoryStreamProvider = GetAllHistoryStreamFamily();
|
||||||
AutoDisposeStreamProvider<List<History>>.internal(
|
|
||||||
getAllHistoryStream,
|
|
||||||
name: r'getAllHistoryStreamProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$getAllHistoryStreamHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef GetAllHistoryStreamRef = AutoDisposeStreamProviderRef<List<History>>;
|
/// See also [getAllHistoryStream].
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
class GetAllHistoryStreamFamily extends Family<AsyncValue<List<History>>> {
|
||||||
|
/// See also [getAllHistoryStream].
|
||||||
|
const GetAllHistoryStreamFamily();
|
||||||
|
|
||||||
|
/// See also [getAllHistoryStream].
|
||||||
|
GetAllHistoryStreamProvider call({
|
||||||
|
required bool isManga,
|
||||||
|
}) {
|
||||||
|
return GetAllHistoryStreamProvider(
|
||||||
|
isManga: isManga,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
GetAllHistoryStreamProvider getProviderOverride(
|
||||||
|
covariant GetAllHistoryStreamProvider provider,
|
||||||
|
) {
|
||||||
|
return call(
|
||||||
|
isManga: provider.isManga,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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'getAllHistoryStreamProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [getAllHistoryStream].
|
||||||
|
class GetAllHistoryStreamProvider
|
||||||
|
extends AutoDisposeStreamProvider<List<History>> {
|
||||||
|
/// See also [getAllHistoryStream].
|
||||||
|
GetAllHistoryStreamProvider({
|
||||||
|
required this.isManga,
|
||||||
|
}) : super.internal(
|
||||||
|
(ref) => getAllHistoryStream(
|
||||||
|
ref,
|
||||||
|
isManga: isManga,
|
||||||
|
),
|
||||||
|
from: getAllHistoryStreamProvider,
|
||||||
|
name: r'getAllHistoryStreamProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$getAllHistoryStreamHash,
|
||||||
|
dependencies: GetAllHistoryStreamFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
GetAllHistoryStreamFamily._allTransitiveDependencies,
|
||||||
|
);
|
||||||
|
|
||||||
|
final bool isManga;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is GetAllHistoryStreamProvider && other.isManga == isManga;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, isManga.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import 'package:mangayomi/models/history.dart';
|
||||||
import 'package:mangayomi/models/manga.dart';
|
import 'package:mangayomi/models/manga.dart';
|
||||||
import 'package:mangayomi/models/settings.dart';
|
import 'package:mangayomi/models/settings.dart';
|
||||||
import 'package:mangayomi/modules/library/providers/local_archive.dart';
|
import 'package:mangayomi/modules/library/providers/local_archive.dart';
|
||||||
|
import 'package:mangayomi/modules/more/categories/providers/isar_providers.dart';
|
||||||
import 'package:mangayomi/modules/widgets/manga_image_card_widget.dart';
|
import 'package:mangayomi/modules/widgets/manga_image_card_widget.dart';
|
||||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||||
import 'package:mangayomi/providers/storage_provider.dart';
|
import 'package:mangayomi/providers/storage_provider.dart';
|
||||||
|
|
@ -27,12 +28,12 @@ import 'package:mangayomi/modules/library/widgets/library_listview_widget.dart';
|
||||||
import 'package:mangayomi/modules/library/widgets/list_tile_manga_category.dart';
|
import 'package:mangayomi/modules/library/widgets/list_tile_manga_category.dart';
|
||||||
import 'package:mangayomi/modules/manga/detail/widgets/chapter_filter_list_tile_widget.dart';
|
import 'package:mangayomi/modules/manga/detail/widgets/chapter_filter_list_tile_widget.dart';
|
||||||
import 'package:mangayomi/modules/manga/detail/widgets/chapter_sort_list_tile_widget.dart';
|
import 'package:mangayomi/modules/manga/detail/widgets/chapter_sort_list_tile_widget.dart';
|
||||||
import 'package:mangayomi/modules/more/categoties/providers/isar_providers.dart';
|
|
||||||
import 'package:mangayomi/modules/widgets/error_text.dart';
|
import 'package:mangayomi/modules/widgets/error_text.dart';
|
||||||
import 'package:mangayomi/modules/widgets/progress_center.dart';
|
import 'package:mangayomi/modules/widgets/progress_center.dart';
|
||||||
|
|
||||||
class LibraryScreen extends ConsumerStatefulWidget {
|
class LibraryScreen extends ConsumerStatefulWidget {
|
||||||
const LibraryScreen({super.key});
|
final bool isManga;
|
||||||
|
const LibraryScreen({required this.isManga, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<LibraryScreen> createState() => _LibraryScreenState();
|
ConsumerState<LibraryScreen> createState() => _LibraryScreenState();
|
||||||
|
|
@ -47,11 +48,14 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
int _tabIndex = 0;
|
int _tabIndex = 0;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final categories = ref.watch(getMangaCategorieStreamProvider);
|
final categories =
|
||||||
final withoutCategories =
|
ref.watch(getMangaCategorieStreamProvider(isManga: widget.isManga));
|
||||||
ref.watch(getAllMangaWithoutCategoriesStreamProvider);
|
final withoutCategories = ref.watch(
|
||||||
final showCategoryTabs = ref.watch(libraryShowCategoryTabsStateProvider);
|
getAllMangaWithoutCategoriesStreamProvider(isManga: widget.isManga));
|
||||||
final mangaAll = ref.watch(getAllMangaStreamProvider(categoryId: null));
|
final showCategoryTabs = ref
|
||||||
|
.watch(libraryShowCategoryTabsStateProvider(isManga: widget.isManga));
|
||||||
|
final mangaAll = ref.watch(
|
||||||
|
getAllMangaStreamProvider(categoryId: null, isManga: widget.isManga));
|
||||||
final l10n = l10nLocalizations(context)!;
|
final l10n = l10nLocalizations(context)!;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: mangaAll.when(
|
body: mangaAll.when(
|
||||||
|
|
@ -73,40 +77,50 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
});
|
});
|
||||||
|
|
||||||
return Consumer(builder: (context, ref, child) {
|
return Consumer(builder: (context, ref, child) {
|
||||||
bool reverse =
|
bool reverse = ref
|
||||||
ref.watch(sortLibraryMangaStateProvider).reverse!;
|
.watch(sortLibraryMangaStateProvider(
|
||||||
|
isManga: widget.isManga))
|
||||||
|
.reverse!;
|
||||||
|
|
||||||
final continueReaderBtn = ref.watch(
|
final continueReaderBtn = ref.watch(
|
||||||
libraryShowContinueReadingButtonStateProvider);
|
libraryShowContinueReadingButtonStateProvider(
|
||||||
final showNumbersOfItems =
|
isManga: widget.isManga));
|
||||||
ref.watch(libraryShowNumbersOfItemsStateProvider);
|
final showNumbersOfItems = ref.watch(
|
||||||
final localSource =
|
libraryShowNumbersOfItemsStateProvider(
|
||||||
ref.watch(libraryLocalSourceStateProvider);
|
isManga: widget.isManga));
|
||||||
final downloadedChapter =
|
final localSource = ref.watch(
|
||||||
ref.watch(libraryDownloadedChaptersStateProvider);
|
libraryLocalSourceStateProvider(
|
||||||
final language =
|
isManga: widget.isManga));
|
||||||
ref.watch(libraryLanguageStateProvider);
|
final downloadedChapter = ref.watch(
|
||||||
|
libraryDownloadedChaptersStateProvider(
|
||||||
|
isManga: widget.isManga));
|
||||||
|
final language = ref.watch(libraryLanguageStateProvider(
|
||||||
|
isManga: widget.isManga));
|
||||||
final displayType = ref
|
final displayType = ref
|
||||||
.read(libraryDisplayTypeStateProvider.notifier)
|
.read(libraryDisplayTypeStateProvider(
|
||||||
.getLibraryDisplayTypeValue(
|
isManga: widget.isManga)
|
||||||
ref.watch(libraryDisplayTypeStateProvider));
|
.notifier)
|
||||||
|
.getLibraryDisplayTypeValue(ref.watch(
|
||||||
|
libraryDisplayTypeStateProvider(
|
||||||
|
isManga: widget.isManga)));
|
||||||
final isNotFiltering = ref.watch(
|
final isNotFiltering = ref.watch(
|
||||||
mangasFilterResultStateProvider(
|
mangasFilterResultStateProvider(
|
||||||
mangaList: _entries));
|
isManga: widget.isManga, mangaList: _entries));
|
||||||
final downloadFilterType = ref.watch(
|
final downloadFilterType = ref.watch(
|
||||||
mangaFilterDownloadedStateProvider(
|
mangaFilterDownloadedStateProvider(
|
||||||
mangaList: _entries));
|
isManga: widget.isManga, mangaList: _entries));
|
||||||
final unreadFilterType = ref.watch(
|
final unreadFilterType = ref.watch(
|
||||||
mangaFilterUnreadStateProvider(
|
mangaFilterUnreadStateProvider(
|
||||||
mangaList: _entries));
|
isManga: widget.isManga, mangaList: _entries));
|
||||||
final startedFilterType = ref.watch(
|
final startedFilterType = ref.watch(
|
||||||
mangaFilterStartedStateProvider(
|
mangaFilterStartedStateProvider(
|
||||||
mangaList: _entries));
|
isManga: widget.isManga, mangaList: _entries));
|
||||||
final bookmarkedFilterType = ref.watch(
|
final bookmarkedFilterType = ref.watch(
|
||||||
mangaFilterBookmarkedStateProvider(
|
mangaFilterBookmarkedStateProvider(
|
||||||
mangaList: _entries));
|
isManga: widget.isManga, mangaList: _entries));
|
||||||
final sortType = ref
|
final sortType = ref
|
||||||
.watch(sortLibraryMangaStateProvider)
|
.watch(sortLibraryMangaStateProvider(
|
||||||
|
isManga: widget.isManga))
|
||||||
.index as int;
|
.index as int;
|
||||||
final numberOfItemsList = _filterAndSortManga(
|
final numberOfItemsList = _filterAndSortManga(
|
||||||
data: man,
|
data: man,
|
||||||
|
|
@ -301,35 +315,50 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return Consumer(builder: (context, ref, child) {
|
return Consumer(builder: (context, ref, child) {
|
||||||
bool reverse =
|
bool reverse = ref
|
||||||
ref.watch(sortLibraryMangaStateProvider).reverse!;
|
.watch(sortLibraryMangaStateProvider(
|
||||||
final continueReaderBtn = ref
|
isManga: widget.isManga))
|
||||||
.watch(libraryShowContinueReadingButtonStateProvider);
|
.reverse!;
|
||||||
final showNumbersOfItems =
|
final continueReaderBtn = ref.watch(
|
||||||
ref.watch(libraryShowNumbersOfItemsStateProvider);
|
libraryShowContinueReadingButtonStateProvider(
|
||||||
final localSource =
|
isManga: widget.isManga));
|
||||||
ref.watch(libraryLocalSourceStateProvider);
|
final showNumbersOfItems = ref.watch(
|
||||||
final downloadedChapter =
|
libraryShowNumbersOfItemsStateProvider(
|
||||||
ref.watch(libraryDownloadedChaptersStateProvider);
|
isManga: widget.isManga));
|
||||||
final language = ref.watch(libraryLanguageStateProvider);
|
final localSource = ref.watch(
|
||||||
|
libraryLocalSourceStateProvider(
|
||||||
|
isManga: widget.isManga));
|
||||||
|
final downloadedChapter = ref.watch(
|
||||||
|
libraryDownloadedChaptersStateProvider(
|
||||||
|
isManga: widget.isManga));
|
||||||
|
final language = ref.watch(libraryLanguageStateProvider(
|
||||||
|
isManga: widget.isManga));
|
||||||
final displayType = ref
|
final displayType = ref
|
||||||
.read(libraryDisplayTypeStateProvider.notifier)
|
.read(libraryDisplayTypeStateProvider(
|
||||||
.getLibraryDisplayTypeValue(
|
isManga: widget.isManga)
|
||||||
ref.watch(libraryDisplayTypeStateProvider));
|
.notifier)
|
||||||
|
.getLibraryDisplayTypeValue(ref.watch(
|
||||||
|
libraryDisplayTypeStateProvider(
|
||||||
|
isManga: widget.isManga)));
|
||||||
final isNotFiltering = ref.watch(
|
final isNotFiltering = ref.watch(
|
||||||
mangasFilterResultStateProvider(mangaList: _entries));
|
mangasFilterResultStateProvider(
|
||||||
|
isManga: widget.isManga, mangaList: _entries));
|
||||||
final downloadFilterType = ref.watch(
|
final downloadFilterType = ref.watch(
|
||||||
mangaFilterDownloadedStateProvider(
|
mangaFilterDownloadedStateProvider(
|
||||||
mangaList: _entries));
|
isManga: widget.isManga, mangaList: _entries));
|
||||||
final unreadFilterType = ref.watch(
|
final unreadFilterType = ref.watch(
|
||||||
mangaFilterUnreadStateProvider(mangaList: _entries));
|
mangaFilterUnreadStateProvider(
|
||||||
|
isManga: widget.isManga, mangaList: _entries));
|
||||||
final startedFilterType = ref.watch(
|
final startedFilterType = ref.watch(
|
||||||
mangaFilterStartedStateProvider(mangaList: _entries));
|
mangaFilterStartedStateProvider(
|
||||||
|
isManga: widget.isManga, mangaList: _entries));
|
||||||
final bookmarkedFilterType = ref.watch(
|
final bookmarkedFilterType = ref.watch(
|
||||||
mangaFilterBookmarkedStateProvider(
|
mangaFilterBookmarkedStateProvider(
|
||||||
mangaList: _entries));
|
isManga: widget.isManga, mangaList: _entries));
|
||||||
final sortType =
|
final sortType = ref
|
||||||
ref.watch(sortLibraryMangaStateProvider).index;
|
.watch(sortLibraryMangaStateProvider(
|
||||||
|
isManga: widget.isManga))
|
||||||
|
.index;
|
||||||
final numberOfItemsList = _filterAndSortManga(
|
final numberOfItemsList = _filterAndSortManga(
|
||||||
data: man,
|
data: man,
|
||||||
downloadFilterType: downloadFilterType,
|
downloadFilterType: downloadFilterType,
|
||||||
|
|
@ -510,8 +539,10 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
required bool downloadedChapter,
|
required bool downloadedChapter,
|
||||||
required bool continueReaderBtn,
|
required bool continueReaderBtn,
|
||||||
required int categoryId}) {
|
required int categoryId}) {
|
||||||
final mangas = ref.watch(getAllMangaStreamProvider(categoryId: categoryId));
|
final mangas = ref.watch(getAllMangaStreamProvider(
|
||||||
final sortType = ref.watch(sortLibraryMangaStateProvider).index;
|
categoryId: categoryId, isManga: widget.isManga));
|
||||||
|
final sortType =
|
||||||
|
ref.watch(sortLibraryMangaStateProvider(isManga: widget.isManga)).index;
|
||||||
return mangas.when(
|
return mangas.when(
|
||||||
data: (data) {
|
data: (data) {
|
||||||
final categoriNumberOfItemsList = _filterAndSortManga(
|
final categoriNumberOfItemsList = _filterAndSortManga(
|
||||||
|
|
@ -555,8 +586,10 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
required WidgetRef ref,
|
required WidgetRef ref,
|
||||||
required DisplayType displayType}) {
|
required DisplayType displayType}) {
|
||||||
final l10n = l10nLocalizations(context)!;
|
final l10n = l10nLocalizations(context)!;
|
||||||
final mangas = ref.watch(getAllMangaStreamProvider(categoryId: categoryId));
|
final mangas = ref.watch(getAllMangaStreamProvider(
|
||||||
final sortType = ref.watch(sortLibraryMangaStateProvider).index;
|
categoryId: categoryId, isManga: widget.isManga));
|
||||||
|
final sortType =
|
||||||
|
ref.watch(sortLibraryMangaStateProvider(isManga: widget.isManga)).index;
|
||||||
final mangaIdsList = ref.watch(mangasListStateProvider);
|
final mangaIdsList = ref.watch(mangasListStateProvider);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: mangas.when(
|
body: mangas.when(
|
||||||
|
|
@ -616,10 +649,13 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
required DisplayType displayType,
|
required DisplayType displayType,
|
||||||
required WidgetRef ref,
|
required WidgetRef ref,
|
||||||
bool withouCategories = false}) {
|
bool withouCategories = false}) {
|
||||||
final sortType = ref.watch(sortLibraryMangaStateProvider).index;
|
final sortType =
|
||||||
|
ref.watch(sortLibraryMangaStateProvider(isManga: widget.isManga)).index;
|
||||||
final manga = withouCategories
|
final manga = withouCategories
|
||||||
? ref.watch(getAllMangaWithoutCategoriesStreamProvider)
|
? ref.watch(
|
||||||
: ref.watch(getAllMangaStreamProvider(categoryId: null));
|
getAllMangaWithoutCategoriesStreamProvider(isManga: widget.isManga))
|
||||||
|
: ref.watch(getAllMangaStreamProvider(
|
||||||
|
categoryId: null, isManga: widget.isManga));
|
||||||
final mangaIdsList = ref.watch(mangasListStateProvider);
|
final mangaIdsList = ref.watch(mangasListStateProvider);
|
||||||
final l10n = l10nLocalizations(context)!;
|
final l10n = l10nLocalizations(context)!;
|
||||||
return manga.when(
|
return manga.when(
|
||||||
|
|
@ -822,99 +858,128 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
}
|
}
|
||||||
return StatefulBuilder(
|
return StatefulBuilder(
|
||||||
builder: (context, setState) {
|
builder: (context, setState) {
|
||||||
return AlertDialog(
|
return StreamBuilder(
|
||||||
title: Text(
|
stream: isar.categorys
|
||||||
l10n.set_categories,
|
.filter()
|
||||||
),
|
.idIsNotNull()
|
||||||
content: SizedBox(
|
.and()
|
||||||
width: mediaWidth(context, 0.8),
|
.forMangaEqualTo(widget.isManga)
|
||||||
child: StreamBuilder(
|
.watch(fireImmediately: true),
|
||||||
stream: isar.categorys
|
builder: (context, snapshot) {
|
||||||
.filter()
|
return AlertDialog(
|
||||||
.idIsNotNull()
|
title: Text(
|
||||||
.watch(fireImmediately: true),
|
l10n.set_categories,
|
||||||
builder: (context, snapshot) {
|
),
|
||||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
content: SizedBox(
|
||||||
final entries = snapshot.data!;
|
width: mediaWidth(context, 0.8),
|
||||||
return ListView.builder(
|
child: Builder(builder: (context) {
|
||||||
shrinkWrap: true,
|
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||||
itemCount: entries.length,
|
final entries = snapshot.data!;
|
||||||
itemBuilder: (context, index) {
|
return ListView.builder(
|
||||||
return ListTileMangaCategory(
|
shrinkWrap: true,
|
||||||
category: entries[index],
|
itemCount: entries.length,
|
||||||
categoryIds: categoryIds,
|
itemBuilder: (context, index) {
|
||||||
mangasList: mangasList,
|
return ListTileMangaCategory(
|
||||||
onTap: () {
|
category: entries[index],
|
||||||
setState(() {
|
categoryIds: categoryIds,
|
||||||
if (categoryIds
|
mangasList: mangasList,
|
||||||
.contains(entries[index].id)) {
|
onTap: () {
|
||||||
categoryIds.remove(entries[index].id);
|
setState(() {
|
||||||
} else {
|
if (categoryIds
|
||||||
|
.contains(entries[index].id)) {
|
||||||
|
categoryIds.remove(entries[index].id);
|
||||||
|
} else {
|
||||||
|
categoryIds.add(entries[index].id!);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
res: (res) {
|
||||||
|
if (res.isNotEmpty) {
|
||||||
categoryIds.add(entries[index].id!);
|
categoryIds.add(entries[index].id!);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
},
|
);
|
||||||
res: (res) {
|
|
||||||
if (res.isNotEmpty) {
|
|
||||||
categoryIds.add(entries[index].id!);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Container();
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
context.push("/categories");
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
child: Text(l10n.edit)),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
},
|
||||||
child: Text(l10n.cancel)),
|
);
|
||||||
const SizedBox(
|
}
|
||||||
width: 15,
|
return Text(l10n.library_no_category_exist);
|
||||||
),
|
}),
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
isar.writeTxnSync(() {
|
|
||||||
for (var id in mangaIdsList) {
|
|
||||||
Manga? manga = isar.mangas.getSync(id);
|
|
||||||
manga!.categories = categoryIds;
|
|
||||||
isar.mangas.putSync(manga);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ref
|
|
||||||
.read(mangasListStateProvider.notifier)
|
|
||||||
.clear();
|
|
||||||
ref
|
|
||||||
.read(isLongPressedMangaStateProvider
|
|
||||||
.notifier)
|
|
||||||
.update(false);
|
|
||||||
if (mounted) {
|
|
||||||
Navigator.pop(context);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
l10n.ok,
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
actions: [
|
||||||
)
|
snapshot.hasData && snapshot.data!.isNotEmpty
|
||||||
],
|
? Row(
|
||||||
);
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
context.push("/categories", extra: (
|
||||||
|
true,
|
||||||
|
widget.isManga ? 0 : 1
|
||||||
|
));
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Text(l10n.edit)),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Text(l10n.cancel)),
|
||||||
|
const SizedBox(
|
||||||
|
width: 15,
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
isar.writeTxnSync(() {
|
||||||
|
for (var id in mangaIdsList) {
|
||||||
|
Manga? manga =
|
||||||
|
isar.mangas.getSync(id);
|
||||||
|
manga!.categories =
|
||||||
|
categoryIds;
|
||||||
|
isar.mangas.putSync(manga);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ref
|
||||||
|
.read(mangasListStateProvider
|
||||||
|
.notifier)
|
||||||
|
.clear();
|
||||||
|
ref
|
||||||
|
.read(
|
||||||
|
isLongPressedMangaStateProvider
|
||||||
|
.notifier)
|
||||||
|
.update(false);
|
||||||
|
if (mounted) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
l10n.ok,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
context.push("/categories", extra: (
|
||||||
|
true,
|
||||||
|
widget.isManga ? 0 : 1
|
||||||
|
));
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
l10n.edit_categories,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -1114,11 +1179,14 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
label: l10n.downloaded,
|
label: l10n.downloaded,
|
||||||
type: ref.watch(
|
type: ref.watch(
|
||||||
mangaFilterDownloadedStateProvider(
|
mangaFilterDownloadedStateProvider(
|
||||||
|
isManga: widget.isManga,
|
||||||
mangaList: _entries)),
|
mangaList: _entries)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(
|
||||||
mangaFilterDownloadedStateProvider(
|
mangaFilterDownloadedStateProvider(
|
||||||
|
isManga:
|
||||||
|
widget.isManga,
|
||||||
mangaList: _entries)
|
mangaList: _entries)
|
||||||
.notifier)
|
.notifier)
|
||||||
.update();
|
.update();
|
||||||
|
|
@ -1127,11 +1195,14 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
label: l10n.unread,
|
label: l10n.unread,
|
||||||
type: ref.watch(
|
type: ref.watch(
|
||||||
mangaFilterUnreadStateProvider(
|
mangaFilterUnreadStateProvider(
|
||||||
|
isManga: widget.isManga,
|
||||||
mangaList: _entries)),
|
mangaList: _entries)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(
|
||||||
mangaFilterUnreadStateProvider(
|
mangaFilterUnreadStateProvider(
|
||||||
|
isManga:
|
||||||
|
widget.isManga,
|
||||||
mangaList: _entries)
|
mangaList: _entries)
|
||||||
.notifier)
|
.notifier)
|
||||||
.update();
|
.update();
|
||||||
|
|
@ -1140,11 +1211,14 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
label: l10n.started,
|
label: l10n.started,
|
||||||
type: ref.watch(
|
type: ref.watch(
|
||||||
mangaFilterStartedStateProvider(
|
mangaFilterStartedStateProvider(
|
||||||
|
isManga: widget.isManga,
|
||||||
mangaList: _entries)),
|
mangaList: _entries)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(
|
||||||
mangaFilterStartedStateProvider(
|
mangaFilterStartedStateProvider(
|
||||||
|
isManga:
|
||||||
|
widget.isManga,
|
||||||
mangaList: _entries)
|
mangaList: _entries)
|
||||||
.notifier)
|
.notifier)
|
||||||
.update();
|
.update();
|
||||||
|
|
@ -1153,12 +1227,15 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
label: l10n.bookmarked,
|
label: l10n.bookmarked,
|
||||||
type: ref.watch(
|
type: ref.watch(
|
||||||
mangaFilterBookmarkedStateProvider(
|
mangaFilterBookmarkedStateProvider(
|
||||||
|
isManga: widget.isManga,
|
||||||
mangaList: _entries)),
|
mangaList: _entries)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(
|
||||||
mangaFilterBookmarkedStateProvider(
|
mangaFilterBookmarkedStateProvider(
|
||||||
|
isManga: widget
|
||||||
|
.isManga,
|
||||||
mangaList:
|
mangaList:
|
||||||
_entries)
|
_entries)
|
||||||
.notifier)
|
.notifier)
|
||||||
|
|
@ -1170,11 +1247,13 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
}),
|
}),
|
||||||
Consumer(builder: (context, ref, chil) {
|
Consumer(builder: (context, ref, chil) {
|
||||||
final reverse = ref
|
final reverse = ref
|
||||||
.read(sortLibraryMangaStateProvider
|
.read(sortLibraryMangaStateProvider(
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.isReverse();
|
.isReverse();
|
||||||
final reverseChapter =
|
final reverseChapter = ref.watch(
|
||||||
ref.watch(sortLibraryMangaStateProvider);
|
sortLibraryMangaStateProvider(
|
||||||
|
isManga: widget.isManga));
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
for (var i = 0; i < 7; i++)
|
for (var i = 0; i < 7; i++)
|
||||||
|
|
@ -1185,7 +1264,9 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(
|
||||||
sortLibraryMangaStateProvider
|
sortLibraryMangaStateProvider(
|
||||||
|
isManga:
|
||||||
|
widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.set(i);
|
.set(i);
|
||||||
},
|
},
|
||||||
|
|
@ -1196,22 +1277,31 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
Consumer(builder: (context, ref, chil) {
|
Consumer(builder: (context, ref, chil) {
|
||||||
final display = ref
|
final display = ref.watch(
|
||||||
.watch(libraryDisplayTypeStateProvider);
|
libraryDisplayTypeStateProvider(
|
||||||
|
isManga: widget.isManga));
|
||||||
final displayV = ref.read(
|
final displayV = ref.read(
|
||||||
libraryDisplayTypeStateProvider.notifier);
|
libraryDisplayTypeStateProvider(
|
||||||
|
isManga: widget.isManga)
|
||||||
|
.notifier);
|
||||||
final showCategoryTabs = ref.watch(
|
final showCategoryTabs = ref.watch(
|
||||||
libraryShowCategoryTabsStateProvider);
|
libraryShowCategoryTabsStateProvider(
|
||||||
|
isManga: widget.isManga));
|
||||||
final continueReaderBtn = ref.watch(
|
final continueReaderBtn = ref.watch(
|
||||||
libraryShowContinueReadingButtonStateProvider);
|
libraryShowContinueReadingButtonStateProvider(
|
||||||
|
isManga: widget.isManga));
|
||||||
final showNumbersOfItems = ref.watch(
|
final showNumbersOfItems = ref.watch(
|
||||||
libraryShowNumbersOfItemsStateProvider);
|
libraryShowNumbersOfItemsStateProvider(
|
||||||
|
isManga: widget.isManga));
|
||||||
final downloadedChapter = ref.watch(
|
final downloadedChapter = ref.watch(
|
||||||
libraryDownloadedChaptersStateProvider);
|
libraryDownloadedChaptersStateProvider(
|
||||||
final language =
|
isManga: widget.isManga));
|
||||||
ref.watch(libraryLanguageStateProvider);
|
final language = ref.watch(
|
||||||
final localSource = ref
|
libraryLanguageStateProvider(
|
||||||
.watch(libraryLocalSourceStateProvider);
|
isManga: widget.isManga));
|
||||||
|
final localSource = ref.watch(
|
||||||
|
libraryLocalSourceStateProvider(
|
||||||
|
isManga: widget.isManga));
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
physics:
|
physics:
|
||||||
const NeverScrollableScrollPhysics(),
|
const NeverScrollableScrollPhysics(),
|
||||||
|
|
@ -1277,9 +1367,10 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
downloadedChapter ? 1 : 0,
|
downloadedChapter ? 1 : 0,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(libraryDownloadedChaptersStateProvider(
|
||||||
libraryDownloadedChaptersStateProvider
|
isManga: widget
|
||||||
.notifier)
|
.isManga)
|
||||||
|
.notifier)
|
||||||
.set(
|
.set(
|
||||||
!downloadedChapter);
|
!downloadedChapter);
|
||||||
}),
|
}),
|
||||||
|
|
@ -1288,9 +1379,10 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
type: language ? 1 : 0,
|
type: language ? 1 : 0,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(libraryLanguageStateProvider(
|
||||||
libraryLanguageStateProvider
|
isManga: widget
|
||||||
.notifier)
|
.isManga)
|
||||||
|
.notifier)
|
||||||
.set(!language);
|
.set(!language);
|
||||||
}),
|
}),
|
||||||
ListTileChapterFilter(
|
ListTileChapterFilter(
|
||||||
|
|
@ -1298,9 +1390,10 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
type: localSource ? 1 : 0,
|
type: localSource ? 1 : 0,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(libraryLocalSourceStateProvider(
|
||||||
libraryLocalSourceStateProvider
|
isManga: widget
|
||||||
.notifier)
|
.isManga)
|
||||||
|
.notifier)
|
||||||
.set(!localSource);
|
.set(!localSource);
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
@ -1327,9 +1420,10 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
showCategoryTabs ? 1 : 0,
|
showCategoryTabs ? 1 : 0,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(libraryShowCategoryTabsStateProvider(
|
||||||
libraryShowCategoryTabsStateProvider
|
isManga: widget
|
||||||
.notifier)
|
.isManga)
|
||||||
|
.notifier)
|
||||||
.set(!showCategoryTabs);
|
.set(!showCategoryTabs);
|
||||||
}),
|
}),
|
||||||
ListTileChapterFilter(
|
ListTileChapterFilter(
|
||||||
|
|
@ -1340,9 +1434,10 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
: 0,
|
: 0,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(libraryShowNumbersOfItemsStateProvider(
|
||||||
libraryShowNumbersOfItemsStateProvider
|
isManga: widget
|
||||||
.notifier)
|
.isManga)
|
||||||
|
.notifier)
|
||||||
.set(
|
.set(
|
||||||
!showNumbersOfItems);
|
!showNumbersOfItems);
|
||||||
}),
|
}),
|
||||||
|
|
@ -1370,9 +1465,10 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
continueReaderBtn ? 1 : 0,
|
continueReaderBtn ? 1 : 0,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(libraryShowContinueReadingButtonStateProvider(
|
||||||
libraryShowContinueReadingButtonStateProvider
|
isManga: widget
|
||||||
.notifier)
|
.isManga)
|
||||||
|
.notifier)
|
||||||
.set(
|
.set(
|
||||||
!continueReaderBtn);
|
!continueReaderBtn);
|
||||||
}),
|
}),
|
||||||
|
|
@ -1420,8 +1516,10 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
||||||
final mangaIdsList = ref.watch(mangasListStateProvider);
|
final mangaIdsList = ref.watch(mangasListStateProvider);
|
||||||
final manga = categoryId == null
|
final manga = categoryId == null
|
||||||
? ref.watch(getAllMangaWithoutCategoriesStreamProvider)
|
? ref.watch(
|
||||||
: ref.watch(getAllMangaStreamProvider(categoryId: categoryId));
|
getAllMangaWithoutCategoriesStreamProvider(isManga: widget.isManga))
|
||||||
|
: ref.watch(getAllMangaStreamProvider(
|
||||||
|
categoryId: categoryId, isManga: widget.isManga));
|
||||||
final l10n = l10nLocalizations(context)!;
|
final l10n = l10nLocalizations(context)!;
|
||||||
return PreferredSize(
|
return PreferredSize(
|
||||||
preferredSize: Size.fromHeight(AppBar().preferredSize.height),
|
preferredSize: Size.fromHeight(AppBar().preferredSize.height),
|
||||||
|
|
@ -1490,7 +1588,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
: Row(
|
: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
l10n.library,
|
widget.isManga ? l10n.manga : l10n.anime,
|
||||||
style:
|
style:
|
||||||
TextStyle(color: Theme.of(context).hintColor),
|
TextStyle(color: Theme.of(context).hintColor),
|
||||||
),
|
),
|
||||||
|
|
@ -1558,7 +1656,8 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
||||||
return [
|
return [
|
||||||
PopupMenuItem<int>(
|
PopupMenuItem<int>(
|
||||||
value: 0, child: Text(l10n.open_random_entry)),
|
value: 0, child: Text(l10n.open_random_entry)),
|
||||||
PopupMenuItem<int>(value: 1, child: Text(l10n.import)),
|
if (widget.isManga)
|
||||||
|
PopupMenuItem<int>(value: 1, child: Text(l10n.import)),
|
||||||
];
|
];
|
||||||
}, onSelected: (value) {
|
}, onSelected: (value) {
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,14 @@ part 'isar_providers.g.dart';
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Stream<List<Manga>> getAllMangaStream(GetAllMangaStreamRef ref,
|
Stream<List<Manga>> getAllMangaStream(GetAllMangaStreamRef ref,
|
||||||
{required int? categoryId}) async* {
|
{required int? categoryId, required bool? isManga}) async* {
|
||||||
yield* categoryId == null
|
yield* categoryId == null
|
||||||
? isar.mangas
|
? isar.mangas
|
||||||
.filter()
|
.filter()
|
||||||
.idIsNotNull()
|
.idIsNotNull()
|
||||||
.favoriteEqualTo(true)
|
.favoriteEqualTo(true)
|
||||||
|
.and()
|
||||||
|
.isMangaEqualTo(isManga)
|
||||||
.watch(fireImmediately: true)
|
.watch(fireImmediately: true)
|
||||||
: isar.mangas
|
: isar.mangas
|
||||||
.filter()
|
.filter()
|
||||||
|
|
@ -19,21 +21,27 @@ Stream<List<Manga>> getAllMangaStream(GetAllMangaStreamRef ref,
|
||||||
.favoriteEqualTo(true)
|
.favoriteEqualTo(true)
|
||||||
.categoriesIsNotEmpty()
|
.categoriesIsNotEmpty()
|
||||||
.categoriesElementEqualTo(categoryId)
|
.categoriesElementEqualTo(categoryId)
|
||||||
|
.and()
|
||||||
|
.isMangaEqualTo(isManga)
|
||||||
.watch(fireImmediately: true);
|
.watch(fireImmediately: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Stream<List<Manga>> getAllMangaWithoutCategoriesStream(
|
Stream<List<Manga>> getAllMangaWithoutCategoriesStream(
|
||||||
GetAllMangaWithoutCategoriesStreamRef ref,
|
GetAllMangaWithoutCategoriesStreamRef ref,
|
||||||
) async* {
|
{required bool? isManga}) async* {
|
||||||
yield* isar.mangas
|
yield* isar.mangas
|
||||||
.filter()
|
.filter()
|
||||||
.idIsNotNull()
|
.idIsNotNull()
|
||||||
.favoriteEqualTo(true)
|
.favoriteEqualTo(true)
|
||||||
.categoriesIsEmpty()
|
.categoriesIsEmpty()
|
||||||
|
.and()
|
||||||
|
.isMangaEqualTo(isManga)
|
||||||
.or()
|
.or()
|
||||||
.idIsNotNull()
|
.idIsNotNull()
|
||||||
.categoriesIsNull()
|
.categoriesIsNull()
|
||||||
.favoriteEqualTo(true)
|
.favoriteEqualTo(true)
|
||||||
|
.and()
|
||||||
|
.isMangaEqualTo(isManga)
|
||||||
.watch(fireImmediately: true);
|
.watch(fireImmediately: true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ part of 'isar_providers.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$getAllMangaStreamHash() => r'880357b7617f6592cd453186336b8114982a081b';
|
String _$getAllMangaStreamHash() => r'd06c3a94ba847055746f2d52566cc94db4c28b7e';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|
@ -43,9 +43,11 @@ class GetAllMangaStreamFamily extends Family<AsyncValue<List<Manga>>> {
|
||||||
/// See also [getAllMangaStream].
|
/// See also [getAllMangaStream].
|
||||||
GetAllMangaStreamProvider call({
|
GetAllMangaStreamProvider call({
|
||||||
required int? categoryId,
|
required int? categoryId,
|
||||||
|
required bool? isManga,
|
||||||
}) {
|
}) {
|
||||||
return GetAllMangaStreamProvider(
|
return GetAllMangaStreamProvider(
|
||||||
categoryId: categoryId,
|
categoryId: categoryId,
|
||||||
|
isManga: isManga,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,6 +57,7 @@ class GetAllMangaStreamFamily extends Family<AsyncValue<List<Manga>>> {
|
||||||
) {
|
) {
|
||||||
return call(
|
return call(
|
||||||
categoryId: provider.categoryId,
|
categoryId: provider.categoryId,
|
||||||
|
isManga: provider.isManga,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,10 +81,12 @@ class GetAllMangaStreamProvider extends AutoDisposeStreamProvider<List<Manga>> {
|
||||||
/// See also [getAllMangaStream].
|
/// See also [getAllMangaStream].
|
||||||
GetAllMangaStreamProvider({
|
GetAllMangaStreamProvider({
|
||||||
required this.categoryId,
|
required this.categoryId,
|
||||||
|
required this.isManga,
|
||||||
}) : super.internal(
|
}) : super.internal(
|
||||||
(ref) => getAllMangaStream(
|
(ref) => getAllMangaStream(
|
||||||
ref,
|
ref,
|
||||||
categoryId: categoryId,
|
categoryId: categoryId,
|
||||||
|
isManga: isManga,
|
||||||
),
|
),
|
||||||
from: getAllMangaStreamProvider,
|
from: getAllMangaStreamProvider,
|
||||||
name: r'getAllMangaStreamProvider',
|
name: r'getAllMangaStreamProvider',
|
||||||
|
|
@ -95,37 +100,111 @@ class GetAllMangaStreamProvider extends AutoDisposeStreamProvider<List<Manga>> {
|
||||||
);
|
);
|
||||||
|
|
||||||
final int? categoryId;
|
final int? categoryId;
|
||||||
|
final bool? isManga;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is GetAllMangaStreamProvider && other.categoryId == categoryId;
|
return other is GetAllMangaStreamProvider &&
|
||||||
|
other.categoryId == categoryId &&
|
||||||
|
other.isManga == isManga;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
hash = _SystemHash.combine(hash, categoryId.hashCode);
|
hash = _SystemHash.combine(hash, categoryId.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, isManga.hashCode);
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$getAllMangaWithoutCategoriesStreamHash() =>
|
String _$getAllMangaWithoutCategoriesStreamHash() =>
|
||||||
r'affd1fab4a6ab0e0bbc16b67384a0b17498fe209';
|
r'03581754f330a87894f953f8eaae528642b0afc2';
|
||||||
|
typedef GetAllMangaWithoutCategoriesStreamRef
|
||||||
|
= AutoDisposeStreamProviderRef<List<Manga>>;
|
||||||
|
|
||||||
/// See also [getAllMangaWithoutCategoriesStream].
|
/// See also [getAllMangaWithoutCategoriesStream].
|
||||||
@ProviderFor(getAllMangaWithoutCategoriesStream)
|
@ProviderFor(getAllMangaWithoutCategoriesStream)
|
||||||
final getAllMangaWithoutCategoriesStreamProvider =
|
const getAllMangaWithoutCategoriesStreamProvider =
|
||||||
AutoDisposeStreamProvider<List<Manga>>.internal(
|
GetAllMangaWithoutCategoriesStreamFamily();
|
||||||
getAllMangaWithoutCategoriesStream,
|
|
||||||
name: r'getAllMangaWithoutCategoriesStreamProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$getAllMangaWithoutCategoriesStreamHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef GetAllMangaWithoutCategoriesStreamRef
|
/// See also [getAllMangaWithoutCategoriesStream].
|
||||||
= AutoDisposeStreamProviderRef<List<Manga>>;
|
class GetAllMangaWithoutCategoriesStreamFamily
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
extends Family<AsyncValue<List<Manga>>> {
|
||||||
|
/// See also [getAllMangaWithoutCategoriesStream].
|
||||||
|
const GetAllMangaWithoutCategoriesStreamFamily();
|
||||||
|
|
||||||
|
/// See also [getAllMangaWithoutCategoriesStream].
|
||||||
|
GetAllMangaWithoutCategoriesStreamProvider call({
|
||||||
|
required bool? isManga,
|
||||||
|
}) {
|
||||||
|
return GetAllMangaWithoutCategoriesStreamProvider(
|
||||||
|
isManga: isManga,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
GetAllMangaWithoutCategoriesStreamProvider getProviderOverride(
|
||||||
|
covariant GetAllMangaWithoutCategoriesStreamProvider provider,
|
||||||
|
) {
|
||||||
|
return call(
|
||||||
|
isManga: provider.isManga,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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'getAllMangaWithoutCategoriesStreamProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [getAllMangaWithoutCategoriesStream].
|
||||||
|
class GetAllMangaWithoutCategoriesStreamProvider
|
||||||
|
extends AutoDisposeStreamProvider<List<Manga>> {
|
||||||
|
/// See also [getAllMangaWithoutCategoriesStream].
|
||||||
|
GetAllMangaWithoutCategoriesStreamProvider({
|
||||||
|
required this.isManga,
|
||||||
|
}) : super.internal(
|
||||||
|
(ref) => getAllMangaWithoutCategoriesStream(
|
||||||
|
ref,
|
||||||
|
isManga: isManga,
|
||||||
|
),
|
||||||
|
from: getAllMangaWithoutCategoriesStreamProvider,
|
||||||
|
name: r'getAllMangaWithoutCategoriesStreamProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$getAllMangaWithoutCategoriesStreamHash,
|
||||||
|
dependencies: GetAllMangaWithoutCategoriesStreamFamily._dependencies,
|
||||||
|
allTransitiveDependencies: GetAllMangaWithoutCategoriesStreamFamily
|
||||||
|
._allTransitiveDependencies,
|
||||||
|
);
|
||||||
|
|
||||||
|
final bool? isManga;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is GetAllMangaWithoutCategoriesStreamProvider &&
|
||||||
|
other.isManga == isManga;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, isManga.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,10 @@ part 'library_state_provider.g.dart';
|
||||||
@riverpod
|
@riverpod
|
||||||
class LibraryDisplayTypeState extends _$LibraryDisplayTypeState {
|
class LibraryDisplayTypeState extends _$LibraryDisplayTypeState {
|
||||||
@override
|
@override
|
||||||
String build() {
|
String build({required bool isManga}) {
|
||||||
return isar.settings.getSync(227)!.displayType.name;
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.displayType.name
|
||||||
|
: isar.settings.getSync(227)!.animeDisplayType.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayType getLibraryDisplayTypeValue(String value) {
|
DisplayType getLibraryDisplayTypeValue(String value) {
|
||||||
|
|
@ -36,10 +38,16 @@ class LibraryDisplayTypeState extends _$LibraryDisplayTypeState {
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLibraryDisplayType(DisplayType displayType) {
|
void setLibraryDisplayType(DisplayType displayType) {
|
||||||
final settings = isar.settings.getSync(227)!;
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
state = displayType.name;
|
state = displayType.name;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..displayType = displayType;
|
||||||
|
} else {
|
||||||
|
settings = settings..animeDisplayType = displayType;
|
||||||
|
}
|
||||||
|
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.settings.putSync(settings..displayType = displayType);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -47,19 +55,26 @@ class LibraryDisplayTypeState extends _$LibraryDisplayTypeState {
|
||||||
@riverpod
|
@riverpod
|
||||||
class MangaFilterDownloadedState extends _$MangaFilterDownloadedState {
|
class MangaFilterDownloadedState extends _$MangaFilterDownloadedState {
|
||||||
@override
|
@override
|
||||||
int build({required List<Manga> mangaList}) {
|
int build({required List<Manga> mangaList, required bool isManga}) {
|
||||||
state = getType();
|
state = getType();
|
||||||
return getType();
|
return getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getType() {
|
int getType() {
|
||||||
return isar.settings.getSync(227)!.libraryFilterMangasDownloadType!;
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.libraryFilterMangasDownloadType!
|
||||||
|
: isar.settings.getSync(227)!.libraryFilterAnimeDownloadType ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setType(int type) {
|
void setType(int type) {
|
||||||
final settings = isar.settings.getSync(227)!;
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..libraryFilterMangasDownloadType = type;
|
||||||
|
} else {
|
||||||
|
settings = settings..libraryFilterAnimeDownloadType = type;
|
||||||
|
}
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.settings.putSync(settings..libraryFilterMangasDownloadType = type);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
state = type;
|
state = type;
|
||||||
}
|
}
|
||||||
|
|
@ -78,19 +93,26 @@ class MangaFilterDownloadedState extends _$MangaFilterDownloadedState {
|
||||||
@riverpod
|
@riverpod
|
||||||
class MangaFilterUnreadState extends _$MangaFilterUnreadState {
|
class MangaFilterUnreadState extends _$MangaFilterUnreadState {
|
||||||
@override
|
@override
|
||||||
int build({required List<Manga> mangaList}) {
|
int build({required List<Manga> mangaList, required bool isManga}) {
|
||||||
state = getType();
|
state = getType();
|
||||||
return getType();
|
return getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getType() {
|
int getType() {
|
||||||
return isar.settings.getSync(227)!.libraryFilterMangasUnreadType!;
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.libraryFilterMangasUnreadType!
|
||||||
|
: isar.settings.getSync(227)!.libraryFilterAnimeUnreadType ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setType(int type) {
|
void setType(int type) {
|
||||||
final settings = isar.settings.getSync(227)!;
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..libraryFilterMangasUnreadType = type;
|
||||||
|
} else {
|
||||||
|
settings = settings..libraryFilterAnimeUnreadType = type;
|
||||||
|
}
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.settings.putSync(settings..libraryFilterMangasUnreadType = type);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
state = type;
|
state = type;
|
||||||
}
|
}
|
||||||
|
|
@ -158,19 +180,26 @@ class MangaFilterUnreadState extends _$MangaFilterUnreadState {
|
||||||
@riverpod
|
@riverpod
|
||||||
class MangaFilterStartedState extends _$MangaFilterStartedState {
|
class MangaFilterStartedState extends _$MangaFilterStartedState {
|
||||||
@override
|
@override
|
||||||
int build({required List<Manga> mangaList}) {
|
int build({required List<Manga> mangaList, required bool isManga}) {
|
||||||
state = getType();
|
state = getType();
|
||||||
return getType();
|
return getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getType() {
|
int getType() {
|
||||||
return isar.settings.getSync(227)!.libraryFilterMangasStartedType!;
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.libraryFilterMangasStartedType!
|
||||||
|
: isar.settings.getSync(227)!.libraryFilterAnimeStartedType ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setType(int type) {
|
void setType(int type) {
|
||||||
final settings = isar.settings.getSync(227)!;
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..libraryFilterMangasStartedType = type;
|
||||||
|
} else {
|
||||||
|
settings = settings..libraryFilterAnimeStartedType = type;
|
||||||
|
}
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.settings.putSync(settings..libraryFilterMangasStartedType = type);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
state = type;
|
state = type;
|
||||||
}
|
}
|
||||||
|
|
@ -238,19 +267,26 @@ class MangaFilterStartedState extends _$MangaFilterStartedState {
|
||||||
@riverpod
|
@riverpod
|
||||||
class MangaFilterBookmarkedState extends _$MangaFilterBookmarkedState {
|
class MangaFilterBookmarkedState extends _$MangaFilterBookmarkedState {
|
||||||
@override
|
@override
|
||||||
int build({required List<Manga> mangaList}) {
|
int build({required List<Manga> mangaList, required bool isManga}) {
|
||||||
state = getType();
|
state = getType();
|
||||||
return getType();
|
return getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getType() {
|
int getType() {
|
||||||
return isar.settings.getSync(227)!.libraryFilterMangasBookMarkedType!;
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.libraryFilterMangasBookMarkedType!
|
||||||
|
: isar.settings.getSync(227)!.libraryFilterAnimeBookMarkedType ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setType(int type) {
|
void setType(int type) {
|
||||||
final settings = isar.settings.getSync(227)!;
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..libraryFilterMangasBookMarkedType = type;
|
||||||
|
} else {
|
||||||
|
settings = settings..libraryFilterAnimeBookMarkedType = type;
|
||||||
|
}
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.settings.putSync(settings..libraryFilterMangasBookMarkedType = type);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
state = type;
|
state = type;
|
||||||
}
|
}
|
||||||
|
|
@ -318,15 +354,15 @@ class MangaFilterBookmarkedState extends _$MangaFilterBookmarkedState {
|
||||||
@riverpod
|
@riverpod
|
||||||
class MangasFilterResultState extends _$MangasFilterResultState {
|
class MangasFilterResultState extends _$MangasFilterResultState {
|
||||||
@override
|
@override
|
||||||
bool build({required List<Manga> mangaList}) {
|
bool build({required List<Manga> mangaList, required bool isManga}) {
|
||||||
final downloadFilterType =
|
final downloadFilterType = ref.watch(mangaFilterDownloadedStateProvider(
|
||||||
ref.watch(mangaFilterDownloadedStateProvider(mangaList: mangaList));
|
mangaList: mangaList, isManga: isManga));
|
||||||
final unreadFilterType =
|
final unreadFilterType = ref.watch(
|
||||||
ref.watch(mangaFilterUnreadStateProvider(mangaList: mangaList));
|
mangaFilterUnreadStateProvider(mangaList: mangaList, isManga: isManga));
|
||||||
final startedFilterType =
|
final startedFilterType = ref.watch(mangaFilterStartedStateProvider(
|
||||||
ref.watch(mangaFilterStartedStateProvider(mangaList: mangaList));
|
mangaList: mangaList, isManga: isManga));
|
||||||
final bookmarkedFilterType =
|
final bookmarkedFilterType = ref.watch(mangaFilterBookmarkedStateProvider(
|
||||||
ref.watch(mangaFilterBookmarkedStateProvider(mangaList: mangaList));
|
mangaList: mangaList, isManga: isManga));
|
||||||
return downloadFilterType == 0 &&
|
return downloadFilterType == 0 &&
|
||||||
unreadFilterType == 0 &&
|
unreadFilterType == 0 &&
|
||||||
startedFilterType == 0 &&
|
startedFilterType == 0 &&
|
||||||
|
|
@ -337,15 +373,22 @@ class MangasFilterResultState extends _$MangasFilterResultState {
|
||||||
@riverpod
|
@riverpod
|
||||||
class LibraryShowCategoryTabsState extends _$LibraryShowCategoryTabsState {
|
class LibraryShowCategoryTabsState extends _$LibraryShowCategoryTabsState {
|
||||||
@override
|
@override
|
||||||
bool build() {
|
bool build({required bool isManga}) {
|
||||||
return isar.settings.getSync(227)!.libraryShowCategoryTabs!;
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.libraryShowCategoryTabs!
|
||||||
|
: isar.settings.getSync(227)!.animeLibraryShowCategoryTabs ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(bool value) {
|
void set(bool value) {
|
||||||
final settings = isar.settings.getSync(227)!;
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..libraryShowCategoryTabs = value;
|
||||||
|
} else {
|
||||||
|
settings = settings..animeLibraryShowCategoryTabs = value;
|
||||||
|
}
|
||||||
state = value;
|
state = value;
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.settings.putSync(settings..libraryShowCategoryTabs = value);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -353,15 +396,22 @@ class LibraryShowCategoryTabsState extends _$LibraryShowCategoryTabsState {
|
||||||
@riverpod
|
@riverpod
|
||||||
class LibraryDownloadedChaptersState extends _$LibraryDownloadedChaptersState {
|
class LibraryDownloadedChaptersState extends _$LibraryDownloadedChaptersState {
|
||||||
@override
|
@override
|
||||||
bool build() {
|
bool build({required bool isManga}) {
|
||||||
return isar.settings.getSync(227)!.libraryDownloadedChapters!;
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.libraryDownloadedChapters!
|
||||||
|
: isar.settings.getSync(227)!.animeLibraryDownloadedChapters ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(bool value) {
|
void set(bool value) {
|
||||||
final settings = isar.settings.getSync(227)!;
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..libraryDownloadedChapters = value;
|
||||||
|
} else {
|
||||||
|
settings = settings..animeLibraryDownloadedChapters = value;
|
||||||
|
}
|
||||||
state = value;
|
state = value;
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.settings.putSync(settings..libraryDownloadedChapters = value);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -369,15 +419,22 @@ class LibraryDownloadedChaptersState extends _$LibraryDownloadedChaptersState {
|
||||||
@riverpod
|
@riverpod
|
||||||
class LibraryLanguageState extends _$LibraryLanguageState {
|
class LibraryLanguageState extends _$LibraryLanguageState {
|
||||||
@override
|
@override
|
||||||
bool build() {
|
bool build({required bool isManga}) {
|
||||||
return isar.settings.getSync(227)!.libraryShowLanguage!;
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.libraryShowLanguage!
|
||||||
|
: isar.settings.getSync(227)!.animeLibraryShowLanguage ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(bool value) {
|
void set(bool value) {
|
||||||
final settings = isar.settings.getSync(227)!;
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..libraryShowLanguage = value;
|
||||||
|
} else {
|
||||||
|
settings = settings..animeLibraryShowLanguage = value;
|
||||||
|
}
|
||||||
state = value;
|
state = value;
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.settings.putSync(settings..libraryShowLanguage = value);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -385,15 +442,22 @@ class LibraryLanguageState extends _$LibraryLanguageState {
|
||||||
@riverpod
|
@riverpod
|
||||||
class LibraryLocalSourceState extends _$LibraryLocalSourceState {
|
class LibraryLocalSourceState extends _$LibraryLocalSourceState {
|
||||||
@override
|
@override
|
||||||
bool build() {
|
bool build({required bool isManga}) {
|
||||||
return isar.settings.getSync(227)!.libraryLocalSource ?? false;
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.libraryLocalSource ?? false
|
||||||
|
: isar.settings.getSync(227)!.animeLibraryLocalSource ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(bool value) {
|
void set(bool value) {
|
||||||
final settings = isar.settings.getSync(227)!;
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..libraryShowLanguage = value;
|
||||||
|
} else {
|
||||||
|
settings = settings..animeLibraryShowLanguage = value;
|
||||||
|
}
|
||||||
state = value;
|
state = value;
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.settings.putSync(settings..libraryShowLanguage = value);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -401,15 +465,22 @@ class LibraryLocalSourceState extends _$LibraryLocalSourceState {
|
||||||
@riverpod
|
@riverpod
|
||||||
class LibraryShowNumbersOfItemsState extends _$LibraryShowNumbersOfItemsState {
|
class LibraryShowNumbersOfItemsState extends _$LibraryShowNumbersOfItemsState {
|
||||||
@override
|
@override
|
||||||
bool build() {
|
bool build({required bool isManga}) {
|
||||||
return isar.settings.getSync(227)!.libraryShowNumbersOfItems!;
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.libraryShowNumbersOfItems!
|
||||||
|
: isar.settings.getSync(227)!.animeLibraryShowNumbersOfItems ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(bool value) {
|
void set(bool value) {
|
||||||
final settings = isar.settings.getSync(227)!;
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..libraryShowNumbersOfItems = value;
|
||||||
|
} else {
|
||||||
|
settings = settings..animeLibraryShowNumbersOfItems = value;
|
||||||
|
}
|
||||||
state = value;
|
state = value;
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.settings.putSync(settings..libraryShowNumbersOfItems = value);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -418,15 +489,23 @@ class LibraryShowNumbersOfItemsState extends _$LibraryShowNumbersOfItemsState {
|
||||||
class LibraryShowContinueReadingButtonState
|
class LibraryShowContinueReadingButtonState
|
||||||
extends _$LibraryShowContinueReadingButtonState {
|
extends _$LibraryShowContinueReadingButtonState {
|
||||||
@override
|
@override
|
||||||
bool build() {
|
bool build({required bool isManga}) {
|
||||||
return isar.settings.getSync(227)!.libraryShowContinueReadingButton!;
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.libraryShowContinueReadingButton!
|
||||||
|
: isar.settings.getSync(227)!.animeLibraryShowContinueReadingButton ??
|
||||||
|
false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(bool value) {
|
void set(bool value) {
|
||||||
final settings = isar.settings.getSync(227)!;
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..libraryShowContinueReadingButton = value;
|
||||||
|
} else {
|
||||||
|
settings = settings..animeLibraryShowContinueReadingButton = value;
|
||||||
|
}
|
||||||
state = value;
|
state = value;
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
isar.settings.putSync(settings..libraryShowContinueReadingButton = value);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -434,18 +513,25 @@ class LibraryShowContinueReadingButtonState
|
||||||
@riverpod
|
@riverpod
|
||||||
class SortLibraryMangaState extends _$SortLibraryMangaState {
|
class SortLibraryMangaState extends _$SortLibraryMangaState {
|
||||||
@override
|
@override
|
||||||
SortLibraryManga build() {
|
SortLibraryManga build({required bool isManga}) {
|
||||||
return isar.settings.getSync(227)!.sortLibraryManga ?? SortLibraryManga();
|
return isManga
|
||||||
|
? isar.settings.getSync(227)!.sortLibraryManga ?? SortLibraryManga()
|
||||||
|
: isar.settings.getSync(227)!.sortLibraryAnime ?? SortLibraryManga();
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(bool reverse, int index) {
|
void update(bool reverse, int index) {
|
||||||
var value = SortLibraryManga()
|
var value = SortLibraryManga()
|
||||||
..index = index
|
..index = index
|
||||||
..reverse = state.index == index ? !reverse : reverse;
|
..reverse = state.index == index ? !reverse : reverse;
|
||||||
|
Settings settings = isar.settings.getSync(227)!;
|
||||||
|
if (isManga) {
|
||||||
|
settings = settings..sortLibraryManga = value;
|
||||||
|
} else {
|
||||||
|
settings = settings..sortLibraryAnime = value;
|
||||||
|
}
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
final settings = isar.settings.getSync(227)!;
|
final settings = isar.settings.getSync(227)!;
|
||||||
isar.settings.putSync(settings..sortLibraryManga = value);
|
isar.settings.putSync(settings);
|
||||||
});
|
});
|
||||||
state = value;
|
state = value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,4 +128,5 @@ class ImportArchivesFromFileProvider
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -45,55 +45,48 @@ class LibraryGridViewWidget extends StatelessWidget {
|
||||||
childAspectRatio: isComfortableGrid ? 0.642 : 0.69,
|
childAspectRatio: isComfortableGrid ? 0.642 : 0.69,
|
||||||
itemCount: entriesManga.length,
|
itemCount: entriesManga.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
|
final entry = entriesManga[index];
|
||||||
return Consumer(builder: (context, ref, child) {
|
return Consumer(builder: (context, ref, child) {
|
||||||
bool isLocalArchive = entriesManga[index].isLocalArchive ?? false;
|
bool isLocalArchive = entry.isLocalArchive ?? false;
|
||||||
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(2),
|
padding: const EdgeInsets.all(2),
|
||||||
child: CoverViewWidget(
|
child: CoverViewWidget(
|
||||||
isLongPressed: mangaIdsList.contains(entriesManga[index].id),
|
isLongPressed: mangaIdsList.contains(entry.id),
|
||||||
bottomTextWidget: BottomTextWidget(
|
bottomTextWidget: BottomTextWidget(
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
text: entriesManga[index].name!,
|
text: entry.name!,
|
||||||
isComfortableGrid: isComfortableGrid,
|
isComfortableGrid: isComfortableGrid,
|
||||||
),
|
),
|
||||||
isComfortableGrid: isComfortableGrid,
|
isComfortableGrid: isComfortableGrid,
|
||||||
image: entriesManga[index].customCoverImage != null
|
image: entry.customCoverImage != null
|
||||||
? MemoryImage(
|
? MemoryImage(entry.customCoverImage as Uint8List)
|
||||||
entriesManga[index].customCoverImage as Uint8List)
|
|
||||||
as ImageProvider
|
as ImageProvider
|
||||||
: CachedNetworkImageProvider(
|
: CachedNetworkImageProvider(
|
||||||
entriesManga[index].imageUrl!,
|
entry.imageUrl!,
|
||||||
headers: ref.watch(headersProvider(
|
headers: ref.watch(headersProvider(
|
||||||
source: entriesManga[index].source!,
|
source: entry.source!, lang: entry.lang!)),
|
||||||
lang: entriesManga[index].lang!)),
|
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (isLongPressed) {
|
if (isLongPressed) {
|
||||||
ref
|
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||||
.read(mangasListStateProvider.notifier)
|
|
||||||
.update(entriesManga[index]);
|
|
||||||
} else {
|
} else {
|
||||||
pushToMangaReaderDetail(
|
pushToMangaReaderDetail(
|
||||||
archiveId: isLocalArchive ? entriesManga[index].id : null,
|
archiveId: isLocalArchive ? entry.id : null,
|
||||||
context: context,
|
context: context,
|
||||||
lang: entriesManga[index].lang!,
|
lang: entry.lang!,
|
||||||
mangaM: entriesManga[index]);
|
mangaM: entry);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
if (!isLongPressed) {
|
if (!isLongPressed) {
|
||||||
ref
|
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||||
.read(mangasListStateProvider.notifier)
|
|
||||||
.update(entriesManga[index]);
|
|
||||||
|
|
||||||
ref
|
ref
|
||||||
.read(isLongPressedMangaStateProvider.notifier)
|
.read(isLongPressedMangaStateProvider.notifier)
|
||||||
.update(!isLongPressed);
|
.update(!isLongPressed);
|
||||||
} else {
|
} else {
|
||||||
ref
|
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||||
.read(mangasListStateProvider.notifier)
|
|
||||||
.update(entriesManga[index]);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -136,19 +129,14 @@ class LibraryGridViewWidget extends StatelessWidget {
|
||||||
List nbrDown = [];
|
List nbrDown = [];
|
||||||
isar.txnSync(() {
|
isar.txnSync(() {
|
||||||
for (var i = 0;
|
for (var i = 0;
|
||||||
i <
|
i < entry.chapters.length;
|
||||||
entriesManga[index]
|
|
||||||
.chapters
|
|
||||||
.length;
|
|
||||||
i++) {
|
i++) {
|
||||||
final entries = isar.downloads
|
final entries = isar.downloads
|
||||||
.filter()
|
.filter()
|
||||||
.idIsNotNull()
|
.idIsNotNull()
|
||||||
.chapterIdEqualTo(
|
.chapterIdEqualTo(entry.chapters
|
||||||
entriesManga[index]
|
.toList()[i]
|
||||||
.chapters
|
.id)
|
||||||
.toList()[i]
|
|
||||||
.id)
|
|
||||||
.findAllSync();
|
.findAllSync();
|
||||||
|
|
||||||
if (entries.isNotEmpty &&
|
if (entries.isNotEmpty &&
|
||||||
|
|
@ -189,10 +177,7 @@ class LibraryGridViewWidget extends StatelessWidget {
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(right: 3),
|
padding: const EdgeInsets.only(right: 3),
|
||||||
child: Text(
|
child: Text(
|
||||||
entriesManga[index]
|
entry.chapters.length.toString(),
|
||||||
.chapters
|
|
||||||
.length
|
|
||||||
.toString(),
|
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -200,7 +185,7 @@ class LibraryGridViewWidget extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
if (language && entriesManga[index].lang!.isNotEmpty)
|
if (language && entry.lang!.isNotEmpty)
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 0,
|
top: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
|
|
@ -219,7 +204,7 @@ class LibraryGridViewWidget extends StatelessWidget {
|
||||||
padding:
|
padding:
|
||||||
const EdgeInsets.only(left: 3, right: 3),
|
const EdgeInsets.only(left: 3, right: 3),
|
||||||
child: Text(
|
child: Text(
|
||||||
entriesManga[index].lang!.toUpperCase(),
|
entry.lang!.toUpperCase(),
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -229,7 +214,7 @@ class LibraryGridViewWidget extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (!isComfortableGrid && !isCoverOnlyGrid)
|
if (!isComfortableGrid && !isCoverOnlyGrid)
|
||||||
BottomTextWidget(text: entriesManga[index].name!),
|
BottomTextWidget(text: entry.name!),
|
||||||
if (continueReaderBtn)
|
if (continueReaderBtn)
|
||||||
Positioned(
|
Positioned(
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
|
|
@ -238,16 +223,16 @@ class LibraryGridViewWidget extends StatelessWidget {
|
||||||
padding: const EdgeInsets.all(9),
|
padding: const EdgeInsets.all(9),
|
||||||
child: Consumer(
|
child: Consumer(
|
||||||
builder: (context, ref, child) {
|
builder: (context, ref, child) {
|
||||||
final history =
|
final history = ref.watch(
|
||||||
ref.watch(getAllHistoryStreamProvider);
|
getAllHistoryStreamProvider(
|
||||||
|
isManga: entry.isManga!));
|
||||||
return history.when(
|
return history.when(
|
||||||
data: (data) {
|
data: (data) {
|
||||||
final incognitoMode =
|
final incognitoMode =
|
||||||
ref.watch(incognitoModeStateProvider);
|
ref.watch(incognitoModeStateProvider);
|
||||||
final entries = data
|
final entries = data
|
||||||
.where((element) =>
|
.where((element) =>
|
||||||
element.mangaId ==
|
element.mangaId == entry.id)
|
||||||
entriesManga[index].id)
|
|
||||||
.toList();
|
.toList();
|
||||||
if (entries.isNotEmpty && !incognitoMode) {
|
if (entries.isNotEmpty && !incognitoMode) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
|
@ -278,9 +263,7 @@ class LibraryGridViewWidget extends StatelessWidget {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
pushMangaReaderView(
|
pushMangaReaderView(
|
||||||
context: context,
|
context: context,
|
||||||
chapter: entriesManga[index]
|
chapter: entry.chapters.last);
|
||||||
.chapters
|
|
||||||
.last);
|
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,8 @@ class LibraryListViewWidget extends StatelessWidget {
|
||||||
return ListViewWidget(
|
return ListViewWidget(
|
||||||
itemCount: entriesManga.length,
|
itemCount: entriesManga.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
bool isLocalArchive = entriesManga[index].isLocalArchive ?? false;
|
final entry = entriesManga[index];
|
||||||
|
bool isLocalArchive = entry.isLocalArchive ?? false;
|
||||||
return Consumer(builder: (context, ref, child) {
|
return Consumer(builder: (context, ref, child) {
|
||||||
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
||||||
return Material(
|
return Material(
|
||||||
|
|
@ -48,34 +49,28 @@ class LibraryListViewWidget extends StatelessWidget {
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (isLongPressed) {
|
if (isLongPressed) {
|
||||||
ref
|
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||||
.read(mangasListStateProvider.notifier)
|
|
||||||
.update(entriesManga[index]);
|
|
||||||
} else {
|
} else {
|
||||||
pushToMangaReaderDetail(
|
pushToMangaReaderDetail(
|
||||||
archiveId: isLocalArchive ? entriesManga[index].id : null,
|
archiveId: isLocalArchive ? entry.id : null,
|
||||||
context: context,
|
context: context,
|
||||||
lang: entriesManga[index].lang!,
|
lang: entry.lang!,
|
||||||
mangaM: entriesManga[index]);
|
mangaM: entry);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
if (!isLongPressed) {
|
if (!isLongPressed) {
|
||||||
ref
|
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||||
.read(mangasListStateProvider.notifier)
|
|
||||||
.update(entriesManga[index]);
|
|
||||||
|
|
||||||
ref
|
ref
|
||||||
.read(isLongPressedMangaStateProvider.notifier)
|
.read(isLongPressedMangaStateProvider.notifier)
|
||||||
.update(!isLongPressed);
|
.update(!isLongPressed);
|
||||||
} else {
|
} else {
|
||||||
ref
|
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||||
.read(mangasListStateProvider.notifier)
|
|
||||||
.update(entriesManga[index]);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
color: mangaIdsList.contains(entriesManga[index].id)
|
color: mangaIdsList.contains(entry.id)
|
||||||
? primaryColor(context).withOpacity(0.4)
|
? primaryColor(context).withOpacity(0.4)
|
||||||
: Colors.transparent,
|
: Colors.transparent,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
|
@ -98,24 +93,18 @@ class LibraryListViewWidget extends StatelessWidget {
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 45,
|
height: 45,
|
||||||
image: entriesManga[index]
|
image: entry.customCoverImage != null
|
||||||
.customCoverImage !=
|
? MemoryImage(entry.customCoverImage
|
||||||
null
|
as Uint8List) as ImageProvider
|
||||||
? MemoryImage(
|
|
||||||
entriesManga[index].customCoverImage
|
|
||||||
as Uint8List) as ImageProvider
|
|
||||||
: CachedNetworkImageProvider(
|
: CachedNetworkImageProvider(
|
||||||
entriesManga[index].imageUrl!,
|
entry.imageUrl!,
|
||||||
headers: ref.watch(headersProvider(
|
headers: ref.watch(headersProvider(
|
||||||
source:
|
source: entry.source!,
|
||||||
entriesManga[index].source!,
|
lang: entry.lang!)),
|
||||||
lang:
|
|
||||||
entriesManga[index].lang!)),
|
|
||||||
),
|
),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
child: Container(
|
child: Container(
|
||||||
color: mangaIdsList
|
color: mangaIdsList.contains(entry.id)
|
||||||
.contains(entriesManga[index].id)
|
|
||||||
? primaryColor(context)
|
? primaryColor(context)
|
||||||
.withOpacity(0.4)
|
.withOpacity(0.4)
|
||||||
: Colors.transparent,
|
: Colors.transparent,
|
||||||
|
|
@ -127,7 +116,7 @@ class LibraryListViewWidget extends StatelessWidget {
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 10),
|
horizontal: 10),
|
||||||
child: Text(entriesManga[index].name!),
|
child: Text(entry.name!),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
@ -168,19 +157,15 @@ class LibraryListViewWidget extends StatelessWidget {
|
||||||
List nbrDown = [];
|
List nbrDown = [];
|
||||||
isar.txnSync(() {
|
isar.txnSync(() {
|
||||||
for (var i = 0;
|
for (var i = 0;
|
||||||
i <
|
i < entry.chapters.length;
|
||||||
entriesManga[index]
|
|
||||||
.chapters
|
|
||||||
.length;
|
|
||||||
i++) {
|
i++) {
|
||||||
final entries = isar.downloads
|
final entries = isar.downloads
|
||||||
.filter()
|
.filter()
|
||||||
.idIsNotNull()
|
.idIsNotNull()
|
||||||
.chapterIdEqualTo(
|
.chapterIdEqualTo(entry
|
||||||
entriesManga[index]
|
.chapters
|
||||||
.chapters
|
.toList()[i]
|
||||||
.toList()[i]
|
.id)
|
||||||
.id)
|
|
||||||
.findAllSync();
|
.findAllSync();
|
||||||
|
|
||||||
if (entries.isNotEmpty &&
|
if (entries.isNotEmpty &&
|
||||||
|
|
@ -220,16 +205,12 @@ class LibraryListViewWidget extends StatelessWidget {
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(right: 3),
|
padding: const EdgeInsets.only(right: 3),
|
||||||
child: Text(
|
child: Text(
|
||||||
entriesManga[index]
|
entry.chapters.length.toString(),
|
||||||
.chapters
|
|
||||||
.length
|
|
||||||
.toString(),
|
|
||||||
style:
|
style:
|
||||||
const TextStyle(color: Colors.white),
|
const TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (language &&
|
if (language && entry.lang!.isNotEmpty)
|
||||||
entriesManga[index].lang!.isNotEmpty)
|
|
||||||
Container(
|
Container(
|
||||||
color: primaryColor(context),
|
color: primaryColor(context),
|
||||||
child: Container(
|
child: Container(
|
||||||
|
|
@ -243,9 +224,7 @@ class LibraryListViewWidget extends StatelessWidget {
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 3, right: 3),
|
left: 3, right: 3),
|
||||||
child: Text(
|
child: Text(
|
||||||
entriesManga[index]
|
entry.lang!.toUpperCase(),
|
||||||
.lang!
|
|
||||||
.toUpperCase(),
|
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white),
|
color: Colors.white),
|
||||||
),
|
),
|
||||||
|
|
@ -260,16 +239,16 @@ class LibraryListViewWidget extends StatelessWidget {
|
||||||
if (continueReaderBtn)
|
if (continueReaderBtn)
|
||||||
Consumer(
|
Consumer(
|
||||||
builder: (context, ref, child) {
|
builder: (context, ref, child) {
|
||||||
final history =
|
final history = ref.watch(
|
||||||
ref.watch(getAllHistoryStreamProvider);
|
getAllHistoryStreamProvider(
|
||||||
|
isManga: entry.isManga!));
|
||||||
return history.when(
|
return history.when(
|
||||||
data: (data) {
|
data: (data) {
|
||||||
final incognitoMode =
|
final incognitoMode =
|
||||||
ref.watch(incognitoModeStateProvider);
|
ref.watch(incognitoModeStateProvider);
|
||||||
final entries = data
|
final entries = data
|
||||||
.where((element) =>
|
.where((element) =>
|
||||||
element.mangaId ==
|
element.mangaId == entry.id)
|
||||||
entriesManga[index].id)
|
|
||||||
.toList();
|
.toList();
|
||||||
if (entries.isNotEmpty && !incognitoMode) {
|
if (entries.isNotEmpty && !incognitoMode) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
|
@ -300,9 +279,7 @@ class LibraryListViewWidget extends StatelessWidget {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
pushMangaReaderView(
|
pushMangaReaderView(
|
||||||
context: context,
|
context: context,
|
||||||
chapter: entriesManga[index]
|
chapter: entry.chapters.last);
|
||||||
.chapters
|
|
||||||
.last);
|
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,11 @@ class _MainScreenState extends State<MainScreen> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final l10n = l10nLocalizations(context)!;
|
final l10n = l10nLocalizations(context)!;
|
||||||
final route = GoRouter.of(context);
|
final route = GoRouter.of(context);
|
||||||
int currentIndex = route.location == '/library'
|
int currentIndex = route.location == '/MangaLibrary'
|
||||||
? 0
|
? 0
|
||||||
: route.location == '/updates'
|
: route.location == '/AnimeLibrary'
|
||||||
? 1
|
? 1
|
||||||
: route.location == '/history'
|
: route.location == '/updates'
|
||||||
? 2
|
? 2
|
||||||
: route.location == '/browse'
|
: route.location == '/browse'
|
||||||
? 3
|
? 3
|
||||||
|
|
@ -80,9 +80,9 @@ class _MainScreenState extends State<MainScreen> {
|
||||||
duration: const Duration(milliseconds: 0),
|
duration: const Duration(milliseconds: 0),
|
||||||
width: isLongPressed
|
width: isLongPressed
|
||||||
? 0
|
? 0
|
||||||
: route.location != '/library' &&
|
: route.location != '/MangaLibrary' &&
|
||||||
|
route.location != '/AnimeLibrary' &&
|
||||||
route.location != '/updates' &&
|
route.location != '/updates' &&
|
||||||
route.location != '/history' &&
|
|
||||||
route.location != '/browse' &&
|
route.location != '/browse' &&
|
||||||
route.location != '/more'
|
route.location != '/more'
|
||||||
? 0
|
? 0
|
||||||
|
|
@ -105,7 +105,18 @@ class _MainScreenState extends State<MainScreen> {
|
||||||
),
|
),
|
||||||
label: Padding(
|
label: Padding(
|
||||||
padding: const EdgeInsets.only(top: 5),
|
padding: const EdgeInsets.only(top: 5),
|
||||||
child: Text(l10n.library))),
|
child: Text(l10n.manga))),
|
||||||
|
NavigationRailDestination(
|
||||||
|
selectedIcon: const Icon(
|
||||||
|
Icons.video_collection,
|
||||||
|
),
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.video_collection_outlined,
|
||||||
|
),
|
||||||
|
label: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 5),
|
||||||
|
child: Text(l10n.anime),
|
||||||
|
)),
|
||||||
NavigationRailDestination(
|
NavigationRailDestination(
|
||||||
selectedIcon: const Icon(
|
selectedIcon: const Icon(
|
||||||
Icons.new_releases,
|
Icons.new_releases,
|
||||||
|
|
@ -116,17 +127,6 @@ class _MainScreenState extends State<MainScreen> {
|
||||||
label: Padding(
|
label: Padding(
|
||||||
padding: const EdgeInsets.only(top: 5),
|
padding: const EdgeInsets.only(top: 5),
|
||||||
child: Text(l10n.updates))),
|
child: Text(l10n.updates))),
|
||||||
NavigationRailDestination(
|
|
||||||
selectedIcon: const Icon(
|
|
||||||
Icons.history,
|
|
||||||
),
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.history_outlined,
|
|
||||||
),
|
|
||||||
label: Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 5),
|
|
||||||
child: Text(l10n.history),
|
|
||||||
)),
|
|
||||||
NavigationRailDestination(
|
NavigationRailDestination(
|
||||||
selectedIcon: const Icon(
|
selectedIcon: const Icon(
|
||||||
Icons.explore,
|
Icons.explore,
|
||||||
|
|
@ -158,11 +158,11 @@ class _MainScreenState extends State<MainScreen> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (newIndex == 0) {
|
if (newIndex == 0) {
|
||||||
route.go('/library');
|
route.go('/MangaLibrary');
|
||||||
} else if (newIndex == 1) {
|
} else if (newIndex == 1) {
|
||||||
route.go('/updates');
|
route.go('/AnimeLibrary');
|
||||||
} else if (newIndex == 2) {
|
} else if (newIndex == 2) {
|
||||||
route.go('/history');
|
route.go('/updates');
|
||||||
} else if (newIndex == 3) {
|
} else if (newIndex == 3) {
|
||||||
route.go('/browse');
|
route.go('/browse');
|
||||||
} else if (newIndex == 4) {
|
} else if (newIndex == 4) {
|
||||||
|
|
@ -187,9 +187,9 @@ class _MainScreenState extends State<MainScreen> {
|
||||||
width: mediaWidth(context, 1),
|
width: mediaWidth(context, 1),
|
||||||
height: isLongPressed
|
height: isLongPressed
|
||||||
? 0
|
? 0
|
||||||
: route.location != '/library' &&
|
: route.location != '/MangaLibrary' &&
|
||||||
|
route.location != '/AnimeLibrary' &&
|
||||||
route.location != '/updates' &&
|
route.location != '/updates' &&
|
||||||
route.location != '/history' &&
|
|
||||||
route.location != '/browse' &&
|
route.location != '/browse' &&
|
||||||
route.location != '/more'
|
route.location != '/more'
|
||||||
? 0
|
? 0
|
||||||
|
|
@ -211,7 +211,15 @@ class _MainScreenState extends State<MainScreen> {
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.collections_bookmark_outlined,
|
Icons.collections_bookmark_outlined,
|
||||||
),
|
),
|
||||||
label: l10n.library),
|
label: l10n.manga),
|
||||||
|
NavigationDestination(
|
||||||
|
selectedIcon: const Icon(
|
||||||
|
Icons.video_collection,
|
||||||
|
),
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.video_collection_outlined,
|
||||||
|
),
|
||||||
|
label: l10n.anime),
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
selectedIcon: const Icon(
|
selectedIcon: const Icon(
|
||||||
Icons.new_releases,
|
Icons.new_releases,
|
||||||
|
|
@ -220,14 +228,6 @@ class _MainScreenState extends State<MainScreen> {
|
||||||
Icons.new_releases_outlined,
|
Icons.new_releases_outlined,
|
||||||
),
|
),
|
||||||
label: l10n.updates),
|
label: l10n.updates),
|
||||||
NavigationDestination(
|
|
||||||
selectedIcon: const Icon(
|
|
||||||
Icons.history,
|
|
||||||
),
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.history_outlined,
|
|
||||||
),
|
|
||||||
label: l10n.history),
|
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
selectedIcon: const Icon(
|
selectedIcon: const Icon(
|
||||||
Icons.explore,
|
Icons.explore,
|
||||||
|
|
@ -252,11 +252,11 @@ class _MainScreenState extends State<MainScreen> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (newIndex == 0) {
|
if (newIndex == 0) {
|
||||||
route.go('/library');
|
route.go('/MangaLibrary');
|
||||||
} else if (newIndex == 1) {
|
} else if (newIndex == 1) {
|
||||||
route.go('/updates');
|
route.go('/AnimeLibrary');
|
||||||
} else if (newIndex == 2) {
|
} else if (newIndex == 2) {
|
||||||
route.go('/history');
|
route.go('/updates');
|
||||||
} else if (newIndex == 3) {
|
} else if (newIndex == 3) {
|
||||||
route.go('/browse');
|
route.go('/browse');
|
||||||
} else if (newIndex == 4) {
|
} else if (newIndex == 4) {
|
||||||
|
|
|
||||||
|
|
@ -373,7 +373,10 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
||||||
];
|
];
|
||||||
}, onSelected: (value) {
|
}, onSelected: (value) {
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
context.push("/categories");
|
context.push("/categories", extra: (
|
||||||
|
true,
|
||||||
|
widget.manga!.isManga! ? 0 : 1
|
||||||
|
));
|
||||||
} else if (value == 1) {
|
} else if (value == 1) {
|
||||||
} else if (value == 2) {
|
} else if (value == 2) {
|
||||||
final source = getSource(widget.manga!.lang!,
|
final source = getSource(widget.manga!.lang!,
|
||||||
|
|
@ -450,8 +453,11 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
||||||
.symmetric(
|
.symmetric(
|
||||||
horizontal: 8),
|
horizontal: 8),
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.n_chapters(
|
widget.manga!.isManga!
|
||||||
chapters.length),
|
? l10n.n_chapters(
|
||||||
|
chapters.length)
|
||||||
|
: l10n.n_episodes(
|
||||||
|
chapters.length),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight:
|
fontWeight:
|
||||||
FontWeight.bold),
|
FontWeight.bold),
|
||||||
|
|
@ -1199,7 +1205,9 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
||||||
padding:
|
padding:
|
||||||
const EdgeInsets.symmetric(horizontal: 8),
|
const EdgeInsets.symmetric(horizontal: 8),
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.n_chapters(chapterLength),
|
widget.manga!.isManga!
|
||||||
|
? l10n.n_chapters(chapterLength)
|
||||||
|
: l10n.n_episodes(chapterLength),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold),
|
fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
|
|
@ -1656,13 +1664,14 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
||||||
mangaId: widget.manga!.id!,
|
mangaId: widget.manga!.id!,
|
||||||
trackPreference: entries[index],
|
trackPreference: entries[index],
|
||||||
trackRes: trackRes.first,
|
trackRes: trackRes.first,
|
||||||
)
|
isManga: widget.manga!.isManga!)
|
||||||
: TrackListile(
|
: TrackListile(
|
||||||
text: l10nLocalizations(context)!.add_tracker,
|
text: l10nLocalizations(context)!.add_tracker,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final trackSearch =
|
final trackSearch =
|
||||||
await trackersSearchraggableMenu(
|
await trackersSearchraggableMenu(
|
||||||
context,
|
context,
|
||||||
|
isManga: widget.manga!.isManga!,
|
||||||
track: Track(
|
track: Track(
|
||||||
status: TrackStatus.planToRead,
|
status: TrackStatus.planToRead,
|
||||||
syncId: entries[index].syncId!,
|
syncId: entries[index].syncId!,
|
||||||
|
|
@ -1670,7 +1679,9 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
||||||
) as TrackSearch?;
|
) as TrackSearch?;
|
||||||
if (trackSearch != null) {
|
if (trackSearch != null) {
|
||||||
await ref
|
await ref
|
||||||
.read(trackStateProvider(track: null)
|
.read(trackStateProvider(
|
||||||
|
track: null,
|
||||||
|
isManga: widget.manga!.isManga!)
|
||||||
.notifier)
|
.notifier)
|
||||||
.setTrackSearch(
|
.setTrackSearch(
|
||||||
trackSearch,
|
trackSearch,
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,8 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
floatingActionButton: Consumer(
|
floatingActionButton: Consumer(
|
||||||
builder: (context, ref, child) {
|
builder: (context, ref, child) {
|
||||||
final history = ref.watch(getAllHistoryStreamProvider);
|
final history = ref.watch(
|
||||||
|
getAllHistoryStreamProvider(isManga: widget.manga.isManga!));
|
||||||
final chaptersList = ref.watch(chaptersListttStateProvider);
|
final chaptersList = ref.watch(chaptersListttStateProvider);
|
||||||
final isExtended = ref.watch(isExtendedStateProvider);
|
final isExtended = ref.watch(isExtendedStateProvider);
|
||||||
return ref.watch(isLongPressedStateProvider) == true
|
return ref.watch(isLongPressedStateProvider) == true
|
||||||
|
|
@ -161,8 +162,12 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
||||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
elevation: 0),
|
elevation: 0),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final checkCategoryList =
|
final checkCategoryList = isar.categorys
|
||||||
isar.categorys.filter().idIsNotNull().isNotEmptySync();
|
.filter()
|
||||||
|
.idIsNotNull()
|
||||||
|
.and()
|
||||||
|
.forMangaEqualTo(widget.manga.isManga)
|
||||||
|
.isNotEmptySync();
|
||||||
if (checkCategoryList) {
|
if (checkCategoryList) {
|
||||||
_openCategory(widget.manga);
|
_openCategory(widget.manga);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -219,6 +224,8 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
||||||
stream: isar.categorys
|
stream: isar.categorys
|
||||||
.filter()
|
.filter()
|
||||||
.idIsNotNull()
|
.idIsNotNull()
|
||||||
|
.and()
|
||||||
|
.forMangaEqualTo(widget.manga.isManga)
|
||||||
.watch(fireImmediately: true),
|
.watch(fireImmediately: true),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||||
|
|
@ -255,7 +262,8 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
||||||
children: [
|
children: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.push("/categories");
|
context.push("/categories",
|
||||||
|
extra: (true, widget.manga.isManga! ? 0 : 1));
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: Text(l10n.edit)),
|
child: Text(l10n.edit)),
|
||||||
|
|
|
||||||
|
|
@ -193,4 +193,5 @@ class GetChaptersStreamProvider
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -979,4 +979,5 @@ class ScanlatorsFilterStateProvider extends AutoDisposeNotifierProviderImpl<
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -9,20 +9,34 @@ part 'track_state_providers.g.dart';
|
||||||
@riverpod
|
@riverpod
|
||||||
class TrackState extends _$TrackState {
|
class TrackState extends _$TrackState {
|
||||||
@override
|
@override
|
||||||
Track build({Track? track}) {
|
Track build({Track? track, required bool? isManga}) {
|
||||||
return track!;
|
return track!;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future updateManga() async {
|
Future updateManga() async {
|
||||||
Track? updateTrack;
|
Track? updateTrack;
|
||||||
if (track!.syncId == 1) {
|
if (track!.syncId == 1) {
|
||||||
updateTrack = await ref
|
updateTrack = isManga!
|
||||||
.read(myAnimeListProvider(syncId: track!.syncId!).notifier)
|
? await ref
|
||||||
.updateManga(track!);
|
.read(
|
||||||
|
myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.updateManga(track!)
|
||||||
|
: await ref
|
||||||
|
.read(
|
||||||
|
myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.updateAnime(track!);
|
||||||
} else if (track!.syncId == 2) {
|
} else if (track!.syncId == 2) {
|
||||||
updateTrack = await ref
|
updateTrack = isManga!
|
||||||
.read(anilistProvider(syncId: track!.syncId!).notifier)
|
? await ref
|
||||||
.updateLibManga(track!);
|
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.updateLibManga(track!)
|
||||||
|
: await ref
|
||||||
|
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.updateLibAnime(track!);
|
||||||
}
|
}
|
||||||
|
|
||||||
ref
|
ref
|
||||||
|
|
@ -36,7 +50,8 @@ class TrackState extends _$TrackState {
|
||||||
maxValue = 10;
|
maxValue = 10;
|
||||||
} else if (track!.syncId == 2) {
|
} else if (track!.syncId == 2) {
|
||||||
maxValue = ref
|
maxValue = ref
|
||||||
.read(anilistProvider(syncId: track!.syncId!).notifier)
|
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
.getScoreValue()
|
.getScoreValue()
|
||||||
.$1;
|
.$1;
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +62,7 @@ class TrackState extends _$TrackState {
|
||||||
if (track!.syncId == 1) {
|
if (track!.syncId == 1) {
|
||||||
} else {
|
} else {
|
||||||
numberText = ref
|
numberText = ref
|
||||||
.read(anilistProvider(syncId: 2).notifier)
|
.read(anilistProvider(syncId: 2, isManga: isManga).notifier)
|
||||||
.displayScore(int.parse(numberText));
|
.displayScore(int.parse(numberText));
|
||||||
}
|
}
|
||||||
return numberText;
|
return numberText;
|
||||||
|
|
@ -59,7 +74,8 @@ class TrackState extends _$TrackState {
|
||||||
step = 1;
|
step = 1;
|
||||||
} else if (track!.syncId == 2) {
|
} else if (track!.syncId == 2) {
|
||||||
step = ref
|
step = ref
|
||||||
.read(anilistProvider(syncId: track!.syncId!).notifier)
|
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
.getScoreValue()
|
.getScoreValue()
|
||||||
.$2;
|
.$2;
|
||||||
}
|
}
|
||||||
|
|
@ -71,8 +87,9 @@ class TrackState extends _$TrackState {
|
||||||
if (track!.syncId == 1) {
|
if (track!.syncId == 1) {
|
||||||
result = score.toString();
|
result = score.toString();
|
||||||
} else {
|
} else {
|
||||||
result =
|
result = ref
|
||||||
ref.read(anilistProvider(syncId: 2).notifier).displayScore(score);
|
.read(anilistProvider(syncId: 2, isManga: isManga).notifier)
|
||||||
|
.displayScore(score);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -94,19 +111,35 @@ class TrackState extends _$TrackState {
|
||||||
finishedReadingDate: 0);
|
finishedReadingDate: 0);
|
||||||
if (syncId == 1) {
|
if (syncId == 1) {
|
||||||
findManga = await ref
|
findManga = await ref
|
||||||
.read(myAnimeListProvider(syncId: syncId).notifier)
|
.read(myAnimeListProvider(syncId: syncId, isManga: isManga).notifier)
|
||||||
.findManga(track);
|
.findManga(track);
|
||||||
} else if (syncId == 2) {
|
} else if (syncId == 2) {
|
||||||
findManga = findManga = await ref
|
findManga = isManga!
|
||||||
.read(anilistProvider(syncId: syncId).notifier)
|
? await ref
|
||||||
.findLibManga(track);
|
.read(anilistProvider(syncId: syncId, isManga: isManga).notifier)
|
||||||
|
.findLibManga(track)
|
||||||
|
: await ref
|
||||||
|
.read(anilistProvider(syncId: syncId, isManga: isManga).notifier)
|
||||||
|
.findLibAnime(track);
|
||||||
if (findManga == null) {
|
if (findManga == null) {
|
||||||
await ref
|
findManga = isManga!
|
||||||
.read(anilistProvider(syncId: syncId).notifier)
|
? await ref
|
||||||
.addLibManga(track);
|
.read(
|
||||||
findManga = await ref
|
anilistProvider(syncId: syncId, isManga: isManga).notifier)
|
||||||
.read(anilistProvider(syncId: syncId).notifier)
|
.addLibManga(track)
|
||||||
.findLibManga(track);
|
: await ref
|
||||||
|
.read(
|
||||||
|
anilistProvider(syncId: syncId, isManga: isManga).notifier)
|
||||||
|
.addLibAnime(track);
|
||||||
|
findManga = isManga!
|
||||||
|
? await ref
|
||||||
|
.read(
|
||||||
|
anilistProvider(syncId: syncId, isManga: isManga).notifier)
|
||||||
|
.findLibManga(track)
|
||||||
|
: await ref
|
||||||
|
.read(
|
||||||
|
anilistProvider(syncId: syncId, isManga: isManga).notifier)
|
||||||
|
.findLibAnime(track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ref
|
ref
|
||||||
|
|
@ -118,13 +151,27 @@ class TrackState extends _$TrackState {
|
||||||
List<TrackStatus> statusList = [];
|
List<TrackStatus> statusList = [];
|
||||||
List<TrackStatus> list = [];
|
List<TrackStatus> list = [];
|
||||||
if (track!.syncId == 1) {
|
if (track!.syncId == 1) {
|
||||||
statusList = ref
|
statusList = isManga!
|
||||||
.read(myAnimeListProvider(syncId: track!.syncId!).notifier)
|
? ref
|
||||||
.myAnimeListStatusList;
|
.read(
|
||||||
|
myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.myAnimeListStatusListManga
|
||||||
|
: ref
|
||||||
|
.read(
|
||||||
|
myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.myAnimeListStatusListAnime;
|
||||||
} else if (track!.syncId == 2) {
|
} else if (track!.syncId == 2) {
|
||||||
statusList = ref
|
statusList = isManga!
|
||||||
.read(anilistProvider(syncId: track!.syncId!).notifier)
|
? ref
|
||||||
.aniListStatusList;
|
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.aniListStatusListManga
|
||||||
|
: ref
|
||||||
|
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.aniListStatusListAnime;
|
||||||
}
|
}
|
||||||
for (var element in TrackStatus.values) {
|
for (var element in TrackStatus.values) {
|
||||||
if (statusList.contains(element)) {
|
if (statusList.contains(element)) {
|
||||||
|
|
@ -138,12 +185,19 @@ class TrackState extends _$TrackState {
|
||||||
Track? findManga;
|
Track? findManga;
|
||||||
if (track!.syncId == 1) {
|
if (track!.syncId == 1) {
|
||||||
findManga = await ref
|
findManga = await ref
|
||||||
.read(myAnimeListProvider(syncId: track!.syncId!).notifier)
|
.read(myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
.findManga(track!);
|
.findManga(track!);
|
||||||
} else if (track!.syncId == 2) {
|
} else if (track!.syncId == 2) {
|
||||||
findManga = findManga = await ref
|
findManga = isManga!
|
||||||
.read(anilistProvider(syncId: track!.syncId!).notifier)
|
? await ref
|
||||||
.findLibManga(track!);
|
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.findLibManga(track!)
|
||||||
|
: await ref
|
||||||
|
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.findLibAnime(track!);
|
||||||
}
|
}
|
||||||
return findManga;
|
return findManga;
|
||||||
}
|
}
|
||||||
|
|
@ -152,12 +206,19 @@ class TrackState extends _$TrackState {
|
||||||
List<TrackSearch>? tracks;
|
List<TrackSearch>? tracks;
|
||||||
if (track!.syncId == 1) {
|
if (track!.syncId == 1) {
|
||||||
tracks = await ref
|
tracks = await ref
|
||||||
.read(myAnimeListProvider(syncId: track!.syncId!).notifier)
|
.read(myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
.search(query);
|
.search(query);
|
||||||
} else if (track!.syncId == 2) {
|
} else if (track!.syncId == 2) {
|
||||||
tracks = await ref
|
tracks = isManga!
|
||||||
.read(anilistProvider(syncId: track!.syncId!).notifier)
|
? await ref
|
||||||
.search(query);
|
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.search(query)
|
||||||
|
: await ref
|
||||||
|
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||||
|
.notifier)
|
||||||
|
.searchAnime(query);
|
||||||
}
|
}
|
||||||
return tracks;
|
return tracks;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ part of 'track_state_providers.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$trackStateHash() => r'7004528230213b458c7db417947eecfc700d44d7';
|
String _$trackStateHash() => r'eeca421125ff52ccf671d434c41e0198bb7b6fea';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|
@ -31,9 +31,11 @@ class _SystemHash {
|
||||||
|
|
||||||
abstract class _$TrackState extends BuildlessAutoDisposeNotifier<Track> {
|
abstract class _$TrackState extends BuildlessAutoDisposeNotifier<Track> {
|
||||||
late final Track? track;
|
late final Track? track;
|
||||||
|
late final bool? isManga;
|
||||||
|
|
||||||
Track build({
|
Track build({
|
||||||
Track? track,
|
Track? track,
|
||||||
|
required bool? isManga,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,9 +51,11 @@ class TrackStateFamily extends Family<Track> {
|
||||||
/// See also [TrackState].
|
/// See also [TrackState].
|
||||||
TrackStateProvider call({
|
TrackStateProvider call({
|
||||||
Track? track,
|
Track? track,
|
||||||
|
required bool? isManga,
|
||||||
}) {
|
}) {
|
||||||
return TrackStateProvider(
|
return TrackStateProvider(
|
||||||
track: track,
|
track: track,
|
||||||
|
isManga: isManga,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,6 +65,7 @@ class TrackStateFamily extends Family<Track> {
|
||||||
) {
|
) {
|
||||||
return call(
|
return call(
|
||||||
track: provider.track,
|
track: provider.track,
|
||||||
|
isManga: provider.isManga,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,8 +90,11 @@ class TrackStateProvider
|
||||||
/// See also [TrackState].
|
/// See also [TrackState].
|
||||||
TrackStateProvider({
|
TrackStateProvider({
|
||||||
this.track,
|
this.track,
|
||||||
|
required this.isManga,
|
||||||
}) : super.internal(
|
}) : super.internal(
|
||||||
() => TrackState()..track = track,
|
() => TrackState()
|
||||||
|
..track = track
|
||||||
|
..isManga = isManga,
|
||||||
from: trackStateProvider,
|
from: trackStateProvider,
|
||||||
name: r'trackStateProvider',
|
name: r'trackStateProvider',
|
||||||
debugGetCreateSourceHash:
|
debugGetCreateSourceHash:
|
||||||
|
|
@ -99,16 +107,20 @@ class TrackStateProvider
|
||||||
);
|
);
|
||||||
|
|
||||||
final Track? track;
|
final Track? track;
|
||||||
|
final bool? isManga;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is TrackStateProvider && other.track == track;
|
return other is TrackStateProvider &&
|
||||||
|
other.track == track &&
|
||||||
|
other.isManga == isManga;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
hash = _SystemHash.combine(hash, track.hashCode);
|
hash = _SystemHash.combine(hash, track.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, isManga.hashCode);
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +131,9 @@ class TrackStateProvider
|
||||||
) {
|
) {
|
||||||
return notifier.build(
|
return notifier.build(
|
||||||
track: track,
|
track: track,
|
||||||
|
isManga: isManga,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ Future<dynamic> updateMangaDetail(UpdateMangaDetailRef ref,
|
||||||
dateFormatLocale: source.dateFormatLocale);
|
dateFormatLocale: source.dateFormatLocale);
|
||||||
final getManga = await ref
|
final getManga = await ref
|
||||||
.watch(getMangaDetailProvider(manga: mangaS, source: source).future);
|
.watch(getMangaDetailProvider(manga: mangaS, source: source).future);
|
||||||
|
|
||||||
final imageUrl = getManga.imageUrl != null && getManga.imageUrl!.isNotEmpty
|
final imageUrl = getManga.imageUrl != null && getManga.imageUrl!.isNotEmpty
|
||||||
? getManga.imageUrl
|
? getManga.imageUrl
|
||||||
: manga.imageUrl ?? "";
|
: manga.imageUrl ?? "";
|
||||||
|
|
@ -39,6 +40,7 @@ Future<dynamic> updateMangaDetail(UpdateMangaDetailRef ref,
|
||||||
.toSet()
|
.toSet()
|
||||||
.toList()
|
.toList()
|
||||||
: manga.genre ?? [];
|
: manga.genre ?? [];
|
||||||
|
|
||||||
final author = getManga.author != null && getManga.author!.isNotEmpty
|
final author = getManga.author != null && getManga.author!.isNotEmpty
|
||||||
? getManga.author!.trim().trimLeft().trimRight()
|
? getManga.author!.trim().trimLeft().trimRight()
|
||||||
: manga.author ?? "";
|
: manga.author ?? "";
|
||||||
|
|
@ -72,6 +74,7 @@ Future<dynamic> updateMangaDetail(UpdateMangaDetailRef ref,
|
||||||
..link = link
|
..link = link
|
||||||
..source = sourceA
|
..source = sourceA
|
||||||
..lang = lang
|
..lang = lang
|
||||||
|
..isManga = source.isManga
|
||||||
..lastUpdate = DateTime.now().millisecondsSinceEpoch;
|
..lastUpdate = DateTime.now().millisecondsSinceEpoch;
|
||||||
|
|
||||||
isar.writeTxnSync(() {
|
isar.writeTxnSync(() {
|
||||||
|
|
@ -99,7 +102,9 @@ Future<dynamic> updateMangaDetail(UpdateMangaDetailRef ref,
|
||||||
final chapters = Chapter(
|
final chapters = Chapter(
|
||||||
name: title,
|
name: title,
|
||||||
url: getManga.urls![i].trim().trimLeft().trimRight(),
|
url: getManga.urls![i].trim().trimLeft().trimRight(),
|
||||||
dateUpload: getManga.chaptersDateUploads![i],
|
dateUpload: getManga.chaptersDateUploads!.isEmpty
|
||||||
|
? null
|
||||||
|
: getManga.chaptersDateUploads![i],
|
||||||
scanlator: scanlator,
|
scanlator: scanlator,
|
||||||
)..manga.value = manga;
|
)..manga.value = manga;
|
||||||
isar.chapters.putSync(chapters);
|
isar.chapters.putSync(chapters);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ part of 'update_manga_detail_providers.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$updateMangaDetailHash() => r'7c8e4cae20be71b2cab42f7d784888fb4037aa00';
|
String _$updateMangaDetailHash() => r'143fc36898ba2d83ee6d42d71b01077ce33dcb19';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|
@ -118,4 +118,5 @@ class UpdateMangaDetailProvider extends AutoDisposeFutureProvider<dynamic> {
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:mangayomi/models/chapter.dart';
|
import 'package:mangayomi/models/chapter.dart';
|
||||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||||
|
import 'package:mangayomi/services/anime_servers/gogo_cdn_extractor.dart';
|
||||||
import 'package:mangayomi/utils/date.dart';
|
import 'package:mangayomi/utils/date.dart';
|
||||||
import 'package:mangayomi/modules/manga/reader/providers/push_router.dart';
|
import 'package:mangayomi/modules/manga/reader/providers/push_router.dart';
|
||||||
import 'package:mangayomi/utils/colors.dart';
|
import 'package:mangayomi/utils/colors.dart';
|
||||||
|
|
@ -74,7 +75,12 @@ class ChapterListTileWidget extends ConsumerWidget {
|
||||||
children: [
|
children: [
|
||||||
if ((chapter.manga.value!.isLocalArchive ?? false) == false)
|
if ((chapter.manga.value!.isLocalArchive ?? false) == false)
|
||||||
Text(
|
Text(
|
||||||
dateFormat(chapter.dateUpload!, ref: ref, context: context),
|
dateFormat(
|
||||||
|
!chapter.manga.value!.isManga!
|
||||||
|
? DateTime.now().millisecondsSinceEpoch.toString()
|
||||||
|
: chapter.dateUpload!,
|
||||||
|
ref: ref,
|
||||||
|
context: context),
|
||||||
style: const TextStyle(fontSize: 11),
|
style: const TextStyle(fontSize: 11),
|
||||||
),
|
),
|
||||||
if (!chapter.isRead!)
|
if (!chapter.isRead!)
|
||||||
|
|
@ -84,7 +90,13 @@ class ChapterListTileWidget extends ConsumerWidget {
|
||||||
children: [
|
children: [
|
||||||
const Text(' • '),
|
const Text(' • '),
|
||||||
Text(
|
Text(
|
||||||
l10n.page(chapter.lastPageRead!),
|
!chapter.manga.value!.isManga!
|
||||||
|
? l10n.episode_progress(Duration(
|
||||||
|
milliseconds:
|
||||||
|
int.parse(chapter.lastPageRead!))
|
||||||
|
.toString()
|
||||||
|
.substringBefore("."))
|
||||||
|
: l10n.page(chapter.lastPageRead!),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
color: isLight(context)
|
color: isLight(context)
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,10 @@ import 'package:mangayomi/utils/colors.dart';
|
||||||
import 'package:mangayomi/utils/media_query.dart';
|
import 'package:mangayomi/utils/media_query.dart';
|
||||||
|
|
||||||
class TrackerWidgetSearch extends ConsumerStatefulWidget {
|
class TrackerWidgetSearch extends ConsumerStatefulWidget {
|
||||||
|
final bool isManga;
|
||||||
final Track track;
|
final Track track;
|
||||||
const TrackerWidgetSearch({required this.track, super.key});
|
const TrackerWidgetSearch(
|
||||||
|
{required this.isManga, required this.track, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<TrackerWidgetSearch> createState() =>
|
ConsumerState<TrackerWidgetSearch> createState() =>
|
||||||
|
|
@ -30,7 +32,8 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
||||||
_init() async {
|
_init() async {
|
||||||
await Future.delayed(const Duration(microseconds: 100));
|
await Future.delayed(const Duration(microseconds: 100));
|
||||||
tracks = await ref
|
tracks = await ref
|
||||||
.read(trackStateProvider(track: widget.track).notifier)
|
.read(trackStateProvider(track: widget.track, isManga: widget.isManga)
|
||||||
|
.notifier)
|
||||||
.search(query);
|
.search(query);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
@ -169,7 +172,9 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
tracks = await ref
|
tracks = await ref
|
||||||
.read(trackStateProvider(track: widget.track)
|
.read(trackStateProvider(
|
||||||
|
track: widget.track,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.search(d.trim());
|
.search(d.trim());
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
|
@ -210,7 +215,8 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trackersSearchraggableMenu(BuildContext context, {required Track track}) async {
|
trackersSearchraggableMenu(BuildContext context,
|
||||||
|
{required Track track, required bool isManga}) async {
|
||||||
return await DraggableMenu.open(
|
return await DraggableMenu.open(
|
||||||
context,
|
context,
|
||||||
DraggableMenu(
|
DraggableMenu(
|
||||||
|
|
@ -240,5 +246,6 @@ trackersSearchraggableMenu(BuildContext context, {required Track track}) async {
|
||||||
maxHeight: mediaHeight(context, 0.9),
|
maxHeight: mediaHeight(context, 0.9),
|
||||||
child: TrackerWidgetSearch(
|
child: TrackerWidgetSearch(
|
||||||
track: track,
|
track: track,
|
||||||
|
isManga: isManga,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,13 @@ import 'package:mangayomi/utils/utils.dart';
|
||||||
import 'package:numberpicker/numberpicker.dart';
|
import 'package:numberpicker/numberpicker.dart';
|
||||||
|
|
||||||
class TrackerWidget extends ConsumerStatefulWidget {
|
class TrackerWidget extends ConsumerStatefulWidget {
|
||||||
|
final bool isManga;
|
||||||
final Track trackRes;
|
final Track trackRes;
|
||||||
final int mangaId;
|
final int mangaId;
|
||||||
final TrackPreference trackPreference;
|
final TrackPreference trackPreference;
|
||||||
const TrackerWidget(
|
const TrackerWidget(
|
||||||
{super.key,
|
{super.key,
|
||||||
|
required this.isManga,
|
||||||
required this.trackPreference,
|
required this.trackPreference,
|
||||||
required this.trackRes,
|
required this.trackRes,
|
||||||
required this.mangaId});
|
required this.mangaId});
|
||||||
|
|
@ -38,7 +40,9 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
||||||
_init() async {
|
_init() async {
|
||||||
await Future.delayed(const Duration(microseconds: 100));
|
await Future.delayed(const Duration(microseconds: 100));
|
||||||
final findManga = await ref
|
final findManga = await ref
|
||||||
.read(trackStateProvider(track: widget.trackRes).notifier)
|
.read(
|
||||||
|
trackStateProvider(track: widget.trackRes, isManga: widget.isManga)
|
||||||
|
.notifier)
|
||||||
.findManga();
|
.findManga();
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ref
|
ref
|
||||||
|
|
@ -83,10 +87,13 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final trackSearch = await trackersSearchraggableMenu(
|
final trackSearch = await trackersSearchraggableMenu(
|
||||||
context,
|
context,
|
||||||
|
isManga: widget.isManga,
|
||||||
track: widget.trackRes) as TrackSearch?;
|
track: widget.trackRes) as TrackSearch?;
|
||||||
if (trackSearch != null) {
|
if (trackSearch != null) {
|
||||||
await ref
|
await ref
|
||||||
.read(trackStateProvider(track: null).notifier)
|
.read(trackStateProvider(
|
||||||
|
track: null, isManga: widget.isManga)
|
||||||
|
.notifier)
|
||||||
.setTrackSearch(trackSearch, widget.mangaId,
|
.setTrackSearch(trackSearch, widget.mangaId,
|
||||||
widget.trackPreference.syncId!);
|
widget.trackPreference.syncId!);
|
||||||
}
|
}
|
||||||
|
|
@ -142,26 +149,33 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemCount: ref
|
itemCount: ref
|
||||||
.read(trackStateProvider(
|
.read(trackStateProvider(
|
||||||
track: widget.trackRes)
|
track: widget.trackRes,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.getStatusList()
|
.getStatusList()
|
||||||
.length,
|
.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final status = ref
|
final status = ref
|
||||||
.read(trackStateProvider(
|
.read(trackStateProvider(
|
||||||
track: widget.trackRes)
|
track: widget.trackRes,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.getStatusList()[index];
|
.getStatusList()[index];
|
||||||
|
print(status);
|
||||||
return RadioListTile(
|
return RadioListTile(
|
||||||
dense: true,
|
dense: true,
|
||||||
contentPadding: const EdgeInsets.all(0),
|
contentPadding: const EdgeInsets.all(0),
|
||||||
value: status,
|
value: status,
|
||||||
groupValue: widget.trackRes.status,
|
groupValue: toStatus(
|
||||||
|
widget.trackRes.status,
|
||||||
|
widget.isManga,
|
||||||
|
widget.trackRes.syncId!),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
ref
|
ref
|
||||||
.read(trackStateProvider(
|
.read(trackStateProvider(
|
||||||
track: widget.trackRes
|
track: widget.trackRes
|
||||||
..status = status)
|
..status = status,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.updateManga();
|
.updateManga();
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
|
@ -189,7 +203,11 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}, text: getTrackStatus(widget.trackRes.status, context)),
|
},
|
||||||
|
text: getTrackStatus(
|
||||||
|
toStatus(widget.trackRes.status, widget.isManga,
|
||||||
|
widget.trackRes.syncId!),
|
||||||
|
context)),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _elevatedButton(context, onPressed: () {
|
child: _elevatedButton(context, onPressed: () {
|
||||||
|
|
@ -241,7 +259,8 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
||||||
.read(trackStateProvider(
|
.read(trackStateProvider(
|
||||||
track: widget.trackRes
|
track: widget.trackRes
|
||||||
..lastChapterRead =
|
..lastChapterRead =
|
||||||
currentIntValue)
|
currentIntValue,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.updateManga();
|
.updateManga();
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
|
@ -282,19 +301,22 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
||||||
minValue: 0,
|
minValue: 0,
|
||||||
maxValue: ref
|
maxValue: ref
|
||||||
.read(trackStateProvider(
|
.read(trackStateProvider(
|
||||||
track: widget.trackRes)
|
track: widget.trackRes,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.getScoreMaxValue(),
|
.getScoreMaxValue(),
|
||||||
textMapper: (numberText) {
|
textMapper: (numberText) {
|
||||||
return ref
|
return ref
|
||||||
.read(trackStateProvider(
|
.read(trackStateProvider(
|
||||||
track: widget.trackRes)
|
track: widget.trackRes,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.getTextMapper(numberText);
|
.getTextMapper(numberText);
|
||||||
},
|
},
|
||||||
step: ref
|
step: ref
|
||||||
.read(trackStateProvider(
|
.read(trackStateProvider(
|
||||||
track: widget.trackRes)
|
track: widget.trackRes,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.getScoreStep(),
|
.getScoreStep(),
|
||||||
haptics: true,
|
haptics: true,
|
||||||
|
|
@ -323,7 +345,8 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
||||||
ref
|
ref
|
||||||
.read(trackStateProvider(
|
.read(trackStateProvider(
|
||||||
track: widget.trackRes
|
track: widget.trackRes
|
||||||
..score = currentIntValue)
|
..score = currentIntValue,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.updateManga();
|
.updateManga();
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
|
@ -341,7 +364,9 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
||||||
},
|
},
|
||||||
text: widget.trackRes.score != 0
|
text: widget.trackRes.score != 0
|
||||||
? ref
|
? ref
|
||||||
.read(trackStateProvider(track: widget.trackRes)
|
.read(trackStateProvider(
|
||||||
|
track: widget.trackRes,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.displayScore(widget.trackRes.score!)
|
.displayScore(widget.trackRes.score!)
|
||||||
: l10n!.score),
|
: l10n!.score),
|
||||||
|
|
@ -366,7 +391,8 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
||||||
.read(trackStateProvider(
|
.read(trackStateProvider(
|
||||||
track: widget.trackRes
|
track: widget.trackRes
|
||||||
..startedReadingDate =
|
..startedReadingDate =
|
||||||
newDate.millisecondsSinceEpoch)
|
newDate.millisecondsSinceEpoch,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.updateManga();
|
.updateManga();
|
||||||
},
|
},
|
||||||
|
|
@ -396,7 +422,8 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
||||||
.read(trackStateProvider(
|
.read(trackStateProvider(
|
||||||
track: widget.trackRes
|
track: widget.trackRes
|
||||||
..finishedReadingDate =
|
..finishedReadingDate =
|
||||||
newDate.millisecondsSinceEpoch)
|
newDate.millisecondsSinceEpoch,
|
||||||
|
isManga: widget.isManga)
|
||||||
.notifier)
|
.notifier)
|
||||||
.updateManga();
|
.updateManga();
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -134,4 +134,5 @@ class ConvertToCBZProvider extends AutoDisposeFutureProvider<List<String>> {
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,7 @@ Future<List<String>> downloadChapter(
|
||||||
bool onlyOnWifi = useWifi ?? ref.watch(onlyOnWifiStateProvider);
|
bool onlyOnWifi = useWifi ?? ref.watch(onlyOnWifiStateProvider);
|
||||||
Directory? path;
|
Directory? path;
|
||||||
final getDownloadLocation = ref.watch(downloadLocationStateProvider).$2;
|
final getDownloadLocation = ref.watch(downloadLocationStateProvider).$2;
|
||||||
final desktopCustomDownloadLocation =
|
final customDownloadLocation = getDownloadLocation.isNotEmpty;
|
||||||
Platform.isWindows && getDownloadLocation.isNotEmpty;
|
|
||||||
bool isOk = false;
|
bool isOk = false;
|
||||||
final manga = chapter.manga.value!;
|
final manga = chapter.manga.value!;
|
||||||
final path1 = await storageProvider.getDirectory();
|
final path1 = await storageProvider.getDirectory();
|
||||||
|
|
@ -99,10 +98,9 @@ Future<List<String>> downloadChapter(
|
||||||
headersProvider(source: manga.source!, lang: manga.lang!)),
|
headersProvider(source: manga.source!, lang: manga.lang!)),
|
||||||
url: pageUrls[index].trim().trimLeft().trimRight(),
|
url: pageUrls[index].trim().trimLeft().trimRight(),
|
||||||
filename: "${padIndex(index + 1)}.jpg",
|
filename: "${padIndex(index + 1)}.jpg",
|
||||||
baseDirectory:
|
baseDirectory: customDownloadLocation
|
||||||
Platform.isAndroid || desktopCustomDownloadLocation
|
? BaseDirectory.temporary
|
||||||
? BaseDirectory.temporary
|
: BaseDirectory.applicationDocuments,
|
||||||
: BaseDirectory.applicationDocuments,
|
|
||||||
directory: 'Mangayomi/$finalPath',
|
directory: 'Mangayomi/$finalPath',
|
||||||
updates: Updates.statusAndProgress,
|
updates: Updates.statusAndProgress,
|
||||||
allowPause: true,
|
allowPause: true,
|
||||||
|
|
@ -119,10 +117,9 @@ Future<List<String>> downloadChapter(
|
||||||
headersProvider(source: manga.source!, lang: manga.lang!)),
|
headersProvider(source: manga.source!, lang: manga.lang!)),
|
||||||
url: pageUrls[index].trim().trimLeft().trimRight(),
|
url: pageUrls[index].trim().trimLeft().trimRight(),
|
||||||
filename: "${padIndex(index + 1)}.jpg",
|
filename: "${padIndex(index + 1)}.jpg",
|
||||||
baseDirectory:
|
baseDirectory: customDownloadLocation
|
||||||
Platform.isAndroid || desktopCustomDownloadLocation
|
? BaseDirectory.temporary
|
||||||
? BaseDirectory.temporary
|
: BaseDirectory.applicationDocuments,
|
||||||
: BaseDirectory.applicationDocuments,
|
|
||||||
directory: 'Mangayomi/$finalPath',
|
directory: 'Mangayomi/$finalPath',
|
||||||
updates: Updates.statusAndProgress,
|
updates: Updates.statusAndProgress,
|
||||||
allowPause: true,
|
allowPause: true,
|
||||||
|
|
@ -188,7 +185,7 @@ Future<List<String>> downloadChapter(
|
||||||
},
|
},
|
||||||
taskProgressCallback: (taskProgress) async {
|
taskProgressCallback: (taskProgress) async {
|
||||||
if (taskProgress.progress == 1.0) {
|
if (taskProgress.progress == 1.0) {
|
||||||
if (Platform.isAndroid || desktopCustomDownloadLocation) {
|
if (customDownloadLocation) {
|
||||||
await File(
|
await File(
|
||||||
"${tempDir.path}/${taskProgress.task.directory}/${taskProgress.task.filename}")
|
"${tempDir.path}/${taskProgress.task.directory}/${taskProgress.task.filename}")
|
||||||
.copy("${path!.path}/${taskProgress.task.filename}");
|
.copy("${path!.path}/${taskProgress.task.filename}");
|
||||||
|
|
|
||||||
|
|
@ -118,4 +118,5 @@ class DownloadChapterProvider extends AutoDisposeFutureProvider<List<String>> {
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -390,6 +390,7 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
||||||
return buildProgressIndicator();
|
return buildProgressIndicator();
|
||||||
}
|
}
|
||||||
return MangaHomeImageCard(
|
return MangaHomeImageCard(
|
||||||
|
isManga: widget.source.isManga ?? true,
|
||||||
manga: data[index]!,
|
manga: data[index]!,
|
||||||
source: widget.source,
|
source: widget.source,
|
||||||
);
|
);
|
||||||
|
|
@ -409,11 +410,13 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
||||||
|
|
||||||
class MangaHomeImageCard extends ConsumerStatefulWidget {
|
class MangaHomeImageCard extends ConsumerStatefulWidget {
|
||||||
final MangaModel manga;
|
final MangaModel manga;
|
||||||
|
final bool isManga;
|
||||||
final Source source;
|
final Source source;
|
||||||
const MangaHomeImageCard({
|
const MangaHomeImageCard({
|
||||||
super.key,
|
super.key,
|
||||||
required this.manga,
|
required this.manga,
|
||||||
required this.source,
|
required this.source,
|
||||||
|
required this.isManga,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -431,6 +434,7 @@ class _MangaHomeImageCardState extends ConsumerState<MangaHomeImageCard>
|
||||||
..lang = widget.source.lang
|
..lang = widget.source.lang
|
||||||
..source = widget.source.name,
|
..source = widget.source.name,
|
||||||
lang: widget.source.lang!,
|
lang: widget.source.lang!,
|
||||||
|
isManga: widget.isManga,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ class SearchResultScreen extends ConsumerWidget {
|
||||||
return MangaHomeImageCard(
|
return MangaHomeImageCard(
|
||||||
manga: data[index]!,
|
manga: data[index]!,
|
||||||
source: source,
|
source: source,
|
||||||
|
isManga: source.isManga ?? true,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -86,86 +86,86 @@ class CropBorderClass {
|
||||||
|
|
||||||
void _autocropImageIsolate(CropBorderClass cropData) async {
|
void _autocropImageIsolate(CropBorderClass cropData) async {
|
||||||
Image? croppedImage;
|
Image? croppedImage;
|
||||||
Image? image = decodeImage(cropData.image!);
|
// // Image? image = decodeImage(cropData.image!);
|
||||||
final old = image;
|
// // final old = image;
|
||||||
image = copyCrop(image!, 0, 0, image.width, image.height);
|
// // image = copyCrop(image!, 0, 0, image.width, image.height);
|
||||||
|
|
||||||
int left = 0;
|
// // int left = 0;
|
||||||
int top = 0;
|
// // int top = 0;
|
||||||
int right = image.width - 1;
|
// // int right = image.width - 1;
|
||||||
int bottom = image.height - 1;
|
// // int bottom = image.height - 1;
|
||||||
|
|
||||||
// Find left coordinate
|
// // // Find left coordinate
|
||||||
for (int x = 0; x < image.width; x++) {
|
// // for (int x = 0; x < image.width; x++) {
|
||||||
bool stop = false;
|
// // bool stop = false;
|
||||||
for (int y = 0; y < image.height; y++) {
|
// // for (int y = 0; y < image.height; y++) {
|
||||||
if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
// // if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
||||||
stop = true;
|
// // stop = true;
|
||||||
break;
|
// // break;
|
||||||
}
|
// // }
|
||||||
}
|
// // }
|
||||||
if (stop) {
|
// // if (stop) {
|
||||||
left = x;
|
// // left = x;
|
||||||
break;
|
// // break;
|
||||||
}
|
// // }
|
||||||
}
|
// // }
|
||||||
|
|
||||||
// Find top coordinate
|
// // // Find top coordinate
|
||||||
for (int y = 0; y < image.height; y++) {
|
// // for (int y = 0; y < image.height; y++) {
|
||||||
bool stop = false;
|
// // bool stop = false;
|
||||||
for (int x = 0; x < image.width; x++) {
|
// // for (int x = 0; x < image.width; x++) {
|
||||||
if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
// // if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
||||||
stop = true;
|
// // stop = true;
|
||||||
break;
|
// // break;
|
||||||
}
|
// // }
|
||||||
}
|
// // }
|
||||||
if (stop) {
|
// // if (stop) {
|
||||||
top = y;
|
// // top = y;
|
||||||
break;
|
// // break;
|
||||||
}
|
// // }
|
||||||
}
|
// // }
|
||||||
|
|
||||||
// Find right coordinate
|
// // // Find right coordinate
|
||||||
for (int x = image.width - 1; x >= 0; x--) {
|
// // for (int x = image.width - 1; x >= 0; x--) {
|
||||||
bool stop = false;
|
// // bool stop = false;
|
||||||
for (int y = 0; y < image.height; y++) {
|
// // for (int y = 0; y < image.height; y++) {
|
||||||
if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
// // if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
||||||
stop = true;
|
// // stop = true;
|
||||||
break;
|
// // break;
|
||||||
}
|
// // }
|
||||||
}
|
// // }
|
||||||
if (stop) {
|
// // if (stop) {
|
||||||
right = x;
|
// // right = x;
|
||||||
break;
|
// // break;
|
||||||
}
|
// // }
|
||||||
}
|
// // }
|
||||||
|
|
||||||
// Find bottom coordinate
|
// // // Find bottom coordinate
|
||||||
for (int y = image.height - 1; y >= 0; y--) {
|
// // for (int y = image.height - 1; y >= 0; y--) {
|
||||||
bool stop = false;
|
// // bool stop = false;
|
||||||
for (int x = 0; x < image.width; x++) {
|
// // for (int x = 0; x < image.width; x++) {
|
||||||
if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
// // if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
||||||
stop = true;
|
// // stop = true;
|
||||||
break;
|
// // break;
|
||||||
}
|
// // }
|
||||||
}
|
// // }
|
||||||
if (stop) {
|
// // if (stop) {
|
||||||
bottom = y;
|
// // bottom = y;
|
||||||
break;
|
// // break;
|
||||||
}
|
// // }
|
||||||
}
|
// // }
|
||||||
|
|
||||||
// Crop the image
|
// // // Crop the image
|
||||||
croppedImage = copyCrop(
|
// // croppedImage = copyCrop(
|
||||||
image,
|
// // image,
|
||||||
left,
|
// // left,
|
||||||
top,
|
// // top,
|
||||||
right - left + 1,
|
// // right - left + 1,
|
||||||
bottom - top + 1,
|
// // bottom - top + 1,
|
||||||
);
|
// // );
|
||||||
if (old != croppedImage) {
|
// if (old != croppedImage) {
|
||||||
cropData.sendPort.send(encodeJpg(croppedImage) as Uint8List);
|
// cropData.sendPort.send(encodeJpg(croppedImage) as Uint8List);
|
||||||
} else {
|
// } else {
|
||||||
cropData.sendPort.send(null);
|
// cropData.sendPort.send(null);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,4 +135,5 @@ class AutoCropBorderProvider
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,14 @@ pushMangaReaderView({
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required Chapter chapter,
|
required Chapter chapter,
|
||||||
}) {
|
}) {
|
||||||
context.push('/mangareaderview', extra: chapter);
|
print(chapter.manga.value!.isManga!);
|
||||||
|
if (chapter.manga.value!.isManga!) {
|
||||||
|
print("aaz");
|
||||||
|
context.pushReplacement('/mangareaderview', extra: chapter);
|
||||||
|
} else {
|
||||||
|
print("object");
|
||||||
|
context.push('/animestreamview', extra: chapter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pushReplacementMangaReaderView({
|
pushReplacementMangaReaderView({
|
||||||
|
|
|
||||||
|
|
@ -122,4 +122,5 @@ class CurrentIndexProvider
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member
|
||||||
|
|
|
||||||
|
|
@ -2,28 +2,82 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:mangayomi/main.dart';
|
import 'package:mangayomi/main.dart';
|
||||||
import 'package:mangayomi/models/category.dart';
|
import 'package:mangayomi/models/category.dart';
|
||||||
import 'package:mangayomi/modules/more/categoties/providers/isar_providers.dart';
|
import 'package:mangayomi/modules/more/categories/providers/isar_providers.dart';
|
||||||
import 'package:mangayomi/modules/more/categoties/widgets/custom_textfield.dart';
|
import 'package:mangayomi/modules/more/categories/widgets/custom_textfield.dart';
|
||||||
import 'package:mangayomi/modules/widgets/progress_center.dart';
|
import 'package:mangayomi/modules/widgets/progress_center.dart';
|
||||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||||
|
|
||||||
class CategoriesScreen extends ConsumerStatefulWidget {
|
class CategoriesScreen extends ConsumerStatefulWidget {
|
||||||
const CategoriesScreen({super.key});
|
final (bool, int) data;
|
||||||
|
const CategoriesScreen({required this.data, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<CategoriesScreen> createState() => _CategoriesScreenState();
|
ConsumerState<CategoriesScreen> createState() => _CategoriesScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CategoriesScreenState extends ConsumerState<CategoriesScreen> {
|
class _CategoriesScreenState extends ConsumerState<CategoriesScreen>
|
||||||
|
with TickerProviderStateMixin {
|
||||||
|
late TabController _tabBarController;
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_tabBarController = TabController(length: 2, vsync: this);
|
||||||
|
_tabBarController.animateTo(widget.data.$2);
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final l10n = l10nLocalizations(context)!;
|
||||||
|
return DefaultTabController(
|
||||||
|
animationDuration: Duration.zero,
|
||||||
|
length: 2,
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
elevation: 0,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
title: Text(
|
||||||
|
widget.data.$1 ? l10n.edit_categories : l10n.categories,
|
||||||
|
style: TextStyle(color: Theme.of(context).hintColor),
|
||||||
|
),
|
||||||
|
bottom: TabBar(
|
||||||
|
indicatorSize: TabBarIndicatorSize.tab,
|
||||||
|
controller: _tabBarController,
|
||||||
|
tabs: [
|
||||||
|
Tab(text: l10n.manga),
|
||||||
|
Tab(text: l10n.anime),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: TabBarView(controller: _tabBarController, children: const [
|
||||||
|
CategoriesTab(
|
||||||
|
isManga: true,
|
||||||
|
),
|
||||||
|
CategoriesTab(
|
||||||
|
isManga: false,
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CategoriesTab extends ConsumerStatefulWidget {
|
||||||
|
final bool isManga;
|
||||||
|
const CategoriesTab({required this.isManga, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<CategoriesTab> createState() => _CategoriesTabState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CategoriesTabState extends ConsumerState<CategoriesTab> {
|
||||||
List<Category> _entries = [];
|
List<Category> _entries = [];
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final l10n = l10nLocalizations(context);
|
final l10n = l10nLocalizations(context)!;
|
||||||
final categories = ref.watch(getMangaCategorieStreamProvider);
|
final categories =
|
||||||
|
ref.watch(getMangaCategorieStreamProvider(isManga: widget.isManga));
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
|
||||||
title: Text(l10n!.edit_categories),
|
|
||||||
),
|
|
||||||
body: categories.when(
|
body: categories.when(
|
||||||
data: (data) {
|
data: (data) {
|
||||||
if (data.isEmpty) {
|
if (data.isEmpty) {
|
||||||
|
|
@ -215,6 +269,7 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen> {
|
||||||
: () async {
|
: () async {
|
||||||
await isar.writeTxn(() async {
|
await isar.writeTxn(() async {
|
||||||
await isar.categorys.put(Category(
|
await isar.categorys.put(Category(
|
||||||
|
forManga: widget.isManga,
|
||||||
name: controller.text,
|
name: controller.text,
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
@ -5,11 +5,12 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
part 'isar_providers.g.dart';
|
part 'isar_providers.g.dart';
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Stream<List<Category>> getMangaCategorieStream(
|
Stream<List<Category>> getMangaCategorieStream(GetMangaCategorieStreamRef ref,
|
||||||
GetMangaCategorieStreamRef ref,
|
{required bool isManga}) async* {
|
||||||
) async* {
|
|
||||||
yield* isar.categorys
|
yield* isar.categorys
|
||||||
.filter()
|
.filter()
|
||||||
.idIsNotNull()
|
.idIsNotNull()
|
||||||
|
.and()
|
||||||
|
.forMangaEqualTo(isManga)
|
||||||
.watch(fireImmediately: true);
|
.watch(fireImmediately: true);
|
||||||
}
|
}
|
||||||