Refactor databinding fields to parent abstract classes

This commit is contained in:
arkon 2020-04-18 14:40:18 -04:00
parent 31b94fd3ff
commit 6a532b836d
24 changed files with 38 additions and 70 deletions

View File

@ -4,6 +4,7 @@ import android.content.res.Configuration
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -11,10 +12,12 @@ import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
abstract class BaseActivity : AppCompatActivity() { abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
val preferences: PreferencesHelper by injectLazy() val preferences: PreferencesHelper by injectLazy()
lateinit var binding: VB
@Suppress("LeakingThis") @Suppress("LeakingThis")
private val secureActivityDelegate = SecureActivityDelegate(this) private val secureActivityDelegate = SecureActivityDelegate(this)

View File

@ -1,16 +1,19 @@
package eu.kanade.tachiyomi.ui.base.activity package eu.kanade.tachiyomi.ui.base.activity
import android.os.Bundle import android.os.Bundle
import androidx.viewbinding.ViewBinding
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import nucleus.view.NucleusAppCompatActivity import nucleus.view.NucleusAppCompatActivity
abstract class BaseRxActivity<P : BasePresenter<*>> : NucleusAppCompatActivity<P>() { abstract class BaseRxActivity<VB : ViewBinding, P : BasePresenter<*>> : NucleusAppCompatActivity<P>() {
@Suppress("LeakingThis") @Suppress("LeakingThis")
private val secureActivityDelegate = SecureActivityDelegate(this) private val secureActivityDelegate = SecureActivityDelegate(this)
lateinit var binding: VB
init { init {
@Suppress("LeakingThis") @Suppress("LeakingThis")
LocaleHelper.updateConfiguration(this) LocaleHelper.updateConfiguration(this)

View File

@ -6,6 +6,7 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import com.bluelinelabs.conductor.Controller import com.bluelinelabs.conductor.Controller
import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.ControllerChangeHandler
import com.bluelinelabs.conductor.ControllerChangeType import com.bluelinelabs.conductor.ControllerChangeType
@ -14,9 +15,11 @@ import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.clearFindViewByIdCache import kotlinx.android.synthetic.clearFindViewByIdCache
import timber.log.Timber import timber.log.Timber
abstract class BaseController(bundle: Bundle? = null) : RestoreViewOnCreateController(bundle), abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) : RestoreViewOnCreateController(bundle),
LayoutContainer { LayoutContainer {
lateinit var binding: VB
init { init {
addLifecycleListener(object : LifecycleListener() { addLifecycleListener(object : LifecycleListener() {
override fun postCreateView(controller: Controller, view: View) { override fun postCreateView(controller: Controller, view: View) {
@ -72,7 +75,7 @@ abstract class BaseController(bundle: Bundle? = null) : RestoreViewOnCreateContr
fun setTitle() { fun setTitle() {
var parentController = parentController var parentController = parentController
while (parentController != null) { while (parentController != null) {
if (parentController is BaseController && parentController.getTitle() != null) { if (parentController is BaseController<*> && parentController.getTitle() != null) {
return return
} }
parentController = parentController.parentController parentController = parentController.parentController

View File

@ -1,13 +1,15 @@
package eu.kanade.tachiyomi.ui.base.controller package eu.kanade.tachiyomi.ui.base.controller
import android.os.Bundle import android.os.Bundle
import androidx.viewbinding.ViewBinding
import eu.kanade.tachiyomi.ui.base.presenter.NucleusConductorDelegate import eu.kanade.tachiyomi.ui.base.presenter.NucleusConductorDelegate
import eu.kanade.tachiyomi.ui.base.presenter.NucleusConductorLifecycleListener import eu.kanade.tachiyomi.ui.base.presenter.NucleusConductorLifecycleListener
import nucleus.factory.PresenterFactory import nucleus.factory.PresenterFactory
import nucleus.presenter.Presenter import nucleus.presenter.Presenter
@Suppress("LeakingThis") @Suppress("LeakingThis")
abstract class NucleusController<P : Presenter<*>>(val bundle: Bundle? = null) : RxController(bundle), abstract class NucleusController<VB : ViewBinding, P : Presenter<*>>(val bundle: Bundle? = null) :
RxController<VB>(bundle),
PresenterFactory<P> { PresenterFactory<P> {
private val delegate = NucleusConductorDelegate(this) private val delegate = NucleusConductorDelegate(this)

View File

@ -3,11 +3,12 @@ package eu.kanade.tachiyomi.ui.base.controller
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.viewbinding.ViewBinding
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
import rx.subscriptions.CompositeSubscription import rx.subscriptions.CompositeSubscription
abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) { abstract class RxController<VB : ViewBinding>(bundle: Bundle? = null) : BaseController<VB>(bundle) {
var untilDetachSubscriptions = CompositeSubscription() var untilDetachSubscriptions = CompositeSubscription()
private set private set

View File

@ -25,7 +25,7 @@ import reactivecircus.flowbinding.android.view.clicks
/** /**
* Controller to manage the categories for the users' library. * Controller to manage the categories for the users' library.
*/ */
class CategoryController : NucleusController<CategoryPresenter>(), class CategoryController : NucleusController<CategoriesControllerBinding, CategoryPresenter>(),
ActionMode.Callback, ActionMode.Callback,
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnItemLongClickListener,
@ -49,8 +49,6 @@ class CategoryController : NucleusController<CategoryPresenter>(),
*/ */
private var undoHelper: UndoHelper? = null private var undoHelper: UndoHelper? = null
private lateinit var binding: CategoriesControllerBinding
/** /**
* Creates the presenter for this controller. Not to be manually called. * Creates the presenter for this controller. Not to be manually called.
*/ */

View File

@ -23,7 +23,7 @@ import rx.android.schedulers.AndroidSchedulers
* Controller that shows the currently active downloads. * Controller that shows the currently active downloads.
* Uses R.layout.fragment_download_queue. * Uses R.layout.fragment_download_queue.
*/ */
class DownloadController : NucleusController<DownloadPresenter>(), class DownloadController : NucleusController<DownloadControllerBinding, DownloadPresenter>(),
DownloadAdapter.DownloadItemListener { DownloadAdapter.DownloadItemListener {
/** /**
@ -41,8 +41,6 @@ class DownloadController : NucleusController<DownloadPresenter>(),
*/ */
private var isRunning: Boolean = false private var isRunning: Boolean = false
private lateinit var binding: DownloadControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }

View File

@ -32,7 +32,7 @@ import uy.kohesive.injekt.api.get
/** /**
* Controller to manage the catalogues available in the app. * Controller to manage the catalogues available in the app.
*/ */
open class ExtensionController : NucleusController<ExtensionPresenter>(), open class ExtensionController : NucleusController<ExtensionControllerBinding, ExtensionPresenter>(),
ExtensionAdapter.OnButtonClickListener, ExtensionAdapter.OnButtonClickListener,
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnItemLongClickListener,
@ -49,8 +49,6 @@ open class ExtensionController : NucleusController<ExtensionPresenter>(),
private var query = "" private var query = ""
private lateinit var binding: ExtensionControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }

View File

@ -38,7 +38,7 @@ import reactivecircus.flowbinding.android.view.clicks
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
class ExtensionDetailsController(bundle: Bundle? = null) : class ExtensionDetailsController(bundle: Bundle? = null) :
NucleusController<ExtensionDetailsPresenter>(bundle), NucleusController<ExtensionDetailControllerBinding, ExtensionDetailsPresenter>(bundle),
PreferenceManager.OnDisplayPreferenceDialogListener, PreferenceManager.OnDisplayPreferenceDialogListener,
DialogPreference.TargetFragment { DialogPreference.TargetFragment {
@ -46,8 +46,6 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
private var preferenceScreen: PreferenceScreen? = null private var preferenceScreen: PreferenceScreen? = null
private lateinit var binding: ExtensionDetailControllerBinding
constructor(pkgName: String) : this(Bundle().apply { constructor(pkgName: String) : this(Bundle().apply {
putString(PKGNAME_KEY, pkgName) putString(PKGNAME_KEY, pkgName)
}) })

View File

@ -51,7 +51,7 @@ import uy.kohesive.injekt.api.get
class LibraryController( class LibraryController(
bundle: Bundle? = null, bundle: Bundle? = null,
private val preferences: PreferencesHelper = Injekt.get() private val preferences: PreferencesHelper = Injekt.get()
) : NucleusController<LibraryPresenter>(bundle), ) : NucleusController<LibraryControllerBinding, LibraryPresenter>(bundle),
RootController, RootController,
TabbedController, TabbedController,
ActionMode.Callback, ActionMode.Callback,
@ -126,8 +126,6 @@ class LibraryController(
private var tabsVisibilitySubscription: Subscription? = null private var tabsVisibilitySubscription: Subscription? = null
private lateinit var binding: LibraryControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
retainViewMode = RetainViewMode.RETAIN_DETACH retainViewMode = RetainViewMode.RETAIN_DETACH

View File

@ -38,7 +38,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
class MainActivity : BaseActivity() { class MainActivity : BaseActivity<MainActivityBinding>() {
private lateinit var router: Router private lateinit var router: Router
@ -55,8 +55,6 @@ class MainActivity : BaseActivity() {
private var isHandlingShortcut: Boolean = false private var isHandlingShortcut: Boolean = false
private lateinit var binding: MainActivityBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)

View File

@ -33,7 +33,7 @@ import rx.Subscription
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
class MangaController : RxController, TabbedController { class MangaController : RxController<MangaControllerBinding>, TabbedController {
constructor(manga: Manga?, fromSource: Boolean = false) : super(Bundle().apply { constructor(manga: Manga?, fromSource: Boolean = false) : super(Bundle().apply {
putLong(MANGA_EXTRA, manga?.id ?: 0) putLong(MANGA_EXTRA, manga?.id ?: 0)
@ -63,8 +63,6 @@ class MangaController : RxController, TabbedController {
val mangaFavoriteRelay: PublishRelay<Boolean> = PublishRelay.create() val mangaFavoriteRelay: PublishRelay<Boolean> = PublishRelay.create()
private lateinit var binding: MangaControllerBinding
private val trackingIconRelay: BehaviorRelay<Boolean> = BehaviorRelay.create() private val trackingIconRelay: BehaviorRelay<Boolean> = BehaviorRelay.create()
private var trackingIconSubscription: Subscription? = null private var trackingIconSubscription: Subscription? = null

View File

@ -40,7 +40,7 @@ import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.swiperefreshlayout.refreshes import reactivecircus.flowbinding.swiperefreshlayout.refreshes
import timber.log.Timber import timber.log.Timber
class ChaptersController : NucleusController<ChaptersPresenter>(), class ChaptersController : NucleusController<ChaptersControllerBinding, ChaptersPresenter>(),
ActionMode.Callback, ActionMode.Callback,
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnItemLongClickListener,
@ -64,8 +64,6 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
private var lastClickPosition = -1 private var lastClickPosition = -1
private lateinit var binding: ChaptersControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
setOptionsMenuHidden(true) setOptionsMenuHidden(true)

View File

@ -71,13 +71,11 @@ import uy.kohesive.injekt.injectLazy
* UI related actions should be called from here. * UI related actions should be called from here.
*/ */
class MangaInfoController(private val fromSource: Boolean = false) : class MangaInfoController(private val fromSource: Boolean = false) :
NucleusController<MangaInfoPresenter>(), NucleusController<MangaInfoControllerBinding, MangaInfoPresenter>(),
ChangeMangaCategoriesDialog.Listener { ChangeMangaCategoriesDialog.Listener {
private val preferences: PreferencesHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy()
private lateinit var binding: MangaInfoControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
setOptionsMenuHidden(true) setOptionsMenuHidden(true)

View File

@ -17,7 +17,7 @@ import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.swiperefreshlayout.refreshes import reactivecircus.flowbinding.swiperefreshlayout.refreshes
import timber.log.Timber import timber.log.Timber
class TrackController : NucleusController<TrackPresenter>(), class TrackController : NucleusController<TrackControllerBinding, TrackPresenter>(),
TrackAdapter.OnClickListener, TrackAdapter.OnClickListener,
SetTrackStatusDialog.Listener, SetTrackStatusDialog.Listener,
SetTrackChaptersDialog.Listener, SetTrackChaptersDialog.Listener,
@ -25,8 +25,6 @@ class TrackController : NucleusController<TrackPresenter>(),
private var adapter: TrackAdapter? = null private var adapter: TrackAdapter? = null
private lateinit var binding: TrackControllerBinding
init { init {
// There's no menu, but this avoids a bug when coming from the catalogue, where the menu // There's no menu, but this avoids a bug when coming from the catalogue, where the menu
// disappears if the searchview is expanded // disappears if the searchview is expanded

View File

@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.databinding.MigrationControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
class MigrationController : NucleusController<MigrationPresenter>(), class MigrationController : NucleusController<MigrationControllerBinding, MigrationPresenter>(),
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
SourceAdapter.OnSelectClickListener { SourceAdapter.OnSelectClickListener {
@ -23,8 +23,6 @@ class MigrationController : NucleusController<MigrationPresenter>(),
setTitle() setTitle()
} }
private lateinit var binding: MigrationControllerBinding
override fun createPresenter(): MigrationPresenter { override fun createPresenter(): MigrationPresenter {
return MigrationPresenter() return MigrationPresenter()
} }

View File

@ -70,7 +70,7 @@ import uy.kohesive.injekt.injectLazy
* viewers, to which calls from the presenter or UI events are delegated. * viewers, to which calls from the presenter or UI events are delegated.
*/ */
@RequiresPresenter(ReaderPresenter::class) @RequiresPresenter(ReaderPresenter::class)
class ReaderActivity : BaseRxActivity<ReaderPresenter>() { class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() {
private val preferences by injectLazy<PreferencesHelper>() private val preferences by injectLazy<PreferencesHelper>()
@ -102,8 +102,6 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
private var progressDialog: ProgressDialog? = null private var progressDialog: ProgressDialog? = null
private lateinit var binding: ReaderActivityBinding
companion object { companion object {
@Suppress("unused") @Suppress("unused")
const val LEFT_TO_RIGHT = 1 const val LEFT_TO_RIGHT = 1

View File

@ -22,7 +22,7 @@ import eu.kanade.tachiyomi.util.system.toast
* Uses [R.layout.history_controller]. * Uses [R.layout.history_controller].
* UI related actions should be called from here. * UI related actions should be called from here.
*/ */
class HistoryController : NucleusController<HistoryPresenter>(), class HistoryController : NucleusController<HistoryControllerBinding, HistoryPresenter>(),
RootController, RootController,
NoToolbarElevationController, NoToolbarElevationController,
FlexibleAdapter.OnUpdateListener, FlexibleAdapter.OnUpdateListener,
@ -37,8 +37,6 @@ class HistoryController : NucleusController<HistoryPresenter>(),
var adapter: HistoryAdapter? = null var adapter: HistoryAdapter? = null
private set private set
private lateinit var binding: HistoryControllerBinding
override fun getTitle(): String? { override fun getTitle(): String? {
return resources?.getString(R.string.label_recent_manga) return resources?.getString(R.string.label_recent_manga)
} }

View File

@ -38,7 +38,7 @@ import timber.log.Timber
* Uses [R.layout.updates_controller]. * Uses [R.layout.updates_controller].
* UI related actions should be called from here. * UI related actions should be called from here.
*/ */
class UpdatesController : NucleusController<UpdatesPresenter>(), class UpdatesController : NucleusController<UpdatesControllerBinding, UpdatesPresenter>(),
RootController, RootController,
NoToolbarElevationController, NoToolbarElevationController,
ActionMode.Callback, ActionMode.Callback,
@ -59,8 +59,6 @@ class UpdatesController : NucleusController<UpdatesPresenter>(),
var adapter: UpdatesAdapter? = null var adapter: UpdatesAdapter? = null
private set private set
private lateinit var binding: UpdatesControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }

View File

@ -61,7 +61,7 @@ abstract class SettingsController : PreferenceController() {
fun setTitle() { fun setTitle() {
var parentController = parentController var parentController = parentController
while (parentController != null) { while (parentController != null) {
if (parentController is BaseController && parentController.getTitle() != null) { if (parentController is BaseController<*> && parentController.getTitle() != null) {
return return
} }
parentController = parentController.parentController parentController = parentController.parentController

View File

@ -44,7 +44,7 @@ import uy.kohesive.injekt.api.get
* [SourceAdapter.OnBrowseClickListener] call function data on browse item click. * [SourceAdapter.OnBrowseClickListener] call function data on browse item click.
* [SourceAdapter.OnLatestClickListener] call function data on latest item click * [SourceAdapter.OnLatestClickListener] call function data on latest item click
*/ */
class SourceController : NucleusController<SourcePresenter>(), class SourceController : NucleusController<SourceMainControllerBinding, SourcePresenter>(),
RootController, RootController,
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnItemLongClickListener,
@ -58,8 +58,6 @@ class SourceController : NucleusController<SourcePresenter>(),
*/ */
private var adapter: SourceAdapter? = null private var adapter: SourceAdapter? = null
private lateinit var binding: SourceMainControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }

View File

@ -53,7 +53,7 @@ import uy.kohesive.injekt.injectLazy
* Controller to manage the catalogues available in the app. * Controller to manage the catalogues available in the app.
*/ */
open class BrowseSourceController(bundle: Bundle) : open class BrowseSourceController(bundle: Bundle) :
NucleusController<BrowseSourcePresenter>(bundle), NucleusController<SourceControllerBinding, BrowseSourcePresenter>(bundle),
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnItemLongClickListener,
FlexibleAdapter.EndlessScrollListener, FlexibleAdapter.EndlessScrollListener,
@ -95,8 +95,6 @@ open class BrowseSourceController(bundle: Bundle) :
*/ */
private var progressItem: ProgressItem? = null private var progressItem: ProgressItem? = null
private lateinit var binding: SourceControllerBinding
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }

View File

@ -30,7 +30,7 @@ import reactivecircus.flowbinding.appcompat.queryTextEvents
open class GlobalSearchController( open class GlobalSearchController(
protected val initialQuery: String? = null, protected val initialQuery: String? = null,
protected val extensionFilter: String? = null protected val extensionFilter: String? = null
) : NucleusController<GlobalSearchPresenter>(), ) : NucleusController<GlobalSearchControllerBinding, GlobalSearchPresenter>(),
GlobalSearchCardAdapter.OnMangaClickListener { GlobalSearchCardAdapter.OnMangaClickListener {
/** /**
@ -38,11 +38,6 @@ open class GlobalSearchController(
*/ */
protected var adapter: GlobalSearchAdapter? = null protected var adapter: GlobalSearchAdapter? = null
private lateinit var binding: GlobalSearchControllerBinding
/**
* Called when controller is initialized.
*/
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }
@ -59,11 +54,6 @@ open class GlobalSearchController(
return binding.root return binding.root
} }
/**
* Set the title of controller.
*
* @return title.
*/
override fun getTitle(): String? { override fun getTitle(): String? {
return presenter.query return presenter.query
} }

View File

@ -23,14 +23,12 @@ import eu.kanade.tachiyomi.util.view.invisible
import eu.kanade.tachiyomi.util.view.visible import eu.kanade.tachiyomi.util.view.visible
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
class WebViewActivity : BaseActivity() { class WebViewActivity : BaseActivity<WebviewActivityBinding>() {
private val sourceManager by injectLazy<SourceManager>() private val sourceManager by injectLazy<SourceManager>()
private var bundle: Bundle? = null private var bundle: Bundle? = null
private lateinit var binding: WebviewActivityBinding
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)