From b3781abdeb05c78717548c7f15fe5bfaff53d7a2 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 27 Feb 2022 09:28:25 +0200 Subject: [PATCH 1/8] New chapters counters in lists --- .../koitharu/kotatsu/core/db/dao/TracksDao.kt | 3 + .../kotatsu/favourites/FavouritesModule.kt | 2 +- .../ui/list/FavouritesListViewModel.kt | 13 +++- .../koitharu/kotatsu/history/HistoryModule.kt | 2 +- .../history/ui/HistoryListViewModel.kt | 13 ++-- .../kotatsu/list/domain/CountersProvider.kt | 6 ++ .../kotatsu/list/ui/adapter/BadgeADUtil.kt | 44 ++++++++++++++ .../list/ui/adapter/MangaGridItemAD.kt | 5 ++ .../ui/adapter/MangaListDetailedItemAD.kt | 5 ++ .../list/ui/adapter/MangaListItemAD.kt | 5 ++ .../list/ui/model/ListModelConversionExt.kt | 59 ++++++++++++++----- .../kotatsu/list/ui/model/MangaGridModel.kt | 3 +- .../list/ui/model/MangaListDetailedModel.kt | 3 +- .../kotatsu/list/ui/model/MangaListModel.kt | 3 +- .../kotatsu/local/ui/LocalListViewModel.kt | 8 ++- .../tracker/domain/TrackingRepository.kt | 3 +- app/src/main/res/layout/item_manga_grid.xml | 1 + app/src/main/res/values/dimens.xml | 2 + app/src/main/res/values/integers.xml | 2 +- 19 files changed, 149 insertions(+), 33 deletions(-) create mode 100644 app/src/main/java/org/koitharu/kotatsu/list/domain/CountersProvider.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/BadgeADUtil.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TracksDao.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TracksDao.kt index d6f7fc571..4bd188966 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TracksDao.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TracksDao.kt @@ -13,6 +13,9 @@ abstract class TracksDao { @Query("SELECT * FROM tracks WHERE manga_id = :mangaId") abstract suspend fun find(mangaId: Long): TrackEntity? + @Query("SELECT chapters_new FROM tracks WHERE manga_id = :mangaId") + abstract suspend fun findNewChapters(mangaId: Long): Int? + @Query("DELETE FROM tracks") abstract suspend fun clear() diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/FavouritesModule.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/FavouritesModule.kt index 4db6c0c27..9cd6e751e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/FavouritesModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/FavouritesModule.kt @@ -13,7 +13,7 @@ val favouritesModule single { FavouritesRepository(get()) } viewModel { categoryId -> - FavouritesListViewModel(categoryId.get(), get(), get()) + FavouritesListViewModel(categoryId.get(), get(), get(), get()) } viewModel { FavouritesCategoriesViewModel(get()) } viewModel { manga -> diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt index 344c3d5a1..bfd8292ae 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt @@ -9,18 +9,21 @@ import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.SortOrder import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.favourites.domain.FavouritesRepository +import org.koitharu.kotatsu.list.domain.CountersProvider import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toUi +import org.koitharu.kotatsu.tracker.domain.TrackingRepository import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct class FavouritesListViewModel( private val categoryId: Long, private val repository: FavouritesRepository, - settings: AppSettings -) : MangaListViewModel(settings) { + private val trackingRepository: TrackingRepository, + settings: AppSettings, +) : MangaListViewModel(settings), CountersProvider { override val content = combine( if (categoryId == 0L) { @@ -42,7 +45,7 @@ class FavouritesListViewModel( } ) ) - else -> list.toUi(mode) + else -> list.toUi(mode, this) } }.catch { emit(listOf(it.toErrorState(canRetry = false))) @@ -61,4 +64,8 @@ class FavouritesListViewModel( } } } + + override suspend fun getCounter(mangaId: Long): Int { + return trackingRepository.getNewChaptersCount(mangaId) + } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/history/HistoryModule.kt b/app/src/main/java/org/koitharu/kotatsu/history/HistoryModule.kt index bf6ea6304..74fb0ef40 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/HistoryModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/HistoryModule.kt @@ -9,5 +9,5 @@ val historyModule get() = module { single { HistoryRepository(get(), get(), get()) } - viewModel { HistoryListViewModel(get(), get(), get()) } + viewModel { HistoryListViewModel(get(), get(), get(), get()) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt index 8422232bd..97fa18c4c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt @@ -14,6 +14,7 @@ import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.MangaWithHistory import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.* +import org.koitharu.kotatsu.tracker.domain.TrackingRepository import org.koitharu.kotatsu.utils.SingleLiveEvent import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct import org.koitharu.kotatsu.utils.ext.daysDiff @@ -24,7 +25,8 @@ import java.util.concurrent.TimeUnit class HistoryListViewModel( private val repository: HistoryRepository, private val settings: AppSettings, - private val shortcutsRepository: ShortcutsRepository + private val shortcutsRepository: ShortcutsRepository, + private val trackingRepository: TrackingRepository, ) : MangaListViewModel(settings) { val onItemRemoved = SingleLiveEvent() @@ -75,7 +77,7 @@ class HistoryListViewModel( settings.historyGrouping = isGroupingEnabled } - private fun mapList( + private suspend fun mapList( list: List, grouped: Boolean, mode: ListMode @@ -93,10 +95,11 @@ class HistoryListViewModel( } prevDate = date } + val counter = trackingRepository.getNewChaptersCount(manga.id) result += when (mode) { - ListMode.LIST -> manga.toListModel() - ListMode.DETAILED_LIST -> manga.toListDetailedModel() - ListMode.GRID -> manga.toGridModel() + ListMode.LIST -> manga.toListModel(counter) + ListMode.DETAILED_LIST -> manga.toListDetailedModel(counter) + ListMode.GRID -> manga.toGridModel(counter) } } return result diff --git a/app/src/main/java/org/koitharu/kotatsu/list/domain/CountersProvider.kt b/app/src/main/java/org/koitharu/kotatsu/list/domain/CountersProvider.kt new file mode 100644 index 000000000..e9594019c --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/list/domain/CountersProvider.kt @@ -0,0 +1,6 @@ +package org.koitharu.kotatsu.list.domain + +fun interface CountersProvider { + + suspend fun getCounter(mangaId: Long): Int +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/BadgeADUtil.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/BadgeADUtil.kt new file mode 100644 index 000000000..10c92e46a --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/BadgeADUtil.kt @@ -0,0 +1,44 @@ +@file:SuppressLint("UnsafeOptInUsageError") +package org.koitharu.kotatsu.list.ui.adapter + +import android.annotation.SuppressLint +import android.view.View +import androidx.core.view.doOnNextLayout +import com.google.android.material.badge.BadgeDrawable +import com.google.android.material.badge.BadgeUtils +import org.koitharu.kotatsu.R + +fun View.bindBadge(badge: BadgeDrawable?, counter: Int): BadgeDrawable? { + return if (counter > 0) { + val badgeDrawable = badge ?: initBadge(this) + badgeDrawable.number = counter + badgeDrawable.isVisible = true + badgeDrawable.align() + badgeDrawable + } else { + badge?.isVisible = false + badge + } +} + +fun View.clearBadge(badge: BadgeDrawable?) { + BadgeUtils.detachBadgeDrawable(badge, this) +} + +private fun initBadge(anchor: View): BadgeDrawable { + val badge = BadgeDrawable.create(anchor.context) + val resources = anchor.resources + badge.maxCharacterCount = resources.getInteger(R.integer.manga_badge_max_character_count) + badge.horizontalOffsetWithoutText = resources.getDimensionPixelOffset(R.dimen.manga_badge_offset_horizontal) + badge.verticalOffsetWithoutText = resources.getDimensionPixelOffset(R.dimen.manga_badge_offset_vertical) + anchor.doOnNextLayout { + BadgeUtils.attachBadgeDrawable(badge, it) + badge.align() + } + return badge +} + +private fun BadgeDrawable.align() { + horizontalOffsetWithText = horizontalOffsetWithoutText + intrinsicWidth / 2 + verticalOffsetWithText = verticalOffsetWithoutText + intrinsicHeight / 2 +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt index 4c5ee8176..002281c70 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import coil.request.Disposable import coil.util.CoilUtils +import com.google.android.material.badge.BadgeDrawable import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener @@ -24,6 +25,7 @@ fun mangaGridItemAD( ) { var imageRequest: Disposable? = null + var badge: BadgeDrawable? = null itemView.setOnClickListener { clickListener.onItemClick(item.manga, it) @@ -43,9 +45,12 @@ fun mangaGridItemAD( .allowRgb565(true) .lifecycle(lifecycleOwner) .enqueueWith(coil) + badge = itemView.bindBadge(badge, item.counter) } onViewRecycled { + itemView.clearBadge(badge) + badge = null imageRequest?.dispose() CoilUtils.clear(binding.imageViewCover) binding.imageViewCover.setImageDrawable(null) diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt index 8927857fb..042540184 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import coil.request.Disposable import coil.util.CoilUtils +import com.google.android.material.badge.BadgeDrawable import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener @@ -25,6 +26,7 @@ fun mangaListDetailedItemAD( ) { var imageRequest: Disposable? = null + var badge: BadgeDrawable? = null itemView.setOnClickListener { clickListener.onItemClick(item.manga, it) @@ -47,9 +49,12 @@ fun mangaListDetailedItemAD( .enqueueWith(coil) binding.textViewRating.textAndVisible = item.rating binding.textViewTags.text = item.tags + itemView.bindBadge(badge, item.counter) } onViewRecycled { + itemView.clearBadge(badge) + badge = null imageRequest?.dispose() CoilUtils.clear(binding.imageViewCover) binding.imageViewCover.setImageDrawable(null) diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt index 18c99374a..0a17d4bc5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import coil.request.Disposable import coil.util.CoilUtils +import com.google.android.material.badge.BadgeDrawable import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener @@ -25,6 +26,7 @@ fun mangaListItemAD( ) { var imageRequest: Disposable? = null + var badge: BadgeDrawable? = null itemView.setOnClickListener { clickListener.onItemClick(item.manga, it) @@ -45,9 +47,12 @@ fun mangaListItemAD( .allowRgb565(true) .lifecycle(lifecycleOwner) .enqueueWith(coil) + itemView.bindBadge(badge, item.counter) } onViewRecycled { + itemView.clearBadge(badge) + badge = null imageRequest?.dispose() CoilUtils.clear(binding.imageViewCover) binding.imageViewCover.setImageDrawable(null) diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt index b7a367591..749e38369 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt @@ -6,44 +6,71 @@ import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.exceptions.resolve.ResolvableException import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.prefs.ListMode +import org.koitharu.kotatsu.list.domain.CountersProvider -fun Manga.toListModel() = MangaListModel( +fun Manga.toListModel(counter: Int) = MangaListModel( id = id, title = title, subtitle = tags.joinToString(", ") { it.title }, coverUrl = coverUrl, - manga = this + manga = this, + counter = counter, ) -fun Manga.toListDetailedModel() = MangaListDetailedModel( +fun Manga.toListDetailedModel(counter: Int) = MangaListDetailedModel( id = id, title = title, subtitle = altTitle, rating = if (rating == Manga.NO_RATING) null else String.format("%.1f", rating * 5), tags = tags.joinToString(", ") { it.title }, coverUrl = coverUrl, - manga = this + manga = this, + counter = counter, ) -fun Manga.toGridModel() = MangaGridModel( +fun Manga.toGridModel(counter: Int) = MangaGridModel( id = id, title = title, coverUrl = coverUrl, - manga = this + manga = this, + counter = counter, ) -fun List.toUi(mode: ListMode): List = when (mode) { - ListMode.LIST -> map(Manga::toListModel) - ListMode.DETAILED_LIST -> map(Manga::toListDetailedModel) - ListMode.GRID -> map(Manga::toGridModel) +suspend fun List.toUi( + mode: ListMode, + countersProvider: CountersProvider, +): List = when (mode) { + ListMode.LIST -> map { it.toListModel(countersProvider.getCounter(it.id)) } + ListMode.DETAILED_LIST -> map { it.toListDetailedModel(countersProvider.getCounter(it.id)) } + ListMode.GRID -> map { it.toGridModel(countersProvider.getCounter(it.id)) } } -fun > List.toUi(destination: C, mode: ListMode): C = - when (mode) { - ListMode.LIST -> mapTo(destination, Manga::toListModel) - ListMode.DETAILED_LIST -> mapTo(destination, Manga::toListDetailedModel) - ListMode.GRID -> mapTo(destination, Manga::toGridModel) - } +suspend fun > List.toUi( + destination: C, + mode: ListMode, + countersProvider: CountersProvider, +): C = when (mode) { + ListMode.LIST -> mapTo(destination) { it.toListModel(countersProvider.getCounter(it.id)) } + ListMode.DETAILED_LIST -> mapTo(destination) { it.toListDetailedModel(countersProvider.getCounter(it.id)) } + ListMode.GRID -> mapTo(destination) { it.toGridModel(countersProvider.getCounter(it.id)) } +} + +fun List.toUi( + mode: ListMode, +): List = when (mode) { + ListMode.LIST -> map { it.toListModel(0) } + ListMode.DETAILED_LIST -> map { it.toListDetailedModel(0) } + ListMode.GRID -> map { it.toGridModel(0) } +} + +fun > List.toUi( + destination: C, + mode: ListMode, +): C = when (mode) { + ListMode.LIST -> mapTo(destination) { it.toListModel(0) } + ListMode.DETAILED_LIST -> mapTo(destination) { it.toListDetailedModel(0) } + ListMode.GRID -> mapTo(destination) { it.toGridModel(0) } +} fun Throwable.toErrorState(canRetry: Boolean = true) = ErrorState( exception = this, diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaGridModel.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaGridModel.kt index 1dc1e245c..3ba8b6b37 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaGridModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaGridModel.kt @@ -6,5 +6,6 @@ data class MangaGridModel( val id: Long, val title: String, val coverUrl: String, - val manga: Manga + val manga: Manga, + val counter: Int, ) : ListModel \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt index cb9b6b2a9..73735224c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt @@ -9,5 +9,6 @@ data class MangaListDetailedModel( val tags: String, val coverUrl: String, val rating: String?, - val manga: Manga + val manga: Manga, + val counter: Int, ) : ListModel \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListModel.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListModel.kt index 1f7d4aab1..603f6b197 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListModel.kt @@ -7,5 +7,6 @@ data class MangaListModel( val title: String, val subtitle: String, val coverUrl: String, - val manga: Manga + val manga: Manga, + val counter: Int, ) : ListModel \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt index f89f50d35..3f721355a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt @@ -43,7 +43,13 @@ class LocalListViewModel( when { error != null -> listOf(error.toErrorState(canRetry = true)) list == null -> listOf(LoadingState) - list.isEmpty() -> listOf(EmptyState(R.drawable.ic_storage, R.string.text_local_holder_primary, R.string.text_local_holder_secondary)) + list.isEmpty() -> listOf( + EmptyState( + R.drawable.ic_storage, + R.string.text_local_holder_primary, + R.string.text_local_holder_secondary + ) + ) else -> ArrayList(list.size + 1).apply { add(headerModel) list.toUi(this, mode) diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt index 8e00198de..7b5aa6fd2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt @@ -12,8 +12,7 @@ class TrackingRepository( ) { suspend fun getNewChaptersCount(mangaId: Long): Int { - val entity = db.tracksDao.find(mangaId) ?: return 0 - return entity.newChapters + return db.tracksDao.findNewChapters(mangaId) ?: 0 } suspend fun getAllTracks(useFavourites: Boolean, useHistory: Boolean): List { diff --git a/app/src/main/res/layout/item_manga_grid.xml b/app/src/main/res/layout/item_manga_grid.xml index 866f9c975..83481a2ec 100644 --- a/app/src/main/res/layout/item_manga_grid.xml +++ b/app/src/main/res/layout/item_manga_grid.xml @@ -5,6 +5,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/list_selector" + android:clipChildren="false" android:orientation="vertical"> 48dp 16dp 72dp + 4dp + 2dp 22sp diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml index 5532e13df..794917074 100644 --- a/app/src/main/res/values/integers.xml +++ b/app/src/main/res/values/integers.xml @@ -2,5 +2,5 @@ @android:integer/config_shortAnimTime - + 3 \ No newline at end of file From 894900e9554335f89d51cf091b0a16d5b6c9fd60 Mon Sep 17 00:00:00 2001 From: Sertinel Date: Sat, 26 Feb 2022 21:48:49 +0100 Subject: [PATCH 2/8] Translated using Weblate (Turkish) Currently translated at 47.8% (120 of 251 strings) Co-authored-by: Sertinel Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/ Translation: Kotatsu/Strings --- app/src/main/res/values-tr/strings.xml | 65 ++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index ec325a3c7..a7c1d0423 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -57,4 +57,69 @@ Detaylar Ayarlar Kaydet + Tekrar başlat + Bir hata oluştu + Uzak kaynaklar + Uyarı + Geçmiş ve önbellek + Temizlendi + Devam + Müsait değil + Boş kategori + Önbellek + Uygulamanın yeni sürümlerini kontrol edin + Kaldır + Sil + Bölüm %1$d / %2$d + Bir ZIP veya CBZ dosyası seçin. + Okuma modu + Izgara boyutu + Webtoon + B|kB|MB|GB|TB + Okuyucu ayarları + Ses butonları + Bir daha sorma + İptal ediliyor… + Hata + Küçük resim önbelleğini temizle + Yalnızca hareketler + Alan adi + Web tarayıcısında aç + Yeni bölümler + Bildirim ayarları + Bildirim sesi + LED göstergesi + Titreşim + Diğer depolama + Güncellemeler + Kısayol oluştur… + İçe aktar + Mangayı sil + Bilgi işleniyor… + Sıralama düzeni + Açıklama yok + Bu işlem desteklenmiyor + Standart + Sayfa önbelleğini temizle + %s üzerinde ara + Dahili depolama + Bildirimler + Sayfaları değiştir + Bu çok fazla veri aktarabilir + Kaydet + İndir + İndirilenler klasörü + Harici depolama + Baştan oku + Kategoriler… + Uygulamanın yeni bir sürümü mevcut + Yeni bir sürüm mevcutsa bildirimini göster + Favori kategoriler + Bitti + Sonra oku + Sayfa animasyonu + Kullanılabilir depolama alanı yok + Yeniden adlandır + \"%s\" cihazdan kalıcı olarak silinsin mi\? + Arama geçmişini temizle \ No newline at end of file From 29df122369d4d5d14e0355d3452f08c6b9605cbf Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 27 Feb 2022 18:47:47 +0200 Subject: [PATCH 3/8] Move workers initialization to background --- .../kotatsu/core/prefs/AppSettings.kt | 4 +- .../koitharu/kotatsu/main/ui/MainActivity.kt | 22 +++++++-- .../kotatsu/settings/AppUpdateChecker.kt | 48 +++++++------------ .../settings/onboard/OnboardDialogFragment.kt | 11 ++--- 4 files changed, 40 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 17b8adeeb..64a407dbc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -56,10 +56,10 @@ class AppSettings(context: Context) { get() = prefs.getBoolean(KEY_TRAFFIC_WARNING, true) set(value) = prefs.edit { putBoolean(KEY_TRAFFIC_WARNING, value) } - val appUpdateAuto: Boolean + val isUpdateCheckingEnabled: Boolean get() = prefs.getBoolean(KEY_APP_UPDATE_AUTO, true) - var appUpdate: Long + var lastUpdateCheckTimestamp: Long get() = prefs.getLong(KEY_APP_UPDATE, 0L) set(value) = prefs.edit { putLong(KEY_APP_UPDATE, value) } diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt index f59e0210b..380b4942b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt @@ -15,12 +15,16 @@ import androidx.drawerlayout.widget.DrawerLayout import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.commit +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.CircularProgressDrawable import com.google.android.material.appbar.AppBarLayout import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.navigation.NavigationView import com.google.android.material.snackbar.Snackbar +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.koin.android.ext.android.get import org.koin.androidx.viewmodel.ext.android.viewModel import org.koitharu.kotatsu.R @@ -28,6 +32,7 @@ import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.core.prefs.AppSection +import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.databinding.ActivityMainBinding import org.koitharu.kotatsu.databinding.NavigationHeaderBinding import org.koitharu.kotatsu.details.ui.DetailsActivity @@ -46,7 +51,10 @@ import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.settings.onboard.OnboardDialogFragment import org.koitharu.kotatsu.tracker.ui.FeedFragment import org.koitharu.kotatsu.tracker.work.TrackWorker -import org.koitharu.kotatsu.utils.ext.* +import org.koitharu.kotatsu.utils.ext.getDisplayMessage +import org.koitharu.kotatsu.utils.ext.hideKeyboard +import org.koitharu.kotatsu.utils.ext.measureHeight +import org.koitharu.kotatsu.utils.ext.resolveDp class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener, AppBarOwner, @@ -334,9 +342,15 @@ class MainActivity : BaseActivity(), } private fun onFirstStart() { - TrackWorker.setup(applicationContext) - AppUpdateChecker(this@MainActivity).launchIfNeeded() - OnboardDialogFragment.showWelcome(get(), supportFragmentManager) + lifecycleScope.launch(Dispatchers.Default) { + TrackWorker.setup(applicationContext) + AppUpdateChecker(this@MainActivity).checkIfNeeded() + if (!get().isSourcesSelected) { + withContext(Dispatchers.Main) { + OnboardDialogFragment.showWelcome(supportFragmentManager) + } + } + } } private companion object { diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/AppUpdateChecker.kt b/app/src/main/java/org/koitharu/kotatsu/settings/AppUpdateChecker.kt index 61f0e05c0..7a991d675 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/AppUpdateChecker.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/AppUpdateChecker.kt @@ -7,11 +7,8 @@ import android.content.pm.PackageManager import android.net.Uri import androidx.activity.ComponentActivity import androidx.annotation.MainThread -import androidx.lifecycle.lifecycleScope import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.koin.android.ext.android.get import org.koitharu.kotatsu.BuildConfig @@ -37,44 +34,31 @@ class AppUpdateChecker(private val activity: ComponentActivity) { private val settings = activity.get() private val repo = activity.get() - fun launchIfNeeded(): Job? { - return if (settings.appUpdateAuto && settings.appUpdate + PERIOD < System.currentTimeMillis()) { - launch() - } else { - null - } - } - - fun launch(): Job? { - return if (isUpdateSupported(activity)) { - launchInternal() - } else { - null - } + suspend fun checkIfNeeded(): Boolean? = if ( + settings.isUpdateCheckingEnabled && + settings.lastUpdateCheckTimestamp + PERIOD < System.currentTimeMillis() + ) { + checkNow() + } else { + null } suspend fun checkNow() = runCatching { - withContext(Dispatchers.Default) { - val version = repo.getLatestVersion() - val newVersionId = VersionId.parse(version.name) - val currentVersionId = VersionId.parse(BuildConfig.VERSION_NAME) - val result = newVersionId > currentVersionId - if (result) { - withContext(Dispatchers.Main) { - showUpdateDialog(version) - } + val version = repo.getLatestVersion() + val newVersionId = VersionId.parse(version.name) + val currentVersionId = VersionId.parse(BuildConfig.VERSION_NAME) + val result = newVersionId > currentVersionId + if (result) { + withContext(Dispatchers.Main) { + showUpdateDialog(version) } - settings.appUpdate = System.currentTimeMillis() - result } + settings.lastUpdateCheckTimestamp = System.currentTimeMillis() + result }.onFailure { it.printStackTrace() }.getOrNull() - private fun launchInternal() = activity.lifecycleScope.launch { - checkNow() - } - @MainThread private fun showUpdateDialog(version: AppVersion) { MaterialAlertDialogBuilder(activity) diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt index 5c0b94478..74dc3ffbe 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt @@ -11,7 +11,6 @@ import org.koin.androidx.viewmodel.ext.android.viewModel import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.AlertDialogFragment import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.databinding.DialogOnboardBinding import org.koitharu.kotatsu.settings.onboard.adapter.SourceLocalesAdapter import org.koitharu.kotatsu.settings.onboard.model.SourceLocale @@ -75,12 +74,10 @@ class OnboardDialogFragment : AlertDialogFragment(), fun show(fm: FragmentManager) = OnboardDialogFragment().show(fm, TAG) - fun showWelcome(settings: AppSettings, fm: FragmentManager) { - if (!settings.isSourcesSelected) { - OnboardDialogFragment().withArgs(1) { - putBoolean(ARG_WELCOME, true) - }.show(fm, TAG) - } + fun showWelcome(fm: FragmentManager) { + OnboardDialogFragment().withArgs(1) { + putBoolean(ARG_WELCOME, true) + }.show(fm, TAG) } } } \ No newline at end of file From 245e32237e60ac458db38e1bd5f1300e03db0c49 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 27 Feb 2022 19:22:59 +0200 Subject: [PATCH 4/8] Update widgets from background --- .../main/java/org/koitharu/kotatsu/widget/WidgetUpdater.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/WidgetUpdater.kt b/app/src/main/java/org/koitharu/kotatsu/widget/WidgetUpdater.kt index 16d12ebbd..3cc3be08e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/widget/WidgetUpdater.kt +++ b/app/src/main/java/org/koitharu/kotatsu/widget/WidgetUpdater.kt @@ -5,9 +5,11 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.retry +import kotlinx.coroutines.plus import org.koitharu.kotatsu.core.model.SortOrder import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.history.domain.HistoryRepository @@ -21,14 +23,14 @@ class WidgetUpdater(private val context: Context) { repository.observeAll(SortOrder.NEWEST) .onEach { updateWidget(ShelfWidgetProvider::class.java) } .retry { error -> error !is CancellationException } - .launchIn(processLifecycleScope) + .launchIn(processLifecycleScope + Dispatchers.Default) } fun subscribeToHistory(repository: HistoryRepository) { repository.observeAll() .onEach { updateWidget(RecentWidgetProvider::class.java) } .retry { error -> error !is CancellationException } - .launchIn(processLifecycleScope) + .launchIn(processLifecycleScope + Dispatchers.Default) } private fun updateWidget(cls: Class<*>) { From 54a914097db8c803e5f993867c539472d3328c67 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 27 Feb 2022 20:28:55 +0200 Subject: [PATCH 5/8] Option to block screenshots in reader #114 --- .../org/koitharu/kotatsu/core/prefs/AppSettings.kt | 7 +++++++ .../koitharu/kotatsu/core/prefs/ScreenshotsPolicy.kt | 7 +++++++ .../org/koitharu/kotatsu/reader/ui/ReaderActivity.kt | 9 +++++++++ .../koitharu/kotatsu/reader/ui/ReaderViewModel.kt | 12 ++++++++++++ app/src/main/res/values-ru/strings.xml | 4 ++++ app/src/main/res/values/arrays.xml | 5 +++++ app/src/main/res/values/constants.xml | 5 +++++ app/src/main/res/values/strings.xml | 4 ++++ app/src/main/res/xml/pref_reader.xml | 9 +++++++++ 9 files changed, 62 insertions(+) create mode 100644 app/src/main/java/org/koitharu/kotatsu/core/prefs/ScreenshotsPolicy.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 64a407dbc..29f565fc3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -123,6 +123,12 @@ class AppSettings(context: Context) { val isPagesNumbersEnabled: Boolean get() = prefs.getBoolean(KEY_PAGES_NUMBERS, false) + val screenshotsPolicy: ScreenshotsPolicy + get() = runCatching { + val key = prefs.getString(KEY_SCREENSHOTS_POLICY, null)?.uppercase(Locale.ROOT) + if (key == null) ScreenshotsPolicy.ALLOW else ScreenshotsPolicy.valueOf(key) + }.getOrDefault(ScreenshotsPolicy.ALLOW) + var mangaStorageDir: File? get() = prefs.getString(KEY_LOCAL_STORAGE, null)?.let { File(it) @@ -224,6 +230,7 @@ class AppSettings(context: Context) { const val KEY_REVERSE_CHAPTERS = "reverse_chapters" const val KEY_HISTORY_EXCLUDE_NSFW = "history_exclude_nsfw" const val KEY_PAGES_NUMBERS = "pages_numbers" + const val KEY_SCREENSHOTS_POLICY = "screenshots_policy" // About const val KEY_APP_UPDATE = "app_update" diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/ScreenshotsPolicy.kt b/app/src/main/java/org/koitharu/kotatsu/core/prefs/ScreenshotsPolicy.kt new file mode 100644 index 000000000..b92d71ec6 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/ScreenshotsPolicy.kt @@ -0,0 +1,7 @@ +package org.koitharu.kotatsu.core.prefs + +enum class ScreenshotsPolicy { + + // Do not rename this + ALLOW, BLOCK_NSFW, BLOCK_ALL; +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index b96a46284..e4ee21e84 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -94,6 +94,7 @@ class ReaderActivity : BaseFullscreenActivity(), viewModel.content.observe(this) { onLoadingStateChanged(viewModel.isLoading.value == true) } + viewModel.isScreenshotsBlockEnabled.observe(this, this::setWindowSecure) } private fun onInitReader(mode: ReaderMode) { @@ -299,6 +300,14 @@ class ReaderActivity : BaseFullscreenActivity(), }.show() } + private fun setWindowSecure(isSecure: Boolean) { + if (isSecure) { + window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) + } else { + window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) + } + } + private fun setUiIsVisible(isUiVisible: Boolean) { if (binding.appbarTop.isVisible != isUiVisible) { if (isUiVisible) { diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt index 201e10262..2e360594c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt @@ -20,6 +20,7 @@ import org.koitharu.kotatsu.core.os.ShortcutsRepository import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ReaderMode +import org.koitharu.kotatsu.core.prefs.ScreenshotsPolicy import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.reader.ui.pager.ReaderPage import org.koitharu.kotatsu.reader.ui.pager.ReaderUiState @@ -69,6 +70,17 @@ class ReaderViewModel( .onStart { emit(settings.readerAnimation) } .asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.IO) + val isScreenshotsBlockEnabled = combine( + mangaData, + settings.observe() + .filter { it == AppSettings.KEY_SCREENSHOTS_POLICY } + .onStart { emit("") } + .map { settings.screenshotsPolicy }, + ) { manga, policy -> + policy == ScreenshotsPolicy.BLOCK_ALL || + (policy == ScreenshotsPolicy.BLOCK_NSFW && manga != null && manga.isNsfw) + }.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.IO) + val onZoomChanged = SingleLiveEvent() init { diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index c15cb6480..095767dfa 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -249,4 +249,8 @@ Доступные источники Динамическая тема Применяет тему приложения, основанную на цветовой палитре обоев на устройстве + Разрешить скриншоты + Разрешить + Запретить для NSFW + Запретить всегда \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 9119e2901..bcfb4dddb 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -24,4 +24,9 @@ @string/detailed_list @string/grid + + @string/screenshots_allow + @string/screenshots_block_nsfw + @string/screenshots_block_all + \ No newline at end of file diff --git a/app/src/main/res/values/constants.xml b/app/src/main/res/values/constants.xml index 42c7b0d1d..7e400c72e 100644 --- a/app/src/main/res/values/constants.xml +++ b/app/src/main/res/values/constants.xml @@ -20,4 +20,9 @@ favourites + + allow + block_nsfw + block_all + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d053d90d6..9cea043a2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -251,4 +251,8 @@ Dynamic theme Applies a theme created on the color scheme of your wallpaper Importing manga: %1$d of %2$d + Screenshots policy + Allow + Block on NSFW + Block always \ No newline at end of file diff --git a/app/src/main/res/xml/pref_reader.xml b/app/src/main/res/xml/pref_reader.xml index 18e6aae70..1d3db4527 100644 --- a/app/src/main/res/xml/pref_reader.xml +++ b/app/src/main/res/xml/pref_reader.xml @@ -38,4 +38,13 @@ android:title="@string/show_pages_numbers" app:iconSpaceReserved="false" /> + + \ No newline at end of file From e8a225f97a91a23fc2c4c65286001dbcde3aeff2 Mon Sep 17 00:00:00 2001 From: Zakhar Timoshenko Date: Mon, 28 Feb 2022 01:18:59 +0300 Subject: [PATCH 6/8] Update material components dependency --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 30f04235b..d8ccb45bf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -83,7 +83,7 @@ dependencies { implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01' implementation 'androidx.preference:preference-ktx:1.2.0' implementation 'androidx.work:work-runtime-ktx:2.7.1' - implementation 'com.google.android.material:material:1.6.0-alpha02' + implementation 'com.google.android.material:material:1.6.0-alpha03' //noinspection LifecycleAnnotationProcessorWithJava8 kapt 'androidx.lifecycle:lifecycle-compiler:2.4.1' From 7fb67be1b640af67160f482d8386af50d4a33352 Mon Sep 17 00:00:00 2001 From: Zakhar Timoshenko Date: Mon, 28 Feb 2022 01:24:21 +0300 Subject: [PATCH 7/8] Some UI changes --- .../kotatsu/base/ui/widgets/CoverImageView.kt | 5 +- .../ui/categories/CategoriesActivity.kt | 4 +- .../kotatsu/list/ui/MangaListFragment.kt | 2 +- .../koitharu/kotatsu/utils/ext/AndroidExt.kt | 1 - .../org/koitharu/kotatsu/utils/ext/UiExt.kt | 21 ---- .../main/res/color/navigation_bar_scrim.xml | 4 + app/src/main/res/drawable/list_selector.xml | 6 +- .../drawable/navigation_item_background.xml | 19 --- .../main/res/layout/activity_categories.xml | 2 +- app/src/main/res/layout/activity_main.xml | 6 +- .../main/res/layout/item_current_filter.xml | 4 +- app/src/main/res/layout/item_header.xml | 2 - app/src/main/res/layout/item_manga_grid.xml | 15 ++- app/src/main/res/layout/item_manga_list.xml | 66 +++++------ .../res/layout/item_manga_list_details.xml | 108 +++++++++--------- .../layout/item_source_config_draggable.xml | 1 - app/src/main/res/values-v23/themes.xml | 10 ++ app/src/main/res/values-v27/themes.xml | 3 +- app/src/main/res/values/dimens.xml | 9 +- app/src/main/res/values/styles.xml | 6 + app/src/main/res/values/themes.xml | 6 +- 21 files changed, 134 insertions(+), 166 deletions(-) delete mode 100644 app/src/main/java/org/koitharu/kotatsu/utils/ext/UiExt.kt create mode 100644 app/src/main/res/color/navigation_bar_scrim.xml delete mode 100644 app/src/main/res/drawable/navigation_item_background.xml create mode 100644 app/src/main/res/values-v23/themes.xml diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CoverImageView.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CoverImageView.kt index a4e7bf748..6f0c9e4e2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CoverImageView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CoverImageView.kt @@ -3,15 +3,14 @@ package org.koitharu.kotatsu.base.ui.widgets import android.content.Context import android.util.AttributeSet import android.widget.LinearLayout -import androidx.appcompat.widget.AppCompatImageView import androidx.core.content.withStyledAttributes +import com.google.android.material.imageview.ShapeableImageView import org.koitharu.kotatsu.R import kotlin.math.roundToInt - class CoverImageView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, -) : AppCompatImageView(context, attrs, defStyleAttr) { +) : ShapeableImageView(context, attrs, defStyleAttr) { private var orientation: Int = HORIZONTAL diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesActivity.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesActivity.kt index f08a83032..8a1076d37 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesActivity.kt @@ -148,7 +148,7 @@ class CategoriesActivity : BaseActivity(), override fun onMove( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, - target: RecyclerView.ViewHolder + target: RecyclerView.ViewHolder, ): Boolean = true override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) = Unit @@ -160,7 +160,7 @@ class CategoriesActivity : BaseActivity(), target: RecyclerView.ViewHolder, toPos: Int, x: Int, - y: Int + y: Int, ) { super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y) viewModel.reorderCategories(fromPos, toPos) diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt index bee787480..a91d3924b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt @@ -257,7 +257,7 @@ abstract class MangaListFragment : BaseFragment(), } ListMode.DETAILED_LIST -> { layoutManager = LinearLayoutManager(context) - val spacing = resources.getDimensionPixelOffset(R.dimen.grid_spacing) + val spacing = resources.getDimensionPixelOffset(R.dimen.list_spacing) updatePadding(left = spacing, right = spacing) addItemDecoration(SpacingItemDecoration(spacing)) } diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/AndroidExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/AndroidExt.kt index 6eef68d17..215e2d185 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/AndroidExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/AndroidExt.kt @@ -4,7 +4,6 @@ import android.content.Context import android.net.ConnectivityManager import android.net.Network import android.net.NetworkRequest -import android.os.Build import androidx.appcompat.app.AlertDialog import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.suspendCancellableCoroutine diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/UiExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/UiExt.kt deleted file mode 100644 index f66e9f880..000000000 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/UiExt.kt +++ /dev/null @@ -1,21 +0,0 @@ -package org.koitharu.kotatsu.utils.ext - -import android.content.Context -import android.graphics.drawable.Drawable -import androidx.appcompat.content.res.AppCompatResources -import androidx.core.graphics.drawable.DrawableCompat -import org.koitharu.kotatsu.R - -fun navigationItemBackground(context: Context): Drawable? { - // Need to inflate the drawable and CSL via AppCompatResources to work on Lollipop - // From Google I/O repo (https://github.com/google/iosched) - var background = AppCompatResources.getDrawable(context, R.drawable.navigation_item_background) - if (background != null) { - val tint = AppCompatResources.getColorStateList( - context, R.color.navigation_item_background_tint - ) - background = DrawableCompat.wrap(background.mutate()) - background.setTintList(tint) - } - return background -} \ No newline at end of file diff --git a/app/src/main/res/color/navigation_bar_scrim.xml b/app/src/main/res/color/navigation_bar_scrim.xml new file mode 100644 index 000000000..6d9fe48af --- /dev/null +++ b/app/src/main/res/color/navigation_bar_scrim.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/drawable/list_selector.xml b/app/src/main/res/drawable/list_selector.xml index 14508c152..99d9a4cfc 100644 --- a/app/src/main/res/drawable/list_selector.xml +++ b/app/src/main/res/drawable/list_selector.xml @@ -10,7 +10,7 @@ android:bottom="2dp" android:left="2dp"> - + @@ -22,7 +22,7 @@ android:bottom="2dp" android:left="2dp"> - + @@ -33,7 +33,7 @@ android:bottom="2dp" android:left="2dp"> - + diff --git a/app/src/main/res/drawable/navigation_item_background.xml b/app/src/main/res/drawable/navigation_item_background.xml deleted file mode 100644 index 8c635e7a3..000000000 --- a/app/src/main/res/drawable/navigation_item_background.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_categories.xml b/app/src/main/res/layout/activity_categories.xml index 5dcfe622d..d553d862d 100644 --- a/app/src/main/res/layout/activity_categories.xml +++ b/app/src/main/res/layout/activity_categories.xml @@ -15,7 +15,7 @@ android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" - android:theme="?attr/actionBarTheme"/> + android:theme="?attr/actionBarTheme" /> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index f02321df3..b944dcc54 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -27,21 +27,21 @@ + android:layout_marginBottom="8dp" + android:background="@drawable/toolbar_background"> + android:layout_height="wrap_content"> \ No newline at end of file diff --git a/app/src/main/res/layout/item_manga_grid.xml b/app/src/main/res/layout/item_manga_grid.xml index 866f9c975..13833e6a8 100644 --- a/app/src/main/res/layout/item_manga_grid.xml +++ b/app/src/main/res/layout/item_manga_grid.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" + xmlns:app="http://schemas.android.com/apk/res-auto" android:background="@drawable/list_selector" android:orientation="vertical"> @@ -11,9 +12,7 @@ android:id="@+id/card" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginHorizontal="8dp" - android:layout_marginTop="8dp" - android:layout_marginBottom="4dp"> + app:cardCornerRadius="12dp"> \ No newline at end of file diff --git a/app/src/main/res/layout/item_manga_list.xml b/app/src/main/res/layout/item_manga_list.xml index 52ee08093..fef7a5c33 100644 --- a/app/src/main/res/layout/item_manga_list.xml +++ b/app/src/main/res/layout/item_manga_list.xml @@ -1,17 +1,16 @@ - + app:cardCornerRadius="12dp"> - + android:orientation="horizontal"> - - - - - + android:layout_gravity="center_vertical" + android:orientation="vertical" + android:paddingStart="20dp" + android:paddingEnd="16dp"> - + + + + + - \ No newline at end of file + diff --git a/app/src/main/res/layout/item_manga_list_details.xml b/app/src/main/res/layout/item_manga_list_details.xml index e3ebb7148..468a1b476 100644 --- a/app/src/main/res/layout/item_manga_list_details.xml +++ b/app/src/main/res/layout/item_manga_list_details.xml @@ -1,17 +1,16 @@ - + app:cardCornerRadius="12dp"> - + android:orientation="horizontal"> - - - - - - - - + tools:src="@tools:sample/backgrounds/scenic" + app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Kotatsu.Cover"/> + android:layout_gravity="center_vertical" + android:layout_margin="16dp" + android:orientation="vertical"> + + - + android:orientation="horizontal" + android:gravity="center"> + + + + + + - \ No newline at end of file + diff --git a/app/src/main/res/layout/item_source_config_draggable.xml b/app/src/main/res/layout/item_source_config_draggable.xml index ffa9a68e5..2e4ae2c57 100644 --- a/app/src/main/res/layout/item_source_config_draggable.xml +++ b/app/src/main/res/layout/item_source_config_draggable.xml @@ -4,7 +4,6 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="?android:listPreferredItemHeightSmall" - android:background="?android:windowBackground" android:gravity="center_vertical" android:orientation="horizontal"> diff --git a/app/src/main/res/values-v23/themes.xml b/app/src/main/res/values-v23/themes.xml new file mode 100644 index 000000000..a0b9e171e --- /dev/null +++ b/app/src/main/res/values-v23/themes.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 0f4b7d260..c99c2e193 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -7,14 +7,9 @@ 36dp 24dp - - 0dp - 100dp - 0dp - 8dp> - 4dp - 4dp + 8dp + 8dp 2dp 86dp 120dp diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index a7593b677..2cdf110c3 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -137,6 +137,12 @@ ?android:attr/textColorSecondary + + + +