Merge branch 'devel' of https://github.com/nv95/Kotatsu into devel
8
.idea/compiler.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel>
|
||||
<module name="Kotatsu.app" target="1.8" />
|
||||
</bytecodeTargetLevel>
|
||||
</component>
|
||||
</project>
|
||||
1
.idea/gradle.xml
generated
@@ -15,6 +15,7 @@
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
<option name="useQualifiedModuleNames" value="true" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
||||
@@ -81,7 +81,7 @@ dependencies {
|
||||
implementation 'com.github.moxy-community:moxy-ktx:2.1.2'
|
||||
kapt 'com.github.moxy-community:moxy-compiler:2.1.2'
|
||||
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.5.0'
|
||||
implementation 'com.squareup.okio:okio:2.5.0'
|
||||
implementation 'org.jsoup:jsoup:1.13.1'
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaChapter
|
||||
import org.koitharu.kotatsu.utils.ext.sub
|
||||
import org.koitharu.kotatsu.utils.ext.takeIfReadable
|
||||
import org.koitharu.kotatsu.utils.ext.toFileName
|
||||
import org.koitharu.kotatsu.utils.ext.toFileNameSafe
|
||||
import java.io.File
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
@@ -91,7 +91,7 @@ class MangaZip(val file: File) {
|
||||
const val INDEX_ENTRY = "index.json"
|
||||
|
||||
fun findInDir(root: File, manga: Manga): MangaZip {
|
||||
val name = manga.title.toFileName() + ".cbz"
|
||||
val name = manga.title.toFileNameSafe() + ".cbz"
|
||||
val file = File(root, name)
|
||||
return MangaZip(file)
|
||||
}
|
||||
|
||||
@@ -25,10 +25,9 @@ import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.ui.browser.BrowserActivity
|
||||
import org.koitharu.kotatsu.ui.common.BaseActivity
|
||||
import org.koitharu.kotatsu.ui.download.DownloadService
|
||||
import org.koitharu.kotatsu.utils.MangaShortcut
|
||||
import org.koitharu.kotatsu.utils.ShareHelper
|
||||
import org.koitharu.kotatsu.utils.ShortcutUtils
|
||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.utils.ext.showDialog
|
||||
|
||||
class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
|
||||
|
||||
@@ -119,14 +118,14 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
|
||||
}
|
||||
R.id.action_delete -> {
|
||||
manga?.let { m ->
|
||||
showDialog {
|
||||
setTitle(R.string.delete_manga)
|
||||
setMessage(getString(R.string.text_delete_local_manga, m.title))
|
||||
setPositiveButton(R.string.delete) { _, _ ->
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.delete_manga)
|
||||
.setMessage(getString(R.string.text_delete_local_manga, m.title))
|
||||
.setPositiveButton(R.string.delete) { _, _ ->
|
||||
presenter.deleteLocal(m)
|
||||
}
|
||||
setNegativeButton(android.R.string.cancel, null)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
true
|
||||
}
|
||||
@@ -156,7 +155,7 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
|
||||
R.id.action_shortcut -> {
|
||||
manga?.let {
|
||||
lifecycleScope.launch {
|
||||
if (!ShortcutUtils.requestPinShortcut(this@MangaDetailsActivity, manga)) {
|
||||
if (!MangaShortcut(it).requestPinShortcut(this@MangaDetailsActivity)) {
|
||||
Snackbar.make(
|
||||
pager,
|
||||
R.string.operation_not_supported,
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.koitharu.kotatsu.core.model.MangaHistory
|
||||
import org.koitharu.kotatsu.domain.history.HistoryRepository
|
||||
import org.koitharu.kotatsu.ui.common.BasePresenter
|
||||
import org.koitharu.kotatsu.ui.main.list.MangaListView
|
||||
import org.koitharu.kotatsu.utils.ShortcutUtils
|
||||
import org.koitharu.kotatsu.utils.MangaShortcut
|
||||
|
||||
@InjectViewState
|
||||
class HistoryListPresenter : BasePresenter<MangaListView<MangaHistory>>() {
|
||||
@@ -62,7 +62,7 @@ class HistoryListPresenter : BasePresenter<MangaListView<MangaHistory>>() {
|
||||
repository.clear()
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
ShortcutUtils.clearAppShortcuts(get())
|
||||
MangaShortcut.clearAppShortcuts(get())
|
||||
}
|
||||
viewState.onListChanged(emptyList())
|
||||
} catch (_: CancellationException) {
|
||||
@@ -84,7 +84,7 @@ class HistoryListPresenter : BasePresenter<MangaListView<MangaHistory>>() {
|
||||
repository.delete(manga)
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
ShortcutUtils.removeAppShortcut(get(), manga)
|
||||
MangaShortcut(manga).removeAppShortcut(get())
|
||||
}
|
||||
viewState.onItemRemoved(manga)
|
||||
} catch (_: CancellationException) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.content.Intent
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.android.synthetic.main.fragment_list.*
|
||||
import moxy.ktx.moxyPresenter
|
||||
@@ -14,7 +15,6 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.ui.main.list.MangaListFragment
|
||||
import org.koitharu.kotatsu.utils.ext.ellipsize
|
||||
import org.koitharu.kotatsu.utils.ext.showDialog
|
||||
import java.io.File
|
||||
|
||||
class LocalListFragment : MangaListFragment<File>() {
|
||||
@@ -81,14 +81,14 @@ class LocalListFragment : MangaListFragment<File>() {
|
||||
override fun onPopupMenuItemSelected(item: MenuItem, data: Manga): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.action_delete -> {
|
||||
context?.showDialog {
|
||||
setTitle(R.string.delete_manga)
|
||||
setMessage(getString(R.string.text_delete_local_manga, data.title))
|
||||
setPositiveButton(R.string.delete) { _, _ ->
|
||||
AlertDialog.Builder(context ?: return false)
|
||||
.setTitle(R.string.delete_manga)
|
||||
.setMessage(getString(R.string.text_delete_local_manga, data.title))
|
||||
.setPositiveButton(R.string.delete) { _, _ ->
|
||||
presenter.delete(data)
|
||||
}
|
||||
setNegativeButton(android.R.string.cancel, null)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
true
|
||||
}
|
||||
else -> super.onPopupMenuItemSelected(item, data)
|
||||
|
||||
@@ -19,8 +19,8 @@ import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.domain.history.HistoryRepository
|
||||
import org.koitharu.kotatsu.ui.common.BasePresenter
|
||||
import org.koitharu.kotatsu.ui.main.list.MangaListView
|
||||
import org.koitharu.kotatsu.utils.MangaShortcut
|
||||
import org.koitharu.kotatsu.utils.MediaStoreCompat
|
||||
import org.koitharu.kotatsu.utils.ShortcutUtils
|
||||
import org.koitharu.kotatsu.utils.ext.safe
|
||||
import org.koitharu.kotatsu.utils.ext.sub
|
||||
import java.io.File
|
||||
@@ -98,7 +98,7 @@ class LocalListPresenter : BasePresenter<MangaListView<File>>() {
|
||||
}
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
ShortcutUtils.removeAppShortcut(get(), manga)
|
||||
MangaShortcut(manga).removeAppShortcut(get())
|
||||
}
|
||||
viewState.onItemRemoved(manga)
|
||||
} catch (e: CancellationException) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.postDelayed
|
||||
import androidx.core.view.updatePadding
|
||||
@@ -34,8 +35,8 @@ import org.koitharu.kotatsu.ui.reader.thumbnails.OnPageSelectListener
|
||||
import org.koitharu.kotatsu.ui.reader.thumbnails.PagesThumbnailsSheet
|
||||
import org.koitharu.kotatsu.ui.reader.wetoon.WebtoonReaderFragment
|
||||
import org.koitharu.kotatsu.utils.GridTouchHelper
|
||||
import org.koitharu.kotatsu.utils.MangaShortcut
|
||||
import org.koitharu.kotatsu.utils.ShareHelper
|
||||
import org.koitharu.kotatsu.utils.ShortcutUtils
|
||||
import org.koitharu.kotatsu.utils.anim.Motion
|
||||
import org.koitharu.kotatsu.utils.ext.*
|
||||
|
||||
@@ -91,7 +92,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
GlobalScope.launch {
|
||||
safe {
|
||||
ShortcutUtils.addAppShortcut(applicationContext, state.manga)
|
||||
MangaShortcut(state.manga).addAppShortcut(applicationContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,16 +208,16 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
showDialog {
|
||||
setTitle(R.string.error_occurred)
|
||||
setMessage(e.message)
|
||||
setPositiveButton(R.string.close, null)
|
||||
if (reader?.hasItems != true) {
|
||||
setOnDismissListener {
|
||||
finish()
|
||||
}
|
||||
val dialog = AlertDialog.Builder(this)
|
||||
.setTitle(R.string.error_occurred)
|
||||
.setMessage(e.message)
|
||||
.setPositiveButton(R.string.close, null)
|
||||
if (reader?.hasItems != true) {
|
||||
dialog.setOnDismissListener {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
override fun onGridTouch(area: Int) {
|
||||
@@ -225,11 +226,13 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
||||
setUiIsVisible(!appbar_top.isVisible)
|
||||
}
|
||||
GridTouchHelper.AREA_TOP,
|
||||
GridTouchHelper.AREA_LEFT -> if (isTapSwitchEnabled) {
|
||||
GridTouchHelper.AREA_LEFT,
|
||||
-> if (isTapSwitchEnabled) {
|
||||
reader?.switchPageBy(-1)
|
||||
}
|
||||
GridTouchHelper.AREA_BOTTOM,
|
||||
GridTouchHelper.AREA_RIGHT -> if (isTapSwitchEnabled) {
|
||||
GridTouchHelper.AREA_RIGHT,
|
||||
-> if (isTapSwitchEnabled) {
|
||||
reader?.switchPageBy(1)
|
||||
}
|
||||
}
|
||||
@@ -267,13 +270,15 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
||||
KeyEvent.KEYCODE_SPACE,
|
||||
KeyEvent.KEYCODE_PAGE_DOWN,
|
||||
KeyEvent.KEYCODE_DPAD_DOWN,
|
||||
KeyEvent.KEYCODE_DPAD_RIGHT -> {
|
||||
KeyEvent.KEYCODE_DPAD_RIGHT,
|
||||
-> {
|
||||
reader?.switchPageBy(1)
|
||||
true
|
||||
}
|
||||
KeyEvent.KEYCODE_PAGE_UP,
|
||||
KeyEvent.KEYCODE_DPAD_UP,
|
||||
KeyEvent.KEYCODE_DPAD_LEFT -> {
|
||||
KeyEvent.KEYCODE_DPAD_LEFT,
|
||||
-> {
|
||||
reader?.switchPageBy(-1)
|
||||
true
|
||||
}
|
||||
|
||||
@@ -22,25 +22,18 @@ import org.koitharu.kotatsu.domain.MangaDataRepository
|
||||
import org.koitharu.kotatsu.ui.details.MangaDetailsActivity
|
||||
import org.koitharu.kotatsu.utils.ext.safe
|
||||
|
||||
object ShortcutUtils {
|
||||
class MangaShortcut(private val manga: Manga) {
|
||||
|
||||
suspend fun requestPinShortcut(context: Context, manga: Manga?): Boolean {
|
||||
return manga != null && ShortcutManagerCompat.requestPinShortcut(
|
||||
context,
|
||||
buildShortcutInfo(context, manga).build(),
|
||||
null
|
||||
)
|
||||
}
|
||||
private val shortcutId = manga.id.toString()
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N_MR1)
|
||||
suspend fun addAppShortcut(context: Context, manga: Manga) {
|
||||
val id = manga.id.toString()
|
||||
val builder = buildShortcutInfo(context, manga)
|
||||
suspend fun addAppShortcut(context: Context) {
|
||||
val manager = context.getSystemService(Context.SHORTCUT_SERVICE) as ShortcutManager
|
||||
val limit = manager.maxShortcutCountPerActivity
|
||||
val builder = buildShortcutInfo(context, manga)
|
||||
val shortcuts = manager.dynamicShortcuts
|
||||
for (shortcut in shortcuts) {
|
||||
if (shortcut.id == id) {
|
||||
if (shortcut.id == shortcutId) {
|
||||
builder.setRank(shortcut.rank + 1)
|
||||
manager.updateShortcuts(listOf(builder.build().toShortcutInfo()))
|
||||
return
|
||||
@@ -53,22 +46,23 @@ object ShortcutUtils {
|
||||
manager.addDynamicShortcuts(listOf(builder.build().toShortcutInfo()))
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N_MR1)
|
||||
fun removeAppShortcut(context: Context, manga: Manga) {
|
||||
val id = manga.id.toString()
|
||||
val manager = context.getSystemService(Context.SHORTCUT_SERVICE) as ShortcutManager
|
||||
manager.removeDynamicShortcuts(listOf(id))
|
||||
suspend fun requestPinShortcut(context: Context): Boolean {
|
||||
return ShortcutManagerCompat.requestPinShortcut(
|
||||
context,
|
||||
buildShortcutInfo(context, manga).build(),
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N_MR1)
|
||||
fun clearAppShortcuts(context: Context) {
|
||||
fun removeAppShortcut(context: Context) {
|
||||
val manager = context.getSystemService(Context.SHORTCUT_SERVICE) as ShortcutManager
|
||||
manager.removeAllDynamicShortcuts()
|
||||
manager.removeDynamicShortcuts(listOf(shortcutId))
|
||||
}
|
||||
|
||||
private suspend fun buildShortcutInfo(
|
||||
context: Context,
|
||||
manga: Manga
|
||||
manga: Manga,
|
||||
): ShortcutInfoCompat.Builder {
|
||||
val icon = safe {
|
||||
val size = getIconSize(context)
|
||||
@@ -77,12 +71,7 @@ object ShortcutUtils {
|
||||
size(size)
|
||||
scale(Scale.FILL)
|
||||
}.toBitmap()
|
||||
ThumbnailUtils.extractThumbnail(
|
||||
bmp,
|
||||
size.width,
|
||||
size.height,
|
||||
0
|
||||
)
|
||||
ThumbnailUtils.extractThumbnail(bmp, size.width, size.height, 0)
|
||||
}
|
||||
}
|
||||
MangaDataRepository().storeManga(manga)
|
||||
@@ -109,4 +98,13 @@ object ShortcutUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N_MR1)
|
||||
fun clearAppShortcuts(context: Context) {
|
||||
val manager = context.getSystemService(Context.SHORTCUT_SERVICE) as ShortcutManager
|
||||
manager.removeAllDynamicShortcuts()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
package org.koitharu.kotatsu.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.view.View
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.koitharu.kotatsu.R
|
||||
@@ -14,16 +12,6 @@ import kotlin.math.roundToInt
|
||||
|
||||
object UiUtils {
|
||||
|
||||
@JvmStatic
|
||||
@ColorInt
|
||||
fun invertColor(@ColorInt color: Int): Int {
|
||||
val red = Color.red(color)
|
||||
val green = Color.green(color)
|
||||
val blue = Color.blue(color)
|
||||
val alpha = Color.alpha(color)
|
||||
return Color.argb(alpha, 255 - red, 255 - green, 255 - blue)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun resolveGridSpanCount(context: Context, width: Int = 0): Int {
|
||||
val scaleFactor = AppSettings(context).gridSize / 100f
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils.ext
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
|
||||
@Deprecated("Useless")
|
||||
fun Context.showDialog(block: AlertDialog.Builder.() -> Unit): AlertDialog {
|
||||
return AlertDialog.Builder(this)
|
||||
.apply(block)
|
||||
.show()
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import okhttp3.internal.closeQuietly
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
fun Response.parseHtml(): Document {
|
||||
try {
|
||||
@@ -28,6 +27,4 @@ fun Response.parseJson(): JSONObject {
|
||||
} finally {
|
||||
closeQuietly()
|
||||
}
|
||||
}
|
||||
|
||||
fun Element.firstChild(): Element? = children().first()
|
||||
}
|
||||
@@ -4,8 +4,6 @@ import java.text.DecimalFormat
|
||||
import java.text.NumberFormat
|
||||
import java.util.*
|
||||
|
||||
fun Number?.asBoolean() = (this?.toInt() ?: 0) > 0
|
||||
|
||||
fun Number.format(decimals: Int = 0, decPoint: Char = '.', thousandsSep: Char? = ' '): String {
|
||||
val formatter = NumberFormat.getInstance(Locale.US) as DecimalFormat
|
||||
val symbols = formatter.decimalFormatSymbols
|
||||
|
||||
@@ -57,7 +57,7 @@ fun String.transliterate(skipMissing: Boolean): String {
|
||||
}
|
||||
}
|
||||
|
||||
fun String.toFileName() = this.transliterate(false)
|
||||
fun String.toFileNameSafe() = this.transliterate(false)
|
||||
.replace(Regex("[^a-z0-9_\\-]", setOf(RegexOption.IGNORE_CASE)), " ")
|
||||
.replace(Regex("\\s+"), "_")
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ fun Context.getThemeDrawable(@AttrRes resId: Int) = obtainStyledAttributes(intAr
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
fun Context.getThemeColor(@AttrRes resId: Int, @ColorInt default: Int = Color.TRANSPARENT) = obtainStyledAttributes(intArrayOf(resId)).use {
|
||||
it.getColor(0, default)
|
||||
}
|
||||
fun Context.getThemeColor(@AttrRes resId: Int, @ColorInt default: Int = Color.TRANSPARENT) =
|
||||
obtainStyledAttributes(intArrayOf(resId)).use {
|
||||
it.getColor(0, default)
|
||||
}
|
||||
@@ -2,11 +2,9 @@ package org.koitharu.kotatsu.utils.ext
|
||||
|
||||
import android.app.Activity
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.annotation.MenuRes
|
||||
@@ -23,7 +21,6 @@ import androidx.viewpager2.widget.ViewPager2
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.chip.ChipGroup
|
||||
import org.koitharu.kotatsu.ui.common.ChipsFactory
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
fun View.hideKeyboard() {
|
||||
val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
@@ -35,14 +32,9 @@ fun View.showKeyboard() {
|
||||
imm.showSoftInput(this, 0)
|
||||
}
|
||||
|
||||
val EditText.plainText
|
||||
get() = text?.toString().orEmpty()
|
||||
|
||||
inline fun <reified T : View> ViewGroup.inflate(@LayoutRes resId: Int) =
|
||||
LayoutInflater.from(context).inflate(resId, this, false) as T
|
||||
|
||||
val TextView.hasText get() = !text.isNullOrEmpty()
|
||||
|
||||
fun RecyclerView.lookupSpanSize(callback: (Int) -> Int) {
|
||||
(layoutManager as? GridLayoutManager)?.spanSizeLookup =
|
||||
object : GridLayoutManager.SpanSizeLookup() {
|
||||
@@ -53,20 +45,6 @@ fun RecyclerView.lookupSpanSize(callback: (Int) -> Int) {
|
||||
val RecyclerView.hasItems: Boolean
|
||||
get() = (adapter?.itemCount ?: 0) > 0
|
||||
|
||||
var TextView.drawableStart: Drawable?
|
||||
get() = compoundDrawablesRelative[0]
|
||||
set(value) {
|
||||
val old = compoundDrawablesRelative
|
||||
setCompoundDrawablesRelativeWithIntrinsicBounds(value, old[1], old[2], old[3])
|
||||
}
|
||||
|
||||
var TextView.drawableEnd: Drawable?
|
||||
get() = compoundDrawablesRelative[2]
|
||||
set(value) {
|
||||
val old = compoundDrawablesRelative
|
||||
setCompoundDrawablesRelativeWithIntrinsicBounds(old[0], old[1], value, old[3])
|
||||
}
|
||||
|
||||
var TextView.textAndVisible: CharSequence?
|
||||
get() = text?.takeIf { visibility == View.VISIBLE }
|
||||
set(value) {
|
||||
@@ -106,7 +84,7 @@ fun View.disableFor(timeInMillis: Long) {
|
||||
|
||||
fun View.showPopupMenu(
|
||||
@MenuRes menuRes: Int, onPrepare: ((Menu) -> Unit)? = null,
|
||||
onItemClick: (MenuItem) -> Boolean
|
||||
onItemClick: (MenuItem) -> Boolean,
|
||||
) {
|
||||
val menu = PopupMenu(context, this)
|
||||
menu.inflate(menuRes)
|
||||
@@ -221,11 +199,6 @@ fun ViewPager2.callOnPageChaneListeners() {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("")
|
||||
fun LinearLayoutManager.findMiddleVisibleItemPosition(): Int {
|
||||
return ((findFirstVisibleItemPosition() + findLastVisibleItemPosition()) / 2.0).roundToInt()
|
||||
}
|
||||
|
||||
fun RecyclerView.findCenterViewPosition(): Int {
|
||||
val centerX = width / 2f
|
||||
val centerY = height / 2f
|
||||
|
||||
@@ -2,16 +2,9 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="#FFFFFF"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<group
|
||||
android:scaleX="0.92"
|
||||
android:scaleY="0.92"
|
||||
android:translateX="0.96"
|
||||
android:translateY="0.96">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M18,22H6A2,2 0,0 1,4 20V4C4,2.89 4.9,2 6,2H7V9L9.5,7.5L12,9V2H18A2,2 0,0 1,20 4V20A2,2 0,0 1,18 22M14,20H16V18H18V16H16V14H14V16H12V18H14V20Z" />
|
||||
</group>
|
||||
</vector>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M4,6H2V20A2,2 0 0,0 4,22H18V20H4V6M20,2H8A2,2 0 0,0 6,4V16A2,2 0 0,0 8,18H20A2,2 0 0,0 22,16V4A2,2 0 0,0 20,2M20,12L17.5,10.5L15,12V4H20V12Z" />
|
||||
</vector>
|
||||
|
Before Width: | Height: | Size: 336 B After Width: | Height: | Size: 323 B |
|
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 291 B |
|
Before Width: | Height: | Size: 480 B After Width: | Height: | Size: 500 B |
|
Before Width: | Height: | Size: 629 B After Width: | Height: | Size: 592 B |
|
Before Width: | Height: | Size: 914 B After Width: | Height: | Size: 938 B |
@@ -9,7 +9,7 @@ buildscript {
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.0-beta03'
|
||||
classpath 'com.android.tools.build:gradle:4.1.0-alpha04'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||