Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be19c32fea | ||
|
|
8da0e98d23 | ||
|
|
73a2f05509 | ||
|
|
bb23f998e0 | ||
|
|
75915ff366 | ||
|
|
517e801580 | ||
|
|
12474e23f9 | ||
|
|
00bdd859a7 | ||
|
|
3a3af9ea00 | ||
|
|
1803b1a2ee | ||
|
|
4175c84363 | ||
|
|
1840d7b50e | ||
|
|
37b69833b3 |
@@ -14,8 +14,8 @@ android {
|
|||||||
applicationId 'org.koitharu.kotatsu'
|
applicationId 'org.koitharu.kotatsu'
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 32
|
targetSdkVersion 32
|
||||||
versionCode 417
|
versionCode 419
|
||||||
versionName '3.4.5'
|
versionName '3.4.7'
|
||||||
generatedDensities = []
|
generatedDensities = []
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ afterEvaluate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation('com.github.nv95:kotatsu-parsers:c4abb758f3') {
|
implementation('com.github.nv95:kotatsu-parsers:7588617316') {
|
||||||
exclude group: 'org.json', module: 'json'
|
exclude group: 'org.json', module: 'json'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package org.koitharu.kotatsu.base.ui.widgets
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.text.Selection
|
||||||
|
import android.text.Spannable
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import androidx.annotation.AttrRes
|
||||||
|
import com.google.android.material.textview.MaterialTextView
|
||||||
|
|
||||||
|
class SelectableTextView @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
@AttrRes defStyleAttr: Int = android.R.attr.textViewStyle,
|
||||||
|
) : MaterialTextView(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
|
||||||
|
fixSelectionRange()
|
||||||
|
return super.dispatchTouchEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/22810147/error-when-selecting-text-from-textview-java-lang-indexoutofboundsexception-se
|
||||||
|
private fun fixSelectionRange() {
|
||||||
|
if (selectionStart < 0 || selectionEnd < 0) {
|
||||||
|
val spannableText = text as? Spannable ?: return
|
||||||
|
Selection.setSelection(spannableText, text.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,10 +2,9 @@ package org.koitharu.kotatsu.browser
|
|||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import org.koin.core.component.KoinComponent
|
import android.webkit.WebViewClient
|
||||||
import org.koitharu.kotatsu.core.network.WebViewClientCompat
|
|
||||||
|
|
||||||
class BrowserClient(private val callback: BrowserCallback) : WebViewClientCompat(), KoinComponent {
|
class BrowserClient(private val callback: BrowserCallback) : WebViewClient() {
|
||||||
|
|
||||||
override fun onPageFinished(webView: WebView, url: String) {
|
override fun onPageFinished(webView: WebView, url: String) {
|
||||||
super.onPageFinished(webView, url)
|
super.onPageFinished(webView, url)
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ package org.koitharu.kotatsu.browser
|
|||||||
|
|
||||||
import android.webkit.WebChromeClient
|
import android.webkit.WebChromeClient
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
|
import android.widget.ProgressBar
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.google.android.material.progressindicator.BaseProgressIndicator
|
import org.koitharu.kotatsu.utils.ext.setProgressCompat
|
||||||
|
|
||||||
private const val PROGRESS_MAX = 100
|
private const val PROGRESS_MAX = 100
|
||||||
|
|
||||||
class ProgressChromeClient(
|
class ProgressChromeClient(
|
||||||
private val progressIndicator: BaseProgressIndicator<*>,
|
private val progressIndicator: ProgressBar,
|
||||||
) : WebChromeClient() {
|
) : WebChromeClient() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -24,7 +25,7 @@ class ProgressChromeClient(
|
|||||||
progressIndicator.isIndeterminate = false
|
progressIndicator.isIndeterminate = false
|
||||||
progressIndicator.setProgressCompat(newProgress.coerceAtMost(PROGRESS_MAX), true)
|
progressIndicator.setProgressCompat(newProgress.coerceAtMost(PROGRESS_MAX), true)
|
||||||
} else {
|
} else {
|
||||||
progressIndicator.setIndeterminate(true)
|
progressIndicator.isIndeterminate = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,19 +2,19 @@ package org.koitharu.kotatsu.browser.cloudflare
|
|||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewClient
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import org.koitharu.kotatsu.core.network.AndroidCookieJar
|
import org.koitharu.kotatsu.core.network.AndroidCookieJar
|
||||||
import org.koitharu.kotatsu.core.network.WebViewClientCompat
|
|
||||||
|
|
||||||
private const val CF_CLEARANCE = "cf_clearance"
|
private const val CF_CLEARANCE = "cf_clearance"
|
||||||
|
|
||||||
class CloudFlareClient(
|
class CloudFlareClient(
|
||||||
private val cookieJar: AndroidCookieJar,
|
private val cookieJar: AndroidCookieJar,
|
||||||
private val callback: CloudFlareCallback,
|
private val callback: CloudFlareCallback,
|
||||||
private val targetUrl: String
|
private val targetUrl: String,
|
||||||
) : WebViewClientCompat() {
|
) : WebViewClient() {
|
||||||
|
|
||||||
private val oldClearance = getCookieValue(CF_CLEARANCE)
|
private val oldClearance = getClearance()
|
||||||
|
|
||||||
override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
|
override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
|
||||||
super.onPageStarted(view, url, favicon)
|
super.onPageStarted(view, url, favicon)
|
||||||
@@ -32,14 +32,14 @@ class CloudFlareClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkClearance() {
|
private fun checkClearance() {
|
||||||
val clearance = getCookieValue(CF_CLEARANCE)
|
val clearance = getClearance()
|
||||||
if (clearance != null && clearance != oldClearance) {
|
if (clearance != null && clearance != oldClearance) {
|
||||||
callback.onCheckPassed()
|
callback.onCheckPassed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCookieValue(name: String): String? {
|
private fun getClearance(): String? {
|
||||||
return cookieJar.loadForRequest(targetUrl.toHttpUrl())
|
return cookieJar.loadForRequest(targetUrl.toHttpUrl())
|
||||||
.find { it.name == name }?.value
|
.find { it.name == CF_CLEARANCE }?.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
package org.koitharu.kotatsu.core.network
|
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
|
||||||
import android.os.Build
|
|
||||||
import android.webkit.*
|
|
||||||
|
|
||||||
@Suppress("OverridingDeprecatedMember")
|
|
||||||
abstract class WebViewClientCompat : WebViewClient() {
|
|
||||||
|
|
||||||
open fun shouldOverrideUrlCompat(view: WebView, url: String): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun shouldInterceptRequestCompat(view: WebView, url: String): WebResourceResponse? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun onReceivedErrorCompat(
|
|
||||||
view: WebView,
|
|
||||||
errorCode: Int,
|
|
||||||
description: String?,
|
|
||||||
failingUrl: String,
|
|
||||||
isMainFrame: Boolean
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
|
||||||
final override fun shouldOverrideUrlLoading(
|
|
||||||
view: WebView,
|
|
||||||
request: WebResourceRequest
|
|
||||||
): Boolean = shouldOverrideUrlCompat(view, request.url.toString())
|
|
||||||
|
|
||||||
final override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
|
|
||||||
return shouldOverrideUrlCompat(view, url)
|
|
||||||
}
|
|
||||||
|
|
||||||
final override fun shouldInterceptRequest(
|
|
||||||
view: WebView,
|
|
||||||
request: WebResourceRequest
|
|
||||||
): WebResourceResponse? = shouldInterceptRequestCompat(view, request.url.toString())
|
|
||||||
|
|
||||||
final override fun shouldInterceptRequest(
|
|
||||||
view: WebView,
|
|
||||||
url: String
|
|
||||||
): WebResourceResponse? = shouldInterceptRequestCompat(view, url)
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.M)
|
|
||||||
final override fun onReceivedError(
|
|
||||||
view: WebView,
|
|
||||||
request: WebResourceRequest,
|
|
||||||
error: WebResourceError
|
|
||||||
) {
|
|
||||||
onReceivedErrorCompat(
|
|
||||||
view,
|
|
||||||
error.errorCode,
|
|
||||||
error.description?.toString(),
|
|
||||||
request.url.toString(),
|
|
||||||
request.isForMainFrame
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
final override fun onReceivedError(
|
|
||||||
view: WebView,
|
|
||||||
errorCode: Int,
|
|
||||||
description: String?,
|
|
||||||
failingUrl: String
|
|
||||||
) {
|
|
||||||
onReceivedErrorCompat(view, errorCode, description, failingUrl, failingUrl == view.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.M)
|
|
||||||
final override fun onReceivedHttpError(
|
|
||||||
view: WebView,
|
|
||||||
request: WebResourceRequest,
|
|
||||||
error: WebResourceResponse
|
|
||||||
) {
|
|
||||||
onReceivedErrorCompat(
|
|
||||||
view,
|
|
||||||
error.statusCode,
|
|
||||||
error.reasonPhrase,
|
|
||||||
request.url
|
|
||||||
.toString(),
|
|
||||||
request.isForMainFrame
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -103,7 +103,8 @@ class DetailsActivity :
|
|||||||
|
|
||||||
private fun onMangaRemoved(manga: Manga) {
|
private fun onMangaRemoved(manga: Manga) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this, getString(R.string._s_deleted_from_local_storage, manga.title),
|
this,
|
||||||
|
getString(R.string._s_deleted_from_local_storage, manga.title),
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
finishAfterTransition()
|
finishAfterTransition()
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ package org.koitharu.kotatsu.favourites.ui.categories.select
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
@@ -26,7 +28,8 @@ class FavouriteCategoriesBottomSheet :
|
|||||||
BaseBottomSheet<DialogFavoriteCategoriesBinding>(),
|
BaseBottomSheet<DialogFavoriteCategoriesBinding>(),
|
||||||
OnListItemClickListener<MangaCategoryItem>,
|
OnListItemClickListener<MangaCategoryItem>,
|
||||||
CategoriesEditDelegate.CategoriesEditCallback,
|
CategoriesEditDelegate.CategoriesEditCallback,
|
||||||
View.OnClickListener {
|
View.OnClickListener,
|
||||||
|
Toolbar.OnMenuItemClickListener {
|
||||||
|
|
||||||
private val viewModel by viewModel<MangaCategoriesViewModel> {
|
private val viewModel by viewModel<MangaCategoriesViewModel> {
|
||||||
parametersOf(requireNotNull(arguments?.getParcelableArrayList<ParcelableManga>(KEY_MANGA_LIST)).map { it.manga })
|
parametersOf(requireNotNull(arguments?.getParcelableArrayList<ParcelableManga>(KEY_MANGA_LIST)).map { it.manga })
|
||||||
@@ -44,7 +47,7 @@ class FavouriteCategoriesBottomSheet :
|
|||||||
adapter = MangaCategoriesAdapter(this)
|
adapter = MangaCategoriesAdapter(this)
|
||||||
binding.recyclerViewCategories.adapter = adapter
|
binding.recyclerViewCategories.adapter = adapter
|
||||||
binding.buttonDone.setOnClickListener(this)
|
binding.buttonDone.setOnClickListener(this)
|
||||||
binding.itemCreate.setOnClickListener(this)
|
binding.toolbar.setOnMenuItemClickListener(this)
|
||||||
|
|
||||||
viewModel.content.observe(viewLifecycleOwner, this::onContentChanged)
|
viewModel.content.observe(viewLifecycleOwner, this::onContentChanged)
|
||||||
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
||||||
@@ -57,11 +60,18 @@ class FavouriteCategoriesBottomSheet :
|
|||||||
|
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.item_create -> startActivity(FavouritesCategoryEditActivity.newIntent(requireContext()))
|
|
||||||
R.id.button_done -> dismiss()
|
R.id.button_done -> dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.action_create -> startActivity(FavouritesCategoryEditActivity.newIntent(requireContext()))
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
override fun onItemClick(item: MangaCategoryItem, view: View) {
|
override fun onItemClick(item: MangaCategoryItem, view: View) {
|
||||||
viewModel.setChecked(item.id, !item.isChecked)
|
viewModel.setChecked(item.id, !item.isChecked)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ abstract class MangaListFragment :
|
|||||||
|
|
||||||
override fun onInflateView(
|
override fun onInflateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?
|
container: ViewGroup?,
|
||||||
) = FragmentListBinding.inflate(inflater, container, false)
|
) = FragmentListBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
@@ -76,13 +76,13 @@ abstract class MangaListFragment :
|
|||||||
listAdapter = MangaListAdapter(
|
listAdapter = MangaListAdapter(
|
||||||
coil = get(),
|
coil = get(),
|
||||||
lifecycleOwner = viewLifecycleOwner,
|
lifecycleOwner = viewLifecycleOwner,
|
||||||
listener = this,
|
listener = this
|
||||||
)
|
)
|
||||||
selectionController = ListSelectionController(
|
selectionController = ListSelectionController(
|
||||||
activity = requireActivity(),
|
activity = requireActivity(),
|
||||||
decoration = MangaSelectionDecoration(view.context),
|
decoration = MangaSelectionDecoration(view.context),
|
||||||
registryOwner = this,
|
registryOwner = this,
|
||||||
callback = this,
|
callback = this
|
||||||
)
|
)
|
||||||
paginationListener = PaginationScrollListener(4, this)
|
paginationListener = PaginationScrollListener(4, this)
|
||||||
with(binding.recyclerView) {
|
with(binding.recyclerView) {
|
||||||
@@ -97,7 +97,7 @@ abstract class MangaListFragment :
|
|||||||
setOnRefreshListener(this@MangaListFragment)
|
setOnRefreshListener(this@MangaListFragment)
|
||||||
isEnabled = isSwipeRefreshEnabled
|
isEnabled = isSwipeRefreshEnabled
|
||||||
}
|
}
|
||||||
addMenuProvider(MangaListMenuProvider(childFragmentManager))
|
addMenuProvider(MangaListMenuProvider(this))
|
||||||
|
|
||||||
viewModel.listMode.observe(viewLifecycleOwner, ::onListModeChanged)
|
viewModel.listMode.observe(viewLifecycleOwner, ::onListModeChanged)
|
||||||
viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged)
|
viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged)
|
||||||
@@ -171,21 +171,21 @@ abstract class MangaListFragment :
|
|||||||
val headerHeight = (activity as? AppBarOwner)?.appBar?.measureHeight() ?: insets.top
|
val headerHeight = (activity as? AppBarOwner)?.appBar?.measureHeight() ?: insets.top
|
||||||
binding.root.updatePadding(
|
binding.root.updatePadding(
|
||||||
left = insets.left,
|
left = insets.left,
|
||||||
right = insets.right,
|
right = insets.right
|
||||||
)
|
)
|
||||||
if (activity is MainActivity) {
|
if (activity is MainActivity) {
|
||||||
binding.recyclerView.updatePadding(
|
binding.recyclerView.updatePadding(
|
||||||
top = headerHeight,
|
top = headerHeight,
|
||||||
bottom = insets.bottom,
|
bottom = insets.bottom
|
||||||
)
|
)
|
||||||
binding.swipeRefreshLayout.setProgressViewOffset(
|
binding.swipeRefreshLayout.setProgressViewOffset(
|
||||||
true,
|
true,
|
||||||
headerHeight + resources.resolveDp(-72),
|
headerHeight + resources.resolveDp(-72),
|
||||||
headerHeight + resources.resolveDp(10),
|
headerHeight + resources.resolveDp(10)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
binding.recyclerView.updatePadding(
|
binding.recyclerView.updatePadding(
|
||||||
bottom = insets.bottom,
|
bottom = insets.bottom
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import android.view.Menu
|
|||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.core.view.MenuProvider
|
import androidx.core.view.MenuProvider
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.Fragment
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
|
|
||||||
class MangaListMenuProvider(
|
class MangaListMenuProvider(
|
||||||
private val fragmentManager: FragmentManager,
|
private val fragment: Fragment,
|
||||||
) : MenuProvider {
|
) : MenuProvider {
|
||||||
|
|
||||||
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||||
@@ -17,7 +17,7 @@ class MangaListMenuProvider(
|
|||||||
|
|
||||||
override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) {
|
override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) {
|
||||||
R.id.action_list_mode -> {
|
R.id.action_list_mode -> {
|
||||||
ListModeSelectDialog.show(fragmentManager)
|
ListModeSelectDialog.show(fragment.childFragmentManager)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else -> false
|
else -> false
|
||||||
|
|||||||
@@ -166,10 +166,9 @@ class ReaderActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.action_save_page -> {
|
R.id.action_save_page -> {
|
||||||
viewModel.getCurrentPage()?.also { page ->
|
|
||||||
viewModel.saveCurrentState(readerManager.currentReader?.getCurrentState())
|
viewModel.saveCurrentState(readerManager.currentReader?.getCurrentState())
|
||||||
|
val page = viewModel.getCurrentPage() ?: return false
|
||||||
viewModel.saveCurrentPage(page, savePageRequest)
|
viewModel.saveCurrentPage(page, savePageRequest)
|
||||||
} ?: return false
|
|
||||||
}
|
}
|
||||||
R.id.action_bookmark -> {
|
R.id.action_bookmark -> {
|
||||||
if (viewModel.isBookmarkAdded.value == true) {
|
if (viewModel.isBookmarkAdded.value == true) {
|
||||||
|
|||||||
12
app/src/main/res/drawable/ic_list_create.xml
Normal file
12
app/src/main/res/drawable/ic_list_create.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#000"
|
||||||
|
android:pathData="M3 16H10V14H3M18 14V10H16V14H12V16H16V20H18V16H22V14M14 6H3V8H14M14 10H3V12H14V10Z" />
|
||||||
|
</vector>
|
||||||
@@ -217,7 +217,7 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/recyclerView_bookmarks"
|
app:layout_constraintTop_toBottomOf="@id/recyclerView_bookmarks"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<TextView
|
<org.koitharu.kotatsu.base.ui.widgets.SelectableTextView
|
||||||
android:id="@+id/textView_description"
|
android:id="@+id/textView_description"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
<com.google.android.material.navigation.NavigationView
|
<com.google.android.material.navigation.NavigationView
|
||||||
android:id="@+id/navigationView"
|
android:id="@+id/navigationView"
|
||||||
android:layout_width="260dp"
|
android:layout_width="230dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fitsSystemWindows="false"
|
android:fitsSystemWindows="false"
|
||||||
app:drawerLayoutCornerSize="0dp"
|
app:drawerLayoutCornerSize="0dp"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:menu="@menu/opt_categories"
|
||||||
app:title="@string/add_to_favourites">
|
app:title="@string/add_to_favourites">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@@ -35,15 +36,4 @@
|
|||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
tools:listitem="@layout/item_checkable_new" />
|
tools:listitem="@layout/item_checkable_new" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/item_create"
|
|
||||||
style="?listItemTextViewStyle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?android:listPreferredItemHeightSmall"
|
|
||||||
android:background="?selectableItemBackground"
|
|
||||||
android:paddingStart="?android:listPreferredItemPaddingStart"
|
|
||||||
android:paddingEnd="?android:listPreferredItemPaddingEnd"
|
|
||||||
android:text="@string/create_category"
|
|
||||||
android:textAppearance="?attr/textAppearanceButton" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -40,8 +40,6 @@
|
|||||||
android:maxLines="4"
|
android:maxLines="4"
|
||||||
android:padding="@dimen/margin_normal"
|
android:padding="@dimen/margin_normal"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
android:textAppearance="@style/TextAppearance.Design.Snackbar.Message"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
tools:text="Look at all the wonderful snack bar text..." />
|
tools:text="Look at all the wonderful snack bar text..." />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@@ -53,7 +51,6 @@
|
|||||||
android:paddingStart="@dimen/margin_normal"
|
android:paddingStart="@dimen/margin_normal"
|
||||||
android:paddingEnd="@dimen/margin_normal"
|
android:paddingEnd="@dimen/margin_normal"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:targetApi="o"
|
|
||||||
tools:text="Action"
|
tools:text="Action"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
|||||||
@@ -214,7 +214,7 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/recyclerView_bookmarks"
|
app:layout_constraintTop_toBottomOf="@id/recyclerView_bookmarks"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<TextView
|
<org.koitharu.kotatsu.base.ui.widgets.SelectableTextView
|
||||||
android:id="@+id/textView_description"
|
android:id="@+id/textView_description"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
12
app/src/main/res/menu/opt_categories.xml
Normal file
12
app/src/main/res/menu/opt_categories.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_create"
|
||||||
|
android:icon="@drawable/ic_list_create"
|
||||||
|
android:title="@string/create_category"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
@@ -317,4 +317,5 @@
|
|||||||
<string name="invalid_domain_message">Ungültige Domäne</string>
|
<string name="invalid_domain_message">Ungültige Domäne</string>
|
||||||
<string name="status_reading">Lesen</string>
|
<string name="status_reading">Lesen</string>
|
||||||
<string name="select_range">Bereich auswählen</string>
|
<string name="select_range">Bereich auswählen</string>
|
||||||
|
<string name="not_found_404">Inhalt nicht gefunden oder entfernt</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -309,4 +309,5 @@
|
|||||||
<string name="data_deletion">Tietojen poistaminen</string>
|
<string name="data_deletion">Tietojen poistaminen</string>
|
||||||
<string name="show_all">Näytä kaikki</string>
|
<string name="show_all">Näytä kaikki</string>
|
||||||
<string name="select_range">Valitse alue</string>
|
<string name="select_range">Valitse alue</string>
|
||||||
|
<string name="not_found_404">Sisältöä ei löydy tai se on poistettu</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -319,4 +319,5 @@
|
|||||||
<string name="status_re_reading">Relecture</string>
|
<string name="status_re_reading">Relecture</string>
|
||||||
<string name="invalid_domain_message">Domaine invalide</string>
|
<string name="invalid_domain_message">Domaine invalide</string>
|
||||||
<string name="select_range">Sélectionner une plage</string>
|
<string name="select_range">Sélectionner une plage</string>
|
||||||
|
<string name="not_found_404">Contenu non trouvé ou supprimé</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -319,4 +319,5 @@
|
|||||||
<string name="status_dropped">Abbandonato</string>
|
<string name="status_dropped">Abbandonato</string>
|
||||||
<string name="invalid_domain_message">Dominio non valido</string>
|
<string name="invalid_domain_message">Dominio non valido</string>
|
||||||
<string name="select_range">Seleziona l\'intervallo</string>
|
<string name="select_range">Seleziona l\'intervallo</string>
|
||||||
|
<string name="not_found_404">Contenuto non trovato o rimosso</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -318,4 +318,6 @@
|
|||||||
<string name="exclude_nsfw_from_history_summary">NSFWとマークされたマンガは履歴に追加されず、進行状況も保存されない</string>
|
<string name="exclude_nsfw_from_history_summary">NSFWとマークされたマンガは履歴に追加されず、進行状況も保存されない</string>
|
||||||
<string name="show_all">すべて表示</string>
|
<string name="show_all">すべて表示</string>
|
||||||
<string name="invalid_domain_message">無効なドメイン</string>
|
<string name="invalid_domain_message">無効なドメイン</string>
|
||||||
|
<string name="select_range">範囲を選択</string>
|
||||||
|
<string name="not_found_404">コンテンツが見つからない、または削除された</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -319,4 +319,5 @@
|
|||||||
<string name="show_all">Tümünü göster</string>
|
<string name="show_all">Tümünü göster</string>
|
||||||
<string name="invalid_domain_message">Geçersiz etki alanı</string>
|
<string name="invalid_domain_message">Geçersiz etki alanı</string>
|
||||||
<string name="select_range">Aralık seç</string>
|
<string name="select_range">Aralık seç</string>
|
||||||
|
<string name="not_found_404">İçerik bulunamadı veya kaldırıldı</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -318,4 +318,6 @@
|
|||||||
<string name="exclude_nsfw_from_history_summary">Манґа, позначена як NSFW, ніколи не буде додана до історії і ваш прогрес не буде збережений</string>
|
<string name="exclude_nsfw_from_history_summary">Манґа, позначена як NSFW, ніколи не буде додана до історії і ваш прогрес не буде збережений</string>
|
||||||
<string name="clear_cookies_summary">Може допомогти в разі виникнення проблем. Усі авторизації будуть анульовані</string>
|
<string name="clear_cookies_summary">Може допомогти в разі виникнення проблем. Усі авторизації будуть анульовані</string>
|
||||||
<string name="show_all">Показати всі</string>
|
<string name="show_all">Показати всі</string>
|
||||||
|
<string name="select_range">Виберіть діапазон</string>
|
||||||
|
<string name="not_found_404">Вміст не знайдено або видалено</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user