diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index fe4de5341..000000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-OpenManga Next
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5888471d0..f16d451de 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,19 +1,18 @@
-
+ android:theme="@style/AppTheme">
@@ -21,6 +20,7 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/repository/ReadmangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/domain/repository/ReadmangaRepository.kt
index 43906e325..c6e637d23 100644
--- a/app/src/main/java/org/koitharu/kotatsu/domain/repository/ReadmangaRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/domain/repository/ReadmangaRepository.kt
@@ -1,72 +1,90 @@
package org.koitharu.kotatsu.domain.repository
+import androidx.core.text.HtmlCompat
+import androidx.core.text.parseAsHtml
import org.koitharu.kotatsu.core.model.*
import org.koitharu.kotatsu.domain.MangaLoaderContext
import org.koitharu.kotatsu.domain.MangaRepository
import org.koitharu.kotatsu.domain.exceptions.ParseException
-import org.koitharu.kotatsu.utils.ext.longHashCode
-import org.koitharu.kotatsu.utils.ext.parseHtml
-import org.koitharu.kotatsu.utils.ext.safe
-import org.koitharu.kotatsu.utils.ext.withDomain
+import org.koitharu.kotatsu.utils.ext.*
class ReadmangaRepository(loaderContext: MangaLoaderContext) : MangaRepository(loaderContext) {
- override suspend fun getList(
- offset: Int,
- query: String?,
- sortOrder: SortOrder?,
- tags: Set?
- ): List {
- val doc = loaderContext.get("https://readmanga.me/list?sortType=updated&offset=$offset")
- .parseHtml()
- val root = doc.body().getElementById("mangaBox")
- ?.selectFirst("div.tiles.row") ?: throw ParseException("Cannot find root")
- return root.select("div.tile").mapNotNull { node ->
- val imgDiv = node.selectFirst("div.img") ?: return@mapNotNull null
- val descDiv = node.selectFirst("div.desc") ?: return@mapNotNull null
- val href = imgDiv.selectFirst("a").attr("href")?.withDomain("readmanga.me")
- ?: return@mapNotNull null
- val title = descDiv.selectFirst("h3")?.selectFirst("a")?.text()
- ?: return@mapNotNull null
- Manga(
- id = href.longHashCode(),
- url = href,
- localizedTitle = title,
- title = descDiv.selectFirst("h4")?.text() ?: title,
- coverUrl = imgDiv.selectFirst("img.lazy")?.attr("data-original").orEmpty(),
- summary = "",
- rating = safe {
- node.selectFirst("div.rating")
- ?.attr("title")
- ?.substringBefore(' ')
- ?.toFloatOrNull()
- ?.div(10f)
- } ?: -1f,
- tags = safe {
- descDiv.selectFirst("div.tile-info")
- ?.select("a.element-link")
- ?.map {
- MangaTag(
- title = it.text(),
- key = it.attr("href").substringAfterLast('/')
- )
- }?.toSet()
- }.orEmpty(),
- state = when {
- node.selectFirst("div.tags")
- ?.selectFirst("span.mangaCompleted") != null -> MangaState.FINISHED
- else -> null
- },
- source = MangaSource.READMANGA_RU
- )
- }
- }
+ override suspend fun getList(
+ offset: Int,
+ query: String?,
+ sortOrder: SortOrder?,
+ tags: Set?
+ ): List {
+ val doc = loaderContext.get("https://readmanga.me/list?sortType=updated&offset=$offset")
+ .parseHtml()
+ val root = doc.body().getElementById("mangaBox")
+ ?.selectFirst("div.tiles.row") ?: throw ParseException("Cannot find root")
+ return root.select("div.tile").mapNotNull { node ->
+ val imgDiv = node.selectFirst("div.img") ?: return@mapNotNull null
+ val descDiv = node.selectFirst("div.desc") ?: return@mapNotNull null
+ val href = imgDiv.selectFirst("a").attr("href")?.withDomain("readmanga.me")
+ ?: return@mapNotNull null
+ val title = descDiv.selectFirst("h3")?.selectFirst("a")?.text()
+ ?: return@mapNotNull null
+ Manga(
+ id = href.longHashCode(),
+ url = href,
+ localizedTitle = title,
+ title = descDiv.selectFirst("h4")?.text() ?: title,
+ coverUrl = imgDiv.selectFirst("img.lazy")?.attr("data-original").orEmpty(),
+ summary = "",
+ rating = safe {
+ node.selectFirst("div.rating")
+ ?.attr("title")
+ ?.substringBefore(' ')
+ ?.toFloatOrNull()
+ ?.div(10f)
+ } ?: -1f,
+ tags = safe {
+ descDiv.selectFirst("div.tile-info")
+ ?.select("a.element-link")
+ ?.map {
+ MangaTag(
+ title = it.text(),
+ key = it.attr("href").substringAfterLast('/')
+ )
+ }?.toSet()
+ }.orEmpty(),
+ state = when {
+ node.selectFirst("div.tags")
+ ?.selectFirst("span.mangaCompleted") != null -> MangaState.FINISHED
+ else -> null
+ },
+ source = MangaSource.READMANGA_RU
+ )
+ }
+ }
- override suspend fun getDetails(manga: Manga): Manga {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
- }
+ override suspend fun getDetails(manga: Manga): Manga {
+ val doc = loaderContext.get(manga.url).parseHtml()
+ val root = doc.body().getElementById("mangaBox")
+ return manga.copy(
+ description = root.selectFirst("div.manga-description").firstChild()?.html()?.parseAsHtml(),
+ largeCoverUrl = root.selectFirst("div.subject-cower")?.selectFirst("img")?.attr(
+ "data-full"
+ ),
+ chapters = root.selectFirst("div.chapters-link")?.selectFirst("table")
+ ?.select("a")?.asReversed()?.mapIndexedNotNull { i, a ->
+ val href =
+ a.attr("href")?.withDomain("readmanga.me") ?: return@mapIndexedNotNull null
+ MangaChapter(
+ id = href.longHashCode(),
+ name = a.ownText(),
+ number = i + 1,
+ url = href,
+ source = MangaSource.READMANGA_RU
+ )
+ }
+ )
+ }
- override suspend fun getPages(chapter: MangaChapter): List {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
- }
+ override suspend fun getPages(chapter: MangaChapter): List {
+ TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/ChipsFactory.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/ChipsFactory.kt
new file mode 100644
index 000000000..b3ab5ad5b
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/ChipsFactory.kt
@@ -0,0 +1,29 @@
+package org.koitharu.kotatsu.ui.common
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.view.View
+import androidx.annotation.DrawableRes
+import com.google.android.material.chip.Chip
+import com.google.android.material.shape.CornerFamily
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.utils.ext.getThemeColor
+
+class ChipsFactory(private val context: Context) {
+
+ fun create(convertView: Chip? = null, text: CharSequence, @DrawableRes iconRes: Int = 0, tag: Any? = null): Chip {
+ val chip = convertView ?: Chip(context).apply {
+ setTextColor(context.getThemeColor(android.R.attr.textColorPrimary))
+ isCloseIconVisible = false
+ }
+ chip.text = text
+ if (iconRes == 0) {
+ chip.isChipIconVisible = false
+ } else {
+ chip.isCheckedIconVisible = true
+ chip.setChipIconResource(iconRes)
+ }
+ chip.tag = tag
+ return chip
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/widgets/RectFrameLayout.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/widgets/SquareLayout.kt
similarity index 88%
rename from app/src/main/java/org/koitharu/kotatsu/ui/common/widgets/RectFrameLayout.kt
rename to app/src/main/java/org/koitharu/kotatsu/ui/common/widgets/SquareLayout.kt
index c3079356d..33cbef26b 100644
--- a/app/src/main/java/org/koitharu/kotatsu/ui/common/widgets/RectFrameLayout.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/widgets/SquareLayout.kt
@@ -4,7 +4,7 @@ import android.content.Context
import android.util.AttributeSet
import android.widget.FrameLayout
-class RectFrameLayout @JvmOverloads constructor(
+class SquareLayout @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/details/ChapterHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/ChapterHolder.kt
new file mode 100644
index 000000000..5e0f2b556
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/ChapterHolder.kt
@@ -0,0 +1,15 @@
+package org.koitharu.kotatsu.ui.main.details
+
+import android.view.ViewGroup
+import kotlinx.android.synthetic.main.item_chapter.*
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.core.model.MangaChapter
+import org.koitharu.kotatsu.ui.common.list.BaseViewHolder
+
+class ChapterHolder(parent: ViewGroup) : BaseViewHolder(parent, R.layout.item_chapter) {
+
+ override fun onBind(data: MangaChapter) {
+ textView_title.text = data.name
+ textView_number.text = data.number.toString()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/details/ChaptersAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/ChaptersAdapter.kt
new file mode 100644
index 000000000..39e9a2965
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/ChaptersAdapter.kt
@@ -0,0 +1,14 @@
+package org.koitharu.kotatsu.ui.main.details
+
+import android.view.ViewGroup
+import org.koitharu.kotatsu.core.model.MangaChapter
+import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter
+import org.koitharu.kotatsu.ui.common.list.BaseViewHolder
+
+class ChaptersAdapter(onItemClickListener: ((MangaChapter) -> Unit)?) :
+ BaseRecyclerAdapter(onItemClickListener) {
+
+ override fun onCreateViewHolder(parent: ViewGroup) = ChapterHolder(parent)
+
+ override fun onGetItemId(item: MangaChapter) = item.id
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/details/ChaptersFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/ChaptersFragment.kt
new file mode 100644
index 000000000..c08c665b4
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/ChaptersFragment.kt
@@ -0,0 +1,40 @@
+package org.koitharu.kotatsu.ui.main.details
+
+import android.os.Bundle
+import android.view.View
+import androidx.core.view.isVisible
+import androidx.recyclerview.widget.DividerItemDecoration
+import androidx.recyclerview.widget.RecyclerView
+import kotlinx.android.synthetic.main.fragment_chapters.*
+import moxy.ktx.moxyPresenter
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.core.model.Manga
+import org.koitharu.kotatsu.ui.common.BaseFragment
+
+class ChaptersFragment : BaseFragment(R.layout.fragment_chapters), MangaDetailsView {
+
+ private val presenter by moxyPresenter { (activity as MangaDetailsActivity).presenter }
+
+ private lateinit var adapter: ChaptersAdapter
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ adapter = ChaptersAdapter {
+
+ }
+ recyclerView_chapters.addItemDecoration(DividerItemDecoration(view.context, RecyclerView.VERTICAL))
+ recyclerView_chapters.adapter = adapter
+ }
+
+ override fun onMangaUpdated(manga: Manga) {
+ adapter.replaceData(manga.chapters.orEmpty())
+ }
+
+ override fun onLoadingStateChanged(isLoading: Boolean) {
+ progressBar.isVisible = isLoading
+ }
+
+ override fun onError(e: Exception) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsActivity.kt
new file mode 100644
index 000000000..f11fb4df1
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsActivity.kt
@@ -0,0 +1,48 @@
+package org.koitharu.kotatsu.ui.main.details
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.viewpager.widget.ViewPager
+import com.google.android.material.snackbar.Snackbar
+import com.google.android.material.tabs.TabLayout
+import kotlinx.android.synthetic.main.activity_details.*
+import moxy.ktx.moxyPresenter
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.core.model.Manga
+import org.koitharu.kotatsu.ui.common.BaseActivity
+import org.koitharu.kotatsu.utils.ext.getDisplayMessage
+
+class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
+
+ val presenter by moxyPresenter(factory = ::MangaDetailsPresenter)
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_details)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ pager.adapter = MangaDetailsAdapter(resources, supportFragmentManager)
+ tabs.setupWithViewPager(pager)
+ intent?.getParcelableExtra(EXTRA_MANGA)?.let {
+ presenter.loadDetails(it)
+ } ?: finish()
+ }
+
+ override fun onMangaUpdated(manga: Manga) {
+ title = manga.title
+ }
+
+ override fun onLoadingStateChanged(isLoading: Boolean) = Unit
+
+ override fun onError(e: Exception) {
+ Snackbar.make(pager, e.getDisplayMessage(resources), Snackbar.LENGTH_LONG).show()
+ }
+
+ companion object {
+
+ private const val EXTRA_MANGA = "manga"
+
+ fun newIntent(context: Context, manga: Manga) = Intent(context, MangaDetailsActivity::class.java)
+ .putExtra(EXTRA_MANGA, manga)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsAdapter.kt
new file mode 100644
index 000000000..087a68fb0
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsAdapter.kt
@@ -0,0 +1,25 @@
+package org.koitharu.kotatsu.ui.main.details
+
+import android.content.res.Resources
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentManager
+import androidx.fragment.app.FragmentPagerAdapter
+import androidx.viewpager2.adapter.FragmentStateAdapter
+import org.koitharu.kotatsu.R
+
+class MangaDetailsAdapter(private val resources: Resources, fm: FragmentManager) : FragmentPagerAdapter(fm, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
+
+ override fun getCount() = 2
+
+ override fun getItem(position: Int): Fragment = when(position) {
+ 0 -> MangaDetailsFragment()
+ 1 -> ChaptersFragment()
+ else -> throw IndexOutOfBoundsException("No fragment for position $position")
+ }
+
+ override fun getPageTitle(position: Int): CharSequence? = when(position) {
+ 0 -> resources.getString(R.string.details)
+ 1 -> resources.getString(R.string.chapters)
+ else -> null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsFragment.kt
new file mode 100644
index 000000000..584913a2b
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsFragment.kt
@@ -0,0 +1,43 @@
+package org.koitharu.kotatsu.ui.main.details
+
+import android.os.Bundle
+import androidx.core.view.isVisible
+import coil.api.load
+import kotlinx.android.synthetic.main.fragment_details.*
+import moxy.ktx.moxyPresenter
+import org.koin.core.get
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.core.model.Manga
+import org.koitharu.kotatsu.ui.common.BaseFragment
+import org.koitharu.kotatsu.utils.ext.setChips
+
+class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetailsView {
+
+ private val presenter by moxyPresenter { (activity as MangaDetailsActivity).presenter }
+
+ override fun onActivityCreated(savedInstanceState: Bundle?) {
+ super.onActivityCreated(savedInstanceState)
+ }
+
+ override fun onMangaUpdated(manga: Manga) {
+ imageView_cover.load(manga.largeCoverUrl ?: manga.coverUrl)
+ textView_title.text = manga.title
+ textView_subtitle.text = manga.localizedTitle
+ textView_description.text = manga.description
+ chips_tags.setChips(manga.tags) {
+ create(
+ text = it.title,
+ iconRes = R.drawable.ic_chip_tag,
+ tag = it
+ )
+ }
+ }
+
+ override fun onLoadingStateChanged(isLoading: Boolean) {
+ progressBar.isVisible = isLoading
+ }
+
+ override fun onError(e: Exception) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsPresenter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsPresenter.kt
new file mode 100644
index 000000000..a72a6cbbc
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsPresenter.kt
@@ -0,0 +1,40 @@
+package org.koitharu.kotatsu.ui.main.details
+
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import moxy.InjectViewState
+import org.koitharu.kotatsu.BuildConfig
+import org.koitharu.kotatsu.core.model.Manga
+import org.koitharu.kotatsu.domain.MangaProviderFactory
+import org.koitharu.kotatsu.ui.common.BasePresenter
+
+@InjectViewState
+class MangaDetailsPresenter : BasePresenter() {
+
+ private var isLoaded = false
+
+ fun loadDetails(manga: Manga) {
+ if (isLoaded) {
+ return
+ }
+ viewState.onMangaUpdated(manga)
+ launch {
+ try {
+ viewState.onLoadingStateChanged(true)
+ val details = withContext(Dispatchers.IO) {
+ MangaProviderFactory.create(manga.source).getDetails(manga)
+ }
+ viewState.onMangaUpdated(details)
+ isLoaded = true
+ } catch (e: Exception) {
+ if (BuildConfig.DEBUG) {
+ e.printStackTrace()
+ }
+ viewState.onError(e)
+ } finally {
+ viewState.onLoadingStateChanged(false)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsView.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsView.kt
new file mode 100644
index 000000000..bf3f9aa3e
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/details/MangaDetailsView.kt
@@ -0,0 +1,19 @@
+package org.koitharu.kotatsu.ui.main.details
+
+import moxy.MvpView
+import moxy.viewstate.strategy.AddToEndSingleStrategy
+import moxy.viewstate.strategy.OneExecutionStateStrategy
+import moxy.viewstate.strategy.StateStrategyType
+import org.koitharu.kotatsu.core.model.Manga
+
+interface MangaDetailsView : MvpView {
+
+ @StateStrategyType(AddToEndSingleStrategy::class)
+ fun onMangaUpdated(manga: Manga)
+
+ @StateStrategyType(AddToEndSingleStrategy::class)
+ fun onLoadingStateChanged(isLoading: Boolean)
+
+ @StateStrategyType(OneExecutionStateStrategy::class)
+ fun onError(e: Exception)
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt
index 98422ce6f..3e874a027 100644
--- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt
@@ -14,6 +14,7 @@ import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.ui.common.BaseFragment
import org.koitharu.kotatsu.ui.common.list.PaginationScrollListener
import org.koitharu.kotatsu.ui.common.list.SpacingItemDecoration
+import org.koitharu.kotatsu.ui.main.details.MangaDetailsActivity
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import org.koitharu.kotatsu.utils.ext.hasItems
import org.koitharu.kotatsu.utils.ext.withArgs
@@ -30,7 +31,7 @@ class MangaListFragment : BaseFragment(R.layout.fragment_list), MangaListView,
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = MangaListAdapter {
-
+ startActivity(MangaDetailsActivity.newIntent(context ?: return@MangaListAdapter, it))
}
// recyclerView.addItemDecoration(SpacingItemDecoration(resources.getDimensionPixelOffset(R.dimen.grid_spacing)))
recyclerView.addItemDecoration(DividerItemDecoration(view.context, RecyclerView.VERTICAL))
diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/JsoupExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/JsoupExt.kt
index 474e8e682..75e3eada3 100644
--- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/JsoupExt.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/JsoupExt.kt
@@ -4,6 +4,7 @@ import okhttp3.Response
import okhttp3.internal.closeQuietly
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
+import org.jsoup.nodes.Element
fun Response.parseHtml(): Document {
val stream = body?.byteStream() ?: throw NullPointerException("Response body is null")
@@ -15,4 +16,6 @@ fun Response.parseHtml(): Document {
)
closeQuietly()
return doc
-}
\ No newline at end of file
+}
+
+fun Element.firstChild(): Element? = children().first()
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt
index 91f4b285a..ba7c82545 100644
--- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt
@@ -9,7 +9,15 @@ fun String.longHashCode(): Long {
return h
}
-fun String.withDomain(domain: String) = when {
- this.startsWith("/") -> "http://$domain"
+fun String.withDomain(domain: String, ssl: Boolean = true) = when {
+ this.startsWith("/") -> buildString {
+ append("http")
+ if (ssl) {
+ append('s')
+ }
+ append("://")
+ append(domain)
+ append(this@withDomain)
+ }
else -> this
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewExt.kt
index 1a46b2bc9..70e8decbf 100644
--- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewExt.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewExt.kt
@@ -13,6 +13,9 @@ import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.chip.Chip
+import com.google.android.material.chip.ChipGroup
+import org.koitharu.kotatsu.ui.common.ChipsFactory
fun View.hideKeyboard() {
val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
@@ -61,4 +64,13 @@ var TextView.textAndVisible: CharSequence?
set(value) {
text = value
isGone = value.isNullOrEmpty()
- }
\ No newline at end of file
+ }
+
+fun ChipGroup.setChips(data: Iterable, action: ChipsFactory.(T) -> Chip) {
+ removeAllViews()
+ val factory = ChipsFactory(context)
+ data.forEach {
+ val chip = factory.action(it)
+ addView(chip)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_round_rect.xml b/app/src/main/res/drawable/bg_round_rect.xml
new file mode 100644
index 000000000..847a0497b
--- /dev/null
+++ b/app/src/main/res/drawable/bg_round_rect.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_chip_tag.xml b/app/src/main/res/drawable/ic_chip_tag.xml
new file mode 100644
index 000000000..d5df0cdda
--- /dev/null
+++ b/app/src/main/res/drawable/ic_chip_tag.xml
@@ -0,0 +1,11 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_history.xml b/app/src/main/res/drawable/ic_history.xml
index b500514ae..2cc05a897 100644
--- a/app/src/main/res/drawable/ic_history.xml
+++ b/app/src/main/res/drawable/ic_history.xml
@@ -1,10 +1,10 @@
-
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?attr/colorControlNormal"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+
diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml
new file mode 100644
index 000000000..d58e21c11
--- /dev/null
+++ b/app/src/main/res/drawable/ic_settings.xml
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_star_half.xml b/app/src/main/res/drawable/ic_star_half.xml
index 4be9bf32c..463042243 100644
--- a/app/src/main/res/drawable/ic_star_half.xml
+++ b/app/src/main/res/drawable/ic_star_half.xml
@@ -1,14 +1,14 @@
-
-
-
-
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?attr/colorControlNormal"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_storage.xml b/app/src/main/res/drawable/ic_storage.xml
index bf3fc357c..622253195 100644
--- a/app/src/main/res/drawable/ic_storage.xml
+++ b/app/src/main/res/drawable/ic_storage.xml
@@ -1,10 +1,10 @@
-
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?attr/colorControlNormal"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+
diff --git a/app/src/main/res/layout/activity_details.xml b/app/src/main/res/layout/activity_details.xml
new file mode 100644
index 000000000..25370ec6e
--- /dev/null
+++ b/app/src/main/res/layout/activity_details.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_chapters.xml b/app/src/main/res/layout/fragment_chapters.xml
new file mode 100644
index 000000000..98874732e
--- /dev/null
+++ b/app/src/main/res/layout/fragment_chapters.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_details.xml b/app/src/main/res/layout/fragment_details.xml
new file mode 100644
index 000000000..cdc0cca09
--- /dev/null
+++ b/app/src/main/res/layout/fragment_details.xml
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_chapter.xml b/app/src/main/res/layout/item_chapter.xml
new file mode 100644
index 000000000..5986d1bcb
--- /dev/null
+++ b/app/src/main/res/layout/item_chapter.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_manga_list.xml b/app/src/main/res/layout/item_manga_list.xml
index ba78c829d..2f63b793b 100644
--- a/app/src/main/res/layout/item_manga_list.xml
+++ b/app/src/main/res/layout/item_manga_list.xml
@@ -1,7 +1,7 @@
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 42ed64e5f..9c088013c 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -1,5 +1,6 @@
5dp
- 84dp
+ 84dp
+ 46dp
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 87d77b1e7..af4c3e7eb 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -7,4 +7,6 @@
History
An error has occurred
Network connection error
+ Details
+ Chapters
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index b4a529bf6..2fba1a29b 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,2 +1,2 @@
include ':app'
-rootProject.name = "OpenManga Next"
\ No newline at end of file
+rootProject.name = "Kotatsu"
\ No newline at end of file