Compare commits

...

15 Commits

Author SHA1 Message Date
Jobobby04 2f9cba87b5 Release v1.9.4 2023-10-29 18:45:34 -04:00
Jobobby04 6ba8318b8a Fix page previews cache
(cherry picked from commit d600ddc11a)

# Conflicts:
#	app/build.gradle.kts
#	app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt
#	app/src/main/java/exh/EXHMigrations.kt
#	app/src/main/java/exh/debug/DebugFunctions.kt
2023-10-29 18:44:01 -04:00
Jobobby04 7565e51f95 Fix page previews after E-H update
(cherry picked from commit d45563e58d)
2023-10-29 18:26:42 -04:00
Jobobby04 230aec370c Fix import of reader preferences in reader
(cherry picked from commit 90281affc4)
2023-10-29 18:26:35 -04:00
Jobobby04 0d894d5977 Fix crash on Chinese
(cherry picked from commit 729e13cc1a)
2023-10-29 18:26:24 -04:00
Luqman 099758f02d Fix Mangadex recommendation (#951)
* Fix Md recs

Disable Md recs if delegated setting is disabled

* Revert "Fix Md recs"

This reverts commit 7dbfa662be2665aa97664720df42e2562bc4adb0.

* Rerun

This reverts commit 971315278b92bcabfbf6b5610cb1c63e281bc172.

(cherry picked from commit 6baa24273a)
2023-10-29 18:25:43 -04:00
AntsyLich e0480ce8c3 pain (#968)
(cherry picked from commit 8fc04d8cc6)
2023-10-29 18:25:23 -04:00
Jobobby04 4cab34e06c Use readableAt
(cherry picked from commit d37463cf0f)
2023-10-29 18:23:41 -04:00
arkon 3aefee3ce0 Update website links
(cherry picked from commit ccc9a5a052b133174f8ba361490386ff0361283e)
(cherry picked from commit bc5ba6092b)

# Conflicts:
#	CONTRIBUTING.md
#	app/src/main/java/eu/kanade/presentation/more/MoreScreen.kt
#	app/src/main/java/eu/kanade/presentation/more/settings/screen/AboutScreen.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateNotifier.kt
#	app/src/main/java/eu/kanade/tachiyomi/source/LocalSource.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreenModel.kt
2023-10-29 18:22:46 -04:00
arkon f645440c12 Update default user agent string
(cherry picked from commit 092d930175e7a9a6e1bb73f8d97948903db06d67)
(cherry picked from commit f25b70cdef)

# Conflicts:
#	core/src/main/java/eu/kanade/tachiyomi/network/NetworkPreferences.kt
2023-10-29 18:20:37 -04:00
arkon 72ac3c275c Avoid opening blobs as webpages
Fixes #10060

(cherry picked from commit 548f7f415a28529522f5aef0d53546e8bc68957e)
(cherry picked from commit 7ccb8eaaf2)

# Conflicts:
#	app/src/main/java/eu/kanade/presentation/webview/WebViewScreenContent.kt
2023-10-29 18:19:32 -04:00
Vlasov Roman d14cf0ccea Change Shikimori domain from ".me" to ".one" (#10027)
(cherry picked from commit 8f3681d79f1624a092e5c356c9459897f4220c29)
(cherry picked from commit 2ba5460096)
2023-10-29 18:17:25 -04:00
arkon c2963709cd Use consistent extension icon URLs
Better caching between versions.

(cherry picked from commit 30f845139d76762798e2cdec7804a38806c3eeca)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt
(cherry picked from commit 01e0c3c040)
2023-10-29 18:17:06 -04:00
Jobobby04 18d3615e6f Release v1.9.3 2023-04-18 17:30:00 -04:00
Jobobby04 326489fef3 Fix crash with restoring backups 2023-04-18 16:59:22 -04:00
30 changed files with 171 additions and 98 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
I acknowledge that: I acknowledge that:
- I have updated: - I have updated:
- To the latest version of the app (stable is v1.9.2) - To the latest version of the app (stable is v1.9.4)
- All extensions - All extensions
- I have tried the troubleshooting guide: https://tachiyomi.org/help/guides/troubleshooting-problems/ - I have tried the troubleshooting guide: https://tachiyomi.org/help/guides/troubleshooting-problems/
- If this is an issue with an extension, that I should be opening an issue in https://github.com/tachiyomiorg/tachiyomi-extensions - If this is an issue with an extension, that I should be opening an issue in https://github.com/tachiyomiorg/tachiyomi-extensions
+2 -2
View File
@@ -53,7 +53,7 @@ body:
label: Tachiyomi version label: Tachiyomi version
description: You can find your Tachiyomi version in **More → About**. description: You can find your Tachiyomi version in **More → About**.
placeholder: | placeholder: |
Example: "1.9.2" Example: "1.9.4"
validations: validations:
required: true required: true
@@ -100,7 +100,7 @@ body:
required: true required: true
- label: I have tried the [troubleshooting guide](https://tachiyomi.org/help/guides/troubleshooting/). - label: I have tried the [troubleshooting guide](https://tachiyomi.org/help/guides/troubleshooting/).
required: true required: true
- label: I have updated the app to version **[1.9.2](https://github.com/jobobby04/tachiyomisy/releases/latest)**. - label: I have updated the app to version **[1.9.4](https://github.com/jobobby04/tachiyomisy/releases/latest)**.
required: true required: true
- label: I have updated all installed extensions. - label: I have updated all installed extensions.
required: true required: true
+1 -1
View File
@@ -33,7 +33,7 @@ body:
required: true required: true
- label: If this is an issue with an extension, I should be opening an issue in the [extensions repository](https://github.com/tachiyomiorg/tachiyomi-extensions/issues/new/choose). - label: If this is an issue with an extension, I should be opening an issue in the [extensions repository](https://github.com/tachiyomiorg/tachiyomi-extensions/issues/new/choose).
required: true required: true
- label: I have updated the app to version **[1.9.2](https://github.com/jobobby04/tachiyomisy/releases/latest)**. - label: I have updated the app to version **[1.9.4](https://github.com/jobobby04/tachiyomisy/releases/latest)**.
required: true required: true
- label: I will fill out all of the requested information in this form. - label: I will fill out all of the requested information in this form.
required: true required: true
+1 -1
View File
@@ -30,7 +30,7 @@ Before you start, please note that the ability to use following technologies is
# Translations # Translations
Translations are done externally via Weblate. See [our website](https://tachiyomi.org/help/contribution/#translation) for more details. Translations are done externally via Weblate. See [our website](https://tachiyomi.org/docs/contribute#translation) for more details.
# Forks # Forks
+2 -2
View File
@@ -26,8 +26,8 @@ android {
defaultConfig { defaultConfig {
applicationId = "eu.kanade.tachiyomi.sy" applicationId = "eu.kanade.tachiyomi.sy"
versionCode = 49 versionCode = 51
versionName = "1.9.2" versionName = "1.9.4"
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"") buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"") buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")
@@ -171,7 +171,7 @@ fun BrowseSourceEHentaiListItem(
drawRect(overlayColor) drawRect(overlayColor)
} }
}, },
data = manga.thumbnailUrl, data = manga,
) )
if (manga.favorite) { if (manga.favorite) {
BadgeGroup( BadgeGroup(
@@ -72,7 +72,7 @@ fun MoreScreen(
WarningBanner( WarningBanner(
textRes = R.string.fdroid_warning, textRes = R.string.fdroid_warning,
modifier = Modifier.clickable { modifier = Modifier.clickable {
uriHandler.openUri("https://tachiyomi.org/help/faq/#how-do-i-migrate-from-the-f-droid-version") uriHandler.openUri("https://tachiyomi.org/docs/faq/general#how-do-i-update-from-the-f-droid-builds")
}, },
) )
} }
@@ -129,7 +129,7 @@ object AboutScreen : Screen {
item { item {
TextPreferenceWidget( TextPreferenceWidget(
title = stringResource(R.string.help_translate), title = stringResource(R.string.help_translate),
onPreferenceClick = { uriHandler.openUri("https://tachiyomi.org/help/contribution/#translation") }, onPreferenceClick = { uriHandler.openUri("https://tachiyomi.org/docs/contribute#translation") },
) )
} }
@@ -143,7 +143,7 @@ object AboutScreen : Screen {
item { item {
TextPreferenceWidget( TextPreferenceWidget(
title = stringResource(R.string.privacy_policy), title = stringResource(R.string.privacy_policy),
onPreferenceClick = { uriHandler.openUri("https://tachiyomi.org/privacy") }, onPreferenceClick = { uriHandler.openUri("https://tachiyomi.org/privacy/") },
) )
} }
@@ -124,6 +124,12 @@ fun WebViewScreenContent(
request: WebResourceRequest?, request: WebResourceRequest?,
): Boolean { ): Boolean {
request?.let { request?.let {
// Don't attempt to open blobs as webpages
if (it.url.toString().startsWith("blob:http")) {
return false
}
// Continue with request, but with custom headers
view?.loadUrl(it.url.toString(), headers) view?.loadUrl(it.url.toString(), headers)
} }
return super.shouldOverrideUrlLoading(view, request) return super.shouldOverrideUrlLoading(view, request)
@@ -9,9 +9,11 @@ import eu.kanade.tachiyomi.util.storage.saveTo
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.Response import logcat.LogPriority
import okio.Source
import okio.buffer import okio.buffer
import okio.sink import okio.sink
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File
@@ -159,7 +161,7 @@ class PagePreviewCache(private val context: Context) {
* @throws IOException page error. * @throws IOException page error.
*/ */
@Throws(IOException::class) @Throws(IOException::class)
fun putImageToCache(imageUrl: String, response: Response) { fun putImageToCache(imageUrl: String, source: Source) {
// Initialize editor (edits the values for an entry). // Initialize editor (edits the values for an entry).
var editor: DiskLruCache.Editor? = null var editor: DiskLruCache.Editor? = null
@@ -169,12 +171,12 @@ class PagePreviewCache(private val context: Context) {
editor = diskCache.edit(key) ?: throw IOException("Unable to edit key") editor = diskCache.edit(key) ?: throw IOException("Unable to edit key")
// Get OutputStream and write page with Okio. // Get OutputStream and write page with Okio.
response.body.source().saveTo(editor.newOutputStream(0)) source.buffer().saveTo(editor.newOutputStream(0))
diskCache.flush() diskCache.flush()
editor.commit() editor.commit()
} finally { } finally {
response.body.close() source.close()
editor?.abortUnlessCommitted() editor?.abortUnlessCommitted()
} }
} }
@@ -207,6 +209,7 @@ class PagePreviewCache(private val context: Context) {
// Remove file from cache. // Remove file from cache.
diskCache.remove(key) diskCache.remove(key)
} catch (e: Exception) { } catch (e: Exception) {
logcat(LogPriority.WARN, e) { "Failed to remove file from cache" }
false false
} }
} }
@@ -24,8 +24,6 @@ import okhttp3.Response
import okhttp3.internal.http.HTTP_NOT_MODIFIED import okhttp3.internal.http.HTTP_NOT_MODIFIED
import okio.Path.Companion.toOkioPath import okio.Path.Companion.toOkioPath
import okio.Source import okio.Source
import okio.buffer
import okio.sink
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File
@@ -39,7 +37,9 @@ import java.io.File
class PagePreviewFetcher( class PagePreviewFetcher(
private val page: PagePreview, private val page: PagePreview,
private val options: Options, private val options: Options,
private val pagePreviewFileLazy: Lazy<File>, private val pagePreviewFile: () -> File,
private val isInCache: () -> Boolean,
private val writeToCache: (Source) -> Unit,
private val diskCacheKeyLazy: Lazy<String>, private val diskCacheKeyLazy: Lazy<String>,
private val sourceLazy: Lazy<PagePreviewSource?>, private val sourceLazy: Lazy<PagePreviewSource?>,
private val callFactoryLazy: Lazy<Call.Factory>, private val callFactoryLazy: Lazy<Call.Factory>,
@@ -62,14 +62,14 @@ class PagePreviewFetcher(
} }
private suspend fun httpLoader(): FetchResult { private suspend fun httpLoader(): FetchResult {
if (pagePreviewFileLazy.value.exists() && options.diskCachePolicy.readEnabled) { if (isInCache() && options.diskCachePolicy.readEnabled) {
return fileLoader(pagePreviewFileLazy.value) return fileLoader(pagePreviewFile())
} }
var snapshot = readFromDiskCache() var snapshot = readFromDiskCache()
try { try {
// Fetch from disk cache // Fetch from disk cache
if (snapshot != null) { if (snapshot != null) {
val snapshotPagePreviewCache = moveSnapshotToPagePreviewCache(snapshot, pagePreviewFileLazy.value) val snapshotPagePreviewCache = moveSnapshotToPagePreviewCache(snapshot)
if (snapshotPagePreviewCache != null) { if (snapshotPagePreviewCache != null) {
// Read from page preview cache // Read from page preview cache
return fileLoader(snapshotPagePreviewCache) return fileLoader(snapshotPagePreviewCache)
@@ -88,7 +88,7 @@ class PagePreviewFetcher(
val responseBody = checkNotNull(response.body) { "Null response source" } val responseBody = checkNotNull(response.body) { "Null response source" }
try { try {
// Read from page preview cache after page preview updated // Read from page preview cache after page preview updated
val responsePagePreviewCache = writeResponseToPagePreviewCache(response, pagePreviewFileLazy.value) val responsePagePreviewCache = writeResponseToPagePreviewCache(response)
if (responsePagePreviewCache != null) { if (responsePagePreviewCache != null) {
return fileLoader(responsePagePreviewCache) return fileLoader(responsePagePreviewCache)
} }
@@ -153,45 +153,44 @@ class PagePreviewFetcher(
return request.build() return request.build()
} }
private fun moveSnapshotToPagePreviewCache(snapshot: DiskCache.Snapshot, cacheFile: File): File? { private fun moveSnapshotToPagePreviewCache(snapshot: DiskCache.Snapshot): File? {
return try { return try {
diskCacheLazy.value.run { diskCacheLazy.value.run {
fileSystem.source(snapshot.data).use { input -> fileSystem.source(snapshot.data).use { input ->
writeSourceToPagePreviewCache(input, cacheFile) writeSourceToPagePreviewCache(input)
} }
remove(diskCacheKey) remove(diskCacheKey)
} }
cacheFile.takeIf { it.exists() } return if (isInCache()) {
pagePreviewFile()
} else {
null
}
} catch (e: Exception) { } catch (e: Exception) {
logcat(LogPriority.ERROR, e) { "Failed to write snapshot data to page preview cache ${cacheFile.name}" } logcat(LogPriority.ERROR, e) { "Failed to write snapshot data to page preview cache $diskCacheKey" }
null null
} }
} }
private fun writeResponseToPagePreviewCache(response: Response, cacheFile: File): File? { private fun writeResponseToPagePreviewCache(response: Response): File? {
if (!options.diskCachePolicy.writeEnabled) return null if (!options.diskCachePolicy.writeEnabled) return null
return try { return try {
response.peekBody(Long.MAX_VALUE).source().use { input -> response.peekBody(Long.MAX_VALUE).source().use { input ->
writeSourceToPagePreviewCache(input, cacheFile) writeSourceToPagePreviewCache(input)
}
return if (isInCache()) {
pagePreviewFile()
} else {
null
} }
cacheFile.takeIf { it.exists() }
} catch (e: Exception) { } catch (e: Exception) {
logcat(LogPriority.ERROR, e) { "Failed to write response data to page preview cache ${cacheFile.name}" } logcat(LogPriority.ERROR, e) { "Failed to write response data to page preview cache $diskCacheKey" }
null null
} }
} }
private fun writeSourceToPagePreviewCache(input: Source, cacheFile: File) { private fun writeSourceToPagePreviewCache(input: Source) {
cacheFile.parentFile?.mkdirs() writeToCache(input)
cacheFile.delete()
try {
cacheFile.sink().buffer().use { output ->
output.writeAll(input)
}
} catch (e: Exception) {
cacheFile.delete()
throw e
}
} }
private fun readFromDiskCache(): DiskCache.Snapshot? { private fun readFromDiskCache(): DiskCache.Snapshot? {
@@ -232,7 +231,9 @@ class PagePreviewFetcher(
return PagePreviewFetcher( return PagePreviewFetcher(
page = data, page = data,
options = options, options = options,
pagePreviewFileLazy = lazy { pagePreviewCache.getImageFile(data.imageUrl) }, pagePreviewFile = { pagePreviewCache.getImageFile(data.imageUrl) },
isInCache = { pagePreviewCache.isImageInCache(data.imageUrl) },
writeToCache = { pagePreviewCache.putImageToCache(data.imageUrl, it) },
diskCacheKeyLazy = lazy { PagePreviewKeyer().key(data, options) }, diskCacheKeyLazy = lazy { PagePreviewKeyer().key(data, options) },
sourceLazy = lazy { sourceManager.get(data.source) as? PagePreviewSource }, sourceLazy = lazy { sourceManager.get(data.source) as? PagePreviewSource },
callFactoryLazy = callFactoryLazy, callFactoryLazy = callFactoryLazy,
@@ -19,7 +19,7 @@ open class MangaImpl : Manga {
// SY --> // SY -->
private val customManga: CustomMangaInfo? private val customManga: CustomMangaInfo?
get() = getCustomMangaInfo.get(id!!) get() = id?.let { getCustomMangaInfo.get(it) }
override var title: String override var title: String
get() = if (favorite) { get() = if (favorite) {
@@ -340,11 +340,11 @@ class LibraryUpdateNotifier(private val context: Context) {
} }
companion object { companion object {
const val HELP_WARNING_URL = "https://tachiyomi.org/help/faq/#why-does-the-app-warn-about-large-bulk-updates-and-downloads" const val HELP_WARNING_URL = "https://tachiyomi.org/docs/faq/library#why-am-i-warned-about-large-bulk-updates-and-downloads"
} }
} }
private const val NOTIF_MAX_CHAPTERS = 5 private const val NOTIF_MAX_CHAPTERS = 5
private const val NOTIF_TITLE_MAX_LEN = 45 private const val NOTIF_TITLE_MAX_LEN = 45
private const val NOTIF_ICON_SIZE = 192 private const val NOTIF_ICON_SIZE = 192
private const val HELP_SKIPPED_URL = "https://tachiyomi.org/help/faq/#why-does-global-update-skip-some-entries" private const val HELP_SKIPPED_URL = "https://tachiyomi.org/docs/faq/library#why-is-global-update-skipping-entries"
@@ -158,7 +158,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
private const val clientId = "1aaf4cf232372708e98b5abc813d795b539c5a916dbbfe9ac61bf02a360832cc" private const val clientId = "1aaf4cf232372708e98b5abc813d795b539c5a916dbbfe9ac61bf02a360832cc"
private const val clientSecret = "229942c742dd4cde803125d17d64501d91c0b12e14cb1e5120184d77d67024c0" private const val clientSecret = "229942c742dd4cde803125d17d64501d91c0b12e14cb1e5120184d77d67024c0"
private const val baseUrl = "https://shikimori.me" private const val baseUrl = "https://shikimori.one"
private const val apiUrl = "$baseUrl/api" private const val apiUrl = "$baseUrl/api"
private const val oauthUrl = "$baseUrl/oauth/token" private const val oauthUrl = "$baseUrl/oauth/token"
private const val loginUrl = "$baseUrl/oauth/authorize" private const val loginUrl = "$baseUrl/oauth/authorize"
@@ -138,7 +138,7 @@ internal class AppUpdateNotifier(private val context: Context) {
setContentTitle(context.getString(R.string.update_check_notification_update_available)) setContentTitle(context.getString(R.string.update_check_notification_update_available))
setContentText(context.getString(R.string.update_check_fdroid_migration_info)) setContentText(context.getString(R.string.update_check_fdroid_migration_info))
setSmallIcon(R.drawable.ic_tachi) setSmallIcon(R.drawable.ic_tachi)
setContentIntent(NotificationHandler.openUrl(context, "https://tachiyomi.org/help/faq/#how-do-i-migrate-from-the-f-droid-version")) setContentIntent(NotificationHandler.openUrl(context, "https://tachiyomi.org/docs/faq/general#how-do-i-update-from-the-f-droid-builds"))
} }
notificationBuilder.show(Notifications.ID_APP_UPDATE_PROMPT) notificationBuilder.show(Notifications.ID_APP_UPDATE_PROMPT)
} }
@@ -151,7 +151,7 @@ internal class ExtensionGithubApi {
hasChangelog = it.hasChangelog == 1, hasChangelog = it.hasChangelog == 1,
sources = it.sources?.toExtensionSources() ?: emptyList(), sources = it.sources?.toExtensionSources() ?: emptyList(),
apkName = it.apk, apkName = it.apk,
iconUrl = "${/* SY --> */ repoUrl /* SY <-- */}icon/${it.apk.replace(".apk", ".png")}", iconUrl = "${/* SY --> */ repoUrl /* SY <-- */}icon/${it.pkg}.png",
// SY --> // SY -->
repoUrl = repoUrl, repoUrl = repoUrl,
isRepoSource = repoSource, isRepoSource = repoSource,
@@ -410,7 +410,7 @@ class LocalSource(
companion object { companion object {
const val ID = 0L const val ID = 0L
const val HELP_URL = "https://tachiyomi.org/help/guides/local-manga/" const val HELP_URL = "https://tachiyomi.org/docs/guides/local-source/"
private const val DEFAULT_COVER_NAME = "cover.jpg" private const val DEFAULT_COVER_NAME = "cover.jpg"
private val LATEST_THRESHOLD = TimeUnit.MILLISECONDS.convert(7, TimeUnit.DAYS) private val LATEST_THRESHOLD = TimeUnit.MILLISECONDS.convert(7, TimeUnit.DAYS)
@@ -1143,18 +1143,23 @@ class EHentai(
.toString(), .toString(),
), ),
).awaitSuccess().asJsoup() ).awaitSuccess().asJsoup()
val previews = if (doc.selectFirst("div#gdo4 .ths")!!.attr("onClick").contains("inline_set=ts_l")) {
doc.body() val body = doc.body()
.select("#gdt div a") val previews = body
.map { .select("#gdt div div")
PagePreviewInfo(it.text().toInt(), imageUrl = it.select("img").attr("src")) .map {
} val preview = parseNormalPreview(it)
} else { PagePreviewInfo(preview.index, imageUrl = preview.toUrl())
parseNormalPreviewSet(doc) }
.map { preview -> .ifEmpty {
PagePreviewInfo(preview.index, imageUrl = preview.toUrl()) body.select("#gdt div a img")
} .map {
} PagePreviewInfo(
it.attr("alt").toInt(),
imageUrl = it.attr("src"),
)
}
}
return PagePreviewPage( return PagePreviewPage(
page = page, page = page,
@@ -1175,37 +1180,33 @@ class EHentai(
/** /**
* Parse normal previews with regular expressions * Parse normal previews with regular expressions
*/ */
private fun parseNormalPreviewSet(doc: Document): List<EHentaiThumbnailPreview> { private fun parseNormalPreview(element: Element): EHentaiThumbnailPreview {
return doc.body() val index = element.selectFirst("img")!!.attr("alt").toInt()
.select("#gdt div div") val styles = element.attr("style").split(";").mapNotNull { it.trimOrNull() }
.map { it.selectFirst("img")!!.attr("alt").toInt() to it.attr("style") } val width = styles.first { it.startsWith("width:") }
.map { (index, style) -> .removePrefix("width:")
val styles = style.split(";").mapNotNull { it.trimOrNull() } .removeSuffix("px")
val width = styles.first { it.startsWith("width:") } .toInt()
.removePrefix("width:")
.removeSuffix("px")
.toInt()
val height = styles.first { it.startsWith("height:") } val height = styles.first { it.startsWith("height:") }
.removePrefix("height:") .removePrefix("height:")
.removeSuffix("px") .removeSuffix("px")
.toInt() .toInt()
val background = styles.first { it.startsWith("background:") } val background = styles.first { it.startsWith("background:") }
.removePrefix("background:") .removePrefix("background:")
.split(" ") .split(" ")
val url = background.first { it.startsWith("url(") } val url = background.first { it.startsWith("url(") }
.removePrefix("url(") .removePrefix("url(")
.removeSuffix(")") .removeSuffix(")")
val widthOffset = background.first { it.startsWith("-") } val widthOffset = background.first { it.startsWith("-") }
.removePrefix("-") .removePrefix("-")
.removeSuffix("px") .removeSuffix("px")
.toInt() .toInt()
EHentaiThumbnailPreview(url, width, height, widthOffset, index) return EHentaiThumbnailPreview(url, width, height, widthOffset, index).also(::println)
}
} }
data class EHentaiThumbnailPreview( data class EHentaiThumbnailPreview(
val imageUrl: String, val imageUrl: String,
@@ -102,7 +102,7 @@ class ExtensionDetailsScreenModel(
val extension = state.value.extension ?: return "" val extension = state.value.extension ?: return ""
if (!extension.hasReadme) { if (!extension.hasReadme) {
return "https://tachiyomi.org/help/faq/#extensions" return "https://tachiyomi.org/docs/faq/browse/extensions"
} }
val pkgName = extension.pkgName.substringAfter("eu.kanade.tachiyomi.extension.") val pkgName = extension.pkgName.substringAfter("eu.kanade.tachiyomi.extension.")
@@ -180,6 +180,7 @@ class MainActivity : BaseActivity() {
libraryPreferences = libraryPreferences, libraryPreferences = libraryPreferences,
readerPreferences = Injekt.get(), readerPreferences = Injekt.get(),
backupPreferences = Injekt.get(), backupPreferences = Injekt.get(),
pagePreviewCache = Injekt.get(),
) )
} else { } else {
false false
@@ -63,6 +63,7 @@ import eu.kanade.tachiyomi.util.system.toShareIntent
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import exh.md.similar.MangaDexSimilarScreen import exh.md.similar.MangaDexSimilarScreen
import exh.pagepreview.PagePreviewScreen import exh.pagepreview.PagePreviewScreen
import exh.pref.DelegateSourcePreferences
import exh.recs.RecommendsScreen import exh.recs.RecommendsScreen
import exh.source.MERGED_SOURCE_ID import exh.source.MERGED_SOURCE_ID
import exh.source.getMainSource import exh.source.getMainSource
@@ -503,7 +504,7 @@ class MangaScreen(
// AZ --> // AZ -->
private fun openRecommends(context: Context, navigator: Navigator, source: Source?, manga: Manga) { private fun openRecommends(context: Context, navigator: Navigator, source: Source?, manga: Manga) {
source ?: return source ?: return
if (source.isMdBasedSource()) { if (source.isMdBasedSource() && Injekt.get<DelegateSourcePreferences>().delegateSources().get()) {
MaterialAlertDialogBuilder(context) MaterialAlertDialogBuilder(context)
.setTitle(R.string.az_recommends) .setTitle(R.string.az_recommends)
.setSingleChoiceItems( .setSingleChoiceItems(
@@ -322,7 +322,7 @@ class ReaderViewModel(
val context = Injekt.get<Application>() val context = Injekt.get<Application>()
// val source = sourceManager.getOrStub(manga.source) // val source = sourceManager.getOrStub(manga.source)
loader = ChapterLoader(context, downloadManager, downloadProvider, manga, source, /* SY --> */sourceManager, mergedReferences, mergedManga/* SY <-- */) loader = ChapterLoader(context, downloadManager, downloadProvider, manga, source, /* SY --> */sourceManager, readerPreferences, mergedReferences, mergedManga/* SY <-- */)
loadChapter(loader!!, chapterList.first { chapterId == it.chapter.id } /* SY --> */, page/* SY <-- */) loadChapter(loader!!, chapterList.first { chapterId == it.chapter.id } /* SY --> */, page/* SY <-- */)
Result.success(true) Result.success(true)
@@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.all.MergedSource import eu.kanade.tachiyomi.source.online.all.MergedSource
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import exh.debug.DebugFunctions.readerPrefs import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
@@ -28,6 +28,7 @@ class ChapterLoader(
private val source: Source, private val source: Source,
// SY --> // SY -->
private val sourceManager: SourceManager, private val sourceManager: SourceManager,
private val readerPrefs: ReaderPreferences,
private val mergedReferences: List<MergedMangaReference>, private val mergedReferences: List<MergedMangaReference>,
private val mergedManga: Map<Long, Manga>, private val mergedManga: Map<Long, Manga>,
// SY <-- // SY <--
+17
View File
@@ -21,6 +21,7 @@ import eu.kanade.domain.ui.UiPreferences
import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.core.security.SecurityPreferences import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
import eu.kanade.tachiyomi.data.cache.PagePreviewCache
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.MANGA_NON_COMPLETED import eu.kanade.tachiyomi.data.preference.MANGA_NON_COMPLETED
@@ -56,6 +57,7 @@ import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.contentOrNull import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
import logcat.LogPriority
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.data.DatabaseHandler import tachiyomi.data.DatabaseHandler
@@ -102,6 +104,7 @@ object EXHMigrations {
libraryPreferences: LibraryPreferences, libraryPreferences: LibraryPreferences,
readerPreferences: ReaderPreferences, readerPreferences: ReaderPreferences,
backupPreferences: BackupPreferences, backupPreferences: BackupPreferences,
pagePreviewCache: PagePreviewCache,
): Boolean { ): Boolean {
val lastVersionCode = preferenceStore.getInt("eh_last_version_code", 0) val lastVersionCode = preferenceStore.getInt("eh_last_version_code", 0)
val oldVersion = lastVersionCode.get() val oldVersion = lastVersionCode.get()
@@ -515,6 +518,20 @@ object EXHMigrations {
val trackManager = Injekt.get<TrackManager>() val trackManager = Injekt.get<TrackManager>()
trackManager.mdList.logout() trackManager.mdList.logout()
} }
if (oldVersion under 51) {
pagePreviewCache.clear()
File(context.cacheDir, PagePreviewCache.PARAMETER_CACHE_DIRECTORY).listFiles()?.forEach {
if (it.name == "journal" || it.name.startsWith("journal.")) {
return@forEach
}
try {
it.delete()
} catch (e: Exception) {
logcat(LogPriority.WARN, e) { "Failed to remove file from cache" }
}
}
}
// if (oldVersion under 1) { } (1 is current release version) // if (oldVersion under 1) { } (1 is current release version)
// do stuff here when releasing changed crap // do stuff here when releasing changed crap
+29 -3
View File
@@ -17,6 +17,7 @@ import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.domain.ui.UiPreferences import eu.kanade.domain.ui.UiPreferences
import eu.kanade.tachiyomi.core.security.SecurityPreferences import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.data.backup.models.Backup import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.cache.PagePreviewCache
import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.network.NetworkPreferences
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.all.NHentai import eu.kanade.tachiyomi.source.online.all.NHentai
@@ -57,17 +58,42 @@ object DebugFunctions {
val getExhFavoriteMangaWithMetadata: GetExhFavoriteMangaWithMetadata by injectLazy() val getExhFavoriteMangaWithMetadata: GetExhFavoriteMangaWithMetadata by injectLazy()
val getSearchMetadata: GetSearchMetadata by injectLazy() val getSearchMetadata: GetSearchMetadata by injectLazy()
val getAllManga: GetAllManga by injectLazy() val getAllManga: GetAllManga by injectLazy()
val pagePreviewCache: PagePreviewCache by injectLazy()
fun forceUpgradeMigration() { fun forceUpgradeMigration() {
val lastVersionCode = prefsStore.getInt("eh_last_version_code", 0) val lastVersionCode = prefsStore.getInt("eh_last_version_code", 0)
lastVersionCode.set(1) lastVersionCode.set(1)
EXHMigrations.upgrade(app, prefsStore, basePrefs, uiPrefs, networkPrefs, sourcePrefs, securityPrefs, libraryPrefs, readerPrefs, backupPrefs) EXHMigrations.upgrade(
context = app,
preferenceStore = prefsStore,
basePreferences = basePrefs,
uiPreferences = uiPrefs,
networkPreferences = networkPrefs,
sourcePreferences = sourcePrefs,
securityPreferences = securityPrefs,
libraryPreferences = libraryPrefs,
readerPreferences = readerPrefs,
backupPreferences = backupPrefs,
pagePreviewCache = pagePreviewCache,
)
} }
fun forceSetupJobs() { fun forceSetupJobs() {
val lastVersionCode = prefsStore.getInt("eh_last_version_code", 0) val lastVersionCode = prefsStore.getInt("eh_last_version_code", 0)
lastVersionCode.set(0) lastVersionCode.set(0)
EXHMigrations.upgrade(app, prefsStore, basePrefs, uiPrefs, networkPrefs, sourcePrefs, securityPrefs, libraryPrefs, readerPrefs, backupPrefs) EXHMigrations.upgrade(
context = app,
preferenceStore = prefsStore,
basePreferences = basePrefs,
uiPreferences = uiPrefs,
networkPreferences = networkPrefs,
sourcePreferences = sourcePrefs,
securityPreferences = securityPrefs,
libraryPreferences = libraryPrefs,
readerPreferences = readerPrefs,
backupPreferences = backupPrefs,
pagePreviewCache = pagePreviewCache,
)
} }
fun resetAgedFlagInEXHManga() { fun resetAgedFlagInEXHManga() {
@@ -187,7 +213,7 @@ object DebugFunctions {
""" """
{ {
id: ${info.id}, id: ${info.id},
isPeriodic: ${j.extras["EXTRA_IS_PERIODIC"]}, isPeriodic: ${j.extras.getBoolean("EXTRA_IS_PERIODIC")},
state: ${info.state.name}, state: ${info.state.name},
tags: [ tags: [
${info.tags.joinToString(separator = ",\n ")} ${info.tags.joinToString(separator = ",\n ")}
@@ -36,6 +36,7 @@ data class ChapterAttributesDto(
val createdAt: String, val createdAt: String,
val updatedAt: String, val updatedAt: String,
val publishAt: String, val publishAt: String,
val readableAt: String,
) )
@Serializable @Serializable
@@ -245,7 +245,7 @@ class ApiMangaParser(
val name = chapterName.toString() val name = chapterName.toString()
// Convert from unix time // Convert from unix time
val dateUpload = MdUtil.parseDate(attributes.publishAt) val dateUpload = MdUtil.parseDate(attributes.readableAt)
val scanlatorName = networkChapter.relationships val scanlatorName = networkChapter.relationships
.filter { .filter {
+13 -1
View File
@@ -1,7 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<changelog bulletedList="true"> <changelog bulletedList="true">
<changelogversion versionName="1.9.4" changeDate="Oct 29,2023">
<changelogtext>[b]Based on Tachiyomi stable 0.14.7(from 0.14.6)[/b]</changelogtext>
<changelogtext>Use ReadableAt for MangaDex dates</changelogtext>
<changelogtext>Fix E-H/Exh page previews</changelogtext>
<changelogtext>Fix page previews cache</changelogtext>
<changelogtext>Fix E-H/Exh browse thumbnails</changelogtext>
<changelogtext>Fix crash on Chinese</changelogtext>
<changelogtext>Fix Mangadex Recommendations when Delegation is off</changelogtext>
</changelogversion>
<changelogversion versionName="1.9.3" changeDate="Apr 18,2023">
<changelogtext>Hotfix for 1.9.2, fix backup restore</changelogtext>
</changelogversion>
<changelogversion versionName="1.9.2" changeDate="Apr 17,2023"> <changelogversion versionName="1.9.2" changeDate="Apr 17,2023">
<changelogtext>Hotfix for 1.9.1</changelogtext> <changelogtext>Hotfix for 1.9.1, fix tag editing</changelogtext>
</changelogversion> </changelogversion>
<changelogversion versionName="1.9.1" changeDate="Apr 16,2023"> <changelogversion versionName="1.9.1" changeDate="Apr 16,2023">
<changelogtext>[b]Based on Tachiyomi stable 0.14.6(from 0.14.3)[/b]</changelogtext> <changelogtext>[b]Based on Tachiyomi stable 0.14.6(from 0.14.3)[/b]</changelogtext>
@@ -17,6 +17,9 @@ class NetworkPreferences(
} }
fun defaultUserAgent(): Preference<String> { fun defaultUserAgent(): Preference<String> {
return preferenceStore.getString("default_user_agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0") return preferenceStore.getString(
"default_user_agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0",
)
} }
} }
@@ -135,7 +135,7 @@
<string name="data_saver_ignore_jpeg">忽略 JPEG 图像</string> <string name="data_saver_ignore_jpeg">忽略 JPEG 图像</string>
<string name="data_saver_ignore_gif">忽略 Gif 动画</string> <string name="data_saver_ignore_gif">忽略 Gif 动画</string>
<string name="data_saver_image_quality">图像质量</string> <string name="data_saver_image_quality">图像质量</string>
<string name="data_saver_image_quality_summary">更高值意味着更高的保存的图像质量,但这意味着更大的文件大小,80% 可以很好地平衡图片质量和文件大小</string> <string name="data_saver_image_quality_summary">更高值意味着更高的保存的图像质量,但这意味着更大的文件大小,80\% 可以很好地平衡图片质量和文件大小</string>
<string name="data_saver_image_format">压缩为 JPEG</string> <string name="data_saver_image_format">压缩为 JPEG</string>
<string name="data_saver_image_format_summary_on">JPEG 文件的大小要比 Webp 小得多(意味着节省了更多的流量),但它也会使图像损失更多的质量。\n目前压缩为 JPEG</string> <string name="data_saver_image_format_summary_on">JPEG 文件的大小要比 Webp 小得多(意味着节省了更多的流量),但它也会使图像损失更多的质量。\n目前压缩为 JPEG</string>
<string name="data_saver_image_format_summary_off">JPEG 文件的大小要比 Webp 小得多(意味着节省了更多的流量),但它也会使图像损失更多的质量。\n目前压缩为 Webp</string> <string name="data_saver_image_format_summary_off">JPEG 文件的大小要比 Webp 小得多(意味着节省了更多的流量),但它也会使图像损失更多的质量。\n目前压缩为 Webp</string>