Compare commits
17 Commits
0ffefddb86
...
b57069c55f
| Author | SHA1 | Date | |
|---|---|---|---|
|
b57069c55f
|
|||
|
5b1a4d3ff5
|
|||
|
2b26f944d0
|
|||
|
a15197f69d
|
|||
|
41f64b2e36
|
|||
|
bec032c7dc
|
|||
|
|
061eaa2a56 | ||
|
|
bc6e29b562 | ||
|
|
d8c1dcef29 | ||
|
|
ca281afba1 | ||
|
|
cde07a60d7 | ||
|
|
e31af0f43f | ||
|
|
15dd0f38e7 | ||
|
|
d93647e889 | ||
|
|
509d9a2fba | ||
|
|
879d05f1a6 | ||
|
|
ecf6bbfb66 |
@@ -16,8 +16,8 @@ android {
|
||||
applicationId 'org.koitharu.kotatsu'
|
||||
minSdk = 21
|
||||
targetSdk = 34
|
||||
versionCode = 631
|
||||
versionName = '6.8.1'
|
||||
versionCode = 632
|
||||
versionName = '6.8.2'
|
||||
generatedDensities = []
|
||||
testInstrumentationRunner 'org.koitharu.kotatsu.HiltTestRunner'
|
||||
ksp {
|
||||
@@ -82,7 +82,7 @@ afterEvaluate {
|
||||
}
|
||||
dependencies {
|
||||
//noinspection GradleDependency
|
||||
implementation('com.github.KotatsuApp:kotatsu-parsers:9821e93d25') {
|
||||
implementation('com.github.KotatsuApp:kotatsu-parsers:44ea9fe709') {
|
||||
exclude group: 'org.json', module: 'json'
|
||||
}
|
||||
|
||||
@@ -127,8 +127,8 @@ dependencies {
|
||||
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl:4.3.2'
|
||||
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:4.3.2'
|
||||
|
||||
implementation 'com.google.dagger:hilt-android:2.51'
|
||||
kapt 'com.google.dagger:hilt-compiler:2.51'
|
||||
implementation 'com.google.dagger:hilt-android:2.51.1'
|
||||
kapt 'com.google.dagger:hilt-compiler:2.51.1'
|
||||
implementation 'androidx.hilt:hilt-work:1.2.0'
|
||||
kapt 'androidx.hilt:hilt-compiler:1.2.0'
|
||||
|
||||
@@ -161,6 +161,6 @@ dependencies {
|
||||
androidTestImplementation 'androidx.room:room-testing:2.6.1'
|
||||
androidTestImplementation 'com.squareup.moshi:moshi-kotlin:1.15.1'
|
||||
|
||||
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.51'
|
||||
kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.51'
|
||||
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.51.1'
|
||||
kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.51.1'
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.koitharu.kotatsu.browser
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -13,17 +12,25 @@ import androidx.core.graphics.Insets
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updatePadding
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.network.CommonHeaders
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
||||
import org.koitharu.kotatsu.core.ui.BaseActivity
|
||||
import org.koitharu.kotatsu.core.util.ext.configureForParser
|
||||
import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat
|
||||
import org.koitharu.kotatsu.core.util.ext.toUriOrNull
|
||||
import org.koitharu.kotatsu.databinding.ActivityBrowserBinding
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import javax.inject.Inject
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
class BrowserActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallback {
|
||||
|
||||
private lateinit var onBackPressedCallback: WebViewBackPressedCallback
|
||||
|
||||
@Inject
|
||||
lateinit var mangaRepositoryFactory: MangaRepository.Factory
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (!setContentViewWebViewSafe { ActivityBrowserBinding.inflate(layoutInflater) }) {
|
||||
@@ -33,7 +40,11 @@ class BrowserActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallback
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
|
||||
}
|
||||
viewBinding.webView.configureForParser(null)
|
||||
val userAgent = intent?.getSerializableExtraCompat<MangaSource>(EXTRA_SOURCE)?.let { source ->
|
||||
val repository = mangaRepositoryFactory.create(source) as? RemoteMangaRepository
|
||||
repository?.headers?.get(CommonHeaders.USER_AGENT)
|
||||
}
|
||||
viewBinding.webView.configureForParser(userAgent)
|
||||
CookieManager.getInstance().setAcceptThirdPartyCookies(viewBinding.webView, true)
|
||||
viewBinding.webView.webViewClient = BrowserClient(this)
|
||||
viewBinding.webView.webChromeClient = ProgressChromeClient(viewBinding.progressBar)
|
||||
@@ -54,16 +65,6 @@ class BrowserActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallback
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
viewBinding.webView.saveState(outState)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
viewBinding.webView.restoreState(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
super.onCreateOptionsMenu(menu)
|
||||
menuInflater.inflate(R.menu.opt_browser, menu)
|
||||
@@ -136,11 +137,13 @@ class BrowserActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallback
|
||||
companion object {
|
||||
|
||||
private const val EXTRA_TITLE = "title"
|
||||
private const val EXTRA_SOURCE = "source"
|
||||
|
||||
fun newIntent(context: Context, url: String, title: String?): Intent {
|
||||
fun newIntent(context: Context, url: String, source: MangaSource?, title: String?): Intent {
|
||||
return Intent(context, BrowserActivity::class.java)
|
||||
.setData(Uri.parse(url))
|
||||
.putExtra(EXTRA_TITLE, title)
|
||||
.putExtra(EXTRA_SOURCE, source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class CaptchaNotifier(
|
||||
) : EventListener {
|
||||
|
||||
fun notify(exception: CloudFlareProtectedException) {
|
||||
if (!context.checkNotificationPermission()) {
|
||||
if (!context.checkNotificationPermission(CHANNEL_ID)) {
|
||||
return
|
||||
}
|
||||
val manager = NotificationManagerCompat.from(context)
|
||||
|
||||
@@ -81,16 +81,6 @@ class CloudFlareActivity : BaseActivity<ActivityBrowserBinding>(), CloudFlareCal
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
viewBinding.webView.saveState(outState)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
viewBinding.webView.restoreState(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.opt_captcha, menu)
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.koitharu.kotatsu.core.exceptions
|
||||
|
||||
import okio.IOException
|
||||
|
||||
class NoDataReceivedException(
|
||||
private val url: String,
|
||||
) : IOException("No data has been received from $url")
|
||||
@@ -82,7 +82,7 @@ class ExceptionResolver : ActivityResultCallback<TaggedActivityResult> {
|
||||
|
||||
private fun openInBrowser(url: String) {
|
||||
val context = activity ?: fragment?.activity ?: return
|
||||
context.startActivity(BrowserActivity.newIntent(context, url, null))
|
||||
context.startActivity(BrowserActivity.newIntent(context, url, null, null))
|
||||
}
|
||||
|
||||
private fun openAlternatives(manga: Manga) {
|
||||
|
||||
@@ -14,7 +14,7 @@ import android.content.ContextWrapper
|
||||
import android.content.OperationApplicationException
|
||||
import android.content.SharedPreferences
|
||||
import android.content.SyncResult
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PackageManager.PERMISSION_GRANTED
|
||||
import android.content.pm.ResolveInfo
|
||||
import android.database.SQLException
|
||||
import android.graphics.Bitmap
|
||||
@@ -216,10 +216,19 @@ fun Context.findActivity(): Activity? = when (this) {
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun Context.checkNotificationPermission(): Boolean = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED
|
||||
} else {
|
||||
NotificationManagerCompat.from(this).areNotificationsEnabled()
|
||||
fun Context.checkNotificationPermission(channelId: String?): Boolean {
|
||||
val hasPermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PERMISSION_GRANTED
|
||||
} else {
|
||||
NotificationManagerCompat.from(this).areNotificationsEnabled()
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && hasPermission && channelId != null) {
|
||||
val channel = NotificationManagerCompat.from(this).getNotificationChannel(channelId)
|
||||
if (channel != null && channel.importance == NotificationManagerCompat.IMPORTANCE_NONE) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return hasPermission
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
|
||||
@@ -8,12 +8,12 @@ import coil.network.HttpException
|
||||
import okio.FileNotFoundException
|
||||
import okio.IOException
|
||||
import org.acra.ktx.sendWithAcra
|
||||
import org.json.JSONException
|
||||
import org.jsoup.HttpStatusException
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.CaughtException
|
||||
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
||||
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
||||
import org.koitharu.kotatsu.core.exceptions.NoDataReceivedException
|
||||
import org.koitharu.kotatsu.core.exceptions.SyncApiException
|
||||
import org.koitharu.kotatsu.core.exceptions.TooManyRequestExceptions
|
||||
import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException
|
||||
@@ -55,6 +55,8 @@ fun Throwable.getDisplayMessage(resources: Resources): String = when (this) {
|
||||
is SocketTimeoutException,
|
||||
-> resources.getString(R.string.network_error)
|
||||
|
||||
is NoDataReceivedException -> resources.getString(R.string.error_no_data_received)
|
||||
|
||||
is WrongPasswordException -> resources.getString(R.string.wrong_password)
|
||||
is NotFoundException -> resources.getString(R.string.not_found_404)
|
||||
is UnsupportedSourceException -> resources.getString(R.string.unsupported_source)
|
||||
@@ -115,6 +117,7 @@ private val reportableExceptions = arraySetOf<Class<*>>(
|
||||
IllegalArgumentException::class.java,
|
||||
ConcurrentModificationException::class.java,
|
||||
UnsupportedOperationException::class.java,
|
||||
NoDataReceivedException::class.java,
|
||||
)
|
||||
|
||||
fun Throwable.isWebViewUnavailable(): Boolean {
|
||||
|
||||
@@ -189,7 +189,7 @@ class DetailsFragment :
|
||||
isVisible = false
|
||||
}
|
||||
}
|
||||
if (manga.source == MangaSource.LOCAL) {
|
||||
if (manga.source == MangaSource.LOCAL || manga.source == MangaSource.DUMMY) {
|
||||
infoLayout.textViewSource.isVisible = false
|
||||
} else {
|
||||
infoLayout.textViewSource.text = manga.source.title
|
||||
@@ -223,7 +223,7 @@ class DetailsFragment :
|
||||
}
|
||||
binding.approximateReadTime.text = time.format(resources)
|
||||
binding.approximateReadTimeTitle.setText(
|
||||
if (time.isContinue) R.string.approximate_remaining_time else R.string.approximate_reading_time
|
||||
if (time.isContinue) R.string.approximate_remaining_time else R.string.approximate_reading_time,
|
||||
)
|
||||
binding.approximateReadTimeLayout.isVisible = true
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ class DetailsMenuProvider(
|
||||
|
||||
R.id.action_browser -> {
|
||||
viewModel.manga.value?.let {
|
||||
activity.startActivity(BrowserActivity.newIntent(activity, it.publicUrl, it.title))
|
||||
activity.startActivity(BrowserActivity.newIntent(activity, it.publicUrl, it.source, it.title))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import okio.Source
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import okio.use
|
||||
import org.koitharu.kotatsu.core.exceptions.NoDataReceivedException
|
||||
import org.koitharu.kotatsu.core.util.FileSize
|
||||
import org.koitharu.kotatsu.core.util.ext.compressToPNG
|
||||
import org.koitharu.kotatsu.core.util.ext.longHashCode
|
||||
@@ -62,7 +63,9 @@ class PagesCache @Inject constructor(@ApplicationContext context: Context) {
|
||||
val bytes = file.sink(append = false).buffer().use {
|
||||
it.writeAllCancellable(source)
|
||||
}
|
||||
check(bytes != 0L) { "No data has been written" }
|
||||
if (bytes == 0L) {
|
||||
throw NoDataReceivedException(url)
|
||||
}
|
||||
lruCache.get().put(url, file)
|
||||
} finally {
|
||||
file.delete()
|
||||
|
||||
@@ -50,7 +50,7 @@ class ImportWorker @AssistedInject constructor(
|
||||
val result = runCatchingCancellable {
|
||||
importer.import(uri).manga
|
||||
}
|
||||
if (applicationContext.checkNotificationPermission()) {
|
||||
if (applicationContext.checkNotificationPermission(CHANNEL_ID)) {
|
||||
val notification = buildNotification(result)
|
||||
notificationManager.notify(uri.hashCode(), notification)
|
||||
}
|
||||
|
||||
@@ -59,6 +59,9 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
|
||||
viewModel.defaultWebtoonZoomOut.take(1).observe(viewLifecycleOwner) {
|
||||
binding.frame.zoom = 1f - it
|
||||
}
|
||||
viewModel.readerSettings.observe(viewLifecycleOwner) {
|
||||
it.applyBackground(binding.root)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
@@ -15,8 +16,7 @@ import org.koitharu.kotatsu.suggestions.ui.SuggestionsWorker
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class SuggestionsSettingsFragment :
|
||||
BasePreferenceFragment(R.string.suggestions),
|
||||
class SuggestionsSettingsFragment : BasePreferenceFragment(R.string.suggestions),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
@Inject
|
||||
@@ -48,16 +48,17 @@ class SuggestionsSettingsFragment :
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
if (key == AppSettings.KEY_SUGGESTIONS && settings.isSuggestionsEnabled) {
|
||||
onSuggestionsEnabled()
|
||||
if (settings.isSuggestionsEnabled && (key == AppSettings.KEY_SUGGESTIONS
|
||||
|| key == AppSettings.KEY_SUGGESTIONS_EXCLUDE_TAGS
|
||||
|| key == AppSettings.KEY_SUGGESTIONS_EXCLUDE_NSFW)
|
||||
) {
|
||||
updateSuggestions()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSuggestionsEnabled() {
|
||||
lifecycleScope.launch {
|
||||
if (repository.isEmpty()) {
|
||||
suggestionsScheduler.startNow()
|
||||
}
|
||||
private fun updateSuggestions() {
|
||||
lifecycleScope.launch(Dispatchers.Default) {
|
||||
suggestionsScheduler.startNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,16 +82,6 @@ class SourceAuthActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallba
|
||||
viewBinding.webView.loadUrl(url)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
viewBinding.webView.saveState(outState)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
viewBinding.webView.restoreState(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
viewBinding.webView.destroy()
|
||||
|
||||
@@ -64,6 +64,8 @@ class SuggestionsViewModel @Inject constructor(
|
||||
override fun onRetry() = Unit
|
||||
|
||||
fun updateSuggestions() {
|
||||
suggestionsScheduler.startNow()
|
||||
launchJob(Dispatchers.Default) {
|
||||
suggestionsScheduler.startNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package org.koitharu.kotatsu.suggestions.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.Manifest
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.os.Build
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.annotation.RequiresPermission
|
||||
import androidx.core.app.NotificationChannelCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
@@ -50,6 +51,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.util.ext.almostEquals
|
||||
import org.koitharu.kotatsu.core.util.ext.asArrayList
|
||||
import org.koitharu.kotatsu.core.util.ext.awaitUniqueWorkInfoByName
|
||||
import org.koitharu.kotatsu.core.util.ext.awaitWorkInfosByTag
|
||||
import org.koitharu.kotatsu.core.util.ext.checkNotificationPermission
|
||||
import org.koitharu.kotatsu.core.util.ext.flatten
|
||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||
@@ -189,7 +191,9 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
.sortedBy { it.relevance }
|
||||
.take(MAX_RESULTS)
|
||||
suggestionRepository.replace(suggestions)
|
||||
if (appSettings.isSuggestionsNotificationAvailable && applicationContext.checkNotificationPermission()) {
|
||||
if (appSettings.isSuggestionsNotificationAvailable
|
||||
&& applicationContext.checkNotificationPermission(MANGA_CHANNEL_ID)
|
||||
) {
|
||||
for (i in 0..3) {
|
||||
try {
|
||||
val manga = suggestions[Random.nextInt(0, suggestions.size / 3)]
|
||||
@@ -252,7 +256,7 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
e.printStackTraceDebug()
|
||||
}.getOrDefault(emptyList())
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@RequiresPermission(Manifest.permission.POST_NOTIFICATIONS)
|
||||
private suspend fun showNotification(manga: Manga) {
|
||||
val channel = NotificationChannelCompat.Builder(MANGA_CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_DEFAULT)
|
||||
.setName(applicationContext.getString(R.string.suggestions))
|
||||
@@ -393,7 +397,10 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
.any { !it.state.isFinished }
|
||||
}
|
||||
|
||||
fun startNow() {
|
||||
suspend fun startNow() {
|
||||
if (workManager.awaitWorkInfosByTag(TAG_ONESHOT).any { !it.state.isFinished }) {
|
||||
return
|
||||
}
|
||||
val constraints = Constraints.Builder()
|
||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||
.build()
|
||||
@@ -402,7 +409,7 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
.addTag(TAG_ONESHOT)
|
||||
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
|
||||
.build()
|
||||
workManager.enqueue(request)
|
||||
workManager.enqueue(request).await()
|
||||
}
|
||||
|
||||
private fun createConstraints() = Constraints.Builder()
|
||||
|
||||
@@ -168,7 +168,7 @@ class TrackWorker @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
}.onEachIndexed { index, it ->
|
||||
if (applicationContext.checkNotificationPermission()) {
|
||||
if (applicationContext.checkNotificationPermission(WORKER_CHANNEL_ID)) {
|
||||
notificationManager.notify(WORKER_NOTIFICATION_ID, createWorkerNotification(tracks.size, index + 1))
|
||||
}
|
||||
when (it) {
|
||||
@@ -197,7 +197,7 @@ class TrackWorker @AssistedInject constructor(
|
||||
channelId: String?,
|
||||
newChapters: List<MangaChapter>,
|
||||
) {
|
||||
if (newChapters.isEmpty() || channelId == null || !applicationContext.checkNotificationPermission()) {
|
||||
if (newChapters.isEmpty() || channelId == null || !applicationContext.checkNotificationPermission(channelId)) {
|
||||
return
|
||||
}
|
||||
val id = manga.url.hashCode()
|
||||
|
||||
@@ -633,4 +633,6 @@
|
||||
<string name="unread">Sin leer</string>
|
||||
<string name="enable_source">Activar fuente</string>
|
||||
<string name="unsupported_source">Esta fuente del manga no es compatible</string>
|
||||
</resources>
|
||||
<string name="show_pages_thumbs">Mostrar miniaturas de las páginas</string>
|
||||
<string name="show_pages_thumbs_summary">Habilite la pestaña \"Páginas\" en la pantalla de detalles</string>
|
||||
</resources>
|
||||
|
||||
@@ -633,4 +633,6 @@
|
||||
<string name="order_oldest">Pinakaluma</string>
|
||||
<string name="enable_source">Paganahin ang source</string>
|
||||
<string name="unsupported_source">Ang manga source na ito ay hindi suportado</string>
|
||||
</resources>
|
||||
<string name="show_pages_thumbs">Ipakita ang mga thumbnail ng pahina</string>
|
||||
<string name="show_pages_thumbs_summary">Paganahin ang tab na \"Mga Pahina\" sa screen ng mga detalye</string>
|
||||
</resources>
|
||||
|
||||
@@ -633,4 +633,6 @@
|
||||
<string name="unread">अपठित</string>
|
||||
<string name="unsupported_source">यह मंगा स्रोत समर्थित नहीं है</string>
|
||||
<string name="enable_source">स्रोत सक्षम करें</string>
|
||||
</resources>
|
||||
<string name="show_pages_thumbs_summary">विवरण स्क्रीन पर \"पेज\" टैब सक्षम करें</string>
|
||||
<string name="show_pages_thumbs">पेज थंबनेल दिखाएँ</string>
|
||||
</resources>
|
||||
|
||||
@@ -633,4 +633,6 @@
|
||||
<string name="unread">Okunmadı</string>
|
||||
<string name="unsupported_source">Bu manga kaynağı desteklenmiyor</string>
|
||||
<string name="enable_source">Kaynağı etkinleştir</string>
|
||||
</resources>
|
||||
<string name="show_pages_thumbs_summary">Ayrıntılar ekranında \"Sayfalar\" sekmesini etkinleştir</string>
|
||||
<string name="show_pages_thumbs">Sayfa küçük resimlerini göster</string>
|
||||
</resources>
|
||||
|
||||
@@ -640,4 +640,5 @@
|
||||
<string name="unsupported_source">This manga source is not supported</string>
|
||||
<string name="show_pages_thumbs">Show pages thumbnails</string>
|
||||
<string name="show_pages_thumbs_summary">Enable the \"Pages\" tab on the details screen</string>
|
||||
<string name="error_no_data_received">No data was received from server</string>
|
||||
</resources>
|
||||
|
||||
@@ -6,7 +6,7 @@ buildscript {
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.3.1'
|
||||
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.23'
|
||||
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.51'
|
||||
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.51.1'
|
||||
classpath 'com.google.devtools.ksp:symbol-processing-gradle-plugin:1.9.23-1.0.19'
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user