Remove unused code

This commit is contained in:
Koitharu
2021-04-29 07:24:26 +03:00
parent 49eebdf554
commit 5b9922d509
23 changed files with 126 additions and 240 deletions

View File

@@ -15,9 +15,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.AppCrashHandler
import org.koitharu.kotatsu.core.ui.uiModule
import org.koitharu.kotatsu.details.detailsModule
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
import org.koitharu.kotatsu.favourites.favouritesModule
import org.koitharu.kotatsu.history.domain.HistoryRepository
import org.koitharu.kotatsu.history.historyModule
import org.koitharu.kotatsu.local.data.PagesCache
import org.koitharu.kotatsu.local.domain.LocalMangaRepository
@@ -37,29 +35,15 @@ class KotatsuApp : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build()
)
StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder()
.detectAll()
.setClassInstanceLimit(LocalMangaRepository::class.java, 1)
.setClassInstanceLimit(PagesCache::class.java, 1)
.setClassInstanceLimit(MangaLoaderContext::class.java, 1)
.penaltyLog()
.build()
)
enableStrictMode()
}
initKoin()
Thread.setDefaultUncaughtExceptionHandler(AppCrashHandler(applicationContext))
AppCompatDelegate.setDefaultNightMode(get<AppSettings>().theme)
registerActivityLifecycleCallbacks(get<AppProtectHelper>())
val widgetUpdater = WidgetUpdater(applicationContext)
FavouritesRepository.subscribe(widgetUpdater)
HistoryRepository.subscribe(widgetUpdater)
widgetUpdater.subscribeToFavourites(get())
widgetUpdater.subscribeToHistory(get())
}
private fun initKoin() {
@@ -85,4 +69,22 @@ class KotatsuApp : Application() {
)
}
}
private fun enableStrictMode() {
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build()
)
StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder()
.detectAll()
.setClassInstanceLimit(LocalMangaRepository::class.java, 1)
.setClassInstanceLimit(PagesCache::class.java, 1)
.setClassInstanceLimit(MangaLoaderContext::class.java, 1)
.penaltyLog()
.build()
)
}
}

View File

@@ -13,6 +13,7 @@ import androidx.core.graphics.drawable.toBitmap
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.details.ui.DetailsActivity
import org.koitharu.kotatsu.utils.PendingIntentCompat
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import kotlin.math.roundToInt
@@ -63,7 +64,7 @@ class DownloadNotification(private val context: Context) {
context,
startId,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
)
}
@@ -146,7 +147,7 @@ class DownloadNotification(private val context: Context) {
context,
manga.hashCode(),
DetailsActivity.newIntent(context, manga),
PendingIntent.FLAG_CANCEL_CURRENT
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
}
}

View File

