Upgrade targetSdk to 33

pull/216/head v4.0-a3
Koitharu 4 years ago
parent b9f2effb86
commit 935826617e
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -7,16 +7,16 @@ plugins {
} }
android { android {
compileSdkVersion 32 compileSdkVersion 33
buildToolsVersion '32.0.0' buildToolsVersion '33.0.0'
namespace 'org.koitharu.kotatsu' namespace 'org.koitharu.kotatsu'
defaultConfig { defaultConfig {
applicationId 'org.koitharu.kotatsu' applicationId 'org.koitharu.kotatsu'
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 32 targetSdkVersion 33
versionCode 491 versionCode 492
versionName '4.0-a2' versionName '4.0-a3'
generatedDensities = [] generatedDensities = []
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -117,19 +117,19 @@ dependencies {
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl:4.3.2' implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl:4.3.2'
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:4.3.2' implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:4.3.2'
implementation "com.google.dagger:hilt-android:2.42" implementation "com.google.dagger:hilt-android:2.43.2"
kapt "com.google.dagger:hilt-compiler:2.42" kapt "com.google.dagger:hilt-compiler:2.43.2"
implementation 'androidx.hilt:hilt-work:1.0.0' implementation 'androidx.hilt:hilt-work:1.0.0'
kapt 'androidx.hilt:hilt-compiler:1.0.0' kapt 'androidx.hilt:hilt-compiler:1.0.0'
implementation 'io.coil-kt:coil-base:2.2.0' implementation 'io.coil-kt:coil-base:2.2.0'
implementation 'io.coil-kt:coil-svg:2.1.0' implementation 'io.coil-kt:coil-svg:2.2.0'
// implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0' // implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
implementation 'com.github.KotatsuApp:subsampling-scale-image-view:2942b797a2' implementation 'com.github.KotatsuApp:subsampling-scale-image-view:2942b797a2'
implementation 'com.github.solkin:disk-lru-cache:1.4' implementation 'com.github.solkin:disk-lru-cache:1.4'
implementation 'ch.acra:acra-http:5.9.5' implementation 'ch.acra:acra-http:5.9.6'
implementation 'ch.acra:acra-dialog:5.9.5' implementation 'ch.acra:acra-dialog:5.9.6'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1' debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
@ -147,6 +147,6 @@ dependencies {
androidTestImplementation 'androidx.room:room-testing:2.4.3' androidTestImplementation 'androidx.room:room-testing:2.4.3'
androidTestImplementation 'com.squareup.moshi:moshi-kotlin:1.13.0' androidTestImplementation 'com.squareup.moshi:moshi-kotlin:1.13.0'
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.42' androidTestImplementation 'com.google.dagger:hilt-android-testing:2.43.2'
kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.42' kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.43.2'
} }

@ -17,6 +17,7 @@
<uses-permission android:name="android.permission.READ_SYNC_STATS" /> <uses-permission android:name="android.permission.READ_SYNC_STATS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application <application
android:name="org.koitharu.kotatsu.KotatsuApp" android:name="org.koitharu.kotatsu.KotatsuApp"
@ -135,8 +136,8 @@
<service <service
android:name="org.koitharu.kotatsu.download.ui.service.DownloadService" android:name="org.koitharu.kotatsu.download.ui.service.DownloadService"
android:stopWithTask="false" android:foregroundServiceType="dataSync"
android:foregroundServiceType="dataSync" /> android:stopWithTask="false" />
<service android:name="org.koitharu.kotatsu.local.ui.LocalChaptersRemoveService" /> <service android:name="org.koitharu.kotatsu.local.ui.LocalChaptersRemoveService" />
<service android:name="org.koitharu.kotatsu.local.ui.ImportService" /> <service android:name="org.koitharu.kotatsu.local.ui.ImportService" />
<service <service

@ -5,6 +5,8 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.utils.ext.getParcelableCompat
import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat
class MangaIntent private constructor( class MangaIntent private constructor(
val manga: Manga?, val manga: Manga?,
@ -13,15 +15,15 @@ class MangaIntent private constructor(
) { ) {
constructor(intent: Intent?) : this( constructor(intent: Intent?) : this(
manga = intent?.getParcelableExtra<ParcelableManga>(KEY_MANGA)?.manga, manga = intent?.getParcelableExtraCompat<ParcelableManga>(KEY_MANGA)?.manga,
mangaId = intent?.getLongExtra(KEY_ID, ID_NONE) ?: ID_NONE, mangaId = intent?.getLongExtra(KEY_ID, ID_NONE) ?: ID_NONE,
uri = intent?.data uri = intent?.data,
) )
constructor(args: Bundle?) : this( constructor(args: Bundle?) : this(
manga = args?.getParcelable<ParcelableManga>(KEY_MANGA)?.manga, manga = args?.getParcelableCompat<ParcelableManga>(KEY_MANGA)?.manga,
mangaId = args?.getLong(KEY_ID, ID_NONE) ?: ID_NONE, mangaId = args?.getLong(KEY_ID, ID_NONE) ?: ID_NONE,
uri = null uri = null,
) )
companion object { companion object {

@ -8,16 +8,18 @@ import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import kotlin.math.hypot
import org.koitharu.kotatsu.utils.ext.animatorDurationScale import org.koitharu.kotatsu.utils.ext.animatorDurationScale
import org.koitharu.kotatsu.utils.ext.measureWidth import org.koitharu.kotatsu.utils.ext.measureWidth
import kotlin.math.hypot
class BubbleAnimator( class BubbleAnimator(
private val bubble: View, private val bubble: View,
) { ) {
private val animationDuration = (bubble.resources.getInteger(android.R.integer.config_shortAnimTime) * private val animationDuration = (
bubble.context.animatorDurationScale).toLong() bubble.resources.getInteger(android.R.integer.config_shortAnimTime) *
bubble.context.animatorDurationScale
).toLong()
private var animator: Animator? = null private var animator: Animator? = null
private var isHiding = false private var isHiding = false
@ -65,12 +67,12 @@ class BubbleAnimator(
private var isCancelled = false private var isCancelled = false
override fun onAnimationCancel(animation: Animator?) { override fun onAnimationCancel(animation: Animator) {
super.onAnimationCancel(animation) super.onAnimationCancel(animation)
isCancelled = true isCancelled = true
} }
override fun onAnimationEnd(animation: Animator?) { override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation) super.onAnimationEnd(animation)
if (!isCancelled && animation === this@BubbleAnimator.animator) { if (!isCancelled && animation === this@BubbleAnimator.animator) {
bubble.isInvisible = true bubble.isInvisible = true

@ -14,8 +14,10 @@ class ScrollbarAnimator(
private val scrollbarPaddingEnd: Float, private val scrollbarPaddingEnd: Float,
) { ) {
private val animationDuration = (scrollbar.resources.getInteger(R.integer.config_defaultAnimTime) * private val animationDuration = (
scrollbar.context.animatorDurationScale).toLong() scrollbar.resources.getInteger(R.integer.config_defaultAnimTime) *
scrollbar.context.animatorDurationScale
).toLong()
private var animator: ViewPropertyAnimator? = null private var animator: ViewPropertyAnimator? = null
private var isHiding = false private var isHiding = false
@ -40,26 +42,28 @@ class ScrollbarAnimator(
} }
animator?.cancel() animator?.cancel()
isHiding = true isHiding = true
animator = scrollbar animator = scrollbar.animate().apply {
.animate() translationX(scrollbarPaddingEnd)
.translationX(scrollbarPaddingEnd) alpha(0f)
.alpha(0f) duration = animationDuration
.setDuration(animationDuration) setListener(HideListener(this))
.setListener(HideListener()) }
} }
private inner class HideListener : AnimatorListenerAdapter() { private inner class HideListener(
private val viewPropertyAnimator: ViewPropertyAnimator,
) : AnimatorListenerAdapter() {
private var isCancelled = false private var isCancelled = false
override fun onAnimationCancel(animation: Animator?) { override fun onAnimationCancel(animation: Animator) {
super.onAnimationCancel(animation) super.onAnimationCancel(animation)
isCancelled = true isCancelled = true
} }
override fun onAnimationEnd(animation: Animator?) { override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation) super.onAnimationEnd(animation)
if (!isCancelled && animation === this@ScrollbarAnimator.animator) { if (!isCancelled && this@ScrollbarAnimator.animator === viewPropertyAnimator) {
scrollbar.isInvisible = true scrollbar.isInvisible = true
isHiding = false isHiding = false
this@ScrollbarAnimator.animator = null this@ScrollbarAnimator.animator = null

@ -100,7 +100,7 @@ class SlidingBottomNavigationView @JvmOverloads constructor(
.applySystemAnimatorScale(context) .applySystemAnimatorScale(context)
.setListener( .setListener(
object : AnimatorListenerAdapter() { object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator?) { override fun onAnimationEnd(animation: Animator) {
currentAnimator = null currentAnimator = null
postInvalidate() postInvalidate()
} }

@ -16,6 +16,8 @@ import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
import org.koitharu.kotatsu.databinding.DialogMangaErrorBinding import org.koitharu.kotatsu.databinding.DialogMangaErrorBinding
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.utils.ext.report import org.koitharu.kotatsu.utils.ext.report
import org.koitharu.kotatsu.utils.ext.requireParcelable
import org.koitharu.kotatsu.utils.ext.requireSerializable
import org.koitharu.kotatsu.utils.ext.withArgs import org.koitharu.kotatsu.utils.ext.withArgs
class MangaErrorDialog : AlertDialogFragment<DialogMangaErrorBinding>() { class MangaErrorDialog : AlertDialogFragment<DialogMangaErrorBinding>() {
@ -26,8 +28,8 @@ class MangaErrorDialog : AlertDialogFragment<DialogMangaErrorBinding>() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val args = requireArguments() val args = requireArguments()
manga = requireNotNull(args.getParcelable<ParcelableManga>(ARG_MANGA)?.manga) manga = args.requireParcelable<ParcelableManga>(ARG_MANGA).manga
error = args.getSerializable(ARG_ERROR) as Throwable error = args.requireSerializable(ARG_ERROR)
} }
override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): DialogMangaErrorBinding { override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): DialogMangaErrorBinding {

@ -35,13 +35,13 @@ class ChaptersMenuProvider(
else -> false else -> false
} }
override fun onMenuItemActionExpand(item: MenuItem?): Boolean { override fun onMenuItemActionExpand(item: MenuItem): Boolean {
bottomSheetMediator?.lock() bottomSheetMediator?.lock()
return true return true
} }
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
(item?.actionView as? SearchView)?.setQuery("", false) (item.actionView as? SearchView)?.setQuery("", false)
viewModel.performChapterSearch(null) viewModel.performChapterSearch(null)
bottomSheetMediator?.unlock() bottomSheetMediator?.unlock()
return true return true

@ -25,6 +25,7 @@ import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity
import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.assistedViewModels
import org.koitharu.kotatsu.utils.ext.getDisplayMessage import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import org.koitharu.kotatsu.utils.ext.getSerializableCompat
@AndroidEntryPoint @AndroidEntryPoint
class FavouritesCategoryEditActivity : class FavouritesCategoryEditActivity :
@ -69,8 +70,8 @@ class FavouritesCategoryEditActivity :
override fun onRestoreInstanceState(savedInstanceState: Bundle) { override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState) super.onRestoreInstanceState(savedInstanceState)
val order = savedInstanceState.getSerializable(KEY_SORT_ORDER) val order = savedInstanceState.getSerializableCompat<SortOrder>(KEY_SORT_ORDER)
if (order != null && order is SortOrder) { if (order != null) {
selectedSortOrder = order selectedSortOrder = order
} }
} }

@ -56,17 +56,17 @@ class ReadingProgressView @JvmOverloads constructor(
getProgressDrawable().progress = p getProgressDrawable().progress = p
} }
override fun onAnimationStart(animation: Animator?) = Unit override fun onAnimationStart(animation: Animator) = Unit
override fun onAnimationEnd(animation: Animator?) { override fun onAnimationEnd(animation: Animator) {
if (percentAnimator === animation) { if (percentAnimator === animation) {
percentAnimator = null percentAnimator = null
} }
} }
override fun onAnimationCancel(animation: Animator?) = Unit override fun onAnimationCancel(animation: Animator) = Unit
override fun onAnimationRepeat(animation: Animator?) = Unit override fun onAnimationRepeat(animation: Animator) = Unit
fun setPercent(value: Float, animate: Boolean) { fun setPercent(value: Float, animate: Boolean) {
val currentDrawable = peekProgressDrawable() val currentDrawable = peekProgressDrawable()

@ -47,12 +47,12 @@ class ItemSizeResolver(resources: Resources, private val settings: AppSettings)
} }
} }
override fun onViewAttachedToWindow(v: View?) { override fun onViewAttachedToWindow(v: View) {
settings.subscribe(this) settings.subscribe(this)
update() update()
} }
override fun onViewDetachedFromWindow(v: View?) { override fun onViewDetachedFromWindow(v: View) {
settings.unsubscribe(this) settings.unsubscribe(this)
} }

@ -6,7 +6,6 @@ import android.os.Bundle
import android.view.* import android.view.*
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseBottomSheet import org.koitharu.kotatsu.base.ui.BaseBottomSheet
import org.koitharu.kotatsu.databinding.SheetFilterBinding import org.koitharu.kotatsu.databinding.SheetFilterBinding
@ -39,7 +38,7 @@ class FilterBottomSheet :
initOptionsMenu() initOptionsMenu()
} }
override fun onMenuItemActionExpand(item: MenuItem?): Boolean { override fun onMenuItemActionExpand(item: MenuItem): Boolean {
setExpanded(isExpanded = true, isLocked = true) setExpanded(isExpanded = true, isLocked = true)
return true return true
} }

@ -1,5 +1,8 @@
package org.koitharu.kotatsu.main.ui package org.koitharu.kotatsu.main.ui
import android.Manifest
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.SparseIntArray import android.util.SparseIntArray
import android.view.MenuItem import android.view.MenuItem
@ -7,6 +10,7 @@ import android.view.View
import androidx.activity.result.ActivityResultCallback import androidx.activity.result.ActivityResultCallback
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.core.app.ActivityCompat
import androidx.core.app.ActivityOptionsCompat import androidx.core.app.ActivityOptionsCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
@ -24,7 +28,6 @@ import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.base.ui.BaseActivity
import org.koitharu.kotatsu.base.ui.widgets.SlidingBottomNavigationView import org.koitharu.kotatsu.base.ui.widgets.SlidingBottomNavigationView
@ -291,12 +294,11 @@ class MainActivity :
TrackWorker.setup(applicationContext) TrackWorker.setup(applicationContext)
SuggestionsWorker.setup(applicationContext) SuggestionsWorker.setup(applicationContext)
} }
requestNotificationsPermission()
when { when {
!settings.isSourcesSelected -> OnboardDialogFragment.showWelcome(supportFragmentManager) !settings.isSourcesSelected -> OnboardDialogFragment.showWelcome(supportFragmentManager)
settings.newSources.isNotEmpty() -> NewSourcesDialogFragment.show(supportFragmentManager) settings.newSources.isNotEmpty() -> NewSourcesDialogFragment.show(supportFragmentManager)
} }
yield()
// TODO get<SyncController>().requestFullSyncAndGc(get())
} }
} }
@ -347,6 +349,15 @@ class MainActivity :
showNav(!isOpened) showNav(!isOpened)
} }
private fun requestNotificationsPermission() {
if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.POST_NOTIFICATIONS), 1)
}
}
private inner class VoiceInputCallback : ActivityResultCallback<String?> { private inner class VoiceInputCallback : ActivityResultCallback<String?> {
override fun onActivityResult(result: String?) { override fun onActivityResult(result: String?) {

@ -9,11 +9,12 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.base.ui.BaseViewModel
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
import org.koitharu.kotatsu.core.github.AppUpdateRepository import org.koitharu.kotatsu.core.github.AppUpdateRepository
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.HistoryRepository
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.sync.domain.SyncController
import org.koitharu.kotatsu.tracker.domain.TrackingRepository import org.koitharu.kotatsu.tracker.domain.TrackingRepository
import org.koitharu.kotatsu.utils.SingleLiveEvent import org.koitharu.kotatsu.utils.SingleLiveEvent
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
@ -23,6 +24,8 @@ class MainViewModel @Inject constructor(
private val historyRepository: HistoryRepository, private val historyRepository: HistoryRepository,
private val appUpdateRepository: AppUpdateRepository, private val appUpdateRepository: AppUpdateRepository,
private val trackingRepository: TrackingRepository, private val trackingRepository: TrackingRepository,
syncController: SyncController,
database: MangaDatabase,
) : BaseViewModel() { ) : BaseViewModel() {
val onOpenReader = SingleLiveEvent<Manga>() val onOpenReader = SingleLiveEvent<Manga>()
@ -45,6 +48,9 @@ class MainViewModel @Inject constructor(
launchJob { launchJob {
appUpdateRepository.fetchUpdate() appUpdateRepository.fetchUpdate()
} }
launchJob {
syncController.requestFullSyncAndGc(database)
}
} }
fun openLastReader() { fun openLastReader() {

@ -22,6 +22,7 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.base.ui.BaseActivity
import org.koitharu.kotatsu.databinding.ActivityProtectBinding import org.koitharu.kotatsu.databinding.ActivityProtectBinding
import org.koitharu.kotatsu.utils.ext.getDisplayMessage import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat
@AndroidEntryPoint @AndroidEntryPoint
class ProtectActivity : class ProtectActivity :
@ -44,7 +45,7 @@ class ProtectActivity :
viewModel.onError.observe(this, this::onError) viewModel.onError.observe(this, this::onError)
viewModel.isLoading.observe(this, this::onLoadingStateChanged) viewModel.isLoading.observe(this, this::onLoadingStateChanged)
viewModel.onUnlockSuccess.observe(this) { viewModel.onUnlockSuccess.observe(this) {
val intent = intent.getParcelableExtra<Intent>(EXTRA_INTENT) val intent = intent.getParcelableExtraCompat<Intent>(EXTRA_INTENT)
startActivity(intent) startActivity(intent)
finishAfterTransition() finishAfterTransition()
} }

@ -6,6 +6,8 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import kotlin.math.roundToInt
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseBottomSheet import org.koitharu.kotatsu.base.ui.BaseBottomSheet
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
@ -17,9 +19,8 @@ import org.koitharu.kotatsu.details.ui.model.ChapterListItem
import org.koitharu.kotatsu.details.ui.model.toListItem import org.koitharu.kotatsu.details.ui.model.toListItem
import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.utils.RecyclerViewScrollCallback import org.koitharu.kotatsu.utils.RecyclerViewScrollCallback
import org.koitharu.kotatsu.utils.ext.getParcelableCompat
import org.koitharu.kotatsu.utils.ext.withArgs import org.koitharu.kotatsu.utils.ext.withArgs
import javax.inject.Inject
import kotlin.math.roundToInt
@AndroidEntryPoint @AndroidEntryPoint
class ChaptersBottomSheet : BaseBottomSheet<SheetChaptersBinding>(), OnListItemClickListener<ChapterListItem> { class ChaptersBottomSheet : BaseBottomSheet<SheetChaptersBinding>(), OnListItemClickListener<ChapterListItem> {
@ -33,7 +34,7 @@ class ChaptersBottomSheet : BaseBottomSheet<SheetChaptersBinding>(), OnListItemC
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val chapters = arguments?.getParcelable<ParcelableMangaChapters>(ARG_CHAPTERS)?.chapters val chapters = arguments?.getParcelableCompat<ParcelableMangaChapters>(ARG_CHAPTERS)?.chapters
if (chapters.isNullOrEmpty()) { if (chapters.isNullOrEmpty()) {
dismissAllowingStateLoss() dismissAllowingStateLoss()
return return

@ -63,7 +63,7 @@ class ReaderActivity :
val viewModel by assistedViewModels { val viewModel by assistedViewModels {
viewModelFactory.create( viewModelFactory.create(
intent = MangaIntent(intent), intent = MangaIntent(intent),
initialState = intent?.getParcelableExtra(EXTRA_STATE), initialState = intent?.getParcelableExtraCompat(EXTRA_STATE),
preselectedBranch = intent?.getStringExtra(EXTRA_BRANCH), preselectedBranch = intent?.getStringExtra(EXTRA_BRANCH),
) )
} }

@ -8,6 +8,7 @@ import androidx.viewbinding.ViewBinding
import org.koitharu.kotatsu.base.ui.BaseFragment import org.koitharu.kotatsu.base.ui.BaseFragment
import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.ReaderState
import org.koitharu.kotatsu.reader.ui.ReaderViewModel import org.koitharu.kotatsu.reader.ui.ReaderViewModel
import org.koitharu.kotatsu.utils.ext.getParcelableCompat
private const val KEY_STATE = "state" private const val KEY_STATE = "state"
@ -18,7 +19,7 @@ abstract class BaseReader<B : ViewBinding> : BaseFragment<B>() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
var restoredState = savedInstanceState?.getParcelable<ReaderState?>(KEY_STATE) var restoredState = savedInstanceState?.getParcelableCompat<ReaderState>(KEY_STATE)
viewModel.content.observe(viewLifecycleOwner) { viewModel.content.observe(viewLifecycleOwner) {
onPagesChanged(it.pages, restoredState ?: it.state) onPagesChanged(it.pages, restoredState ?: it.state)

@ -24,6 +24,7 @@ import org.koitharu.kotatsu.parsers.model.MangaPage
import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.domain.PageLoader
import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter
import org.koitharu.kotatsu.utils.ext.getParcelableCompat
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
import org.koitharu.kotatsu.utils.ext.withArgs import org.koitharu.kotatsu.utils.ext.withArgs
@ -52,7 +53,7 @@ class PagesThumbnailsSheet :
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val pages = arguments?.getParcelable<ParcelableMangaPages>(ARG_PAGES)?.pages val pages = arguments?.getParcelableCompat<ParcelableMangaPages>(ARG_PAGES)?.pages
if (pages.isNullOrEmpty()) { if (pages.isNullOrEmpty()) {
dismissAllowingStateLoss() dismissAllowingStateLoss()
return return

@ -99,7 +99,7 @@ class RemoteListFragment : MangaListFragment() {
override fun onQueryTextChange(newText: String?): Boolean = false override fun onQueryTextChange(newText: String?): Boolean = false
override fun onMenuItemActionExpand(item: MenuItem?): Boolean { override fun onMenuItemActionExpand(item: MenuItem): Boolean {
(activity as? AppBarOwner)?.appBar?.setExpanded(false, true) (activity as? AppBarOwner)?.appBar?.setExpanded(false, true)
return true return true
} }

@ -26,6 +26,7 @@ import org.koitharu.kotatsu.scrobbling.ui.selector.adapter.ShikiMangaSelectionDe
import org.koitharu.kotatsu.scrobbling.ui.selector.adapter.ShikimoriSelectorAdapter import org.koitharu.kotatsu.scrobbling.ui.selector.adapter.ShikimoriSelectorAdapter
import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.assistedViewModels
import org.koitharu.kotatsu.utils.ext.getDisplayMessage import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import org.koitharu.kotatsu.utils.ext.requireParcelable
import org.koitharu.kotatsu.utils.ext.withArgs import org.koitharu.kotatsu.utils.ext.withArgs
@AndroidEntryPoint @AndroidEntryPoint
@ -47,7 +48,7 @@ class ScrobblingSelectorBottomSheet :
private val viewModel by assistedViewModels { private val viewModel by assistedViewModels {
viewModelFactory.create( viewModelFactory.create(
requireNotNull(requireArguments().getParcelable<ParcelableManga>(MangaIntent.KEY_MANGA)).manga, requireArguments().requireParcelable<ParcelableManga>(MangaIntent.KEY_MANGA).manga,
) )
} }
@ -84,7 +85,7 @@ class ScrobblingSelectorBottomSheet :
dismiss() dismiss()
} }
viewModel.searchQuery.observe(viewLifecycleOwner) { viewModel.searchQuery.observe(viewLifecycleOwner) {
binding.headerBar.toolbar.subtitle = it binding.headerBar.subtitle = it
} }
} }
@ -102,7 +103,7 @@ class ScrobblingSelectorBottomSheet :
viewModel.loadList(append = true) viewModel.loadList(append = true)
} }
override fun onMenuItemActionExpand(item: MenuItem?): Boolean { override fun onMenuItemActionExpand(item: MenuItem): Boolean {
setExpanded(isExpanded = true, isLocked = true) setExpanded(isExpanded = true, isLocked = true)
return true return true
} }

@ -17,6 +17,7 @@ import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.remotelist.ui.RemoteListFragment import org.koitharu.kotatsu.remotelist.ui.RemoteListFragment
import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat
@AndroidEntryPoint @AndroidEntryPoint
class MangaListActivity : class MangaListActivity :
@ -29,7 +30,7 @@ class MangaListActivity :
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityContainerBinding.inflate(layoutInflater)) setContentView(ActivityContainerBinding.inflate(layoutInflater))
val tags = intent.getParcelableExtra<ParcelableMangaTags>(EXTRA_TAGS)?.tags val tags = intent.getParcelableExtraCompat<ParcelableMangaTags>(EXTRA_TAGS)?.tags
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
val source = intent.getSerializableExtra(EXTRA_SOURCE) as? MangaSource ?: tags?.firstOrNull()?.source val source = intent.getSerializableExtra(EXTRA_SOURCE) as? MangaSource ?: tags?.firstOrNull()?.source
if (source == null) { if (source == null) {

@ -120,7 +120,7 @@ class SourcesSettingsFragment :
else -> false else -> false
} }
override fun onMenuItemActionExpand(item: MenuItem?): Boolean { override fun onMenuItemActionExpand(item: MenuItem): Boolean {
(activity as? AppBarOwner)?.appBar?.setExpanded(false, true) (activity as? AppBarOwner)?.appBar?.setExpanded(false, true)
return true return true
} }

@ -0,0 +1,46 @@
package org.koitharu.kotatsu.utils.ext
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import java.io.Serializable
@Suppress("DEPRECATION")
inline fun <reified T : Parcelable> Bundle.getParcelableCompat(key: String): T? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getParcelable(key, T::class.java)
} else {
getParcelable(key) as? T
}
}
@Suppress("DEPRECATION")
inline fun <reified T : Parcelable> Intent.getParcelableExtraCompat(key: String): T? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getParcelableExtra(key, T::class.java)
} else {
getParcelableExtra(key) as? T
}
}
@Suppress("DEPRECATION")
inline fun <reified T : Serializable> Bundle.getSerializableCompat(key: String): T? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getSerializable(key, T::class.java)
} else {
getSerializable(key) as? T
}
}
inline fun <reified T : Serializable> Bundle.requireSerializable(key: String): T {
return checkNotNull(getSerializableCompat(key)) {
"Serializable of type \"${T::class.java.name}\" not found at \"$key\""
}
}
inline fun <reified T : Parcelable> Bundle.requireParcelable(key: String): T {
return checkNotNull(getParcelableCompat(key)) {
"Parcelable of type \"${T::class.java.name}\" not found at \"$key\""
}
}

@ -1,7 +1,6 @@
package org.koitharu.kotatsu.utils.ext package org.koitharu.kotatsu.utils.ext
import android.os.Bundle import android.os.Bundle
import android.os.Parcelable
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -20,14 +19,6 @@ inline fun <T : Fragment> T.withArgs(size: Int, block: Bundle.() -> Unit): T {
val Fragment.viewLifecycleScope val Fragment.viewLifecycleScope
inline get() = viewLifecycleOwner.lifecycle.coroutineScope inline get() = viewLifecycleOwner.lifecycle.coroutineScope
fun <T : Parcelable> Fragment.parcelableArgument(name: String): Lazy<T> {
return lazy(LazyThreadSafetyMode.NONE) {
requireNotNull(arguments?.getParcelable(name)) {
"No argument $name passed into ${javaClass.simpleName}"
}
}
}
fun <T : Serializable> Fragment.serializableArgument(name: String): Lazy<T> { fun <T : Serializable> Fragment.serializableArgument(name: String): Lazy<T> {
return lazy(LazyThreadSafetyMode.NONE) { return lazy(LazyThreadSafetyMode.NONE) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")

@ -5,7 +5,7 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.2.1' classpath 'com.android.tools.build:gradle:7.2.2'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21' classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21'
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.42' classpath 'com.google.dagger:hilt-android-gradle-plugin:2.42'

@ -1,7 +1,7 @@
#Sun May 15 16:26:09 EEST 2022 #Wed Aug 24 10:43:54 EEST 2022
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
distributionSha256Sum=29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda distributionSha256Sum=f6b8596b10cce501591e92f229816aa4046424f3b24d771751b06779d58c8ec4

Loading…
Cancel
Save