Tune ui
This commit is contained in:
@@ -3,6 +3,7 @@ package org.koitharu.kotatsu
|
|||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.StrictMode
|
import android.os.StrictMode
|
||||||
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.fragment.app.strictmode.FragmentStrictMode
|
import androidx.fragment.app.strictmode.FragmentStrictMode
|
||||||
import androidx.hilt.work.HiltWorkerFactory
|
import androidx.hilt.work.HiltWorkerFactory
|
||||||
@@ -10,6 +11,8 @@ import androidx.room.InvalidationTracker
|
|||||||
import androidx.work.Configuration
|
import androidx.work.Configuration
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.acra.ReportField
|
import org.acra.ReportField
|
||||||
import org.acra.config.dialog
|
import org.acra.config.dialog
|
||||||
import org.acra.config.mailSender
|
import org.acra.config.mailSender
|
||||||
@@ -20,6 +23,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
|||||||
import org.koitharu.kotatsu.local.data.PagesCache
|
import org.koitharu.kotatsu.local.data.PagesCache
|
||||||
import org.koitharu.kotatsu.local.domain.LocalMangaRepository
|
import org.koitharu.kotatsu.local.domain.LocalMangaRepository
|
||||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||||
|
import org.koitharu.kotatsu.utils.ext.processLifecycleScope
|
||||||
|
|
||||||
@HiltAndroidApp
|
@HiltAndroidApp
|
||||||
class KotatsuApp : Application(), Configuration.Provider {
|
class KotatsuApp : Application(), Configuration.Provider {
|
||||||
@@ -46,7 +50,9 @@ class KotatsuApp : Application(), Configuration.Provider {
|
|||||||
}
|
}
|
||||||
AppCompatDelegate.setDefaultNightMode(settings.theme)
|
AppCompatDelegate.setDefaultNightMode(settings.theme)
|
||||||
setupActivityLifecycleCallbacks()
|
setupActivityLifecycleCallbacks()
|
||||||
setupDatabaseObservers()
|
processLifecycleScope.launch(Dispatchers.Default) {
|
||||||
|
setupDatabaseObservers()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context?) {
|
override fun attachBaseContext(base: Context?) {
|
||||||
@@ -86,6 +92,7 @@ class KotatsuApp : Application(), Configuration.Provider {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
private fun setupDatabaseObservers() {
|
private fun setupDatabaseObservers() {
|
||||||
val tracker = database.invalidationTracker
|
val tracker = database.invalidationTracker
|
||||||
databaseObservers.forEach {
|
databaseObservers.forEach {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ class SpacingItemDecoration(@Px private val spacing: Int) : RecyclerView.ItemDec
|
|||||||
outRect: Rect,
|
outRect: Rect,
|
||||||
view: View,
|
view: View,
|
||||||
parent: RecyclerView,
|
parent: RecyclerView,
|
||||||
state: RecyclerView.State
|
state: RecyclerView.State,
|
||||||
) {
|
) {
|
||||||
outRect.set(spacing, spacing, spacing, spacing)
|
outRect.set(spacing, spacing, spacing, spacing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import android.view.WindowInsets
|
|||||||
import android.view.animation.AccelerateDecelerateInterpolator
|
import android.view.animation.AccelerateDecelerateInterpolator
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.content.withStyledAttributes
|
import androidx.core.content.withStyledAttributes
|
||||||
@@ -147,6 +148,14 @@ class BottomSheetHeaderBar @JvmOverloads constructor(
|
|||||||
expansionListeners.remove(listener)
|
expansionListeners.remove(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setTitle(@StringRes resId: Int) {
|
||||||
|
binding.toolbar.setTitle(resId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSubtitle(@StringRes resId: Int) {
|
||||||
|
binding.toolbar.setSubtitle(resId)
|
||||||
|
}
|
||||||
|
|
||||||
private fun setBottomSheetBehavior(behavior: BottomSheetBehavior<*>?) {
|
private fun setBottomSheetBehavior(behavior: BottomSheetBehavior<*>?) {
|
||||||
bottomSheetBehavior?.removeBottomSheetCallback(bottomSheetCallback)
|
bottomSheetBehavior?.removeBottomSheetCallback(bottomSheetCallback)
|
||||||
bottomSheetBehavior = behavior
|
bottomSheetBehavior = behavior
|
||||||
|
|||||||
@@ -2,9 +2,13 @@ package org.koitharu.kotatsu.core.db
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
|
import androidx.room.InvalidationTracker
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.room.migration.Migration
|
import androidx.room.migration.Migration
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.koitharu.kotatsu.bookmarks.data.BookmarkEntity
|
import org.koitharu.kotatsu.bookmarks.data.BookmarkEntity
|
||||||
import org.koitharu.kotatsu.bookmarks.data.BookmarksDao
|
import org.koitharu.kotatsu.bookmarks.data.BookmarksDao
|
||||||
import org.koitharu.kotatsu.core.db.dao.MangaDao
|
import org.koitharu.kotatsu.core.db.dao.MangaDao
|
||||||
@@ -29,6 +33,7 @@ import org.koitharu.kotatsu.suggestions.data.SuggestionEntity
|
|||||||
import org.koitharu.kotatsu.tracker.data.TrackEntity
|
import org.koitharu.kotatsu.tracker.data.TrackEntity
|
||||||
import org.koitharu.kotatsu.tracker.data.TrackLogEntity
|
import org.koitharu.kotatsu.tracker.data.TrackLogEntity
|
||||||
import org.koitharu.kotatsu.tracker.data.TracksDao
|
import org.koitharu.kotatsu.tracker.data.TracksDao
|
||||||
|
import org.koitharu.kotatsu.utils.ext.processLifecycleScope
|
||||||
|
|
||||||
const val DATABASE_VERSION = 14
|
const val DATABASE_VERSION = 14
|
||||||
|
|
||||||
@@ -88,3 +93,12 @@ fun MangaDatabase(context: Context): MangaDatabase = Room
|
|||||||
.addMigrations(*databaseMigrations)
|
.addMigrations(*databaseMigrations)
|
||||||
.addCallback(DatabasePrePopulateCallback(context.resources))
|
.addCallback(DatabasePrePopulateCallback(context.resources))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
fun InvalidationTracker.removeObserverAsync(observer: InvalidationTracker.Observer) {
|
||||||
|
val scope = processLifecycleScope
|
||||||
|
if (scope.isActive) {
|
||||||
|
processLifecycleScope.launch(Dispatchers.Default) {
|
||||||
|
removeObserver(observer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,13 +7,11 @@ import android.content.IntentFilter
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.core.graphics.Insets
|
import androidx.core.graphics.Insets
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updateLayoutParams
|
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.android.material.badge.BadgeDrawable
|
import com.google.android.material.badge.BadgeDrawable
|
||||||
@@ -209,7 +207,7 @@ class DetailsActivity :
|
|||||||
right = insets.right,
|
right = insets.right,
|
||||||
)
|
)
|
||||||
if (insets.bottom > 0) {
|
if (insets.bottom > 0) {
|
||||||
window.setNavigationBarTransparentCompat(this, binding.layoutBottom?.elevation ?: 0f)
|
window.setNavigationBarTransparentCompat(this, binding.layoutBottom?.elevation ?: 0f, 0.9f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.koitharu.kotatsu.download.ui
|
package org.koitharu.kotatsu.download.ui
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||||
@@ -9,6 +10,7 @@ import kotlinx.coroutines.flow.launchIn
|
|||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.databinding.ItemDownloadBinding
|
import org.koitharu.kotatsu.databinding.ItemDownloadBinding
|
||||||
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||||
import org.koitharu.kotatsu.download.domain.DownloadState
|
import org.koitharu.kotatsu.download.domain.DownloadState
|
||||||
import org.koitharu.kotatsu.parsers.util.format
|
import org.koitharu.kotatsu.parsers.util.format
|
||||||
import org.koitharu.kotatsu.utils.ext.*
|
import org.koitharu.kotatsu.utils.ext.*
|
||||||
@@ -22,6 +24,19 @@ fun downloadItemAD(
|
|||||||
var job: Job? = null
|
var job: Job? = null
|
||||||
val percentPattern = context.resources.getString(R.string.percent_string_pattern)
|
val percentPattern = context.resources.getString(R.string.percent_string_pattern)
|
||||||
|
|
||||||
|
val clickListener = View.OnClickListener { v ->
|
||||||
|
when (v.id) {
|
||||||
|
R.id.button_cancel -> item.cancel()
|
||||||
|
R.id.button_resume -> item.resume()
|
||||||
|
else -> context.startActivity(
|
||||||
|
DetailsActivity.newIntent(context, item.progressValue.manga),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.buttonCancel.setOnClickListener(clickListener)
|
||||||
|
binding.buttonResume.setOnClickListener(clickListener)
|
||||||
|
itemView.setOnClickListener(clickListener)
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
job?.cancel()
|
job?.cancel()
|
||||||
job = item.progressAsFlow().onFirst { state ->
|
job = item.progressAsFlow().onFirst { state ->
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ import kotlinx.coroutines.flow.flatMapLatest
|
|||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
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.list.decor.SpacingItemDecoration
|
||||||
import org.koitharu.kotatsu.databinding.ActivityDownloadsBinding
|
import org.koitharu.kotatsu.databinding.ActivityDownloadsBinding
|
||||||
import org.koitharu.kotatsu.download.ui.service.DownloadService
|
import org.koitharu.kotatsu.download.ui.service.DownloadService
|
||||||
import org.koitharu.kotatsu.utils.bindServiceWithLifecycle
|
import org.koitharu.kotatsu.utils.bindServiceWithLifecycle
|
||||||
@@ -30,6 +32,8 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>() {
|
|||||||
setContentView(ActivityDownloadsBinding.inflate(layoutInflater))
|
setContentView(ActivityDownloadsBinding.inflate(layoutInflater))
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
val adapter = DownloadsAdapter(lifecycleScope, coil)
|
val adapter = DownloadsAdapter(lifecycleScope, coil)
|
||||||
|
val spacing = resources.getDimensionPixelOffset(R.dimen.grid_spacing)
|
||||||
|
binding.recyclerView.addItemDecoration(SpacingItemDecoration(spacing))
|
||||||
binding.recyclerView.setHasFixedSize(true)
|
binding.recyclerView.setHasFixedSize(true)
|
||||||
binding.recyclerView.adapter = adapter
|
binding.recyclerView.adapter = adapter
|
||||||
bindServiceWithLifecycle(
|
bindServiceWithLifecycle(
|
||||||
|
|||||||
@@ -139,6 +139,8 @@ class DownloadService : BaseService() {
|
|||||||
notification.create(job.progressValue, -1L)
|
notification.create(job.progressValue, -1L)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
jobs.remove(job.progressValue.startId)
|
||||||
|
jobCount.value = jobs.size
|
||||||
stopSelf(startId)
|
stopSelf(startId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,8 +160,7 @@ class DownloadService : BaseService() {
|
|||||||
when (intent?.action) {
|
when (intent?.action) {
|
||||||
ACTION_DOWNLOAD_CANCEL -> {
|
ACTION_DOWNLOAD_CANCEL -> {
|
||||||
val cancelId = intent.getIntExtra(EXTRA_CANCEL_ID, 0)
|
val cancelId = intent.getIntExtra(EXTRA_CANCEL_ID, 0)
|
||||||
jobs.remove(cancelId)?.cancel()
|
jobs[cancelId]?.cancel()
|
||||||
jobCount.value = jobs.size
|
|
||||||
}
|
}
|
||||||
ACTION_DOWNLOAD_RESUME -> {
|
ACTION_DOWNLOAD_RESUME -> {
|
||||||
val cancelId = intent.getIntExtra(EXTRA_CANCEL_ID, 0)
|
val cancelId = intent.getIntExtra(EXTRA_CANCEL_ID, 0)
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ abstract class FavouriteCategoriesDao {
|
|||||||
@Query("UPDATE favourite_categories SET `order` = :order WHERE category_id = :id")
|
@Query("UPDATE favourite_categories SET `order` = :order WHERE category_id = :id")
|
||||||
abstract suspend fun updateOrder(id: Long, order: String)
|
abstract suspend fun updateOrder(id: Long, order: String)
|
||||||
|
|
||||||
// @Query("UPDATE favourite_categories SET `track` = :isEnabled WHERE category_id = :id")
|
@Query("UPDATE favourite_categories SET `track` = :isEnabled WHERE category_id = :id")
|
||||||
// abstract suspend fun updateTracking(id: Long, isEnabled: Boolean)
|
abstract suspend fun updateTracking(id: Long, isEnabled: Boolean)
|
||||||
|
|
||||||
@Query("UPDATE favourite_categories SET `show_in_lib` = :isEnabled WHERE category_id = :id")
|
@Query("UPDATE favourite_categories SET `show_in_lib` = :isEnabled WHERE category_id = :id")
|
||||||
abstract suspend fun updateLibVisibility(id: Long, isEnabled: Boolean)
|
abstract suspend fun updateLibVisibility(id: Long, isEnabled: Boolean)
|
||||||
|
|||||||
@@ -108,6 +108,10 @@ class FavouritesRepository @Inject constructor(
|
|||||||
db.favouriteCategoriesDao.updateLibVisibility(id, isVisibleInLibrary)
|
db.favouriteCategoriesDao.updateLibVisibility(id, isVisibleInLibrary)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun updateCategoryTracking(id: Long, isTrackingEnabled: Boolean) {
|
||||||
|
db.favouriteCategoriesDao.updateTracking(id, isTrackingEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun removeCategory(id: Long) {
|
suspend fun removeCategory(id: Long) {
|
||||||
db.withTransaction {
|
db.withTransaction {
|
||||||
db.favouriteCategoriesDao.delete(id)
|
db.favouriteCategoriesDao.delete(id)
|
||||||
|
|||||||
@@ -130,8 +130,8 @@ class LibraryViewModel @Inject constructor(
|
|||||||
if (result.isEmpty()) {
|
if (result.isEmpty()) {
|
||||||
result += EmptyState(
|
result += EmptyState(
|
||||||
icon = R.drawable.ic_empty_history,
|
icon = R.drawable.ic_empty_history,
|
||||||
textPrimary = R.string.text_history_holder_primary,
|
textPrimary = R.string.text_shelf_holder_primary,
|
||||||
textSecondary = R.string.text_history_holder_secondary,
|
textSecondary = R.string.text_shelf_holder_secondary,
|
||||||
actionStringRes = 0,
|
actionStringRes = 0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -168,11 +168,13 @@ class LibraryViewModel @Inject constructor(
|
|||||||
favourites: Map<FavouriteCategory, List<Manga>>,
|
favourites: Map<FavouriteCategory, List<Manga>>,
|
||||||
) {
|
) {
|
||||||
for ((category, list) in favourites) {
|
for ((category, list) in favourites) {
|
||||||
destination += LibrarySectionModel.Favourites(
|
if (list.isNotEmpty()) {
|
||||||
items = list.toUi(ListMode.GRID, this),
|
destination += LibrarySectionModel.Favourites(
|
||||||
category = category,
|
items = list.toUi(ListMode.GRID, this),
|
||||||
showAllButtonText = R.string.show_all,
|
category = category,
|
||||||
)
|
showAllButtonText = R.string.show_all,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,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.scrobbling.shikimori.ui.ShikimoriSettingsFragment
|
import org.koitharu.kotatsu.scrobbling.shikimori.ui.ShikimoriSettingsFragment
|
||||||
import org.koitharu.kotatsu.settings.sources.SourcesSettingsFragment
|
import org.koitharu.kotatsu.settings.sources.SourcesSettingsFragment
|
||||||
|
import org.koitharu.kotatsu.settings.tracker.TrackerSettingsFragment
|
||||||
import org.koitharu.kotatsu.utils.ext.isScrolledToTop
|
import org.koitharu.kotatsu.utils.ext.isScrolledToTop
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.Comparator
|
|
||||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||||
import org.koitharu.kotatsu.core.model.MangaSource
|
import org.koitharu.kotatsu.core.model.MangaSource
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
@@ -41,6 +40,7 @@ class OnboardViewModel @Inject constructor(
|
|||||||
if (selectedLocales.isEmpty()) {
|
if (selectedLocales.isEmpty()) {
|
||||||
selectedLocales += "en"
|
selectedLocales += "en"
|
||||||
}
|
}
|
||||||
|
selectedLocales += null
|
||||||
}
|
}
|
||||||
rebuildList()
|
rebuildList()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.koitharu.kotatsu.settings
|
package org.koitharu.kotatsu.settings.tracker
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
@@ -15,20 +15,18 @@ import android.view.View
|
|||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.text.buildSpannedString
|
import androidx.core.text.buildSpannedString
|
||||||
import androidx.core.text.inSpans
|
import androidx.core.text.inSpans
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.preference.MultiSelectListPreference
|
import androidx.preference.MultiSelectListPreference
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BasePreferenceFragment
|
import org.koitharu.kotatsu.base.ui.BasePreferenceFragment
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity
|
import org.koitharu.kotatsu.settings.tracker.categories.TrackerCategoriesConfigSheet
|
||||||
import org.koitharu.kotatsu.settings.utils.MultiSummaryProvider
|
import org.koitharu.kotatsu.settings.utils.MultiSummaryProvider
|
||||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
|
||||||
import org.koitharu.kotatsu.tracker.work.TrackerNotificationChannels
|
import org.koitharu.kotatsu.tracker.work.TrackerNotificationChannels
|
||||||
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
|
||||||
|
|
||||||
private const val KEY_IGNORE_DOZE = "ignore_dose"
|
private const val KEY_IGNORE_DOZE = "ignore_dose"
|
||||||
|
|
||||||
@@ -37,8 +35,7 @@ class TrackerSettingsFragment :
|
|||||||
BasePreferenceFragment(R.string.check_for_new_chapters),
|
BasePreferenceFragment(R.string.check_for_new_chapters),
|
||||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
@Inject
|
private val viewModel by viewModels<TrackerSettingsViewModel>()
|
||||||
lateinit var repository: TrackingRepository
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var channels: TrackerNotificationChannels
|
lateinit var channels: TrackerNotificationChannels
|
||||||
@@ -66,13 +63,13 @@ class TrackerSettingsFragment :
|
|||||||
findPreference<Preference>(KEY_IGNORE_DOZE)?.run {
|
findPreference<Preference>(KEY_IGNORE_DOZE)?.run {
|
||||||
isVisible = isDozeIgnoreAvailable(context)
|
isVisible = isDozeIgnoreAvailable(context)
|
||||||
}
|
}
|
||||||
updateCategoriesSummary()
|
|
||||||
updateNotificationsSummary()
|
updateNotificationsSummary()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
settings.subscribe(this)
|
settings.subscribe(this)
|
||||||
|
viewModel.categoriesCount.observe(viewLifecycleOwner, ::onCategoriesCountChanged)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
@@ -109,7 +106,7 @@ class TrackerSettingsFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
AppSettings.KEY_TRACK_CATEGORIES -> {
|
AppSettings.KEY_TRACK_CATEGORIES -> {
|
||||||
startActivity(FavouriteCategoriesActivity.newIntent(preference.context))
|
TrackerCategoriesConfigSheet.show(childFragmentManager)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
KEY_IGNORE_DOZE -> {
|
KEY_IGNORE_DOZE -> {
|
||||||
@@ -136,11 +133,10 @@ class TrackerSettingsFragment :
|
|||||||
pref.isEnabled = settings.isTrackerEnabled && AppSettings.TRACK_FAVOURITES in settings.trackSources
|
pref.isEnabled = settings.isTrackerEnabled && AppSettings.TRACK_FAVOURITES in settings.trackSources
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateCategoriesSummary() {
|
private fun onCategoriesCountChanged(count: IntArray?) {
|
||||||
val pref = findPreference<Preference>(AppSettings.KEY_TRACK_CATEGORIES) ?: return
|
val pref = findPreference<Preference>(AppSettings.KEY_TRACK_CATEGORIES) ?: return
|
||||||
viewLifecycleScope.launch {
|
pref.summary = count?.let {
|
||||||
val count = repository.getCategoriesCount()
|
getString(R.string.enabled_d_of_d, count[0], count[1])
|
||||||
pref.summary = getString(R.string.enabled_d_of_d, count[0], count[1])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.tracker
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.room.InvalidationTracker
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import okio.Closeable
|
||||||
|
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||||
|
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||||
|
import org.koitharu.kotatsu.core.db.TABLE_FAVOURITE_CATEGORIES
|
||||||
|
import org.koitharu.kotatsu.core.db.removeObserverAsync
|
||||||
|
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class TrackerSettingsViewModel @Inject constructor(
|
||||||
|
private val repository: TrackingRepository,
|
||||||
|
private val database: MangaDatabase,
|
||||||
|
) : BaseViewModel() {
|
||||||
|
|
||||||
|
val categoriesCount = MutableLiveData<IntArray?>(null)
|
||||||
|
|
||||||
|
init {
|
||||||
|
updateCategoriesCount()
|
||||||
|
val databaseObserver = DatabaseObserver(this)
|
||||||
|
addCloseable(databaseObserver)
|
||||||
|
launchJob(Dispatchers.Default) {
|
||||||
|
database.invalidationTracker.addObserver(databaseObserver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateCategoriesCount() {
|
||||||
|
launchJob(Dispatchers.Default) {
|
||||||
|
categoriesCount.postValue(repository.getCategoriesCount())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DatabaseObserver(private var vm: TrackerSettingsViewModel?) :
|
||||||
|
InvalidationTracker.Observer(arrayOf(TABLE_FAVOURITE_CATEGORIES)),
|
||||||
|
Closeable {
|
||||||
|
|
||||||
|
override fun onInvalidated(tables: MutableSet<String>) {
|
||||||
|
vm?.updateCategoriesCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
(vm ?: return).database.invalidationTracker.removeObserverAsync(this)
|
||||||
|
vm = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.tracker.categories
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter
|
||||||
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
|
||||||
|
class TrackerCategoriesConfigAdapter(
|
||||||
|
listener: OnListItemClickListener<FavouriteCategory>,
|
||||||
|
) : AsyncListDifferDelegationAdapter<FavouriteCategory>(DiffCallback()) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
delegatesManager.addDelegate(trackerCategoryAD(listener))
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiffCallback : DiffUtil.ItemCallback<FavouriteCategory>() {
|
||||||
|
|
||||||
|
override fun areItemsTheSame(oldItem: FavouriteCategory, newItem: FavouriteCategory): Boolean {
|
||||||
|
return oldItem.id == newItem.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: FavouriteCategory, newItem: FavouriteCategory): Boolean {
|
||||||
|
return oldItem.isTrackingEnabled == newItem.isTrackingEnabled && oldItem.title == newItem.title
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getChangePayload(oldItem: FavouriteCategory, newItem: FavouriteCategory): Any? {
|
||||||
|
return if (oldItem.isTrackingEnabled == newItem.isTrackingEnabled) {
|
||||||
|
super.getChangePayload(oldItem, newItem)
|
||||||
|
} else Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.tracker.categories
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.base.ui.BaseBottomSheet
|
||||||
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
import org.koitharu.kotatsu.databinding.SheetBaseBinding
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class TrackerCategoriesConfigSheet :
|
||||||
|
BaseBottomSheet<SheetBaseBinding>(),
|
||||||
|
OnListItemClickListener<FavouriteCategory>,
|
||||||
|
View.OnClickListener {
|
||||||
|
|
||||||
|
private val viewModel by viewModels<TrackerCategoriesConfigViewModel>()
|
||||||
|
|
||||||
|
override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetBaseBinding {
|
||||||
|
return SheetBaseBinding.inflate(inflater, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
binding.headerBar.setTitle(R.string.favourites_categories)
|
||||||
|
binding.buttonDone.isVisible = true
|
||||||
|
binding.buttonDone.setOnClickListener(this)
|
||||||
|
val adapter = TrackerCategoriesConfigAdapter(this)
|
||||||
|
binding.recyclerView.adapter = adapter
|
||||||
|
|
||||||
|
viewModel.content.observe(viewLifecycleOwner) { adapter.items = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClick(item: FavouriteCategory, view: View) {
|
||||||
|
viewModel.toggleItem(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View?) {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val TAG = "TrackerCategoriesConfigSheet"
|
||||||
|
|
||||||
|
fun show(fm: FragmentManager) = TrackerCategoriesConfigSheet().show(fm, TAG)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.tracker.categories
|
||||||
|
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||||
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||||
|
import org.koitharu.kotatsu.utils.asFlowLiveData
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class TrackerCategoriesConfigViewModel @Inject constructor(
|
||||||
|
private val favouritesRepository: FavouritesRepository,
|
||||||
|
) : BaseViewModel() {
|
||||||
|
|
||||||
|
val content = favouritesRepository.observeCategories()
|
||||||
|
.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList())
|
||||||
|
|
||||||
|
private var updateJob: Job? = null
|
||||||
|
|
||||||
|
fun toggleItem(category: FavouriteCategory) {
|
||||||
|
val prevJob = updateJob
|
||||||
|
updateJob = launchJob(Dispatchers.Default) {
|
||||||
|
prevJob?.join()
|
||||||
|
favouritesRepository.updateCategoryTracking(category.id, !category.isTrackingEnabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.tracker.categories
|
||||||
|
|
||||||
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||||
|
import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter
|
||||||
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
import org.koitharu.kotatsu.databinding.ItemCategoryCheckableMultipleBinding
|
||||||
|
|
||||||
|
fun trackerCategoryAD(
|
||||||
|
listener: OnListItemClickListener<FavouriteCategory>,
|
||||||
|
) = adapterDelegateViewBinding<FavouriteCategory, FavouriteCategory, ItemCategoryCheckableMultipleBinding>(
|
||||||
|
{ layoutInflater, parent -> ItemCategoryCheckableMultipleBinding.inflate(layoutInflater, parent, false) },
|
||||||
|
) {
|
||||||
|
val eventListener = AdapterDelegateClickListenerAdapter(this, listener)
|
||||||
|
itemView.setOnClickListener(eventListener)
|
||||||
|
|
||||||
|
bind {
|
||||||
|
binding.root.text = item.title
|
||||||
|
binding.root.isChecked = item.isTrackingEnabled
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,14 +15,11 @@ import android.net.Uri
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.ViewPropertyAnimator
|
import android.view.ViewPropertyAnimator
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.annotation.IntegerRes
|
import androidx.annotation.IntegerRes
|
||||||
import androidx.core.app.ActivityOptionsCompat
|
import androidx.core.app.ActivityOptionsCompat
|
||||||
import androidx.core.view.children
|
|
||||||
import androidx.core.view.descendants
|
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.coroutineScope
|
import androidx.lifecycle.coroutineScope
|
||||||
import androidx.work.CoroutineWorker
|
import androidx.work.CoroutineWorker
|
||||||
@@ -104,7 +101,7 @@ fun SyncResult.onError(error: Throwable) {
|
|||||||
error.printStackTraceDebug()
|
error.printStackTraceDebug()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Window.setNavigationBarTransparentCompat(context: Context, elevation: Float = 0F) {
|
fun Window.setNavigationBarTransparentCompat(context: Context, elevation: Float, alphaFactor: Float = 0.7f) {
|
||||||
navigationBarColor = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
|
navigationBarColor = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
|
||||||
!InternalResourceHelper.getBoolean(context, "config_navBarNeedsScrim", true)
|
!InternalResourceHelper.getBoolean(context, "config_navBarNeedsScrim", true)
|
||||||
) {
|
) {
|
||||||
@@ -112,7 +109,7 @@ fun Window.setNavigationBarTransparentCompat(context: Context, elevation: Float
|
|||||||
} else {
|
} else {
|
||||||
// Set navbar scrim 70% of navigationBarColor
|
// Set navbar scrim 70% of navigationBarColor
|
||||||
ElevationOverlayProvider(context).compositeOverlayIfNeeded(
|
ElevationOverlayProvider(context).compositeOverlayIfNeeded(
|
||||||
context.getResourceColor(android.R.attr.navigationBarColor, 0.7F),
|
context.getThemeColor(android.R.attr.navigationBarColor, alphaFactor),
|
||||||
elevation,
|
elevation,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
package org.koitharu.kotatsu.utils.ext
|
package org.koitharu.kotatsu.utils.ext
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Color
|
|
||||||
import androidx.annotation.AttrRes
|
|
||||||
import androidx.annotation.ColorInt
|
|
||||||
import androidx.annotation.Px
|
import androidx.annotation.Px
|
||||||
import androidx.core.graphics.alpha
|
|
||||||
import androidx.core.graphics.blue
|
|
||||||
import androidx.core.graphics.green
|
|
||||||
import androidx.core.graphics.red
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@Px
|
@Px
|
||||||
@@ -17,17 +9,3 @@ fun Resources.resolveDp(dp: Int) = (dp * displayMetrics.density).roundToInt()
|
|||||||
|
|
||||||
@Px
|
@Px
|
||||||
fun Resources.resolveDp(dp: Float) = dp * displayMetrics.density
|
fun Resources.resolveDp(dp: Float) = dp * displayMetrics.density
|
||||||
|
|
||||||
@ColorInt
|
|
||||||
fun Context.getResourceColor(@AttrRes resource: Int, alphaFactor: Float = 1f): Int {
|
|
||||||
val typedArray = obtainStyledAttributes(intArrayOf(resource))
|
|
||||||
val color = typedArray.getColor(0, 0)
|
|
||||||
typedArray.recycle()
|
|
||||||
|
|
||||||
if (alphaFactor < 1f) {
|
|
||||||
val alpha = (color.alpha * alphaFactor).roundToInt()
|
|
||||||
return Color.argb(alpha, color.red, color.green, color.blue)
|
|
||||||
}
|
|
||||||
|
|
||||||
return color
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,9 @@ import android.content.Context
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
|
import androidx.annotation.FloatRange
|
||||||
import androidx.core.content.res.use
|
import androidx.core.content.res.use
|
||||||
|
import androidx.core.graphics.ColorUtils
|
||||||
|
|
||||||
fun Context.getThemeDrawable(
|
fun Context.getThemeDrawable(
|
||||||
@AttrRes resId: Int,
|
@AttrRes resId: Int,
|
||||||
@@ -15,13 +17,29 @@ fun Context.getThemeDrawable(
|
|||||||
@ColorInt
|
@ColorInt
|
||||||
fun Context.getThemeColor(
|
fun Context.getThemeColor(
|
||||||
@AttrRes resId: Int,
|
@AttrRes resId: Int,
|
||||||
@ColorInt default: Int = Color.TRANSPARENT
|
@ColorInt fallback: Int = Color.TRANSPARENT,
|
||||||
) = obtainStyledAttributes(intArrayOf(resId)).use {
|
) = obtainStyledAttributes(intArrayOf(resId)).use {
|
||||||
it.getColor(0, default)
|
it.getColor(0, fallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ColorInt
|
||||||
|
fun Context.getThemeColor(
|
||||||
|
@AttrRes resId: Int,
|
||||||
|
@FloatRange(from = 0.0, to = 1.0) alphaFactor: Float,
|
||||||
|
@ColorInt fallback: Int = Color.TRANSPARENT,
|
||||||
|
): Int {
|
||||||
|
if (alphaFactor <= 0f) {
|
||||||
|
return Color.TRANSPARENT
|
||||||
|
}
|
||||||
|
val color = getThemeColor(resId, fallback)
|
||||||
|
if (alphaFactor >= 1f) {
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
return ColorUtils.setAlphaComponent(color, (0xFF * alphaFactor).toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.getThemeColorStateList(
|
fun Context.getThemeColorStateList(
|
||||||
@AttrRes resId: Int,
|
@AttrRes resId: Int,
|
||||||
) = obtainStyledAttributes(intArrayOf(resId)).use {
|
) = obtainStyledAttributes(intArrayOf(resId)).use {
|
||||||
it.getColorStateList(0)
|
it.getColorStateList(0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@
|
|||||||
|
|
||||||
<RatingBar
|
<RatingBar
|
||||||
android:id="@+id/rating_bar"
|
android:id="@+id/rating_bar"
|
||||||
style="@style/Widget.AppCompat.RatingBar.Small"
|
style="?ratingBarStyleSmall"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:isIndicator="true"
|
android:isIndicator="true"
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
|
|
||||||
<RatingBar
|
<RatingBar
|
||||||
android:id="@+id/rating_bar"
|
android:id="@+id/rating_bar"
|
||||||
style="@style/Widget.AppCompat.RatingBar.Small"
|
style="?ratingBarStyleSmall"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
<RatingBar
|
<RatingBar
|
||||||
android:id="@+id/ratingBar"
|
android:id="@+id/ratingBar"
|
||||||
style="@style/Widget.AppCompat.RatingBar.Small"
|
style="?ratingBarStyleSmall"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/textView_title"
|
android:layout_below="@id/textView_title"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginVertical="8dp"
|
android:layout_marginVertical="8dp"
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"
|
||||||
|
app:cardBackgroundColor="?colorOnPrimary"
|
||||||
app:cardCornerRadius="24dp">
|
app:cardCornerRadius="24dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -58,4 +59,4 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|||||||
@@ -120,6 +120,8 @@
|
|||||||
<string name="text_search_holder_secondary">Try to reformulate the query.</string>
|
<string name="text_search_holder_secondary">Try to reformulate the query.</string>
|
||||||
<string name="text_history_holder_primary">What you read will be displayed here</string>
|
<string name="text_history_holder_primary">What you read will be displayed here</string>
|
||||||
<string name="text_history_holder_secondary">Find what to read in side menu.</string>
|
<string name="text_history_holder_secondary">Find what to read in side menu.</string>
|
||||||
|
<string name="text_shelf_holder_primary">Your manga will be displayed here</string>
|
||||||
|
<string name="text_shelf_holder_secondary">Find what to read in the «Explore» section</string>
|
||||||
<string name="text_local_holder_primary">Save something first</string>
|
<string name="text_local_holder_primary">Save something first</string>
|
||||||
<string name="text_local_holder_secondary">Save it from online sources or import files.</string>
|
<string name="text_local_holder_secondary">Save it from online sources or import files.</string>
|
||||||
<string name="manga_shelf">Shelf</string>
|
<string name="manga_shelf">Shelf</string>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
android:title="@string/reader_settings" />
|
android:title="@string/reader_settings" />
|
||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
android:fragment="org.koitharu.kotatsu.settings.TrackerSettingsFragment"
|
android:fragment="org.koitharu.kotatsu.settings.tracker.TrackerSettingsFragment"
|
||||||
android:icon="@drawable/ic_feed"
|
android:icon="@drawable/ic_feed"
|
||||||
android:title="@string/check_for_new_chapters" />
|
android:title="@string/check_for_new_chapters" />
|
||||||
|
|
||||||
@@ -34,4 +34,4 @@
|
|||||||
android:icon="@drawable/ic_info_outline"
|
android:icon="@drawable/ic_info_outline"
|
||||||
android:title="@string/about" />
|
android:title="@string/about" />
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|||||||
Reference in New Issue
Block a user