diff --git a/app/build.gradle b/app/build.gradle
index d5ddf9b34..806f25c63 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -19,11 +19,11 @@ def getGitSha = {
}
android {
- compileSdkVersion 31
+ compileSdkVersion 33
defaultConfig {
applicationId APP_ID
minSdkVersion 23
- targetSdkVersion 31
+ targetSdkVersion 33
versionCode 94
versionName "19.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -108,16 +108,17 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx3:$coroutinesVersion"
- implementation "androidx.core:core-ktx:1.8.0"
- implementation "androidx.appcompat:appcompat:1.4.2"
- implementation "androidx.fragment:fragment-ktx:1.5.1"
+ implementation "androidx.core:core-ktx:1.9.0"
+ implementation "androidx.appcompat:appcompat:1.5.1"
+ implementation "androidx.activity:activity-ktx:1.6.0"
+ implementation "androidx.fragment:fragment-ktx:1.5.3"
implementation "androidx.browser:browser:1.4.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation "androidx.recyclerview:recyclerview:1.2.1"
- implementation "androidx.exifinterface:exifinterface:1.3.3"
+ implementation "androidx.exifinterface:exifinterface:1.3.4"
implementation "androidx.cardview:cardview:1.0.0"
implementation "androidx.preference:preference-ktx:1.2.0"
- implementation "androidx.sharetarget:sharetarget:1.2.0-rc01"
+ implementation "androidx.sharetarget:sharetarget:1.2.0"
implementation "androidx.emoji2:emoji2:$emoji2_version"
implementation "androidx.emoji2:emoji2-views:$emoji2_version"
implementation "androidx.emoji2:emoji2-views-helper:$emoji2_version"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5600bbe2d..659786e1b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,6 +4,7 @@
package="com.keylesspalace.tusky">
+
diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountListActivity.kt b/app/src/main/java/com/keylesspalace/tusky/AccountListActivity.kt
index ca23f7912..723a35193 100644
--- a/app/src/main/java/com/keylesspalace/tusky/AccountListActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/AccountListActivity.kt
@@ -20,6 +20,7 @@ import android.content.Intent
import android.os.Bundle
import com.keylesspalace.tusky.databinding.ActivityAccountListBinding
import com.keylesspalace.tusky.fragment.AccountListFragment
+import com.keylesspalace.tusky.util.requireSerializableExtra
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import javax.inject.Inject
@@ -44,7 +45,7 @@ class AccountListActivity : BaseActivity(), HasAndroidInjector {
val binding = ActivityAccountListBinding.inflate(layoutInflater)
setContentView(binding.root)
- val type = intent.getSerializableExtra(EXTRA_TYPE) as Type
+ val type: Type = intent.requireSerializableExtra(EXTRA_TYPE)
val id: String? = intent.getStringExtra(EXTRA_ID)
val accountLocked: Boolean = intent.getBooleanExtra(EXTRA_ACCOUNT_LOCKED, false)
diff --git a/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java b/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java
index d34dd6df8..eaf2db8b9 100644
--- a/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java
+++ b/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java
@@ -132,7 +132,7 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
- onBackPressed();
+ getOnBackPressedDispatcher().onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt b/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt
index bc3b2b688..80bcfde33 100644
--- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt
@@ -15,9 +15,11 @@
package com.keylesspalace.tusky
+import android.Manifest
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
+import android.content.pm.PackageManager
import android.content.res.ColorStateList
import android.graphics.Bitmap
import android.graphics.Color
@@ -31,8 +33,11 @@ import android.view.KeyEvent
import android.view.MenuItem
import android.view.View
import android.widget.ImageView
+import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog
import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.view.GravityCompat
import androidx.lifecycle.Lifecycle
@@ -267,6 +272,33 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
}
selectedEmojiPack = preferences.getString(EMOJI_PREFERENCE, "")
+
+ onBackPressedDispatcher.addCallback(
+ this,
+ object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ when {
+ binding.mainDrawerLayout.isOpen -> {
+ binding.mainDrawerLayout.close()
+ }
+ binding.viewPager.currentItem != 0 -> {
+ binding.viewPager.currentItem = 0
+ }
+ else -> {
+ finish()
+ }
+ }
+ }
+ }
+ )
+
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
+ ActivityCompat.requestPermissions(
+ this,
+ arrayOf(Manifest.permission.POST_NOTIFICATIONS),
+ 1
+ )
+ }
}
override fun onResume() {
@@ -292,20 +324,6 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
}
}
- override fun onBackPressed() {
- when {
- binding.mainDrawerLayout.isOpen -> {
- binding.mainDrawerLayout.close()
- }
- binding.viewPager.currentItem != 0 -> {
- binding.viewPager.currentItem = 0
- }
- else -> {
- super.onBackPressed()
- }
- }
- }
-
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
when (keyCode) {
KeyEvent.KEYCODE_MENU -> {
diff --git a/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt b/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt
index 76418e019..0f20a7851 100644
--- a/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt
@@ -20,9 +20,9 @@ import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.FrameLayout
+import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatEditText
-import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
@@ -74,6 +74,12 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
private val hashtagRegex by lazy { Pattern.compile("([\\w_]*[\\p{Alpha}_][\\w_]*)", Pattern.CASE_INSENSITIVE) }
+ private val onFabDismissedCallback = object : OnBackPressedCallback(false) {
+ override fun handleOnBackPressed() {
+ toggleFab(false)
+ }
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -149,6 +155,8 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
binding.maxTabsInfo.text = resources.getQuantityString(R.plurals.max_tab_number_reached, MAX_TAB_COUNT, MAX_TAB_COUNT)
updateAvailableTabs()
+
+ onBackPressedDispatcher.addCallback(onFabDismissedCallback)
}
override fun onTabAdded(tab: TabData) {
@@ -209,6 +217,8 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
binding.actionButton.visible(!expand)
binding.sheet.visible(expand)
binding.scrim.visible(expand)
+
+ onFabDismissedCallback.isEnabled = expand
}
private fun showAddHashtagDialog(tab: TabData? = null, tabPosition: Int = 0) {
@@ -338,14 +348,6 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
tabsChanged = true
}
- override fun onBackPressed() {
- if (binding.actionButton.isVisible) {
- super.onBackPressed()
- } else {
- toggleFab(false)
- }
- }
-
override fun onPause() {
super.onPause()
if (tabsChanged) {
diff --git a/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.kt b/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.kt
index 2a96cb7fe..94bc288a8 100644
--- a/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.kt
@@ -54,6 +54,7 @@ import com.keylesspalace.tusky.fragment.ViewImageFragment
import com.keylesspalace.tusky.pager.ImagePagerAdapter
import com.keylesspalace.tusky.pager.SingleImagePagerAdapter
import com.keylesspalace.tusky.util.getTemporaryMediaFilename
+import com.keylesspalace.tusky.util.parcelableArrayListExtra
import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.viewdata.AttachmentViewData
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
@@ -94,7 +95,7 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
supportPostponeEnterTransition()
// Gather the parameters.
- attachments = intent.getParcelableArrayListExtra(EXTRA_ATTACHMENTS)
+ attachments = intent.parcelableArrayListExtra(EXTRA_ATTACHMENTS)
val initialPosition = intent.getIntExtra(EXTRA_ATTACHMENT_INDEX, 0)
// Adapter is actually of existential type PageAdapter & SharedElementsTransitionListener
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt
index 8106c7ff1..cb2c2130b 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt
@@ -40,6 +40,7 @@ import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.PopupMenu
import android.widget.Toast
+import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.annotation.ColorInt
@@ -92,6 +93,8 @@ import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.highlightSpans
import com.keylesspalace.tusky.util.loadAvatar
import com.keylesspalace.tusky.util.onTextChanged
+import com.keylesspalace.tusky.util.parcelableArrayListExtra
+import com.keylesspalace.tusky.util.parcelableExtra
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible
@@ -237,8 +240,7 @@ class ComposeActivity :
/* If the composer is started up as a reply to another post, override the "starting" state
* based on what the intent from the reply request passes. */
-
- val composeOptions: ComposeOptions? = intent.getParcelableExtra(COMPOSE_OPTIONS_EXTRA)
+ val composeOptions: ComposeOptions? = intent.parcelableExtra(COMPOSE_OPTIONS_EXTRA)
viewModel.setup(composeOptions)
@@ -299,12 +301,12 @@ class ComposeActivity :
if (type.startsWith("image/") || type.startsWith("video/") || type.startsWith("audio/")) {
when (intent.action) {
Intent.ACTION_SEND -> {
- intent.getParcelableExtra(Intent.EXTRA_STREAM)?.let { uri ->
+ intent.parcelableExtra(Intent.EXTRA_STREAM)?.let { uri ->
pickMedia(uri)
}
}
Intent.ACTION_SEND_MULTIPLE -> {
- intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)?.forEach { uri ->
+ intent.parcelableArrayListExtra(Intent.EXTRA_STREAM)?.forEach { uri ->
pickMedia(uri)
}
}
@@ -510,6 +512,27 @@ class ComposeActivity :
binding.actionPhotoTake.setOnClickListener { initiateCameraApp() }
binding.actionPhotoPick.setOnClickListener { onMediaPick() }
binding.addPollTextActionTextView.setOnClickListener { openPollDialog() }
+
+ onBackPressedDispatcher.addCallback(
+ this,
+ object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ if (composeOptionsBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
+ addMediaBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
+ emojiBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
+ scheduleBehavior.state == BottomSheetBehavior.STATE_EXPANDED
+ ) {
+ composeOptionsBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ addMediaBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ emojiBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ scheduleBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ return
+ }
+
+ handleCloseButton()
+ }
+ }
+ )
}
private fun setupLanguageSpinner(initialLanguage: String?) {
@@ -1069,23 +1092,6 @@ class ComposeActivity :
return super.onOptionsItemSelected(item)
}
- override fun onBackPressed() {
- // Acting like a teen: deliberately ignoring parent.
- if (composeOptionsBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
- addMediaBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
- emojiBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
- scheduleBehavior.state == BottomSheetBehavior.STATE_EXPANDED
- ) {
- composeOptionsBehavior.state = BottomSheetBehavior.STATE_HIDDEN
- addMediaBehavior.state = BottomSheetBehavior.STATE_HIDDEN
- emojiBehavior.state = BottomSheetBehavior.STATE_HIDDEN
- scheduleBehavior.state = BottomSheetBehavior.STATE_HIDDEN
- return
- }
-
- handleCloseButton()
- }
-
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
Log.d(TAG, event.toString())
if (event.action == KeyEvent.ACTION_DOWN) {
@@ -1098,7 +1104,7 @@ class ComposeActivity :
}
if (keyCode == KeyEvent.KEYCODE_BACK) {
- onBackPressed()
+ onBackPressedDispatcher.onBackPressed()
return true
}
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/compose/dialog/CaptionDialog.kt b/app/src/main/java/com/keylesspalace/tusky/components/compose/dialog/CaptionDialog.kt
index 614b87eed..54fb645d6 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/compose/dialog/CaptionDialog.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/compose/dialog/CaptionDialog.kt
@@ -38,6 +38,7 @@ import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.github.chrisbanes.photoview.PhotoView
import com.keylesspalace.tusky.R
+import com.keylesspalace.tusky.util.parcelable
// https://github.com/tootsuite/mastodon/blob/c6904c0d3766a2ea8a81ab025c127169ecb51373/app/models/media_attachment.rb#L32
private const val MEDIA_DESCRIPTION_CHARACTER_LIMIT = 1500
@@ -93,8 +94,7 @@ class CaptionDialog : DialogFragment() {
val window = dialog.window
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
- val previewUri =
- arguments?.getParcelable(PREVIEW_URI_ARG) ?: error("Preview Uri is null")
+ val previewUri: Uri = arguments?.parcelable(PREVIEW_URI_ARG) ?: error("Preview Uri is null")
// Load the image and manually set it into the ImageView because it doesn't have a fixed size.
Glide.with(this)
.load(previewUri)
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/login/LoginWebViewActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/login/LoginWebViewActivity.kt
index 07bd56529..b38e86f12 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/login/LoginWebViewActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/login/LoginWebViewActivity.kt
@@ -23,6 +23,7 @@ import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.ActivityLoginWebviewBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.util.hide
+import com.keylesspalace.tusky.util.parcelableExtra
import com.keylesspalace.tusky.util.viewBinding
import kotlinx.parcelize.Parcelize
@@ -39,7 +40,7 @@ class OauthLogin : ActivityResultContract() {
return if (resultCode == Activity.RESULT_CANCELED) {
LoginResult.Cancel
} else {
- intent!!.getParcelableExtra(RESULT_EXTRA)!!
+ intent!!.parcelableExtra(RESULT_EXTRA)!!
}
}
@@ -48,7 +49,7 @@ class OauthLogin : ActivityResultContract() {
private const val DATA_EXTRA = "data"
fun parseData(intent: Intent): LoginData {
- return intent.getParcelableExtra(DATA_EXTRA)!!
+ return intent.parcelableExtra(DATA_EXTRA)!!
}
fun makeResultIntent(result: LoginResult): Intent {
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesActivity.kt
index 8ae4e0560..878766fa9 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesActivity.kt
@@ -20,6 +20,7 @@ import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
+import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import androidx.preference.PreferenceManager
@@ -47,7 +48,17 @@ class PreferencesActivity :
@Inject
lateinit var androidInjector: DispatchingAndroidInjector
- private var restartActivitiesOnExit: Boolean = false
+ private val restartActivitiesOnBackPressedCallback = object : OnBackPressedCallback(false) {
+ override fun handleOnBackPressed() {
+ /* Switching themes won't actually change the theme of activities on the back stack.
+ * Either the back stack activities need to all be recreated, or do the easier thing, which
+ * is hijack the back button press and use it to launch a new MainActivity and clear the
+ * back stack. */
+ val intent = Intent(this@PreferencesActivity, MainActivity::class.java)
+ intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ startActivityWithSlideInAnimation(intent)
+ }
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -92,7 +103,8 @@ class PreferencesActivity :
replace(R.id.fragment_container, fragment, fragmentTag)
}
- restartActivitiesOnExit = intent.getBooleanExtra("restart", false)
+ onBackPressedDispatcher.addCallback(this, restartActivitiesOnBackPressedCallback)
+ restartActivitiesOnBackPressedCallback.isEnabled = savedInstanceState?.getBoolean(EXTRA_RESTART_ON_BACK, false) ?: false
}
override fun onResume() {
@@ -106,11 +118,11 @@ class PreferencesActivity :
}
private fun saveInstanceState(outState: Bundle) {
- outState.putBoolean("restart", restartActivitiesOnExit)
+ outState.putBoolean(EXTRA_RESTART_ON_BACK, restartActivitiesOnBackPressedCallback.isEnabled)
}
override fun onSaveInstanceState(outState: Bundle) {
- outState.putBoolean("restart", restartActivitiesOnExit)
+ outState.putBoolean(EXTRA_RESTART_ON_BACK, restartActivitiesOnBackPressedCallback.isEnabled)
super.onSaveInstanceState(outState)
}
@@ -121,16 +133,16 @@ class PreferencesActivity :
Log.d("activeTheme", theme)
ThemeUtils.setAppNightMode(theme)
- restartActivitiesOnExit = true
+ restartActivitiesOnBackPressedCallback.isEnabled = true
this.restartCurrentActivity()
}
"statusTextSize", "absoluteTimeView", "showBotOverlay", "animateGifAvatars", "useBlurhash",
"showSelfUsername", "showCardsInTimelines", "confirmReblogs", "confirmFavourites",
"enableSwipeForTabs", "mainNavPosition", PrefKeys.HIDE_TOP_TOOLBAR -> {
- restartActivitiesOnExit = true
+ restartActivitiesOnBackPressedCallback.isEnabled = true
}
"language" -> {
- restartActivitiesOnExit = true
+ restartActivitiesOnBackPressedCallback.isEnabled = true
this.restartCurrentActivity()
}
}
@@ -148,20 +160,6 @@ class PreferencesActivity :
overridePendingTransition(R.anim.fade_in, R.anim.fade_out)
}
- override fun onBackPressed() {
- /* Switching themes won't actually change the theme of activities on the back stack.
- * Either the back stack activities need to all be recreated, or do the easier thing, which
- * is hijack the back button press and use it to launch a new MainActivity and clear the
- * back stack. */
- if (restartActivitiesOnExit) {
- val intent = Intent(this, MainActivity::class.java)
- intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
- startActivityWithSlideInAnimation(intent)
- } else {
- super.onBackPressed()
- }
- }
-
override fun androidInjector() = androidInjector
companion object {
@@ -172,6 +170,7 @@ class PreferencesActivity :
const val TAB_FILTER_PREFERENCES = 3
const val PROXY_PREFERENCES = 4
private const val EXTRA_PREFERENCE_TYPE = "EXTRA_PREFERENCE_TYPE"
+ private const val EXTRA_RESTART_ON_BACK = "restart"
@JvmStatic
fun newIntent(context: Context, preferenceType: Int): Intent {
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt
index a799bee3c..b15b9e0f3 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt
@@ -383,7 +383,7 @@ class SearchStatusesFragment : SearchFragment(), Status
} != null
}
- private fun showOpenAsDialog(statusUrl: String, dialogTitle: CharSequence) {
+ private fun showOpenAsDialog(statusUrl: String, dialogTitle: CharSequence?) {
bottomSheetActivity?.showAccountChooserDialog(
dialogTitle, false,
object : AccountSelectionListener {
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt
index cee6f0462..9fe91b921 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt
@@ -102,7 +102,7 @@ class ViewThreadFragment : SFragment(), OnRefreshListener, StatusActionListener,
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.toolbar.setNavigationOnClickListener {
- activity?.onBackPressed()
+ activity?.onBackPressedDispatcher?.onBackPressed()
}
binding.toolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt
index 465b9f216..8cc855ce6 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt
@@ -49,6 +49,7 @@ import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.HttpHeaderLink
import com.keylesspalace.tusky.util.hide
+import com.keylesspalace.tusky.util.requireSerializable
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.view.EndlessOnScrollListener
@@ -78,8 +79,8 @@ class AccountListFragment : Fragment(R.layout.fragment_account_list), AccountAct
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- type = arguments?.getSerializable(ARG_TYPE) as Type
- id = arguments?.getString(ARG_ID)
+ type = requireArguments().requireSerializable(ARG_TYPE)
+ id = requireArguments().getString(ARG_ID)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -100,7 +101,7 @@ class AccountListFragment : Fragment(R.layout.fragment_account_list), AccountAct
Type.BLOCKS -> BlocksAdapter(this, animateAvatar, animateEmojis)
Type.MUTES -> MutesAdapter(this, animateAvatar, animateEmojis)
Type.FOLLOW_REQUESTS -> {
- val headerAdapter = FollowRequestsHeaderAdapter(accountManager.activeAccount!!.domain, arguments?.get(ARG_ACCOUNT_LOCKED) == true)
+ val headerAdapter = FollowRequestsHeaderAdapter(accountManager.activeAccount!!.domain, arguments?.getBoolean(ARG_ACCOUNT_LOCKED) == true)
val followRequestsAdapter = FollowRequestsAdapter(this, animateAvatar, animateEmojis)
binding.recyclerView.adapter = ConcatAdapter(headerAdapter, followRequestsAdapter)
followRequestsAdapter
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewImageFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewImageFragment.kt
index 0362da9c7..53e174bfc 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewImageFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewImageFragment.kt
@@ -36,6 +36,7 @@ import com.keylesspalace.tusky.ViewMediaActivity
import com.keylesspalace.tusky.databinding.FragmentViewImageBinding
import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.util.hide
+import com.keylesspalace.tusky.util.parcelable
import com.keylesspalace.tusky.util.visible
import io.reactivex.rxjava3.subjects.BehaviorSubject
import kotlin.math.abs
@@ -92,7 +93,7 @@ class ViewImageFragment : ViewMediaFragment() {
super.onViewCreated(view, savedInstanceState)
val arguments = this.requireArguments()
- val attachment = arguments.getParcelable(ARG_ATTACHMENT)
+ val attachment: Attachment? = arguments.parcelable(ARG_ATTACHMENT)
this.shouldStartTransition = arguments.getBoolean(ARG_START_POSTPONED_TRANSITION)
val url: String?
var description: String? = null
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewVideoFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewVideoFragment.kt
index 214741a8e..6ae334988 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewVideoFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewVideoFragment.kt
@@ -31,6 +31,7 @@ import com.keylesspalace.tusky.ViewMediaActivity
import com.keylesspalace.tusky.databinding.FragmentViewVideoBinding
import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.util.hide
+import com.keylesspalace.tusky.util.parcelable
import com.keylesspalace.tusky.util.visible
import com.keylesspalace.tusky.view.ExposedPlayPauseVideoView
@@ -170,7 +171,7 @@ class ViewVideoFragment : ViewMediaFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- val attachment = arguments?.getParcelable(ARG_ATTACHMENT)
+ val attachment: Attachment? = requireArguments().parcelable(ARG_ATTACHMENT)
if (attachment == null) {
throw IllegalArgumentException("attachment has to be set")
diff --git a/app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt b/app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt
index c1f5a2cca..6ef027f2a 100644
--- a/app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt
@@ -29,6 +29,7 @@ import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.service.SendStatusService
import com.keylesspalace.tusky.service.StatusToSend
import com.keylesspalace.tusky.util.randomAlphanumericString
+import com.keylesspalace.tusky.util.requireSerializableExtra
import dagger.android.AndroidInjection
import javax.inject.Inject
@@ -48,7 +49,7 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
val senderIdentifier = intent.getStringExtra(NotificationHelper.KEY_SENDER_ACCOUNT_IDENTIFIER)
val senderFullName = intent.getStringExtra(NotificationHelper.KEY_SENDER_ACCOUNT_FULL_NAME)
val citedStatusId = intent.getStringExtra(NotificationHelper.KEY_CITED_STATUS_ID)
- val visibility = intent.getSerializableExtra(NotificationHelper.KEY_VISIBILITY) as Status.Visibility
+ val visibility: Status.Visibility = intent.requireSerializableExtra(NotificationHelper.KEY_VISIBILITY)!!
val spoiler = intent.getStringExtra(NotificationHelper.KEY_SPOILER) ?: ""
val mentions = intent.getStringArrayExtra(NotificationHelper.KEY_MENTIONS) ?: emptyArray()
diff --git a/app/src/main/java/com/keylesspalace/tusky/service/SendStatusService.kt b/app/src/main/java/com/keylesspalace/tusky/service/SendStatusService.kt
index 3cdd27c33..d47105525 100644
--- a/app/src/main/java/com/keylesspalace/tusky/service/SendStatusService.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/service/SendStatusService.kt
@@ -31,6 +31,7 @@ import com.keylesspalace.tusky.entity.NewPoll
import com.keylesspalace.tusky.entity.NewStatus
import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.network.MastodonApi
+import com.keylesspalace.tusky.util.parcelableExtra
import dagger.android.AndroidInjection
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -72,7 +73,7 @@ class SendStatusService : Service(), Injectable {
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
if (intent.hasExtra(KEY_STATUS)) {
- val statusToSend = intent.getParcelableExtra(KEY_STATUS)
+ val statusToSend: StatusToSend = intent.parcelableExtra(KEY_STATUS)
?: throw IllegalStateException("SendStatusService started without $KEY_STATUS extra")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/CompatExtensions.kt b/app/src/main/java/com/keylesspalace/tusky/util/CompatExtensions.kt
new file mode 100644
index 000000000..55d2f44b4
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/util/CompatExtensions.kt
@@ -0,0 +1,49 @@
+@file:Suppress("DEPRECATION")
+
+package com.keylesspalace.tusky.util
+
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import android.os.Parcelable
+import java.io.Serializable
+
+inline fun Intent.requireSerializableExtra(name: String?): T {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getSerializableExtra(name, T::class.java)!!
+ } else {
+ getSerializableExtra(name) as T
+ }
+}
+
+inline fun Intent.parcelableArrayListExtra(name: String?): ArrayList? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getParcelableArrayListExtra(name, T::class.java)
+ } else {
+ getParcelableArrayListExtra(name)
+ }
+}
+
+inline fun Bundle.parcelable(name: String?): T? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getParcelable(name, T::class.java)
+ } else {
+ getParcelable(name)
+ }
+}
+
+inline fun Intent.parcelableExtra(name: String?): T? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getParcelableExtra(name, T::class.java)
+ } else {
+ getParcelableExtra(name) as T?
+ }
+}
+
+inline fun Bundle.requireSerializable(name: String?): T {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getSerializable(name, T::class.java)!!
+ } else {
+ getSerializable(name) as T
+ }
+}
diff --git a/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt b/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt
index 6542b603d..bfc4282be 100644
--- a/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt
+++ b/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt
@@ -464,7 +464,7 @@ class ComposeActivityTest {
}
private fun clickBack() {
- activity.onBackPressed()
+ activity.onBackPressedDispatcher.onBackPressed()
}
private fun insertSomeTextInContent(text: String? = null) {