diff --git a/app/src/main/java/eu/kanade/tachiyomi/App.kt b/app/src/main/java/eu/kanade/tachiyomi/App.kt index 1f6d849de..d60982fcf 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/App.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/App.kt @@ -34,6 +34,7 @@ import exh.debug.DebugToggles import exh.log.CrashlyticsPrinter import exh.log.EHDebugModeOverlay import exh.log.EHLogLevel +import exh.syDebugVersion import io.realm.Realm import io.realm.RealmConfiguration import java.io.File @@ -183,7 +184,7 @@ open class App : Application(), LifecycleObserver { .Builder(logFolder.absolutePath) .fileNameGenerator(object : DateFileNameGenerator() { override fun generateFileName(logLevel: Int, timestamp: Long): String { - return super.generateFileName(logLevel, timestamp) + "-${BuildConfig.BUILD_TYPE}" + return super.generateFileName(logLevel, timestamp) + "-${BuildConfig.BUILD_TYPE}.log" } }) .cleanStrategy(FileLastModifiedCleanStrategy(7.days.inMilliseconds.longValue)) @@ -201,6 +202,17 @@ open class App : Application(), LifecycleObserver { ) XLog.d("Application booting...") + XLog.nst().d( + "App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.FLAVOR}, ${BuildConfig.COMMIT_SHA}, ${BuildConfig.VERSION_CODE})\n" + + "Preview build: $syDebugVersion\n" + + "Android version: ${Build.VERSION.RELEASE} (SDK ${Build.VERSION.SDK_INT}) \n" + + "Android build ID: ${Build.DISPLAY}\n" + + "Device brand: ${Build.BRAND}\n" + + "Device manufacturer: ${Build.MANUFACTURER}\n" + + "Device name: ${Build.DEVICE}\n" + + "Device model: ${Build.MODEL}\n" + + "Device product name: ${Build.PRODUCT}" + ) } // EXH diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaPlus.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaPlus.kt index a4edc15c6..9289efcb7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaPlus.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaPlus.kt @@ -31,7 +31,7 @@ import rx.Observable import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -@ExperimentalSerializationApi +@OptIn(ExperimentalSerializationApi::class) class MangaPlus(delegate: HttpSource, val context: Context) : DelegatedHttpSource(delegate), ConfigurableSource { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/design/MigrationBottomSheetDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/design/MigrationBottomSheetDialog.kt index af65fa2b2..4a4934d6e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/design/MigrationBottomSheetDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/design/MigrationBottomSheetDialog.kt @@ -23,22 +23,20 @@ import kotlinx.android.synthetic.main.migration_bottom_sheet.mig_categories import kotlinx.android.synthetic.main.migration_bottom_sheet.mig_chapters import kotlinx.android.synthetic.main.migration_bottom_sheet.mig_tracking import kotlinx.android.synthetic.main.migration_bottom_sheet.use_smart_search +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import reactivecircus.flowbinding.android.view.clicks import uy.kohesive.injekt.injectLazy -class MigrationBottomSheetDialog( - activity: Activity, - theme: Int, - private val listener: - StartMigrationListener -) : - BottomSheetDialog( - activity, - theme - ) { +class MigrationBottomSheetDialog(activity: Activity, theme: Int, private val listener: StartMigrationListener) : BottomSheetDialog(activity, theme) { /** * Preferences helper. */ private val preferences by injectLazy() + private val scope = CoroutineScope(Job() + Dispatchers.Main) init { // Use activity theme for this layout @@ -61,7 +59,7 @@ class MigrationBottomSheetDialog( initPreferences() - fab.setOnClickListener { + fab.clicks().onEach { preferences.skipPreMigration().set(skip_step.isChecked) listener.startMigration( if (use_smart_search.isChecked && extra_search_param_text.text.isNotBlank()) { @@ -69,7 +67,7 @@ class MigrationBottomSheetDialog( } else null ) dismiss() - } + }.launchIn(scope) } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/design/PreMigrationController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/design/PreMigrationController.kt index 582fc3051..c2d77eaee 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/design/PreMigrationController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/design/PreMigrationController.kt @@ -9,9 +9,11 @@ import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.bluelinelabs.conductor.Router import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog +import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper @@ -19,17 +21,23 @@ import eu.kanade.tachiyomi.databinding.PreMigrationControllerBinding import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.base.controller.BaseController +import eu.kanade.tachiyomi.ui.base.controller.FabController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationListController import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationProcedureConfig -import eu.kanade.tachiyomi.ui.main.offsetAppbarHeight import eu.kanade.tachiyomi.util.view.shrinkOnScroll +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import reactivecircus.flowbinding.android.view.clicks import uy.kohesive.injekt.injectLazy class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), - FlexibleAdapter - .OnItemClickListener, + FlexibleAdapter.OnItemClickListener, + FabController, StartMigrationListener { private val sourceManager: SourceManager by injectLazy() private val prefs: PreferencesHelper by injectLazy() @@ -38,7 +46,10 @@ class PreMigrationController(bundle: Bundle? = null) : private val config: LongArray = args.getLongArray(MANGA_IDS_EXTRA) ?: LongArray(0) - private var showingOptions = false + val scope = CoroutineScope(Job() + Dispatchers.Main) + + private var actionFab: ExtendedFloatingActionButton? = null + private var actionFabScrollListener: RecyclerView.OnScrollListener? = null private var dialog: BottomSheetDialog? = null @@ -64,24 +75,34 @@ class PreMigrationController(bundle: Bundle? = null) : ourAdapter.isHandleDragEnabled = true dialog = null - binding.fab.shrinkOnScroll(binding.recycler) + actionFabScrollListener = actionFab?.shrinkOnScroll(binding.recycler) + } - binding.fab.setOnClickListener { - if (dialog?.isShowing != true) { - dialog = MigrationBottomSheetDialog(activity!!, R.style.SheetDialog, this) - dialog?.show() - val bottomSheet = dialog?.findViewById( - com.google.android.material.R.id.design_bottom_sheet - ) - if (bottomSheet != null) { - val behavior: BottomSheetBehavior<*> = BottomSheetBehavior.from(bottomSheet) - behavior.state = BottomSheetBehavior.STATE_EXPANDED - behavior.skipCollapsed = true + override fun configureFab(fab: ExtendedFloatingActionButton) { + actionFab = fab + fab.setText(R.string.action_migrate) + fab.setIconResource(R.drawable.ic_arrow_forward_24dp) + fab.clicks() + .onEach { + if (dialog?.isShowing != true) { + dialog = MigrationBottomSheetDialog(activity!!, R.style.SheetDialog, this) + dialog?.show() + val bottomSheet = dialog?.findViewById( + com.google.android.material.R.id.design_bottom_sheet + ) + if (bottomSheet != null) { + val behavior: BottomSheetBehavior<*> = BottomSheetBehavior.from(bottomSheet) + behavior.state = BottomSheetBehavior.STATE_EXPANDED + behavior.skipCollapsed = true + } } } - } - binding.fab.shrinkOnScroll(binding.recycler) - binding.fab.offsetAppbarHeight(activity!!) + .launchIn(scope) + } + + override fun cleanupFab(fab: ExtendedFloatingActionButton) { + actionFabScrollListener?.let { binding.recycler.removeOnScrollListener(it) } + actionFab = null } override fun startMigration(extraParam: String?) { @@ -127,20 +148,12 @@ class PreMigrationController(bundle: Bundle? = null) : private fun getEnabledSources(): List { val languages = prefs.enabledLanguages().get() val sourcesSaved = prefs.migrationSources().get().split("/") - var sources = sourceManager.getVisibleCatalogueSources() + val sources = sourceManager.getVisibleCatalogueSources() .filterIsInstance() .filter { it.lang in languages } .sortedBy { "(${it.lang}) ${it.name}" } - sources = - sources.filter { isEnabled(it.id.toString()) }.sortedBy { - sourcesSaved.indexOf( - it.id - .toString() - ) - } + - sources.filterNot { isEnabled(it.id.toString()) } - return sources + return sources.filter { isEnabled(it.id.toString()) }.sortedBy { sourcesSaved.indexOf(it.id.toString()) } + sources.filterNot { isEnabled(it.id.toString()) } } fun isEnabled(id: String): Boolean { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt index f5cdd55e0..7cb616398 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt @@ -33,8 +33,13 @@ import kotlinx.android.synthetic.main.migration_process_item.migration_manga_car import kotlinx.android.synthetic.main.migration_process_item.migration_manga_card_to import kotlinx.android.synthetic.main.migration_process_item.migration_menu import kotlinx.android.synthetic.main.migration_process_item.skip_manga +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.withContext +import reactivecircus.flowbinding.android.view.clicks import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy @@ -47,6 +52,7 @@ class MigrationProcessHolder( private val sourceManager: SourceManager by injectLazy() private var item: MigrationProcessItem? = null private val gson: Gson by injectLazy() + private val scope = CoroutineScope(Job() + Dispatchers.Main) init { // We need to post a Runnable to show the popup to make sure that the PopupMenu is @@ -80,14 +86,15 @@ class MigrationProcessHolder( if (manga != null) { withContext(Dispatchers.Main) { migration_manga_card_from.attachManga(manga, source) - migration_manga_card_from.setOnClickListener { - adapter.controller.router.pushController( - MangaController( - manga, - true - ).withFadeTransaction() - ) - } + migration_manga_card_from.clicks() + .onEach { + adapter.controller.router.pushController( + MangaController( + manga, + true + ).withFadeTransaction() + ) + }.launchIn(scope) } /*launchUI { @@ -115,13 +122,14 @@ class MigrationProcessHolder( } if (searchResult != null && resultSource != null) { migration_manga_card_to.attachManga(searchResult, resultSource) - migration_manga_card_to.setOnClickListener { - adapter.controller.router.pushController( - MangaController( - searchResult, true - ).withFadeTransaction() - ) - } + migration_manga_card_to.clicks() + .onEach { + adapter.controller.router.pushController( + MangaController( + searchResult, true + ).withFadeTransaction() + ) + }.launchIn(scope) } else { migration_manga_card_to.loading_group.isVisible = false migration_manga_card_to.title.text = view.context.applicationContext @@ -143,7 +151,7 @@ class MigrationProcessHolder( manga_chapters.text = "" manga_chapters.isVisible = false manga_last_chapter_label.text = "" - migration_manga_card_to.setOnClickListener(null) + migration_manga_card_to.clicks() } private fun View.attachManga(manga: Manga, source: Source) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/index/IndexController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/index/IndexController.kt index 413c02b7e..444cbf5ae 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/index/IndexController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/index/IndexController.kt @@ -32,6 +32,7 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import reactivecircus.flowbinding.android.view.clicks import reactivecircus.flowbinding.appcompat.QueryTextEvent import reactivecircus.flowbinding.appcompat.queryTextEvents import uy.kohesive.injekt.Injekt @@ -245,7 +246,9 @@ open class IndexController : filterSheet?.setOnShowListener { actionFab?.isVisible = false } filterSheet?.setOnDismissListener { actionFab?.isVisible = true } - actionFab?.setOnClickListener { filterSheet?.show() } + actionFab?.clicks() + ?.onEach { filterSheet?.show() } + ?.launchIn(scope) actionFab?.isVisible = true } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt index df3115a77..8e4b3efb2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt @@ -34,6 +34,9 @@ import kotlinx.android.synthetic.main.edit_manga_dialog.view.manga_genres_tags import kotlinx.android.synthetic.main.edit_manga_dialog.view.reset_cover import kotlinx.android.synthetic.main.edit_manga_dialog.view.reset_tags import kotlinx.android.synthetic.main.edit_manga_dialog.view.title +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import reactivecircus.flowbinding.android.view.clicks import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -131,16 +134,19 @@ class EditMangaDialog : DialogController { } } view.manga_genres_tags.clearFocus() - view.cover_layout.setOnClickListener { - infoController.changeCover() - } - view.reset_tags.setOnClickListener { resetTags() } + view.cover_layout.clicks() + .onEach { infoController.changeCover() } + .launchIn(infoController.scope) + view.reset_tags.clicks() + .onEach { resetTags() } + .launchIn(infoController.scope) view.reset_cover.isVisible = !isLocal - view.reset_cover.setOnClickListener { - view.context.toast(R.string.cover_reset_toast) - customCoverUri = null - willResetCover = true - } + view.reset_cover.clicks() + .onEach { + view.context.toast(R.string.cover_reset_toast) + customCoverUri = null + willResetCover = true + }.launchIn(infoController.scope) } private fun resetTags() { @@ -198,7 +204,7 @@ class EditMangaDialog : DialogController { chipIcon?.setTint(context.getResourceColor(R.attr.colorAccent)) textStartPadding = 0F - setOnClickListener { + clicks().onEach { MaterialDialog(context) .title(R.string.add_tag) .input(inputType = InputType.TYPE_CLASS_TEXT) @@ -210,7 +216,7 @@ class EditMangaDialog : DialogController { } .negativeButton(android.R.string.cancel) .show() - } + }.launchIn(infoController.scope) } addView(addTagChip) } diff --git a/app/src/main/res/layout/pre_migration_controller.xml b/app/src/main/res/layout/pre_migration_controller.xml index 238f6c38d..b18592be0 100644 --- a/app/src/main/res/layout/pre_migration_controller.xml +++ b/app/src/main/res/layout/pre_migration_controller.xml @@ -20,17 +20,4 @@ - - \ No newline at end of file