From 05c7e7b8066506830f6c0bf9112e7beab90ef00c Mon Sep 17 00:00:00 2001 From: Christophe Beyls Date: Sun, 5 May 2024 08:34:41 +0200 Subject: [PATCH] Fix various lint warnings (#4409) - Remove empty file `ExampleInstrumentedTest.java`. - Replace deprecated `MigrationTestHelper` constructor call. - Add reified inline extension methods for `Bundle` and `Intent` to retrieve `Parcelable` and `Serializable` objects by calling the core `BundleCompat` and `IntentCompat` methods, to allow shorter syntax and removing the need to pass the class explicitly. - Replace deprecated `drawable.setColorFilter()` with simpler `drawable.setTint()` (uses blend mode `SRC_IN` by default, has the same effect as `SRC_ATOP` when the source is a color). - Rename shadowed variables (mostly caught exceptions). - Remove unnecessary `.orEmpty()` on non-null fields. - Replace `.size() == 0` with `.isEmpty()`. - Prevent `NullPointerException` when `account.getDisplayName()` is `null` in `StatusBaseViewHolder.setDisplayName()`. - Declare `customEmojis` argument as non-null in `StatusBaseViewHolder.setDisplayName()` because it calls `CustomEmojiHelper.emojify()` which now requires it to be non-null. - Prevent `NullPointerException` when no matching filter is found in `StatusBaseViewHolder.setupFilterPlaceholder()`. - Remove deprecated call to `setTargetFragment()` (target fragment is not used anyway). - Remove deprecated call to `isUserVisibleHint()` and test if the view has been destroyed instead. - Remove some unused imports. - Remove unnecessary casts. - Rename arguments to supertype names when a warning is shown. - Prevent a potential memory leak by clearing the `toolbarVisibilityDisposable` reference in `onDestroyView()`. --- .../tusky/ExampleInstrumentedTest.java | 0 .../com/keylesspalace/tusky/MigrationsTest.kt | 4 +- .../com/keylesspalace/tusky/MainActivity.kt | 9 ++-- .../keylesspalace/tusky/StatusListActivity.kt | 8 ++-- .../keylesspalace/tusky/ViewMediaActivity.kt | 8 +--- .../tusky/adapter/StatusBaseViewHolder.java | 15 +++++-- .../adapter/StatusDetailedViewHolder.java | 3 -- .../accountlist/AccountListActivity.kt | 3 +- .../accountlist/AccountListFragment.kt | 11 ++--- .../components/compose/ComposeActivity.kt | 45 +++++++------------ .../compose/dialog/CaptionDialog.kt | 4 +- .../conversation/ConversationViewHolder.java | 8 +++- .../components/filters/EditFilterActivity.kt | 4 +- .../components/login/LoginWebViewActivity.kt | 9 ++-- .../components/login/LoginWebViewViewModel.kt | 4 +- .../StatusNotificationViewHolder.kt | 3 +- .../preference/PreferencesActivity.kt | 1 - .../keylesspalace/tusky/db/AccountManager.kt | 2 +- .../tusky/fragment/ViewImageFragment.kt | 12 ++--- .../tusky/fragment/ViewMediaFragment.kt | 1 + .../tusky/fragment/ViewVideoFragment.kt | 5 ++- .../receiver/SendStatusBroadcastReceiver.kt | 6 +-- .../tusky/service/SendStatusService.kt | 12 ++--- .../tusky/util/BundleExtensions.kt | 23 ++++++++++ .../tusky/util/PickMediaFiles.kt | 4 +- .../keylesspalace/tusky/util/ThemeUtils.kt | 6 +-- .../tusky/view/MediaPreviewLayout.kt | 4 +- 27 files changed, 108 insertions(+), 106 deletions(-) delete mode 100644 app/src/androidTest/java/com/keylesspalace/tusky/ExampleInstrumentedTest.java create mode 100644 app/src/main/java/com/keylesspalace/tusky/util/BundleExtensions.kt diff --git a/app/src/androidTest/java/com/keylesspalace/tusky/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/keylesspalace/tusky/ExampleInstrumentedTest.java deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/src/androidTest/java/com/keylesspalace/tusky/MigrationsTest.kt b/app/src/androidTest/java/com/keylesspalace/tusky/MigrationsTest.kt index ccfc4ca62..313ab8e20 100644 --- a/app/src/androidTest/java/com/keylesspalace/tusky/MigrationsTest.kt +++ b/app/src/androidTest/java/com/keylesspalace/tusky/MigrationsTest.kt @@ -1,7 +1,6 @@ package com.keylesspalace.tusky import androidx.room.testing.MigrationTestHelper -import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import com.keylesspalace.tusky.db.AppDatabase @@ -19,8 +18,7 @@ class MigrationsTest { @Rule var helper: MigrationTestHelper = MigrationTestHelper( InstrumentationRegistry.getInstrumentation(), - AppDatabase::class.java.canonicalName!!, - FrameworkSQLiteOpenHelperFactory() + AppDatabase::class.java ) @Test diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt b/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt index 81789396e..c99c54d3c 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt @@ -45,7 +45,6 @@ import androidx.appcompat.content.res.AppCompatResources import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat -import androidx.core.content.IntentCompat import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.view.GravityCompat import androidx.core.view.MenuProvider @@ -107,6 +106,7 @@ import com.keylesspalace.tusky.util.ShareShortcutHelper import com.keylesspalace.tusky.util.deleteStaleCachedMedia import com.keylesspalace.tusky.util.emojify import com.keylesspalace.tusky.util.getDimension +import com.keylesspalace.tusky.util.getParcelableExtraCompat import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.reduceSwipeSensitivity import com.keylesspalace.tusky.util.show @@ -531,11 +531,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje } private fun forwardToComposeActivity(intent: Intent) { - val composeOptions = IntentCompat.getParcelableExtra( - intent, - COMPOSE_OPTIONS, - ComposeActivity.ComposeOptions::class.java - ) + val composeOptions = + intent.getParcelableExtraCompat(COMPOSE_OPTIONS) val composeIntent = if (composeOptions != null) { ComposeActivity.startIntent(this, composeOptions) diff --git a/app/src/main/java/com/keylesspalace/tusky/StatusListActivity.kt b/app/src/main/java/com/keylesspalace/tusky/StatusListActivity.kt index c844f2256..a06c47d95 100644 --- a/app/src/main/java/com/keylesspalace/tusky/StatusListActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/StatusListActivity.kt @@ -219,8 +219,8 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector { } updateTagMuteState(mutedFilterV1 != null) }, - { throwable -> - Log.e(TAG, "Error getting filters: $throwable") + { throwable2 -> + Log.e(TAG, "Error getting filters: $throwable2") } ) } else { @@ -292,13 +292,13 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector { eventHub.dispatch(PreferenceChangedEvent(filter.context[0])) filterCreateSuccess = true }, - { throwable -> + { throwable2 -> Snackbar.make( binding.root, getString(R.string.error_muting_hashtag_format, tag), Snackbar.LENGTH_SHORT ).show() - Log.e(TAG, "Failed to mute #$tag", throwable) + Log.e(TAG, "Failed to mute #$tag", throwable2) } ) } else { diff --git a/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.kt b/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.kt index 7e9340580..a8d4e6061 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.kt @@ -40,7 +40,6 @@ import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.core.app.ShareCompat import androidx.core.content.FileProvider -import androidx.core.content.IntentCompat import androidx.fragment.app.FragmentActivity import androidx.lifecycle.lifecycleScope import androidx.viewpager2.adapter.FragmentStateAdapter @@ -54,6 +53,7 @@ import com.keylesspalace.tusky.fragment.ViewImageFragment import com.keylesspalace.tusky.fragment.ViewVideoFragment import com.keylesspalace.tusky.pager.ImagePagerAdapter import com.keylesspalace.tusky.pager.SingleImagePagerAdapter +import com.keylesspalace.tusky.util.getParcelableArrayListExtraCompat import com.keylesspalace.tusky.util.getTemporaryMediaFilename import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation import com.keylesspalace.tusky.util.submitAsync @@ -118,11 +118,7 @@ class ViewMediaActivity : supportPostponeEnterTransition() // Gather the parameters. - attachments = IntentCompat.getParcelableArrayListExtra( - intent, - EXTRA_ATTACHMENTS, - AttachmentViewData::class.java - ) + attachments = intent.getParcelableArrayListExtraCompat(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/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index 0b64acebc..a110b2c54 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -200,7 +200,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { TouchDelegateHelper.expandTouchSizeToFillRow((ViewGroup) itemView, CollectionsKt.listOfNotNull(replyButton, reblogButton, favouriteButton, bookmarkButton, moreButton)); } - protected void setDisplayName(@NonNull String name, @Nullable List customEmojis, @NonNull StatusDisplayOptions statusDisplayOptions) { + protected void setDisplayName(@NonNull String name, @NonNull List customEmojis, @NonNull StatusDisplayOptions statusDisplayOptions) { CharSequence emojifiedName = CustomEmojiHelper.emojify( name, customEmojis, displayName, statusDisplayOptions.animateEmojis() ); @@ -790,7 +790,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { if (statusDisplayOptions.mediaPreviewEnabled() && hasPreviewableAttachment(attachments)) { setMediaPreviews(attachments, sensitive, listener, status.isShowingContent(), statusDisplayOptions.useBlurhash()); - if (attachments.size() == 0) { + if (attachments.isEmpty()) { hideSensitiveMediaWarning(); } // Hide the unused label. @@ -877,7 +877,14 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { } } - filteredPlaceholderLabel.setText(itemView.getContext().getString(R.string.status_filter_placeholder_label_format, matchedFilter.getTitle())); + final String matchedFilterTitle; + if (matchedFilter == null) { + matchedFilterTitle = ""; + } else { + matchedFilterTitle = matchedFilter.getTitle(); + } + + filteredPlaceholderLabel.setText(itemView.getContext().getString(R.string.status_filter_placeholder_label_format, matchedFilterTitle)); filteredPlaceholderShowButton.setOnClickListener(view -> listener.clearWarningAction(getBindingAdapterPosition())); } @@ -1154,7 +1161,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { final Card card = actionable.getCard(); if (cardViewMode != CardViewMode.NONE && - actionable.getAttachments().size() == 0 && + actionable.getAttachments().isEmpty() && actionable.getPoll() == null && card != null && !TextUtils.isEmpty(card.getUrl()) && diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java index bb5a78e4e..d8921c28e 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java @@ -9,13 +9,11 @@ import android.text.method.LinkMovementMethod; import android.text.style.DynamicDrawableSpan; import android.text.style.ImageSpan; import android.view.View; -import android.widget.Button; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.content.res.AppCompatResources; -import androidx.appcompat.widget.ViewUtils; import androidx.recyclerview.widget.RecyclerView; import com.keylesspalace.tusky.R; @@ -25,7 +23,6 @@ import com.keylesspalace.tusky.util.CardViewMode; import com.keylesspalace.tusky.util.LinkHelper; import com.keylesspalace.tusky.util.NoUnderlineURLSpan; import com.keylesspalace.tusky.util.StatusDisplayOptions; -import com.keylesspalace.tusky.util.ViewExtensionsKt; import com.keylesspalace.tusky.viewdata.StatusViewData; import java.text.DateFormat; diff --git a/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListActivity.kt index 2419dc915..70888bbf3 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListActivity.kt @@ -22,6 +22,7 @@ import androidx.fragment.app.commit import com.keylesspalace.tusky.BottomSheetActivity import com.keylesspalace.tusky.R import com.keylesspalace.tusky.databinding.ActivityAccountListBinding +import com.keylesspalace.tusky.util.getSerializableExtraCompat import dagger.android.DispatchingAndroidInjector import dagger.android.HasAndroidInjector import javax.inject.Inject @@ -46,7 +47,7 @@ class AccountListActivity : BottomSheetActivity(), HasAndroidInjector { val binding = ActivityAccountListBinding.inflate(layoutInflater) setContentView(binding.root) - val type = intent.getSerializableExtra(EXTRA_TYPE) as Type + val type = intent.getSerializableExtraCompat(EXTRA_TYPE)!! val id: String? = intent.getStringExtra(EXTRA_ID) setSupportActionBar(binding.includedToolbar.toolbar) diff --git a/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListFragment.kt index 729933114..11550d115 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListFragment.kt @@ -50,6 +50,7 @@ import com.keylesspalace.tusky.interfaces.LinkListener import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.util.HttpHeaderLink +import com.keylesspalace.tusky.util.getSerializableCompat import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation @@ -83,7 +84,7 @@ class AccountListFragment : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - type = requireArguments().getSerializable(ARG_TYPE) as Type + type = requireArguments().getSerializableCompat(ARG_TYPE)!! id = requireArguments().getString(ARG_ID) } @@ -244,12 +245,12 @@ class AccountListFragment : Log.e(TAG, "Failed to $verb account accountId $accountId") } - override fun onRespondToFollowRequest(accept: Boolean, accountId: String, position: Int) { + override fun onRespondToFollowRequest(accept: Boolean, id: String, position: Int) { viewLifecycleOwner.lifecycleScope.launch { if (accept) { - api.authorizeFollowRequest(accountId) + api.authorizeFollowRequest(id) } else { - api.rejectFollowRequest(accountId) + api.rejectFollowRequest(id) }.fold( onSuccess = { onRespondToFollowRequestSuccess(position) @@ -260,7 +261,7 @@ class AccountListFragment : } else { "reject" } - Log.e(TAG, "Failed to $verb account id $accountId.", throwable) + Log.e(TAG, "Failed to $verb account id $id.", throwable) } ) } 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 f0631fce0..4c064dd05 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 @@ -22,8 +22,6 @@ import android.content.Context import android.content.Intent import android.content.SharedPreferences import android.graphics.Bitmap -import android.graphics.PorterDuff -import android.graphics.PorterDuffColorFilter import android.icu.text.BreakIterator import android.net.Uri import android.os.Build @@ -50,9 +48,7 @@ import androidx.annotation.StringRes import androidx.annotation.VisibleForTesting import androidx.appcompat.app.AlertDialog import androidx.core.content.FileProvider -import androidx.core.content.IntentCompat import androidx.core.content.res.use -import androidx.core.os.BundleCompat import androidx.core.view.ContentInfoCompat import androidx.core.view.OnReceiveContentListener import androidx.core.view.isGone @@ -100,6 +96,10 @@ import com.keylesspalace.tusky.util.PickMediaFiles import com.keylesspalace.tusky.util.getInitialLanguages import com.keylesspalace.tusky.util.getLocaleList import com.keylesspalace.tusky.util.getMediaSize +import com.keylesspalace.tusky.util.getParcelableArrayListExtraCompat +import com.keylesspalace.tusky.util.getParcelableCompat +import com.keylesspalace.tusky.util.getParcelableExtraCompat +import com.keylesspalace.tusky.util.getSerializableCompat import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.highlightSpans import com.keylesspalace.tusky.util.loadAvatar @@ -287,11 +287,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? = IntentCompat.getParcelableExtra( - intent, - COMPOSE_OPTIONS_EXTRA, - ComposeOptions::class.java - ) + val composeOptions: ComposeOptions? = intent.getParcelableExtraCompat(COMPOSE_OPTIONS_EXTRA) viewModel.setup(composeOptions) setupButtons() @@ -325,11 +321,9 @@ class ComposeActivity : /* Finally, overwrite state with data from saved instance state. */ savedInstanceState?.let { - photoUploadUri = BundleCompat.getParcelable(it, PHOTO_UPLOAD_URI_KEY, Uri::class.java) + photoUploadUri = it.getParcelableCompat(PHOTO_UPLOAD_URI_KEY) - (it.getSerializable(VISIBILITY_KEY) as Status.Visibility).apply { - setStatusVisibility(this) - } + setStatusVisibility(it.getSerializableCompat(VISIBILITY_KEY)!!) it.getBoolean(CONTENT_WARNING_VISIBLE_KEY).apply { viewModel.contentWarningChanged(this) @@ -354,22 +348,15 @@ class ComposeActivity : if (type.startsWith("image/") || type.startsWith("video/") || type.startsWith("audio/")) { when (intent.action) { Intent.ACTION_SEND -> { - IntentCompat.getParcelableExtra( - intent, - Intent.EXTRA_STREAM, - Uri::class.java - )?.let { uri -> + intent.getParcelableExtraCompat(Intent.EXTRA_STREAM)?.let { uri -> pickMedia(uri) } } Intent.ACTION_SEND_MULTIPLE -> { - IntentCompat.getParcelableArrayListExtra( - intent, - Intent.EXTRA_STREAM, - Uri::class.java - )?.forEach { uri -> - pickMedia(uri) - } + intent.getParcelableArrayListExtraCompat(Intent.EXTRA_STREAM) + ?.forEach { uri -> + pickMedia(uri) + } } } } @@ -854,7 +841,7 @@ class ComposeActivity : ) } } - binding.composeHideMediaButton.drawable.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN) + binding.composeHideMediaButton.drawable.setTint(color) var oneMediaWithoutDescription = false for (media in viewModel.media.value) { @@ -880,7 +867,7 @@ class ComposeActivity : } else { getColor(R.color.tusky_blue) } - binding.composeScheduleButton.drawable.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN) + binding.composeScheduleButton.drawable.setTint(color) } } @@ -1182,7 +1169,7 @@ class ComposeActivity : } ) binding.addPollTextActionTextView.setTextColor(textColor) - binding.addPollTextActionTextView.compoundDrawablesRelative[0].colorFilter = PorterDuffColorFilter(textColor, PorterDuff.Mode.SRC_IN) + binding.addPollTextActionTextView.compoundDrawablesRelative[0].setTint(textColor) } private fun editImageInQueue(item: QueuedMedia) { @@ -1273,7 +1260,7 @@ class ComposeActivity : android.R.attr.textColorTertiary ) } - binding.composeContentWarningButton.drawable.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN) + binding.composeContentWarningButton.drawable.setTint(color) } override fun onOptionsItemSelected(item: MenuItem): Boolean { 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 154c83ed8..d78009a49 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 @@ -25,7 +25,6 @@ import android.view.View import android.view.ViewGroup import android.view.WindowManager import android.widget.LinearLayout -import androidx.core.os.BundleCompat import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import com.bumptech.glide.Glide @@ -34,6 +33,7 @@ import com.bumptech.glide.request.target.CustomTarget import com.bumptech.glide.request.transition.Transition import com.keylesspalace.tusky.R import com.keylesspalace.tusky.databinding.DialogImageDescriptionBinding +import com.keylesspalace.tusky.util.getParcelableCompat import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.viewBinding @@ -82,7 +82,7 @@ class CaptionDialog : DialogFragment() { isCancelable = true - val previewUri = BundleCompat.getParcelable(requireArguments(), PREVIEW_URI_ARG, Uri::class.java) ?: error("Preview Uri is null") + val previewUri = arguments?.getParcelableCompat(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) diff --git a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java index 3c3103e0d..f73fe854a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java @@ -80,7 +80,11 @@ public class ConversationViewHolder extends StatusBaseViewHolder { setupCollapsedState(statusViewData.isCollapsible(), statusViewData.isCollapsed(), statusViewData.isExpanded(), status.getSpoilerText(), listener); - setDisplayName(account.getDisplayName(), account.getEmojis(), statusDisplayOptions); + String displayName = account.getDisplayName(); + if (displayName == null) { + displayName = ""; + } + setDisplayName(displayName, account.getEmojis(), statusDisplayOptions); setUsername(account.getUsername()); setMetaData(statusViewData, statusDisplayOptions, listener); setIsReply(status.getInReplyToId() != null); @@ -92,7 +96,7 @@ public class ConversationViewHolder extends StatusBaseViewHolder { setMediaPreviews(attachments, sensitive, listener, statusViewData.isShowingContent(), statusDisplayOptions.useBlurhash()); - if (attachments.size() == 0) { + if (attachments.isEmpty()) { hideSensitiveMediaWarning(); } // Hide the unused label. diff --git a/app/src/main/java/com/keylesspalace/tusky/components/filters/EditFilterActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/filters/EditFilterActivity.kt index 709e2c5f7..a10b709f6 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/filters/EditFilterActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/filters/EditFilterActivity.kt @@ -8,7 +8,6 @@ import android.widget.AdapterView import android.widget.ArrayAdapter import androidx.activity.viewModels import androidx.appcompat.app.AlertDialog -import androidx.core.content.IntentCompat import androidx.core.view.size import androidx.core.widget.doAfterTextChanged import androidx.lifecycle.lifecycleScope @@ -26,6 +25,7 @@ import com.keylesspalace.tusky.di.ViewModelFactory import com.keylesspalace.tusky.entity.Filter import com.keylesspalace.tusky.entity.FilterKeyword import com.keylesspalace.tusky.network.MastodonApi +import com.keylesspalace.tusky.util.getParcelableExtraCompat import com.keylesspalace.tusky.util.isHttpNotFound import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.visible @@ -53,7 +53,7 @@ class EditFilterActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - originalFilter = IntentCompat.getParcelableExtra(intent, FILTER_TO_EDIT, Filter::class.java) + originalFilter = intent.getParcelableExtraCompat(FILTER_TO_EDIT) filter = originalFilter ?: Filter("", "", listOf(), null, Filter.Action.WARN.action, listOf()) binding.apply { contextSwitches = mapOf( 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 421f81032..a3e65d577 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 @@ -33,7 +33,6 @@ import android.webkit.WebViewClient import androidx.activity.result.contract.ActivityResultContract import androidx.activity.viewModels import androidx.appcompat.app.AlertDialog -import androidx.core.content.IntentCompat import androidx.core.net.toUri import androidx.lifecycle.lifecycleScope import com.keylesspalace.tusky.BaseActivity @@ -42,6 +41,7 @@ import com.keylesspalace.tusky.R import com.keylesspalace.tusky.databinding.ActivityLoginWebviewBinding import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.di.ViewModelFactory +import com.keylesspalace.tusky.util.getParcelableExtraCompat import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.visible @@ -62,9 +62,8 @@ class OauthLogin : ActivityResultContract() { return if (resultCode == Activity.RESULT_CANCELED) { LoginResult.Cancel } else { - intent?.let { - IntentCompat.getParcelableExtra(it, RESULT_EXTRA, LoginResult::class.java) - } ?: LoginResult.Err("failed parsing LoginWebViewActivity result") + intent?.getParcelableExtraCompat(RESULT_EXTRA) + ?: LoginResult.Err("failed parsing LoginWebViewActivity result") } } @@ -73,7 +72,7 @@ class OauthLogin : ActivityResultContract() { private const val DATA_EXTRA = "data" fun parseData(intent: Intent): LoginData { - return IntentCompat.getParcelableExtra(intent, DATA_EXTRA, LoginData::class.java)!! + return intent.getParcelableExtraCompat(DATA_EXTRA)!! } fun makeResultIntent(result: LoginResult): Intent { diff --git a/app/src/main/java/com/keylesspalace/tusky/components/login/LoginWebViewViewModel.kt b/app/src/main/java/com/keylesspalace/tusky/components/login/LoginWebViewViewModel.kt index 2e9198d16..6c4caf8aa 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/login/LoginWebViewViewModel.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/login/LoginWebViewViewModel.kt @@ -49,11 +49,11 @@ class LoginWebViewViewModel @Inject constructor( { instance -> _instanceRules.value = instance.rules.map { rule -> rule.text } }, - { throwable -> + { throwable2 -> Log.w( "LoginWebViewViewModel", "failed to load instance info", - throwable + throwable2 ) } ) diff --git a/app/src/main/java/com/keylesspalace/tusky/components/notifications/StatusNotificationViewHolder.kt b/app/src/main/java/com/keylesspalace/tusky/components/notifications/StatusNotificationViewHolder.kt index 6defe1ac6..89657fcac 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/notifications/StatusNotificationViewHolder.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/notifications/StatusNotificationViewHolder.kt @@ -18,7 +18,6 @@ package com.keylesspalace.tusky.components.notifications import android.content.Context -import android.graphics.PorterDuff import android.graphics.Typeface import android.graphics.drawable.Drawable import android.text.InputFilter @@ -175,7 +174,7 @@ internal class StatusNotificationViewHolder( @ColorRes color: Int ): Drawable? { val icon = ContextCompat.getDrawable(context, drawable) - icon?.setColorFilter(context.getColor(color), PorterDuff.Mode.SRC_ATOP) + icon?.setTint(context.getColor(color)) return icon } 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 3e82f01d2..c2972fa18 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 @@ -112,7 +112,6 @@ class PreferencesActivity : pref.fragment!! ) fragment.arguments = args - fragment.setTargetFragment(caller, 0) supportFragmentManager.commit { setCustomAnimations( R.anim.activity_open_enter, diff --git a/app/src/main/java/com/keylesspalace/tusky/db/AccountManager.kt b/app/src/main/java/com/keylesspalace/tusky/db/AccountManager.kt index 1ff06afc1..83f8dada8 100644 --- a/app/src/main/java/com/keylesspalace/tusky/db/AccountManager.kt +++ b/app/src/main/java/com/keylesspalace/tusky/db/AccountManager.kt @@ -157,7 +157,7 @@ class AccountManager @Inject constructor(db: AppDatabase) { it.defaultPostPrivacy = account.source?.privacy ?: Status.Visibility.PUBLIC it.defaultPostLanguage = account.source?.language.orEmpty() it.defaultMediaSensitivity = account.source?.sensitive ?: false - it.emojis = account.emojis.orEmpty() + it.emojis = account.emojis it.locked = account.locked Log.d(TAG, "updateActiveAccount: saving account with id " + it.id) 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 cc8733961..0aa18781d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewImageFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewImageFragment.kt @@ -28,7 +28,6 @@ import android.view.MotionEvent import android.view.View import android.view.ViewGroup import android.widget.ImageView -import androidx.core.os.BundleCompat import androidx.lifecycle.lifecycleScope import com.bumptech.glide.Glide import com.bumptech.glide.load.DataSource @@ -39,6 +38,7 @@ import com.keylesspalace.tusky.R import com.keylesspalace.tusky.ViewMediaActivity import com.keylesspalace.tusky.databinding.FragmentViewImageBinding import com.keylesspalace.tusky.entity.Attachment +import com.keylesspalace.tusky.util.getParcelableCompat import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.visible @@ -100,12 +100,8 @@ class ViewImageFragment : ViewMediaFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val arguments = this.requireArguments() - val attachment = BundleCompat.getParcelable( - arguments, - ARG_ATTACHMENT, - Attachment::class.java - ) + val arguments = requireArguments() + val attachment = arguments.getParcelableCompat(ARG_ATTACHMENT) this.shouldStartTransition = arguments.getBoolean(ARG_START_POSTPONED_TRANSITION) val url: String? var description: String? = null @@ -231,7 +227,7 @@ class ViewImageFragment : ViewMediaFragment() { } override fun onToolbarVisibilityChange(visible: Boolean) { - if (!userVisibleHint) return + if (view == null) return isDescriptionVisible = showingDescription && visible val alpha = if (isDescriptionVisible) 1.0f else 0.0f diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.kt index a3f880cb7..1e6f45625 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.kt @@ -100,6 +100,7 @@ abstract class ViewMediaFragment : Fragment() { override fun onDestroyView() { toolbarVisibilityDisposable?.invoke() + toolbarVisibilityDisposable = null super.onDestroyView() } } 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 ecc8a773b..73b144072 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewVideoFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewVideoFragment.kt @@ -52,6 +52,7 @@ import com.keylesspalace.tusky.ViewMediaActivity import com.keylesspalace.tusky.databinding.FragmentViewVideoBinding import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.entity.Attachment +import com.keylesspalace.tusky.util.getParcelableCompat import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.visible @@ -130,7 +131,7 @@ class ViewVideoFragment : ViewMediaFragment(), Injectable { @SuppressLint("ClickableViewAccessibility") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val attachment = arguments?.getParcelable(ARG_ATTACHMENT) + val attachment = arguments?.getParcelableCompat(ARG_ATTACHMENT) ?: throw IllegalArgumentException("attachment has to be set") val url = attachment.url @@ -377,7 +378,7 @@ class ViewVideoFragment : ViewMediaFragment(), Injectable { } override fun onToolbarVisibilityChange(visible: Boolean) { - if (!userVisibleHint) { + if (view == null) { return } 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 098400199..fcc8a76b4 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.db.AccountManager import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.service.SendStatusService import com.keylesspalace.tusky.service.StatusToSend +import com.keylesspalace.tusky.util.getSerializableExtraCompat import com.keylesspalace.tusky.util.randomAlphanumericString import dagger.android.AndroidInjection import javax.inject.Inject @@ -54,9 +55,8 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() { 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 = + intent.getSerializableExtraCompat(NotificationHelper.KEY_VISIBILITY)!! val spoiler = intent.getStringExtra(NotificationHelper.KEY_SPOILER).orEmpty() val mentions = intent.getStringArrayExtra(NotificationHelper.KEY_MENTIONS).orEmpty() 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 5f463e6bf..1fe58676b 100644 --- a/app/src/main/java/com/keylesspalace/tusky/service/SendStatusService.kt +++ b/app/src/main/java/com/keylesspalace/tusky/service/SendStatusService.kt @@ -31,7 +31,6 @@ import android.util.Log import androidx.annotation.StringRes import androidx.core.app.NotificationCompat import androidx.core.app.ServiceCompat -import androidx.core.content.IntentCompat import at.connyduck.calladapter.networkresult.fold import com.keylesspalace.tusky.MainActivity import com.keylesspalace.tusky.R @@ -52,6 +51,7 @@ import com.keylesspalace.tusky.entity.NewStatus import com.keylesspalace.tusky.entity.ScheduledStatus import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.network.MastodonApi +import com.keylesspalace.tusky.util.getParcelableExtraCompat import com.keylesspalace.tusky.util.unsafeLazy import dagger.android.AndroidInjection import java.util.concurrent.ConcurrentHashMap @@ -102,7 +102,7 @@ class SendStatusService : Service(), Injectable { override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { if (intent.hasExtra(KEY_STATUS)) { - val statusToSend: StatusToSend = IntentCompat.getParcelableExtra(intent, KEY_STATUS, StatusToSend::class.java) + val statusToSend: StatusToSend = intent.getParcelableExtraCompat(KEY_STATUS) ?: throw IllegalStateException("SendStatusService started without $KEY_STATUS extra") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -247,11 +247,11 @@ class SendStatusService : Service(), Injectable { scheduledAt = statusToSend.scheduledAt, poll = statusToSend.poll, language = statusToSend.language, - mediaAttributes = media.map { media -> + mediaAttributes = media.map { mediaItem -> MediaAttribute( - id = media.id!!, - description = media.description, - focus = media.focus?.toMastodonApiString(), + id = mediaItem.id!!, + description = mediaItem.description, + focus = mediaItem.focus?.toMastodonApiString(), thumbnail = null ) } diff --git a/app/src/main/java/com/keylesspalace/tusky/util/BundleExtensions.kt b/app/src/main/java/com/keylesspalace/tusky/util/BundleExtensions.kt new file mode 100644 index 000000000..4aea34920 --- /dev/null +++ b/app/src/main/java/com/keylesspalace/tusky/util/BundleExtensions.kt @@ -0,0 +1,23 @@ +package com.keylesspalace.tusky.util + +import android.content.Intent +import android.os.Bundle +import android.os.Parcelable +import androidx.core.content.IntentCompat +import androidx.core.os.BundleCompat +import java.io.Serializable + +inline fun Bundle.getParcelableCompat(key: String?): T? = + BundleCompat.getParcelable(this, key, T::class.java) + +inline fun Bundle.getSerializableCompat(key: String?): T? = + BundleCompat.getSerializable(this, key, T::class.java) + +inline fun Intent.getParcelableExtraCompat(key: String?): T? = + IntentCompat.getParcelableExtra(this, key, T::class.java) + +inline fun Intent.getSerializableExtraCompat(key: String?): T? = + IntentCompat.getSerializableExtra(this, key, T::class.java) + +inline fun Intent.getParcelableArrayListExtraCompat(key: String?): ArrayList? = + IntentCompat.getParcelableArrayListExtra(this, key, T::class.java) diff --git a/app/src/main/java/com/keylesspalace/tusky/util/PickMediaFiles.kt b/app/src/main/java/com/keylesspalace/tusky/util/PickMediaFiles.kt index 4d3fcd5b4..a5f465531 100644 --- a/app/src/main/java/com/keylesspalace/tusky/util/PickMediaFiles.kt +++ b/app/src/main/java/com/keylesspalace/tusky/util/PickMediaFiles.kt @@ -22,13 +22,13 @@ import android.net.Uri import androidx.activity.result.contract.ActivityResultContract class PickMediaFiles : ActivityResultContract>() { - override fun createIntent(context: Context, allowMultiple: Boolean): Intent { + override fun createIntent(context: Context, input: Boolean): Intent { return Intent(Intent.ACTION_GET_CONTENT) .addCategory(Intent.CATEGORY_OPENABLE) .setType("*/*") .apply { putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*", "video/*", "audio/*")) - putExtra(Intent.EXTRA_ALLOW_MULTIPLE, allowMultiple) + putExtra(Intent.EXTRA_ALLOW_MULTIPLE, input) } } diff --git a/app/src/main/java/com/keylesspalace/tusky/util/ThemeUtils.kt b/app/src/main/java/com/keylesspalace/tusky/util/ThemeUtils.kt index fc7df19df..08aa992c7 100644 --- a/app/src/main/java/com/keylesspalace/tusky/util/ThemeUtils.kt +++ b/app/src/main/java/com/keylesspalace/tusky/util/ThemeUtils.kt @@ -19,7 +19,6 @@ package com.keylesspalace.tusky.util import android.content.Context import android.content.res.Configuration import android.graphics.Color -import android.graphics.PorterDuff import android.graphics.drawable.Drawable import androidx.annotation.AttrRes import androidx.appcompat.app.AppCompatDelegate @@ -39,10 +38,7 @@ fun getDimension(context: Context, @AttrRes attribute: Int): Int { } fun setDrawableTint(context: Context, drawable: Drawable, @AttrRes attribute: Int) { - drawable.setColorFilter( - MaterialColors.getColor(context, attribute, Color.BLACK), - PorterDuff.Mode.SRC_IN - ) + drawable.setTint(MaterialColors.getColor(context, attribute, Color.BLACK)) } fun setAppNightMode(flavor: String?) { diff --git a/app/src/main/java/com/keylesspalace/tusky/view/MediaPreviewLayout.kt b/app/src/main/java/com/keylesspalace/tusky/view/MediaPreviewLayout.kt index 854b72009..1d26d5b3b 100644 --- a/app/src/main/java/com/keylesspalace/tusky/view/MediaPreviewLayout.kt +++ b/app/src/main/java/com/keylesspalace/tusky/view/MediaPreviewLayout.kt @@ -189,8 +189,8 @@ class MediaPreviewLayout(context: Context, attrs: AttributeSet? = null) : val wrapper = getChildAt(index) action( index, - wrapper.findViewById(R.id.preview_image_view) as MediaPreviewImageView, - wrapper.findViewById(R.id.preview_media_description_indicator) as TextView + wrapper.findViewById(R.id.preview_image_view), + wrapper.findViewById(R.id.preview_media_description_indicator) ) } }