@@ -85,7 +85,7 @@ class DownloadService : BaseService() {
wakeLock.acquire(TimeUnit.HOURS.toMillis(1))
notification.fillFrom(manga)
notification.setCancelId(startId)
withContext(Dispatchers.Main.immediate) {
withContext(Dispatchers.Main) {
startForeground(DownloadNotification.NOTIFICATION_ID, notification())
}
val destination = settings.getStorageDir(this@DownloadService)
@@ -174,8 +174,8 @@ class DownloadService : BaseService() {
withContext(NonCancellable) {
jobs.remove(startId)
output?.cleanup()
destination.sub("page.tmp").delete()
withContext(Dispatchers.Main.immediate) {
destination.sub(TEMP_PAGE_FILE).deleteAwait()
withContext(Dispatchers.Main) {
stopForeground(true)
notification.dismiss()
stopSelf(startId)
@@ -196,13 +196,25 @@ class DownloadService : BaseService() {
.cacheControl(CacheUtils.CONTROL_DISABLED)
.get()
.build()
return retryUntilSuccess(3) {
okHttp.newCall(request).await().use { response ->
val file = destination.sub("page.tmp")
file.outputStream().use { out ->
response.body!!.byteStream().copyTo(out)
val call = okHttp.newCall(request)
var attempts = MAX_DOWNLOAD_ATTEMPTS
val file = destination.sub(TEMP_PAGE_FILE)
while (true) {
try {
val response = call.clone().await()
withContext(Dispatchers.IO) {
file.outputStream().use { out ->
checkNotNull(response.body).byteStream().copyTo(out)
}
}
return file
} catch (e: IOException) {
attempts--
if (attempts <= 0) {
throw e
} else {
delay(DOWNLOAD_ERROR_DELAY)
}
file
}
}
}
@@ -218,6 +230,10 @@ class DownloadService : BaseService() {
private const val EXTRA_CHAPTERS_IDS = "chapters_ids"
private const val EXTRA_CANCEL_ID = "cancel_id"
private const val MAX_DOWNLOAD_ATTEMPTS = 3
private const val DOWNLOAD_ERROR_DELAY = 500L
private const val TEMP_PAGE_FILE = "page.tmp"
fun start(context: Context, manga: Manga, chaptersIds: Collection<Long>? = null) {
confirmDataTransfer(context) {
val intent = Intent(context, DownloadService::class.java)

View File

@@ -1,12 +1,9 @@
package org.koitharu.kotatsu.favourites.domain
import androidx.collection.ArraySet
import androidx.room.withTransaction
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.entity.MangaEntity
import org.koitharu.kotatsu.core.db.entity.TagEntity
@@ -83,18 +80,15 @@ class FavouritesRepository(private val db: MangaDatabase) {
categoryId = 0
)
val id = db.favouriteCategoriesDao.insert(entity)
notifyCategoriesChanged()
return entity.toFavouriteCategory(id)
}
suspend fun renameCategory(id: Long, title: String) {
db.favouriteCategoriesDao.update(id, title)
notifyCategoriesChanged()
}
suspend fun removeCategory(id: Long) {
db.favouriteCategoriesDao.delete(id)
notifyCategoriesChanged()
}
suspend fun reorderCategories(orderedIds: List<Long>) {
@@ -104,7 +98,6 @@ class FavouritesRepository(private val db: MangaDatabase) {
dao.update(id, i)
}
}
notifyCategoriesChanged()
}
suspend fun addToCategory(manga: Manga, categoryId: Long) {
@@ -115,41 +108,13 @@ class FavouritesRepository(private val db: MangaDatabase) {
val entity = FavouriteEntity(manga.id, categoryId, System.currentTimeMillis())
db.favouritesDao.insert(entity)
}
notifyFavouritesChanged(manga.id)
}
suspend fun removeFromCategory(manga: Manga, categoryId: Long) {
db.favouritesDao.delete(categoryId, manga.id)
notifyFavouritesChanged(manga.id)
}
suspend fun removeFromFavourites(manga: Manga) {
db.favouritesDao.delete(manga.id)
notifyFavouritesChanged(manga.id)
}
companion object {
private val listeners = ArraySet<OnFavouritesChangeListener>()
fun subscribe(listener: OnFavouritesChangeListener) {
listeners += listener
}
fun unsubscribe(listener: OnFavouritesChangeListener) {
listeners -= listener
}
private suspend fun notifyFavouritesChanged(mangaId: Long) {
withContext(Dispatchers.Main) {
listeners.forEach { x -> x.onFavouritesChanged(mangaId) }
}
}
private suspend fun notifyCategoriesChanged() {
withContext(Dispatchers.Main) {
listeners.forEach { x -> x.onCategoriesChanged() }
}
}
}
}

View File

@@ -1,9 +0,0 @@
package org.koitharu.kotatsu.favourites.domain
@Deprecated("Use flow")
fun interface OnFavouritesChangeListener {
fun onFavouritesChanged(mangaId: Long)
fun onCategoriesChanged() = Unit
}

View File

@@ -8,6 +8,6 @@ import org.koitharu.kotatsu.history.ui.HistoryListViewModel
val historyModule
get() = module {
single { HistoryRepository(get()) }
single { HistoryRepository(get(), get()) }
viewModel { HistoryListViewModel(get(), get(), get()) }
}

View File

@@ -1,11 +1,8 @@
package org.koitharu.kotatsu.history.domain
import androidx.collection.ArraySet
import androidx.room.withTransaction
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.entity.MangaEntity
import org.koitharu.kotatsu.core.db.entity.TagEntity
@@ -64,7 +61,6 @@ class HistoryRepository(
)
trackingRepository.upsert(manga)
}
notifyHistoryChanged()
}
suspend fun getOne(manga: Manga): MangaHistory? {
@@ -73,12 +69,10 @@ class HistoryRepository(
suspend fun clear() {
db.historyDao.clear()
notifyHistoryChanged()
}
suspend fun delete(manga: Manga) {
db.historyDao.delete(manga.id)
notifyHistoryChanged()
}
/**
@@ -88,26 +82,6 @@ class HistoryRepository(
suspend fun deleteOrSwap(manga: Manga, alternative: Manga?) {
if (alternative == null || db.mangaDao.update(MangaEntity.from(alternative)) <= 0) {
db.historyDao.delete(manga.id)
notifyHistoryChanged()
}
}
companion object {
private val listeners = ArraySet<OnHistoryChangeListener>()
fun subscribe(listener: OnHistoryChangeListener) {
listeners += listener
}
fun unsubscribe(listener: OnHistoryChangeListener) {
listeners -= listener
}
private suspend fun notifyHistoryChanged() {
withContext(Dispatchers.Main) {
listeners.forEach { x -> x.onHistoryChanged() }
}
}
}
}

View File

@@ -1,6 +0,0 @@
package org.koitharu.kotatsu.history.domain
fun interface OnHistoryChangeListener {
fun onHistoryChanged()
}

View File

@@ -9,14 +9,9 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
class AppProtectHelper(private val settings: AppSettings) : Application.ActivityLifecycleCallbacks {
private var isUnlocked = settings.appPassword.isNullOrEmpty()
private var activityCounter = 0
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
if (activity is ProtectActivity) {
return
}
activityCounter++
if (!isUnlocked) {
if (activity !is ProtectActivity && !isUnlocked) {
val sourceIntent = Intent(activity, activity.javaClass)
activity.intent?.let {
sourceIntent.putExtras(it)
@@ -39,11 +34,7 @@ class AppProtectHelper(private val settings: AppSettings) : Application.Activity
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit
override fun onActivityDestroyed(activity: Activity) {
if (activity is ProtectActivity) {
return
}
activityCounter--
if (activityCounter == 0) {
if (activity !is ProtectActivity && activity.isTaskRoot) {
restoreLock()
}
}

View File

@@ -23,6 +23,7 @@ import org.koitharu.kotatsu.core.model.MangaChapter
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.details.ui.DetailsActivity
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
import org.koitharu.kotatsu.utils.PendingIntentCompat
import org.koitharu.kotatsu.utils.ext.mangaRepositoryOf
import org.koitharu.kotatsu.utils.ext.toBitmapOrNull
import org.koitharu.kotatsu.utils.ext.toUriOrNull
@@ -174,7 +175,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) :
setContentIntent(
PendingIntent.getActivity(
applicationContext, id,
intent, PendingIntent.FLAG_UPDATE_CURRENT
intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
)
setAutoCancel(true)

View File

@@ -7,7 +7,6 @@ import okhttp3.Cache
import okhttp3.CacheControl
import org.koitharu.kotatsu.utils.ext.computeSize
import org.koitharu.kotatsu.utils.ext.sub
import org.koitharu.kotatsu.utils.ext.sumByLong
import java.io.File
object CacheUtils {
@@ -25,7 +24,7 @@ object CacheUtils {
@WorkerThread
fun computeCacheSize(context: Context, name: String) = getCacheDirs(context)
.map { it.sub(name) }
.sumByLong { x -> x.computeSize() }
.sumOf { x -> x.computeSize() }
@WorkerThread
fun clearCache(context: Context, name: String) = getCacheDirs(context)

View File

@@ -0,0 +1,13 @@
package org.koitharu.kotatsu.utils
import android.app.PendingIntent
import android.os.Build
object PendingIntentCompat {
val FLAG_IMMUTABLE = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else {
0
}
}

View File

@@ -9,22 +9,6 @@ fun <T> MutableCollection<T>.replaceWith(subject: Iterable<T>) {
addAll(subject)
}
inline fun <T> Array<out T>.sumByLong(selector: (T) -> Long): Long {
var sum = 0L
for (element in this) {
sum += selector(element)
}
return sum
}
inline fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long {
var sum = 0L
for (element in this) {
sum += selector(element)
}
return sum
}
fun <T> List<T>.medianOrNull(): T? = when {
isEmpty() -> null
else -> get((size / 2).coerceIn(indices))

View File

@@ -8,22 +8,6 @@ import org.koitharu.kotatsu.core.exceptions.*
import java.io.FileNotFoundException
import java.net.SocketTimeoutException
suspend inline fun <T, R> T.retryUntilSuccess(maxAttempts: Int, action: T.() -> R): R {
var attempts = maxAttempts
while (true) {
try {
return this.action()
} catch (e: Exception) {
attempts--
if (attempts <= 0) {
throw e
} else {
delay(1000)
}
}
}
}
fun Throwable.getDisplayMessage(resources: Resources) = when (this) {
is AuthRequiredException -> resources.getString(R.string.auth_required)
is CloudFlareProtectedException -> resources.getString(R.string.captcha_required)

View File

@@ -14,25 +14,6 @@ import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
suspend fun Call.await() = suspendCancellableCoroutine<Response> { cont ->
this.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
if (cont.isActive) {
cont.resumeWithException(e)
}
}
override fun onResponse(call: Call, response: Response) {
if (cont.isActive) {
cont.resume(response)
}
}
})
cont.invokeOnCancellation {
this.cancel()
}
}
inline fun CoroutineScope.launchAfter(
job: Job?,
context: CoroutineContext = EmptyCoroutineContext,

View File

@@ -5,6 +5,8 @@ import android.net.Uri
import android.os.Build
import android.os.Environment
import android.os.storage.StorageManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.R
import java.io.File
import java.util.zip.ZipEntry
@@ -19,7 +21,7 @@ fun ZipFile.readText(entry: ZipEntry) = getInputStream(entry).bufferedReader().u
it.readText()
}
fun File.computeSize(): Long = listFiles()?.sumByLong { x ->
fun File.computeSize(): Long = listFiles()?.sumOf { x ->
if (x.isDirectory) {
x.computeSize()
} else {
@@ -49,4 +51,8 @@ fun File.getStorageName(context: Context): String = runCatching {
}
}.getOrNull() ?: context.getString(R.string.other_storage)
fun Uri.toFileOrNull() = if (scheme == "file") path?.let(::File) else null
fun Uri.toFileOrNull() = if (scheme == "file") path?.let(::File) else null
suspend fun File.deleteAwait() = withContext(Dispatchers.IO) {
delete()
}

View File

@@ -13,7 +13,7 @@ inline fun <T : Fragment> T.withArgs(size: Int, block: Bundle.() -> Unit): T {
}
val Fragment.viewLifecycleScope
get() = viewLifecycleOwner.lifecycle.coroutineScope
inline get() = viewLifecycleOwner.lifecycle.coroutineScope
@Suppress("NOTHING_TO_INLINE")
inline fun <T : Parcelable> Fragment.parcelableArgument(name: String): Lazy<T> {

View File

@@ -1,7 +1,32 @@
package org.koitharu.kotatsu.utils.ext
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Response
import org.koitharu.kotatsu.core.network.CommonHeaders
import java.io.IOException
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
suspend fun Call.await() = suspendCancellableCoroutine<Response> { cont ->
this.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
if (cont.isActive) {
cont.resumeWithException(e)
}
}
override fun onResponse(call: Call, response: Response) {
if (cont.isActive) {
cont.resume(response)
}
}
})
cont.invokeOnCancellation {
this.cancel()
}
}
val Response.mimeType: String?
get() = body?.contentType()?.run { "$type/$subtype" }

View File

@@ -7,7 +7,7 @@ import androidx.core.view.isGone
var TextView.textAndVisible: CharSequence?
inline get() = text?.takeIf { visibility == View.VISIBLE }
set(value) {
inline set(value) {
text = value
isGone = value.isNullOrEmpty()
}

View File

@@ -2,26 +2,20 @@ package org.koitharu.kotatsu.utils.ext
import android.app.Activity
import android.graphics.Rect
import android.util.Log
import android.view.LayoutInflater
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.TextView
import androidx.annotation.LayoutRes
import androidx.annotation.MenuRes
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.children
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.view.postDelayed
import androidx.drawerlayout.widget.DrawerLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup
fun View.hideKeyboard() {
val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
@@ -54,13 +48,6 @@ var RecyclerView.firstItem: Int
}
}
fun View.disableFor(timeInMillis: Long) {
isEnabled = false
postDelayed(timeInMillis) {
isEnabled = true
}
}
inline fun View.showPopupMenu(
@MenuRes menuRes: Int,
onPrepare: (Menu) -> Unit = {},
@@ -134,7 +121,7 @@ inline fun ViewPager2.doOnPageChanged(crossinline callback: (Int) -> Unit) {
}
val ViewPager2.recyclerView: RecyclerView?
get() = children.find { it is RecyclerView } as? RecyclerView
inline get() = children.find { it is RecyclerView } as? RecyclerView
fun View.resetTransformations() {
alpha = 1f
@@ -161,49 +148,9 @@ inline fun RecyclerView.doOnCurrentItemChanged(crossinline callback: (Int) -> Un
})
}
@Deprecated("Reflection")
fun RecyclerView.callOnScrollListeners() {
try {
val field = RecyclerView::class.java.getDeclaredField("mScrollListeners")
field.isAccessible = true
val listeners = field.get(this) as List<*>
for (x in listeners) {
(x as RecyclerView.OnScrollListener).onScrolled(this, 0, 0)
}
} catch (e: Throwable) {
Log.e(null, "RecyclerView.callOnScrollListeners() failed", e)
}
}
@Deprecated("Reflection")
fun ViewPager2.callOnPageChaneListeners() {
try {
val field = ViewPager2::class.java.getDeclaredField("mExternalPageChangeCallbacks")
field.isAccessible = true
val compositeCallback = field.get(this)
val field2 = compositeCallback.javaClass.getDeclaredField("mCallbacks")
field2.isAccessible = true
val listeners = field2.get(compositeCallback) as List<*>
val position = currentItem
for (x in listeners) {
(x as ViewPager2.OnPageChangeCallback).onPageSelected(position)
}
} catch (e: Throwable) {
Log.e(null, "ViewPager2.callOnPageChaneListeners() failed", e)
}
}
fun RecyclerView.findCenterViewPosition(): Int {
val centerX = width / 2f
val centerY = height / 2f
val view = findChildViewUnder(centerX, centerY) ?: return RecyclerView.NO_POSITION
return getChildAdapterPosition(view)
}
fun ViewPager2.swapAdapter(newAdapter: RecyclerView.Adapter<*>?) {
val position = currentItem
adapter = newAdapter
if (adapter != null && position != RecyclerView.NO_POSITION) {
setCurrentItem(position, false)
}
}

View File

@@ -4,20 +4,30 @@ import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import org.koitharu.kotatsu.favourites.domain.OnFavouritesChangeListener
import org.koitharu.kotatsu.history.domain.OnHistoryChangeListener
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.retry
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
import org.koitharu.kotatsu.history.domain.HistoryRepository
import org.koitharu.kotatsu.utils.ext.processLifecycleScope
import org.koitharu.kotatsu.widget.recent.RecentWidgetProvider
import org.koitharu.kotatsu.widget.shelf.ShelfWidgetProvider
class WidgetUpdater(private val context: Context) : OnFavouritesChangeListener,
OnHistoryChangeListener {
class WidgetUpdater(private val context: Context) {
override fun onFavouritesChanged(mangaId: Long) {
updateWidget(ShelfWidgetProvider::class.java)
fun subscribeToFavourites(repository: FavouritesRepository) {
repository.observeAll()
.onEach { updateWidget(ShelfWidgetProvider::class.java) }
.retry { error -> error !is CancellationException }
.launchIn(processLifecycleScope)
}
override fun onHistoryChanged() {
updateWidget(RecentWidgetProvider::class.java)
fun subscribeToHistory(repository: HistoryRepository) {
repository.observeAll()
.onEach { updateWidget(RecentWidgetProvider::class.java) }
.retry { error -> error !is CancellationException }
.launchIn(processLifecycleScope)
}
private fun updateWidget(cls: Class<*>) {

View File

@@ -9,6 +9,7 @@ import android.net.Uri
import android.widget.RemoteViews
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.utils.PendingIntentCompat
class RecentWidgetProvider : AppWidgetProvider() {
@@ -30,7 +31,7 @@ class RecentWidgetProvider : AppWidgetProvider() {
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
)
views.setEmptyView(R.id.stackView, R.id.textView_holder)

View File

@@ -9,6 +9,7 @@ import android.net.Uri
import android.widget.RemoteViews
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.utils.PendingIntentCompat
class ShelfWidgetProvider : AppWidgetProvider() {
@@ -30,7 +31,7 @@ class ShelfWidgetProvider : AppWidgetProvider() {
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
)
)
views.setEmptyView(R.id.gridView, R.id.textView_holder)