refactor: Provide properties for more shared preferences (#992)

Continues the work of providing properties with accessors for specific
shared preferences.
This commit is contained in:
Nik Clayton 2024-10-10 13:12:56 +02:00 committed by GitHub
parent 367747838d
commit e307796251
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 54 additions and 43 deletions

View File

@ -109,7 +109,7 @@ import app.pachli.core.navigation.pachliAccountId
import app.pachli.core.network.model.Account import app.pachli.core.network.model.Account
import app.pachli.core.network.model.Notification import app.pachli.core.network.model.Notification
import app.pachli.core.preferences.MainNavigationPosition import app.pachli.core.preferences.MainNavigationPosition
import app.pachli.core.preferences.PrefKeys import app.pachli.core.preferences.PrefKeys.FONT_FAMILY
import app.pachli.core.ui.extensions.reduceSwipeSensitivity import app.pachli.core.ui.extensions.reduceSwipeSensitivity
import app.pachli.core.ui.makeIcon import app.pachli.core.ui.makeIcon
import app.pachli.databinding.ActivityMainBinding import app.pachli.databinding.ActivityMainBinding
@ -320,7 +320,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
// Determine which of the three toolbars should be the supportActionBar (which hosts // Determine which of the three toolbars should be the supportActionBar (which hosts
// the options menu). // the options menu).
val hideTopToolbar = sharedPreferencesRepository.getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false) val hideTopToolbar = sharedPreferencesRepository.hideTopToolbar
if (hideTopToolbar) { if (hideTopToolbar) {
when (sharedPreferencesRepository.mainNavigationPosition) { when (sharedPreferencesRepository.mainNavigationPosition) {
MainNavigationPosition.TOP -> setSupportActionBar(binding.topNav) MainNavigationPosition.TOP -> setSupportActionBar(binding.topNav)
@ -591,9 +591,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
header.currentProfileName.setTextColor(headerTextColor) header.currentProfileName.setTextColor(headerTextColor)
header.currentProfileEmail.setTextColor(headerTextColor) header.currentProfileEmail.setTextColor(headerTextColor)
val animateAvatars = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false) DrawerImageLoader.init(MainDrawerImageLoader(glide, sharedPreferencesRepository.animateAvatars))
DrawerImageLoader.init(MainDrawerImageLoader(glide, animateAvatars))
binding.mainDrawer.apply { binding.mainDrawer.apply {
refreshMainDrawerItems(activeAccountId, addSearchButton) refreshMainDrawerItems(activeAccountId, addSearchButton)
@ -860,7 +858,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
} }
updateMainDrawerTypeface( updateMainDrawerTypeface(
EmbeddedFontFamily.from(sharedPreferencesRepository.getString(PrefKeys.FONT_FAMILY, "default")), EmbeddedFontFamily.from(sharedPreferencesRepository.getString(FONT_FAMILY, "default")),
) )
} }
@ -978,8 +976,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
val pageMargin = resources.getDimensionPixelSize(DR.dimen.tab_page_margin) val pageMargin = resources.getDimensionPixelSize(DR.dimen.tab_page_margin)
binding.viewPager.setPageTransformer(MarginPageTransformer(pageMargin)) binding.viewPager.setPageTransformer(MarginPageTransformer(pageMargin))
val enableSwipeForTabs = sharedPreferencesRepository.getBoolean(PrefKeys.ENABLE_SWIPE_FOR_TABS, true) binding.viewPager.isUserInputEnabled = sharedPreferencesRepository.enableTabSwipe
binding.viewPager.isUserInputEnabled = enableSwipeForTabs
onTabSelectedListener?.let { onTabSelectedListener?.let {
activeTabLayout.removeOnTabSelectedListener(it) activeTabLayout.removeOnTabSelectedListener(it)
@ -1122,8 +1119,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
private fun loadDrawerAvatar(avatarUrl: String, showPlaceholder: Boolean) { private fun loadDrawerAvatar(avatarUrl: String, showPlaceholder: Boolean) {
val hideTopToolbar = sharedPreferencesRepository.getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false) val hideTopToolbar = sharedPreferencesRepository.hideTopToolbar
val animateAvatars = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false) val animateAvatars = sharedPreferencesRepository.animateAvatars
val activeToolbar = if (hideTopToolbar) { val activeToolbar = if (hideTopToolbar) {
when (sharedPreferencesRepository.mainNavigationPosition) { when (sharedPreferencesRepository.mainNavigationPosition) {
@ -1227,7 +1224,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
} }
private fun updateProfiles() { private fun updateProfiles() {
val animateEmojis = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) val animateEmojis = sharedPreferencesRepository.animateEmojis
val profiles: MutableList<IProfile> = val profiles: MutableList<IProfile> =
accountManager.getAllAccountsOrderedByActive().map { acc -> accountManager.getAllAccountsOrderedByActive().map { acc ->
ProfileDrawerItem().apply { ProfileDrawerItem().apply {

View File

@ -151,8 +151,8 @@ class AccountActivity :
private var subscribing: Boolean = false private var subscribing: Boolean = false
private var loadedAccount: Account? = null private var loadedAccount: Account? = null
private var animateAvatar: Boolean = false private var animateAvatar: Boolean = sharedPreferencesRepository.animateAvatars
private var animateEmojis: Boolean = false private var animateEmojis: Boolean = sharedPreferencesRepository.animateEmojis
// fields for scroll animation // fields for scroll animation
private var hideFab: Boolean = false private var hideFab: Boolean = false
@ -199,8 +199,6 @@ class AccountActivity :
// Obtain information to fill out the profile. // Obtain information to fill out the profile.
viewModel.setAccountInfo(AccountActivityIntent.getAccountId(intent)) viewModel.setAccountInfo(AccountActivityIntent.getAccountId(intent))
animateAvatar = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false)
animateEmojis = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
hideFab = sharedPreferencesRepository.getBoolean(PrefKeys.FAB_HIDE, false) hideFab = sharedPreferencesRepository.getBoolean(PrefKeys.FAB_HIDE, false)
handleWindowInsets() handleWindowInsets()
@ -297,8 +295,7 @@ class AccountActivity :
val pageMargin = resources.getDimensionPixelSize(DR.dimen.tab_page_margin) val pageMargin = resources.getDimensionPixelSize(DR.dimen.tab_page_margin)
binding.accountFragmentViewPager.setPageTransformer(MarginPageTransformer(pageMargin)) binding.accountFragmentViewPager.setPageTransformer(MarginPageTransformer(pageMargin))
val enableSwipeForTabs = sharedPreferencesRepository.getBoolean(PrefKeys.ENABLE_SWIPE_FOR_TABS, true) binding.accountFragmentViewPager.isUserInputEnabled = sharedPreferencesRepository.enableTabSwipe
binding.accountFragmentViewPager.isUserInputEnabled = enableSwipeForTabs
binding.accountTabLayout.addOnTabSelectedListener( binding.accountTabLayout.addOnTabSelectedListener(
object : TabLayout.OnTabSelectedListener { object : TabLayout.OnTabSelectedListener {

View File

@ -118,8 +118,8 @@ class AccountListFragment :
binding.swipeRefreshLayout.setOnRefreshListener { fetchAccounts() } binding.swipeRefreshLayout.setOnRefreshListener { fetchAccounts() }
binding.swipeRefreshLayout.setColorSchemeColors(MaterialColors.getColor(binding.root, androidx.appcompat.R.attr.colorPrimary)) binding.swipeRefreshLayout.setColorSchemeColors(MaterialColors.getColor(binding.root, androidx.appcompat.R.attr.colorPrimary))
val animateAvatar = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false) val animateAvatar = sharedPreferencesRepository.animateAvatars
val animateEmojis = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) val animateEmojis = sharedPreferencesRepository.animateEmojis
val showBotOverlay = sharedPreferencesRepository.getBoolean(PrefKeys.SHOW_BOT_OVERLAY, true) val showBotOverlay = sharedPreferencesRepository.getBoolean(PrefKeys.SHOW_BOT_OVERLAY, true)
val activeAccount = accountManager.activeAccount!! val activeAccount = accountManager.activeAccount!!

View File

@ -99,7 +99,7 @@ class AnnouncementsActivity :
) )
val wellbeingEnabled = sharedPreferencesRepository.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false) val wellbeingEnabled = sharedPreferencesRepository.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false)
val animateEmojis = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) val animateEmojis = sharedPreferencesRepository.animateEmojis
val useAbsoluteTime = sharedPreferencesRepository.getBoolean(PrefKeys.ABSOLUTE_TIME_VIEW, false) val useAbsoluteTime = sharedPreferencesRepository.getBoolean(PrefKeys.ABSOLUTE_TIME_VIEW, false)
adapter = AnnouncementAdapter(emptyList(), this, wellbeingEnabled, animateEmojis, useAbsoluteTime) adapter = AnnouncementAdapter(emptyList(), this, wellbeingEnabled, animateEmojis, useAbsoluteTime)

View File

@ -415,8 +415,8 @@ class ComposeActivity :
binding.composeEditField.setAdapter( binding.composeEditField.setAdapter(
ComposeAutoCompleteAdapter( ComposeAutoCompleteAdapter(
this, this,
preferences.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false), sharedPreferencesRepository.animateAvatars,
preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false), sharedPreferencesRepository.animateEmojis,
preferences.getBoolean(PrefKeys.SHOW_BOT_OVERLAY, true), preferences.getBoolean(PrefKeys.SHOW_BOT_OVERLAY, true),
), ),
) )
@ -629,12 +629,11 @@ class ComposeActivity :
a.getDimensionPixelSize(0, 1) a.getDimensionPixelSize(0, 1)
} }
val animateAvatars = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false)
loadAvatar( loadAvatar(
activeAccount.profilePictureUrl, activeAccount.profilePictureUrl,
binding.composeAvatar, binding.composeAvatar,
avatarSize / 8, avatarSize / 8,
animateAvatars, sharedPreferencesRepository.animateAvatars,
) )
binding.composeAvatar.contentDescription = getString( binding.composeAvatar.contentDescription = getString(
R.string.compose_active_account_description, R.string.compose_active_account_description,
@ -1368,7 +1367,7 @@ class ComposeActivity :
private fun setEmojiList(emojiList: List<Emoji>?) { private fun setEmojiList(emojiList: List<Emoji>?) {
if (emojiList != null) { if (emojiList != null) {
val animateEmojis = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) val animateEmojis = sharedPreferencesRepository.animateEmojis
binding.emojiView.adapter = EmojiAdapter(emojiList, this@ComposeActivity, animateEmojis) binding.emojiView.adapter = EmojiAdapter(emojiList, this@ComposeActivity, animateEmojis)
enableButton(binding.composeEmojiButton, true, emojiList.isNotEmpty()) enableButton(binding.composeEmojiButton, true, emojiList.isNotEmpty())
} }

View File

@ -90,7 +90,6 @@ import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_IS_SE
import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE import app.pachli.core.model.ServerOperation.ORG_JOINMASTODON_SEARCH_QUERY_LANGUAGE
import app.pachli.core.navigation.pachliAccountId import app.pachli.core.navigation.pachliAccountId
import app.pachli.core.network.Server import app.pachli.core.network.Server
import app.pachli.core.preferences.PrefKeys
import app.pachli.core.ui.extensions.await import app.pachli.core.ui.extensions.await
import app.pachli.core.ui.extensions.awaitSingleChoiceItem import app.pachli.core.ui.extensions.awaitSingleChoiceItem
import app.pachli.core.ui.extensions.reduceSwipeSensitivity import app.pachli.core.ui.extensions.reduceSwipeSensitivity
@ -154,8 +153,7 @@ class SearchActivity :
binding.pages.reduceSwipeSensitivity() binding.pages.reduceSwipeSensitivity()
binding.pages.adapter = SearchPagerAdapter(this, intent.pachliAccountId) binding.pages.adapter = SearchPagerAdapter(this, intent.pachliAccountId)
val enableSwipeForTabs = sharedPreferencesRepository.getBoolean(PrefKeys.ENABLE_SWIPE_FOR_TABS, true) binding.pages.isUserInputEnabled = sharedPreferencesRepository.enableTabSwipe
binding.pages.isUserInputEnabled = enableSwipeForTabs
TabLayoutMediator(binding.tabs, binding.pages) { tab, position -> TabLayoutMediator(binding.tabs, binding.pages) { tab, position ->
tab.text = getPageTitle(position) tab.text = getPageTitle(position)

View File

@ -44,8 +44,8 @@ class SearchAccountsFragment : SearchFragment<TimelineAccount>() {
override fun createAdapter(): PagingDataAdapter<TimelineAccount, *> { override fun createAdapter(): PagingDataAdapter<TimelineAccount, *> {
return SearchAccountsAdapter( return SearchAccountsAdapter(
this, this,
sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false), sharedPreferencesRepository.animateAvatars,
sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false), sharedPreferencesRepository.animateEmojis,
sharedPreferencesRepository.getBoolean(PrefKeys.SHOW_BOT_OVERLAY, true), sharedPreferencesRepository.getBoolean(PrefKeys.SHOW_BOT_OVERLAY, true),
) )
} }

View File

@ -97,8 +97,8 @@ class ViewEditsFragment :
statusId = requireArguments().getString(ARG_STATUS_ID)!! statusId = requireArguments().getString(ARG_STATUS_ID)!!
val animateAvatars = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false) val animateAvatars = sharedPreferencesRepository.animateAvatars
val animateEmojis = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) val animateEmojis = sharedPreferencesRepository.animateEmojis
val useBlurhash = sharedPreferencesRepository.getBoolean(PrefKeys.USE_BLURHASH, true) val useBlurhash = sharedPreferencesRepository.getBoolean(PrefKeys.USE_BLURHASH, true)
val avatarRadius: Int = requireContext().resources.getDimensionPixelSize(DR.dimen.avatar_radius_48dp) val avatarRadius: Int = requireContext().resources.getDimensionPixelSize(DR.dimen.avatar_radius_48dp)

View File

@ -26,9 +26,12 @@ import androidx.preference.PreferenceManager
import app.pachli.core.activity.databinding.ItemAutocompleteAccountBinding import app.pachli.core.activity.databinding.ItemAutocompleteAccountBinding
import app.pachli.core.database.model.AccountEntity import app.pachli.core.database.model.AccountEntity
import app.pachli.core.designsystem.R as DR import app.pachli.core.designsystem.R as DR
import app.pachli.core.preferences.PrefKeys
class AccountSelectionAdapter(context: Context) : ArrayAdapter<AccountEntity>(context, R.layout.item_autocomplete_account) { class AccountSelectionAdapter(
context: Context,
private val animateAvatars: Boolean,
private val animateEmojis: Boolean,
) : ArrayAdapter<AccountEntity>(context, R.layout.item_autocomplete_account) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val binding = if (convertView == null) { val binding = if (convertView == null) {
@ -40,16 +43,14 @@ class AccountSelectionAdapter(context: Context) : ArrayAdapter<AccountEntity>(co
val account = getItem(position) val account = getItem(position)
if (account != null) { if (account != null) {
val pm = PreferenceManager.getDefaultSharedPreferences(binding.avatar.context) val pm = PreferenceManager.getDefaultSharedPreferences(binding.avatar.context)
val animateEmojis = pm.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
binding.username.text = account.fullName binding.username.text = account.fullName
binding.displayName.text = account.displayName.emojify(account.emojis, binding.displayName, animateEmojis) binding.displayName.text = account.displayName.emojify(account.emojis, binding.displayName, animateEmojis)
binding.avatarBadge.visibility = View.GONE // We never want to display the bot badge here binding.avatarBadge.visibility = View.GONE // We never want to display the bot badge here
val avatarRadius = context.resources.getDimensionPixelSize(DR.dimen.avatar_radius_42dp) val avatarRadius = context.resources.getDimensionPixelSize(DR.dimen.avatar_radius_42dp)
val animateAvatar = pm.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false)
loadAvatar(account.profilePictureUrl, binding.avatar, avatarRadius, animateAvatar) loadAvatar(account.profilePictureUrl, binding.avatar, avatarRadius, animateAvatars)
} }
return binding.root return binding.root

View File

@ -241,7 +241,11 @@ abstract class BaseActivity : AppCompatActivity(), MenuProvider {
if (!showActiveAccount) { if (!showActiveAccount) {
accounts.remove(activeAccount) accounts.remove(activeAccount)
} }
val adapter = AccountSelectionAdapter(this) val adapter = AccountSelectionAdapter(
this,
sharedPreferencesRepository.animateAvatars,
sharedPreferencesRepository.animateEmojis,
)
adapter.addAll(accounts) adapter.addAll(accounts)
AlertDialog.Builder(this) AlertDialog.Builder(this)
.setTitle(dialogTitle) .setTitle(dialogTitle)

View File

@ -175,8 +175,8 @@ class StatusDisplayOptionsRepository @Inject constructor(
@VisibleForTesting(otherwise = PRIVATE) @VisibleForTesting(otherwise = PRIVATE)
fun initialStatusDisplayOptions(account: AccountEntity? = null): StatusDisplayOptions { fun initialStatusDisplayOptions(account: AccountEntity? = null): StatusDisplayOptions {
return StatusDisplayOptions( return StatusDisplayOptions(
animateAvatars = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, default.animateAvatars), animateAvatars = sharedPreferencesRepository.animateAvatars,
animateEmojis = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, default.animateEmojis), animateEmojis = sharedPreferencesRepository.animateEmojis,
mediaPreviewEnabled = account?.mediaPreviewEnabled ?: default.mediaPreviewEnabled, mediaPreviewEnabled = account?.mediaPreviewEnabled ?: default.mediaPreviewEnabled,
useAbsoluteTime = sharedPreferencesRepository.getBoolean(PrefKeys.ABSOLUTE_TIME_VIEW, default.useAbsoluteTime), useAbsoluteTime = sharedPreferencesRepository.getBoolean(PrefKeys.ABSOLUTE_TIME_VIEW, default.useAbsoluteTime),
showBotOverlay = sharedPreferencesRepository.getBoolean(PrefKeys.SHOW_BOT_OVERLAY, default.showBotOverlay), showBotOverlay = sharedPreferencesRepository.getBoolean(PrefKeys.SHOW_BOT_OVERLAY, default.showBotOverlay),

View File

@ -49,10 +49,26 @@ class SharedPreferencesRepository @Inject constructor(
val appTheme: AppTheme val appTheme: AppTheme
get() = getEnum(PrefKeys.APP_THEME, AppTheme.AUTO_SYSTEM) get() = getEnum(PrefKeys.APP_THEME, AppTheme.AUTO_SYSTEM)
/** True if avatars should be animated. */
val animateAvatars: Boolean
get() = getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false)
/** True if emojis should be animated. */
val animateEmojis: Boolean
get() = getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
/** Location of downloaded files. */ /** Location of downloaded files. */
val downloadLocation: DownloadLocation val downloadLocation: DownloadLocation
get() = getEnum(PrefKeys.DOWNLOAD_LOCATION, DownloadLocation.DOWNLOADS) get() = getEnum(PrefKeys.DOWNLOAD_LOCATION, DownloadLocation.DOWNLOADS)
/** True if swipe-gesture between tabs should be enabled. */
val enableTabSwipe: Boolean
get() = getBoolean(PrefKeys.ENABLE_SWIPE_FOR_TABS, true)
/** Whether to hide the top toolbar. */
val hideTopToolbar: Boolean
get() = getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false)
/** Screen location of primary navigation UI (tabs, etc). */ /** Screen location of primary navigation UI (tabs, etc). */
val mainNavigationPosition: MainNavigationPosition val mainNavigationPosition: MainNavigationPosition
get() = getEnum(PrefKeys.MAIN_NAV_POSITION, MainNavigationPosition.TOP) get() = getEnum(PrefKeys.MAIN_NAV_POSITION, MainNavigationPosition.TOP)

View File

@ -44,7 +44,6 @@ import app.pachli.core.data.repository.ListsError
import app.pachli.core.designsystem.R as DR import app.pachli.core.designsystem.R as DR
import app.pachli.core.network.model.TimelineAccount import app.pachli.core.network.model.TimelineAccount
import app.pachli.core.network.retrofit.apiresult.ApiError import app.pachli.core.network.retrofit.apiresult.ApiError
import app.pachli.core.preferences.PrefKeys
import app.pachli.core.preferences.SharedPreferencesRepository import app.pachli.core.preferences.SharedPreferencesRepository
import app.pachli.core.ui.BindingHolder import app.pachli.core.ui.BindingHolder
import app.pachli.feature.lists.databinding.FragmentAccountsInListBinding import app.pachli.feature.lists.databinding.FragmentAccountsInListBinding
@ -89,8 +88,8 @@ class AccountsInListFragment : DialogFragment() {
@Inject @Inject
lateinit var sharedPreferencesRepository: SharedPreferencesRepository lateinit var sharedPreferencesRepository: SharedPreferencesRepository
private val animateAvatar by unsafeLazy { sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false) } private val animateAvatar by unsafeLazy { sharedPreferencesRepository.animateAvatars }
private val animateEmojis by unsafeLazy { sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) } private val animateEmojis by unsafeLazy { sharedPreferencesRepository.animateEmojis }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)