diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt index 65592dd2b..e4240324d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt @@ -40,7 +40,6 @@ import org.koitharu.kotatsu.core.parser.favicon.FaviconFetcher import org.koitharu.kotatsu.core.ui.image.CoilImageGetter import org.koitharu.kotatsu.core.ui.util.ActivityRecreationHandle import org.koitharu.kotatsu.core.util.AcraScreenLogger -import org.koitharu.kotatsu.core.util.IncognitoModeIndicator import org.koitharu.kotatsu.core.util.ext.connectivityManager import org.koitharu.kotatsu.core.util.ext.isLowRamDevice import org.koitharu.kotatsu.details.ui.pager.pages.MangaPageFetcher @@ -147,12 +146,10 @@ interface AppModule { fun provideActivityLifecycleCallbacks( appProtectHelper: AppProtectHelper, activityRecreationHandle: ActivityRecreationHandle, - incognitoModeIndicator: IncognitoModeIndicator, acraScreenLogger: AcraScreenLogger, ): Set<@JvmSuppressWildcards Application.ActivityLifecycleCallbacks> = arraySetOf( appProtectHelper, activityRecreationHandle, - incognitoModeIndicator, acraScreenLogger, ) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/TipView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/TipView.kt index 65ab7f8f5..27915c2a6 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/TipView.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/TipView.kt @@ -12,6 +12,7 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.core.content.ContextCompat import androidx.core.content.withStyledAttributes +import androidx.core.view.isVisible import androidx.core.view.setPadding import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.ShapeAppearanceModel @@ -103,16 +104,22 @@ class TipView @JvmOverloads constructor( fun setPrimaryButtonText(@StringRes resId: Int) { binding.buttonPrimary.setTextAndVisible(resId) + updateButtonsLayout() } fun setSecondaryButtonText(@StringRes resId: Int) { binding.buttonSecondary.setTextAndVisible(resId) + updateButtonsLayout() } fun setIcon(@DrawableRes resId: Int) { icon = ContextCompat.getDrawable(context, resId) } + private fun updateButtonsLayout() { + binding.layoutButtons.isVisible = binding.buttonPrimary.isVisible || binding.buttonSecondary.isVisible + } + interface OnButtonClickListener { fun onPrimaryButtonClick(tipView: TipView) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt deleted file mode 100644 index 7dc2ee1ac..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt +++ /dev/null @@ -1,46 +0,0 @@ -package org.koitharu.kotatsu.core.util - -import android.app.Activity -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.ContextCompat -import androidx.lifecycle.flowWithLifecycle -import androidx.lifecycle.lifecycleScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.core.prefs.observeAsFlow -import org.koitharu.kotatsu.core.ui.DefaultActivityLifecycleCallbacks -import org.koitharu.kotatsu.core.util.ext.getThemeColor -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class IncognitoModeIndicator @Inject constructor( - private val settings: AppSettings, -) : DefaultActivityLifecycleCallbacks { - - override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { - if (activity !is AppCompatActivity) { - return - } - settings.observeAsFlow( - key = AppSettings.KEY_INCOGNITO_MODE, - valueProducer = { isIncognitoModeEnabled }, - ).flowOn(Dispatchers.IO) - .flowWithLifecycle(activity.lifecycle) - .onEach { updateStatusBar(activity, it) } - .launchIn(activity.lifecycleScope) - } - - private fun updateStatusBar(activity: AppCompatActivity, isIncognitoModeEnabled: Boolean) { - activity.window.statusBarColor = if (isIncognitoModeEnabled) { - ContextCompat.getColor(activity, R.color.status_bar_incognito) - } else { - activity.getThemeColor(android.R.attr.statusBarColor) - } - } -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index 13216d25f..246ff8204 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -35,6 +35,7 @@ import com.google.android.material.chip.Chip import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filterNotNull import org.koitharu.kotatsu.R import org.koitharu.kotatsu.bookmarks.domain.Bookmark @@ -160,12 +161,13 @@ class DetailsActivity : viewModel.newChaptersCount.observe(this, ::onNewChaptersChanged) viewModel.onError.observeEvent(this, DetailsErrorObserver(this, viewModel, exceptionResolver)) viewModel.onActionDone.observeEvent(this, ReversibleActionObserver(viewBinding.scrollView, null)) - viewModel.historyInfo.observe(this, ::onHistoryChanged) + combine(viewModel.historyInfo, viewModel.isLoading, ::Pair).observe(this) { + onHistoryChanged(it.first, it.second) + } viewModel.isLoading.observe(this, ::onLoadingStateChanged) viewModel.scrobblingInfo.observe(this, ::onScrobblingInfoChanged) viewModel.localSize.observe(this, ::onLocalSizeChanged) viewModel.relatedManga.observe(this, ::onRelatedMangaChanged) - // viewModel.chapters.observe(this, ::onChaptersChanged) viewModel.readingTime.observe(this, ::onReadingTimeChanged) viewModel.selectedBranch.observe(this) { viewBinding.infoLayout.chipBranch.text = it.ifNullOrEmpty { getString(R.string.system_default) } @@ -197,9 +199,7 @@ class DetailsActivity : when (v.id) { R.id.button_read -> openReader(isIncognitoMode = false) R.id.chip_branch -> showBranchPopupMenu(v) - R.id.button_chapters -> { - ChaptersPagesSheet.show(supportFragmentManager) - } + R.id.button_chapters -> ChaptersPagesSheet.show(supportFragmentManager) R.id.chip_author -> { val manga = viewModel.manga.value ?: return @@ -342,10 +342,6 @@ class DetailsActivity : } } - private fun onChaptersChanged(chapters: List?) { - // TODO - } - private fun onFavoritesChanged(categories: Set) { val chip = viewBinding.infoLayout.chipFavorite chip.setChipIconResource(if (categories.isEmpty()) R.drawable.ic_heart_outline else R.drawable.ic_heart) @@ -449,7 +445,6 @@ class DetailsActivity : private fun onMangaUpdated(details: MangaDetails) { with(viewBinding) { val manga = details.toManga() - val hasChapters = !manga.chapters.isNullOrEmpty() // Main loadCover(manga) textViewTitle.text = manga.title @@ -500,9 +495,7 @@ class DetailsActivity : .enqueueWith(coil) } - buttonChapters?.isEnabled = hasChapters title = manga.title - buttonRead.isEnabled = hasChapters invalidateOptionsMenu() } } @@ -531,30 +524,18 @@ class DetailsActivity : ) } - private fun onHistoryChanged(info: HistoryInfo) { - with(viewBinding.buttonRead) { - if (info.history != null) { - setTitle(R.string._continue) - } else { - setTitle(R.string.read) - } - } - viewBinding.buttonRead.subtitle = when { - !info.isValid -> getString(R.string.loading_) - info.currentChapter >= 0 -> getString( - R.string.chapter_d_of_d, - info.currentChapter + 1, - info.totalChapters, - ) - + private fun onHistoryChanged(info: HistoryInfo, isLoading: Boolean) = with(viewBinding) { + buttonRead.setTitle(if (info.history != null) R.string._continue else R.string.read) + buttonRead.subtitle = when { + isLoading -> getString(R.string.loading_) + info.isIncognitoMode -> getString(R.string.incognito_mode) + info.currentChapter >= 0 -> getString(R.string.chapter_d_of_d, info.currentChapter + 1, info.totalChapters) info.totalChapters == 0 -> getString(R.string.no_chapters) - else -> resources.getQuantityString( - R.plurals.chapters, - info.totalChapters, - info.totalChapters, - ) + else -> resources.getQuantityString(R.plurals.chapters, info.totalChapters, info.totalChapters) } - viewBinding.buttonRead.setProgress(info.history?.percent?.coerceIn(0f, 1f) ?: 0f, true) + buttonRead.setProgress(info.history?.percent?.coerceIn(0f, 1f) ?: 0f, true) + buttonChapters?.isEnabled = info.isValid + buttonRead.isEnabled = info.isValid } private fun onNewChaptersChanged(count: Int) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt index 973d4a42b..ecee9a70f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt @@ -35,6 +35,7 @@ import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListHeader import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingState +import org.koitharu.kotatsu.list.ui.model.TipModel import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toGridModel import org.koitharu.kotatsu.list.ui.model.toListDetailedModel @@ -82,7 +83,8 @@ class HistoryListViewModel @Inject constructor( isGroupingEnabled, listMode, networkState, - ) { list, grouped, mode, online -> + settings.observeAsFlow(AppSettings.KEY_INCOGNITO_MODE) { isIncognitoModeEnabled }, + ) { list, grouped, mode, online, incognito -> when { list.isEmpty() -> listOf( EmptyState( @@ -93,7 +95,7 @@ class HistoryListViewModel @Inject constructor( ), ) - else -> mapList(list, grouped, mode, online) + else -> mapList(list, grouped, mode, online, incognito) } }.onStart { loadingCounter.increment() @@ -141,8 +143,19 @@ class HistoryListViewModel @Inject constructor( grouped: Boolean, mode: ListMode, isOnline: Boolean, + isIncognito: Boolean, ): List { - val result = ArrayList(if (grouped) (list.size * 1.4).toInt() else list.size + 1) + val result = ArrayList(if (grouped) (list.size * 1.4).toInt() else list.size + 2) + if (isIncognito) { + result += TipModel( + key = AppSettings.KEY_INCOGNITO_MODE, + title = R.string.incognito_mode, + text = R.string.incognito_mode_hint, + icon = R.drawable.ic_incognito, + primaryButtonText = 0, + secondaryButtonText = 0, + ) + } val order = sortOrder.value var prevHeader: ListHeader? = null if (!isOnline) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/preview/PreviewFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/preview/PreviewFragment.kt index cb4640e48..450986b23 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/preview/PreviewFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/preview/PreviewFragment.kt @@ -131,38 +131,21 @@ class PreviewFragment : BaseFragment(), View.OnClickList private fun onFooterUpdated(footer: PreviewViewModel.FooterInfo?) { with(requireViewBinding()) { - toolbarBottom.isVisible = footer != null - if (footer == null) { - return - } - toolbarBottom.title = when { - footer.isInProgress() -> { - getString(R.string.chapter_d_of_d, footer.currentChapter, footer.totalChapters) - } + buttonRead.isEnabled = footer != null + buttonRead.setTitle(if (footer?.isInProgress() == true) R.string._continue else R.string.read) + buttonRead.subtitle = when { + footer == null -> getString(R.string.loading_) + footer.isIncognito -> getString(R.string.incognito_mode) + footer.currentChapter >= 0 -> getString( + R.string.chapter_d_of_d, + footer.currentChapter + 1, + footer.totalChapters, + ) - footer.totalChapters > 0 -> { - resources.getQuantityString(R.plurals.chapters, footer.totalChapters, footer.totalChapters) - } - - else -> { - getString(R.string.no_chapters) - } + footer.totalChapters == 0 -> getString(R.string.no_chapters) + else -> resources.getQuantityString(R.plurals.chapters, footer.totalChapters, footer.totalChapters) } - buttonRead.isEnabled = footer.totalChapters > 0 - buttonRead.setIconResource( - when { - footer.isIncognito -> R.drawable.ic_incognito - footer.isInProgress() -> R.drawable.ic_play - else -> R.drawable.ic_read - }, - ) - buttonRead.setText( - if (footer.isInProgress()) { - R.string._continue - } else { - R.string.read - }, - ) + buttonRead.setProgress(footer?.percent?.coerceIn(0f, 1f) ?: 0f, true) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/preview/PreviewViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/preview/PreviewViewModel.kt index e3e03d63b..01632a90f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/preview/PreviewViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/preview/PreviewViewModel.kt @@ -29,6 +29,7 @@ import org.koitharu.kotatsu.core.ui.widgets.ChipsView import org.koitharu.kotatsu.core.util.ext.require import org.koitharu.kotatsu.core.util.ext.sanitize import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.list.domain.ListExtraProvider import javax.inject.Inject @@ -56,7 +57,7 @@ class PreviewViewModel @Inject constructor( val b = m.getPreferredBranch(history) val chapters = m.getChapters(b).orEmpty() FooterInfo( - branch = b, + percent = history?.percent ?: PROGRESS_NONE, currentChapter = history?.chapterId?.let { chapters.indexOfFirst { x -> x.id == it } } ?: -1, @@ -109,10 +110,10 @@ class PreviewViewModel @Inject constructor( } data class FooterInfo( - val branch: String?, val currentChapter: Int, val totalChapters: Int, val isIncognito: Boolean, + val percent: Float, ) { fun isInProgress() = currentChapter >= 0 diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt index e213ded93..c3716f9cf 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt @@ -130,9 +130,6 @@ class MainActivity : BaseActivity(), AppBarOwner, BottomNav viewModel.onFirstStart.observeEvent(this) { WelcomeSheet.show(supportFragmentManager) } - viewModel.isIncognitoMode.observe(this) { - adjustSearchUI(isSearchOpened(), false) - } searchSuggestionViewModel.isIncognitoModeEnabled.observe(this, this::onIncognitoModeChanged) } @@ -368,10 +365,10 @@ class MainActivity : BaseActivity(), AppBarOwner, BottomNav adjustFabVisibility(isSearchOpened = isOpened) supportActionBar?.apply { setHomeAsUpIndicator( - when { - isOpened -> materialR.drawable.abc_ic_ab_back_material - viewModel.isIncognitoMode.value -> R.drawable.ic_incognito - else -> materialR.drawable.abc_ic_search_api_material + if (isOpened) { + materialR.drawable.abc_ic_ab_back_material + } else { + materialR.drawable.abc_ic_search_api_material }, ) setHomeActionContentDescription( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt index c62274e39..505f8cc07 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt @@ -9,7 +9,6 @@ import kotlinx.coroutines.plus import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException import org.koitharu.kotatsu.core.github.AppUpdateRepository import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.core.prefs.observeAsStateFlow import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.util.ext.MutableEventFlow import org.koitharu.kotatsu.core.util.ext.call @@ -39,12 +38,6 @@ class MainViewModel @Inject constructor( initialValue = false, ) - val isIncognitoMode = settings.observeAsStateFlow( - scope = viewModelScope + Dispatchers.Default, - key = AppSettings.KEY_INCOGNITO_MODE, - valueProducer = { isIncognitoModeEnabled }, - ) - val appUpdate = appUpdateRepository.observeAvailableUpdate() val feedCounter = trackingRepository.observeUpdatedMangaCount() diff --git a/app/src/main/res/layout/activity_details.xml b/app/src/main/res/layout/activity_details.xml index 5853c19c6..a35045cac 100644 --- a/app/src/main/res/layout/activity_details.xml +++ b/app/src/main/res/layout/activity_details.xml @@ -182,7 +182,6 @@ android:gravity="center" android:paddingHorizontal="6dp" android:paddingVertical="8dp" - android:textColor="?colorOnPrimaryContainer" app:baseColor="?colorSecondaryContainer" app:layout_constraintEnd_toStartOf="@id/button_chapters" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/activity_image.xml b/app/src/main/res/layout/activity_image.xml index cea3c59e8..14872d55c 100644 --- a/app/src/main/res/layout/activity_image.xml +++ b/app/src/main/res/layout/activity_image.xml @@ -22,7 +22,7 @@ android:contentDescription="@string/back" android:elevation="@dimen/m3_sys_elevation_level1" android:scaleType="center" - android:src="?homeAsUpIndicator" /> + app:srcCompat="?homeAsUpIndicator" /> - + android:layout_height="match_parent" + tools:background="@macro/m3_comp_filled_card_container_color"> - + android:paddingBottom="?actionBarSize"> - + + + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:ellipsize="end" + android:maxLines="5" + android:textAppearance="?attr/textAppearanceHeadlineSmall" + app:layout_constraintEnd_toStartOf="@id/button_open" + app:layout_constraintStart_toEndOf="@id/imageView_cover" + app:layout_constraintTop_toTopOf="parent" + app:layout_goneMarginEnd="16dp" + tools:text="@tools:sample/lorem" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_marginTop="4dp" + android:layout_marginEnd="4dp" + android:background="?selectableItemBackgroundBorderless" + android:contentDescription="@string/close" + android:padding="12dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="?actionModeCloseDrawable" + app:tint="?colorControlNormal" /> - + - + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/view_tip.xml b/app/src/main/res/layout/view_tip.xml index 011b635bf..86f049d4b 100644 --- a/app/src/main/res/layout/view_tip.xml +++ b/app/src/main/res/layout/view_tip.xml @@ -30,6 +30,7 @@ tools:text="Включите их, чтобы ничего не пропускать. Откройте настройки системы и разрешите их отправку." />