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 2b65c60a3..d9178713c 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 @@ -134,6 +134,20 @@ class AppSettings(context: Context) { val isSourcesSelected: Boolean get() = KEY_SOURCES_HIDDEN in prefs + val newSources: Set + get() { + val known = sourcesOrder.toSet() + val hidden = hiddenSources + return remoteMangaSources + .filterNotTo(EnumSet.noneOf(MangaSource::class.java)) { x -> + x.name in known || x.name in hidden + } + } + + fun markKnownSources(sources: Collection) { + sourcesOrder = sourcesOrder + sources.map { it.name } + } + val isPagesNumbersEnabled: Boolean get() = prefs.getBoolean(KEY_PAGES_NUMBERS, false) 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 d1e033cb7..24805aa84 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 @@ -49,6 +49,7 @@ import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionViewModel import org.koitharu.kotatsu.settings.AppUpdateChecker import org.koitharu.kotatsu.settings.SettingsActivity +import org.koitharu.kotatsu.settings.newsources.NewSourcesDialogFragment import org.koitharu.kotatsu.settings.onboard.OnboardDialogFragment import org.koitharu.kotatsu.suggestions.ui.SuggestionsFragment import org.koitharu.kotatsu.suggestions.ui.SuggestionsWorker @@ -390,10 +391,14 @@ class MainActivity : if (AppUpdateChecker.isUpdateSupported(this@MainActivity)) { AppUpdateChecker(this@MainActivity).checkIfNeeded() } - if (!get().isSourcesSelected) { - withContext(Dispatchers.Main) { + val settings = get() + when { + !settings.isSourcesSelected -> withContext(Dispatchers.Main) { OnboardDialogFragment.showWelcome(supportFragmentManager) } + settings.newSources.isNotEmpty() -> withContext(Dispatchers.Main) { + NewSourcesDialogFragment.show(supportFragmentManager) + } } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SettingsModule.kt b/app/src/main/java/org/koitharu/kotatsu/settings/SettingsModule.kt index e8e7f97ae..b1fd14c50 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/SettingsModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/SettingsModule.kt @@ -9,6 +9,7 @@ import org.koitharu.kotatsu.core.backup.RestoreRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.settings.backup.BackupViewModel import org.koitharu.kotatsu.settings.backup.RestoreViewModel +import org.koitharu.kotatsu.settings.newsources.NewSourcesViewModel import org.koitharu.kotatsu.settings.onboard.OnboardViewModel import org.koitharu.kotatsu.settings.protect.ProtectSetupViewModel import org.koitharu.kotatsu.settings.sources.SourcesSettingsViewModel @@ -27,4 +28,5 @@ val settingsModule viewModel { ProtectSetupViewModel(get()) } viewModel { OnboardViewModel(get()) } viewModel { SourcesSettingsViewModel(get()) } + viewModel { NewSourcesViewModel(get()) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt new file mode 100644 index 000000000..9718e5306 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt @@ -0,0 +1,68 @@ +package org.koitharu.kotatsu.settings.newsources + +import android.content.DialogInterface +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.FragmentManager +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import org.koin.android.ext.android.get +import org.koin.androidx.viewmodel.ext.android.viewModel +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.AlertDialogFragment +import org.koitharu.kotatsu.databinding.DialogOnboardBinding +import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigAdapter +import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigListener +import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem + +class NewSourcesDialogFragment : + AlertDialogFragment(), + SourceConfigListener, + DialogInterface.OnClickListener { + + private val viewModel by viewModel() + + override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): DialogOnboardBinding { + return DialogOnboardBinding.inflate(inflater, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val adapter = SourceConfigAdapter(this, get(), viewLifecycleOwner) + binding.recyclerView.adapter = adapter + binding.textViewTitle.setText(R.string.new_sources_text) + + viewModel.sources.observe(viewLifecycleOwner) { adapter.items = it } + } + + override fun onBuildDialog(builder: MaterialAlertDialogBuilder) { + builder + .setPositiveButton(R.string.done, this) + .setCancelable(true) + .setTitle(R.string.remote_sources) + } + + override fun onClick(dialog: DialogInterface, which: Int) { + viewModel.apply() + dialog.dismiss() + } + + override fun onItemSettingsClick(item: SourceConfigItem.SourceItem) = Unit + + override fun onItemEnabledChanged(item: SourceConfigItem.SourceItem, isEnabled: Boolean) { + viewModel.onItemEnabledChanged(item, isEnabled) + } + + override fun onDragHandleTouch(holder: RecyclerView.ViewHolder) = Unit + + override fun onHeaderClick(header: SourceConfigItem.LocaleGroup) = Unit + + companion object { + + private const val TAG = "NewSources" + + fun show(fm: FragmentManager) = NewSourcesDialogFragment().show(fm, TAG) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt new file mode 100644 index 000000000..530851d46 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt @@ -0,0 +1,42 @@ +package org.koitharu.kotatsu.settings.newsources + +import androidx.lifecycle.MutableLiveData +import org.koitharu.kotatsu.base.ui.BaseViewModel +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem + +class NewSourcesViewModel( + private val settings: AppSettings, +) : BaseViewModel() { + + val sources = MutableLiveData>() + private val initialList = settings.newSources + + init { + buildList() + } + + fun onItemEnabledChanged(item: SourceConfigItem.SourceItem, isEnabled: Boolean) { + if (isEnabled) { + settings.hiddenSources -= item.source.name + } else { + settings.hiddenSources += item.source.name + } + } + + fun apply() { + settings.markKnownSources(initialList) + } + + private fun buildList() { + val hidden = settings.hiddenSources + sources.value = initialList.map { + SourceConfigItem.SourceItem( + source = it, + summary = null, + isEnabled = it.name !in hidden, + isDraggable = false, + ) + } + } +} \ No newline at end of file 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 005469b96..92fee1db9 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 @@ -53,6 +53,7 @@ class OnboardDialogFragment : AlertDialogFragment(), super.onViewCreated(view, savedInstanceState) val adapter = SourceLocalesAdapter(this) binding.recyclerView.adapter = adapter + binding.textViewTitle.setText(R.string.onboard_text) viewModel.list.observeNotNull(viewLifecycleOwner) { adapter.items = it } diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsFragment.kt index ad27cec65..60a5b6ff9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesSettingsFragment.kt @@ -141,7 +141,10 @@ class SourcesSettingsFragment : BaseFragment(), recyclerView: RecyclerView, current: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder, - ): Boolean = current.itemViewType == target.itemViewType + ): Boolean = current.itemViewType == target.itemViewType && viewModel.canReorder( + current.bindingAdapterPosition, + target.bindingAdapterPosition, + ) override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) = Unit diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt index 48f0e74c5..752e3d33e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt @@ -83,7 +83,9 @@ fun sourceConfigDraggableItemDelegate( on = { item, _, _ -> item is SourceConfigItem.SourceItem && item.isDraggable } ) { - val eventListener = object : View.OnClickListener, View.OnTouchListener, + val eventListener = object : + View.OnClickListener, + View.OnTouchListener, CompoundButton.OnCheckedChangeListener { override fun onClick(v: View?) = listener.onItemSettingsClick(item) diff --git a/app/src/main/res/layout/dialog_onboard.xml b/app/src/main/res/layout/dialog_onboard.xml index 03346c04d..e9757cc61 100644 --- a/app/src/main/res/layout/dialog_onboard.xml +++ b/app/src/main/res/layout/dialog_onboard.xml @@ -8,14 +8,15 @@ android:orientation="vertical"> + android:textAppearance="?attr/textAppearanceBodyMedium" + tools:text="@string/onboard_text" /> Помогает избежать блокировки IP-адреса Обработка сохранённой манги Главы будут удалены в фоновом режиме. Это может занять какое-то время + Скрыть + Доступны новые источники манги \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cca5b5410..692597cee 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -280,4 +280,5 @@ Saved manga processing Chapters will be removed in the background. It can take some time Hide + New manga sources are available \ No newline at end of file