This commit is contained in:
tom5079
2021-12-18 14:57:25 +09:00
parent a57b1d5614
commit 02751233f8
5 changed files with 122 additions and 5 deletions

17
.idea/deploymentTargetDropDown.xml generated Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/Pixel_3a_API_30_x86.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2021-12-18T04:42:03.889339Z" />
</component>
</project>

View File

@@ -24,6 +24,7 @@ import androidx.compose.runtime.Composable
import io.ktor.http.* import io.ktor.http.*
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import org.kodein.di.* import org.kodein.di.*
import xyz.quaver.pupil.sources.manatoki.Manatoki
interface ItemInfo : Parcelable { interface ItemInfo : Parcelable {
val source: String val source: String
@@ -61,9 +62,10 @@ val sourceModule = DI.Module(name = "source") {
listOf<(Application) -> (Source)>( listOf<(Application) -> (Source)>(
{ Hitomi(it) }, { Hitomi(it) },
{ Hiyobi_io(it) } { Hiyobi_io(it) },
{ Manatoki(it) }
).forEach { source -> ).forEach { source ->
inSet { singleton { source.invoke(instance()).let { it.name to it } } } inSet { singleton { source(instance()).let { it.name to it } } }
} }
bind { singleton { History(di) } } bind { singleton { History(di) } }

View File

@@ -0,0 +1,101 @@
/*
* Pupil, Hitomi.la viewer for Android
* Copyright (C) 2021 tom5079
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package xyz.quaver.pupil.sources.manatoki
import android.app.Application
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import org.jsoup.Jsoup
import org.kodein.di.DIAware
import org.kodein.di.android.closestDI
import org.kodein.log.LoggerFactory
import org.kodein.log.newLogger
import xyz.quaver.pupil.R
import xyz.quaver.pupil.sources.ItemInfo
import xyz.quaver.pupil.sources.Source
@Parcelize
class ManatokiItemInfo(
override val itemID: String,
override val title: String
) : ItemInfo {
override val source: String = "manatoki.net"
}
class Manatoki(app: Application) : Source(), DIAware {
override val di by closestDI(app)
private val logger = newLogger(LoggerFactory.default)
override val name = "manatoki.net"
override val availableSortMode: List<String> = emptyList()
override val iconResID: Int = R.drawable.manatoki
override suspend fun search(
query: String,
range: IntRange,
sortMode: Int
): Pair<Channel<ItemInfo>, Int> {
TODO("Not yet implemented")
}
override suspend fun images(itemID: String): List<String> = coroutineScope {
val jsoup = withContext(Dispatchers.IO) {
Jsoup.connect("https://manatoki116.net/comic/$itemID").get()
}
val htmlData = jsoup
.selectFirst(".view-padding > script")!!
.data()
.splitToSequence('\n')
.fold(StringBuilder()) { sb, line ->
if (!line.startsWith("html_data")) return@fold sb
line.drop(12).dropLast(2).split('.').forEach {
if (it.isNotBlank()) sb.appendCodePoint(it.toInt(16))
}
sb
}.toString()
Jsoup.parse(htmlData)
.select("img[^data-]:not([style])")
.map {
it.attributes()
.first { it.key.startsWith("data-") }
.value
}
}
override suspend fun info(itemID: String): ItemInfo = coroutineScope {
val jsoup = withContext(Dispatchers.IO) {
Jsoup.connect("https://manatoki116.net/comic/$itemID").get()
}
val title = jsoup.selectFirst(".toon-title")!!.ownText()
ManatokiItemInfo(
itemID,
title
)
}
}

View File

@@ -33,17 +33,14 @@ import org.kodein.di.DIAware
import org.kodein.di.android.x.closestDI import org.kodein.di.android.x.closestDI
import org.kodein.di.direct import org.kodein.di.direct
import org.kodein.di.instance import org.kodein.di.instance
import org.kodein.di.instanceOrNull
import org.kodein.log.LoggerFactory import org.kodein.log.LoggerFactory
import org.kodein.log.newLogger import org.kodein.log.newLogger
import xyz.quaver.pupil.db.AppDatabase import xyz.quaver.pupil.db.AppDatabase
import xyz.quaver.pupil.db.Bookmark
import xyz.quaver.pupil.db.History import xyz.quaver.pupil.db.History
import xyz.quaver.pupil.sources.ItemInfo import xyz.quaver.pupil.sources.ItemInfo
import xyz.quaver.pupil.sources.Source import xyz.quaver.pupil.sources.Source
import xyz.quaver.pupil.util.NetworkCache import xyz.quaver.pupil.util.NetworkCache
import xyz.quaver.pupil.util.source import xyz.quaver.pupil.util.source
import java.nio.file.Files.delete
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware { class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware {

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB