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()`.
This commit is contained in:
Christophe Beyls 2024-05-05 08:34:41 +02:00 committed by GitHub
parent 7dc71a5888
commit 05c7e7b806
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 108 additions and 106 deletions

View File

@ -1,7 +1,6 @@
package com.keylesspalace.tusky package com.keylesspalace.tusky
import androidx.room.testing.MigrationTestHelper import androidx.room.testing.MigrationTestHelper
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import com.keylesspalace.tusky.db.AppDatabase import com.keylesspalace.tusky.db.AppDatabase
@ -19,8 +18,7 @@ class MigrationsTest {
@Rule @Rule
var helper: MigrationTestHelper = MigrationTestHelper( var helper: MigrationTestHelper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(), InstrumentationRegistry.getInstrumentation(),
AppDatabase::class.java.canonicalName!!, AppDatabase::class.java
FrameworkSQLiteOpenHelperFactory()
) )
@Test @Test

View File

@ -45,7 +45,6 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.IntentCompat
import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.view.GravityCompat import androidx.core.view.GravityCompat
import androidx.core.view.MenuProvider 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.deleteStaleCachedMedia
import com.keylesspalace.tusky.util.emojify import com.keylesspalace.tusky.util.emojify
import com.keylesspalace.tusky.util.getDimension import com.keylesspalace.tusky.util.getDimension
import com.keylesspalace.tusky.util.getParcelableExtraCompat
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.reduceSwipeSensitivity import com.keylesspalace.tusky.util.reduceSwipeSensitivity
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
@ -531,11 +531,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
} }
private fun forwardToComposeActivity(intent: Intent) { private fun forwardToComposeActivity(intent: Intent) {
val composeOptions = IntentCompat.getParcelableExtra( val composeOptions =
intent, intent.getParcelableExtraCompat<ComposeActivity.ComposeOptions>(COMPOSE_OPTIONS)
COMPOSE_OPTIONS,
ComposeActivity.ComposeOptions::class.java
)
val composeIntent = if (composeOptions != null) { val composeIntent = if (composeOptions != null) {
ComposeActivity.startIntent(this, composeOptions) ComposeActivity.startIntent(this, composeOptions)

View File

@ -219,8 +219,8 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
} }
updateTagMuteState(mutedFilterV1 != null) updateTagMuteState(mutedFilterV1 != null)
}, },
{ throwable -> { throwable2 ->
Log.e(TAG, "Error getting filters: $throwable") Log.e(TAG, "Error getting filters: $throwable2")
} }
) )
} else { } else {
@ -292,13 +292,13 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
eventHub.dispatch(PreferenceChangedEvent(filter.context[0])) eventHub.dispatch(PreferenceChangedEvent(filter.context[0]))
filterCreateSuccess = true filterCreateSuccess = true
}, },
{ throwable -> { throwable2 ->
Snackbar.make( Snackbar.make(
binding.root, binding.root,
getString(R.string.error_muting_hashtag_format, tag), getString(R.string.error_muting_hashtag_format, tag),
Snackbar.LENGTH_SHORT Snackbar.LENGTH_SHORT
).show() ).show()
Log.e(TAG, "Failed to mute #$tag", throwable) Log.e(TAG, "Failed to mute #$tag", throwable2)
} }
) )
} else { } else {

View File

@ -40,7 +40,6 @@ import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ShareCompat import androidx.core.app.ShareCompat
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.content.IntentCompat
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.adapter.FragmentStateAdapter 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.fragment.ViewVideoFragment
import com.keylesspalace.tusky.pager.ImagePagerAdapter import com.keylesspalace.tusky.pager.ImagePagerAdapter
import com.keylesspalace.tusky.pager.SingleImagePagerAdapter import com.keylesspalace.tusky.pager.SingleImagePagerAdapter
import com.keylesspalace.tusky.util.getParcelableArrayListExtraCompat
import com.keylesspalace.tusky.util.getTemporaryMediaFilename import com.keylesspalace.tusky.util.getTemporaryMediaFilename
import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
import com.keylesspalace.tusky.util.submitAsync import com.keylesspalace.tusky.util.submitAsync
@ -118,11 +118,7 @@ class ViewMediaActivity :
supportPostponeEnterTransition() supportPostponeEnterTransition()
// Gather the parameters. // Gather the parameters.
attachments = IntentCompat.getParcelableArrayListExtra( attachments = intent.getParcelableArrayListExtraCompat(EXTRA_ATTACHMENTS)
intent,
EXTRA_ATTACHMENTS,
AttachmentViewData::class.java
)
val initialPosition = intent.getIntExtra(EXTRA_ATTACHMENT_INDEX, 0) val initialPosition = intent.getIntExtra(EXTRA_ATTACHMENT_INDEX, 0)
// Adapter is actually of existential type PageAdapter & SharedElementsTransitionListener // Adapter is actually of existential type PageAdapter & SharedElementsTransitionListener

View File

@ -200,7 +200,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
TouchDelegateHelper.expandTouchSizeToFillRow((ViewGroup) itemView, CollectionsKt.listOfNotNull(replyButton, reblogButton, favouriteButton, bookmarkButton, moreButton)); TouchDelegateHelper.expandTouchSizeToFillRow((ViewGroup) itemView, CollectionsKt.listOfNotNull(replyButton, reblogButton, favouriteButton, bookmarkButton, moreButton));
} }
protected void setDisplayName(@NonNull String name, @Nullable List<Emoji> customEmojis, @NonNull StatusDisplayOptions statusDisplayOptions) { protected void setDisplayName(@NonNull String name, @NonNull List<Emoji> customEmojis, @NonNull StatusDisplayOptions statusDisplayOptions) {
CharSequence emojifiedName = CustomEmojiHelper.emojify( CharSequence emojifiedName = CustomEmojiHelper.emojify(
name, customEmojis, displayName, statusDisplayOptions.animateEmojis() name, customEmojis, displayName, statusDisplayOptions.animateEmojis()
); );
@ -790,7 +790,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
if (statusDisplayOptions.mediaPreviewEnabled() && hasPreviewableAttachment(attachments)) { if (statusDisplayOptions.mediaPreviewEnabled() && hasPreviewableAttachment(attachments)) {
setMediaPreviews(attachments, sensitive, listener, status.isShowingContent(), statusDisplayOptions.useBlurhash()); setMediaPreviews(attachments, sensitive, listener, status.isShowingContent(), statusDisplayOptions.useBlurhash());
if (attachments.size() == 0) { if (attachments.isEmpty()) {
hideSensitiveMediaWarning(); hideSensitiveMediaWarning();
} }
// Hide the unused label. // 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())); filteredPlaceholderShowButton.setOnClickListener(view -> listener.clearWarningAction(getBindingAdapterPosition()));
} }
@ -1154,7 +1161,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
final Card card = actionable.getCard(); final Card card = actionable.getCard();
if (cardViewMode != CardViewMode.NONE && if (cardViewMode != CardViewMode.NONE &&
actionable.getAttachments().size() == 0 && actionable.getAttachments().isEmpty() &&
actionable.getPoll() == null && actionable.getPoll() == null &&
card != null && card != null &&
!TextUtils.isEmpty(card.getUrl()) && !TextUtils.isEmpty(card.getUrl()) &&

View File

@ -9,13 +9,11 @@ import android.text.method.LinkMovementMethod;
import android.text.style.DynamicDrawableSpan; import android.text.style.DynamicDrawableSpan;
import android.text.style.ImageSpan; import android.text.style.ImageSpan;
import android.view.View; import android.view.View;
import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.ViewUtils;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.keylesspalace.tusky.R; 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.LinkHelper;
import com.keylesspalace.tusky.util.NoUnderlineURLSpan; import com.keylesspalace.tusky.util.NoUnderlineURLSpan;
import com.keylesspalace.tusky.util.StatusDisplayOptions; import com.keylesspalace.tusky.util.StatusDisplayOptions;
import com.keylesspalace.tusky.util.ViewExtensionsKt;
import com.keylesspalace.tusky.viewdata.StatusViewData; import com.keylesspalace.tusky.viewdata.StatusViewData;
import java.text.DateFormat; import java.text.DateFormat;

View File

@ -22,6 +22,7 @@ import androidx.fragment.app.commit
import com.keylesspalace.tusky.BottomSheetActivity import com.keylesspalace.tusky.BottomSheetActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.ActivityAccountListBinding import com.keylesspalace.tusky.databinding.ActivityAccountListBinding
import com.keylesspalace.tusky.util.getSerializableExtraCompat
import dagger.android.DispatchingAndroidInjector import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import javax.inject.Inject import javax.inject.Inject
@ -46,7 +47,7 @@ class AccountListActivity : BottomSheetActivity(), HasAndroidInjector {
val binding = ActivityAccountListBinding.inflate(layoutInflater) val binding = ActivityAccountListBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
val type = intent.getSerializableExtra(EXTRA_TYPE) as Type val type = intent.getSerializableExtraCompat<Type>(EXTRA_TYPE)!!
val id: String? = intent.getStringExtra(EXTRA_ID) val id: String? = intent.getStringExtra(EXTRA_ID)
setSupportActionBar(binding.includedToolbar.toolbar) setSupportActionBar(binding.includedToolbar.toolbar)

View File

@ -50,6 +50,7 @@ import com.keylesspalace.tusky.interfaces.LinkListener
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.HttpHeaderLink import com.keylesspalace.tusky.util.HttpHeaderLink
import com.keylesspalace.tusky.util.getSerializableCompat
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
@ -83,7 +84,7 @@ class AccountListFragment :
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
type = requireArguments().getSerializable(ARG_TYPE) as Type type = requireArguments().getSerializableCompat(ARG_TYPE)!!
id = requireArguments().getString(ARG_ID) id = requireArguments().getString(ARG_ID)
} }
@ -244,12 +245,12 @@ class AccountListFragment :
Log.e(TAG, "Failed to $verb account accountId $accountId") 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 { viewLifecycleOwner.lifecycleScope.launch {
if (accept) { if (accept) {
api.authorizeFollowRequest(accountId) api.authorizeFollowRequest(id)
} else { } else {
api.rejectFollowRequest(accountId) api.rejectFollowRequest(id)
}.fold( }.fold(
onSuccess = { onSuccess = {
onRespondToFollowRequestSuccess(position) onRespondToFollowRequestSuccess(position)
@ -260,7 +261,7 @@ class AccountListFragment :
} else { } else {
"reject" "reject"
} }
Log.e(TAG, "Failed to $verb account id $accountId.", throwable) Log.e(TAG, "Failed to $verb account id $id.", throwable)
} }
) )
} }

View File

@ -22,8 +22,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.icu.text.BreakIterator import android.icu.text.BreakIterator
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
@ -50,9 +48,7 @@ import androidx.annotation.StringRes
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.content.IntentCompat
import androidx.core.content.res.use import androidx.core.content.res.use
import androidx.core.os.BundleCompat
import androidx.core.view.ContentInfoCompat import androidx.core.view.ContentInfoCompat
import androidx.core.view.OnReceiveContentListener import androidx.core.view.OnReceiveContentListener
import androidx.core.view.isGone 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.getInitialLanguages
import com.keylesspalace.tusky.util.getLocaleList import com.keylesspalace.tusky.util.getLocaleList
import com.keylesspalace.tusky.util.getMediaSize 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.hide
import com.keylesspalace.tusky.util.highlightSpans import com.keylesspalace.tusky.util.highlightSpans
import com.keylesspalace.tusky.util.loadAvatar 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 /* 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. */ * based on what the intent from the reply request passes. */
val composeOptions: ComposeOptions? = IntentCompat.getParcelableExtra( val composeOptions: ComposeOptions? = intent.getParcelableExtraCompat(COMPOSE_OPTIONS_EXTRA)
intent,
COMPOSE_OPTIONS_EXTRA,
ComposeOptions::class.java
)
viewModel.setup(composeOptions) viewModel.setup(composeOptions)
setupButtons() setupButtons()
@ -325,11 +321,9 @@ class ComposeActivity :
/* Finally, overwrite state with data from saved instance state. */ /* Finally, overwrite state with data from saved instance state. */
savedInstanceState?.let { 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(it.getSerializableCompat(VISIBILITY_KEY)!!)
setStatusVisibility(this)
}
it.getBoolean(CONTENT_WARNING_VISIBLE_KEY).apply { it.getBoolean(CONTENT_WARNING_VISIBLE_KEY).apply {
viewModel.contentWarningChanged(this) viewModel.contentWarningChanged(this)
@ -354,20 +348,13 @@ class ComposeActivity :
if (type.startsWith("image/") || type.startsWith("video/") || type.startsWith("audio/")) { if (type.startsWith("image/") || type.startsWith("video/") || type.startsWith("audio/")) {
when (intent.action) { when (intent.action) {
Intent.ACTION_SEND -> { Intent.ACTION_SEND -> {
IntentCompat.getParcelableExtra( intent.getParcelableExtraCompat<Uri>(Intent.EXTRA_STREAM)?.let { uri ->
intent,
Intent.EXTRA_STREAM,
Uri::class.java
)?.let { uri ->
pickMedia(uri) pickMedia(uri)
} }
} }
Intent.ACTION_SEND_MULTIPLE -> { Intent.ACTION_SEND_MULTIPLE -> {
IntentCompat.getParcelableArrayListExtra( intent.getParcelableArrayListExtraCompat<Uri>(Intent.EXTRA_STREAM)
intent, ?.forEach { uri ->
Intent.EXTRA_STREAM,
Uri::class.java
)?.forEach { uri ->
pickMedia(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 var oneMediaWithoutDescription = false
for (media in viewModel.media.value) { for (media in viewModel.media.value) {
@ -880,7 +867,7 @@ class ComposeActivity :
} else { } else {
getColor(R.color.tusky_blue) 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.setTextColor(textColor)
binding.addPollTextActionTextView.compoundDrawablesRelative[0].colorFilter = PorterDuffColorFilter(textColor, PorterDuff.Mode.SRC_IN) binding.addPollTextActionTextView.compoundDrawablesRelative[0].setTint(textColor)
} }
private fun editImageInQueue(item: QueuedMedia) { private fun editImageInQueue(item: QueuedMedia) {
@ -1273,7 +1260,7 @@ class ComposeActivity :
android.R.attr.textColorTertiary 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 { override fun onOptionsItemSelected(item: MenuItem): Boolean {

View File

@ -25,7 +25,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.core.os.BundleCompat
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import com.bumptech.glide.Glide 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.bumptech.glide.request.transition.Transition
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.DialogImageDescriptionBinding import com.keylesspalace.tusky.databinding.DialogImageDescriptionBinding
import com.keylesspalace.tusky.util.getParcelableCompat
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
@ -82,7 +82,7 @@ class CaptionDialog : DialogFragment() {
isCancelable = true isCancelable = true
val previewUri = BundleCompat.getParcelable(requireArguments(), PREVIEW_URI_ARG, Uri::class.java) ?: error("Preview Uri is null") val previewUri = arguments?.getParcelableCompat<Uri>(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. // Load the image and manually set it into the ImageView because it doesn't have a fixed size.
Glide.with(this) Glide.with(this)

View File

@ -80,7 +80,11 @@ public class ConversationViewHolder extends StatusBaseViewHolder {
setupCollapsedState(statusViewData.isCollapsible(), statusViewData.isCollapsed(), statusViewData.isExpanded(), status.getSpoilerText(), listener); 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()); setUsername(account.getUsername());
setMetaData(statusViewData, statusDisplayOptions, listener); setMetaData(statusViewData, statusDisplayOptions, listener);
setIsReply(status.getInReplyToId() != null); setIsReply(status.getInReplyToId() != null);
@ -92,7 +96,7 @@ public class ConversationViewHolder extends StatusBaseViewHolder {
setMediaPreviews(attachments, sensitive, listener, statusViewData.isShowingContent(), setMediaPreviews(attachments, sensitive, listener, statusViewData.isShowingContent(),
statusDisplayOptions.useBlurhash()); statusDisplayOptions.useBlurhash());
if (attachments.size() == 0) { if (attachments.isEmpty()) {
hideSensitiveMediaWarning(); hideSensitiveMediaWarning();
} }
// Hide the unused label. // Hide the unused label.

View File

@ -8,7 +8,6 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.IntentCompat
import androidx.core.view.size import androidx.core.view.size
import androidx.core.widget.doAfterTextChanged import androidx.core.widget.doAfterTextChanged
import androidx.lifecycle.lifecycleScope 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.Filter
import com.keylesspalace.tusky.entity.FilterKeyword import com.keylesspalace.tusky.entity.FilterKeyword
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.getParcelableExtraCompat
import com.keylesspalace.tusky.util.isHttpNotFound import com.keylesspalace.tusky.util.isHttpNotFound
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
@ -53,7 +53,7 @@ class EditFilterActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) 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()) filter = originalFilter ?: Filter("", "", listOf(), null, Filter.Action.WARN.action, listOf())
binding.apply { binding.apply {
contextSwitches = mapOf( contextSwitches = mapOf(

View File

@ -33,7 +33,6 @@ import android.webkit.WebViewClient
import androidx.activity.result.contract.ActivityResultContract import androidx.activity.result.contract.ActivityResultContract
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.IntentCompat
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.keylesspalace.tusky.BaseActivity import com.keylesspalace.tusky.BaseActivity
@ -42,6 +41,7 @@ import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.ActivityLoginWebviewBinding import com.keylesspalace.tusky.databinding.ActivityLoginWebviewBinding
import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.util.getParcelableExtraCompat
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
@ -62,9 +62,8 @@ class OauthLogin : ActivityResultContract<LoginData, LoginResult>() {
return if (resultCode == Activity.RESULT_CANCELED) { return if (resultCode == Activity.RESULT_CANCELED) {
LoginResult.Cancel LoginResult.Cancel
} else { } else {
intent?.let { intent?.getParcelableExtraCompat(RESULT_EXTRA)
IntentCompat.getParcelableExtra(it, RESULT_EXTRA, LoginResult::class.java) ?: LoginResult.Err("failed parsing LoginWebViewActivity result")
} ?: LoginResult.Err("failed parsing LoginWebViewActivity result")
} }
} }
@ -73,7 +72,7 @@ class OauthLogin : ActivityResultContract<LoginData, LoginResult>() {
private const val DATA_EXTRA = "data" private const val DATA_EXTRA = "data"
fun parseData(intent: Intent): LoginData { fun parseData(intent: Intent): LoginData {
return IntentCompat.getParcelableExtra(intent, DATA_EXTRA, LoginData::class.java)!! return intent.getParcelableExtraCompat(DATA_EXTRA)!!
} }
fun makeResultIntent(result: LoginResult): Intent { fun makeResultIntent(result: LoginResult): Intent {

View File

@ -49,11 +49,11 @@ class LoginWebViewViewModel @Inject constructor(
{ instance -> { instance ->
_instanceRules.value = instance.rules.map { rule -> rule.text } _instanceRules.value = instance.rules.map { rule -> rule.text }
}, },
{ throwable -> { throwable2 ->
Log.w( Log.w(
"LoginWebViewViewModel", "LoginWebViewViewModel",
"failed to load instance info", "failed to load instance info",
throwable throwable2
) )
} }
) )

View File

@ -18,7 +18,6 @@
package com.keylesspalace.tusky.components.notifications package com.keylesspalace.tusky.components.notifications
import android.content.Context import android.content.Context
import android.graphics.PorterDuff
import android.graphics.Typeface import android.graphics.Typeface
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.text.InputFilter import android.text.InputFilter
@ -175,7 +174,7 @@ internal class StatusNotificationViewHolder(
@ColorRes color: Int @ColorRes color: Int
): Drawable? { ): Drawable? {
val icon = ContextCompat.getDrawable(context, drawable) val icon = ContextCompat.getDrawable(context, drawable)
icon?.setColorFilter(context.getColor(color), PorterDuff.Mode.SRC_ATOP) icon?.setTint(context.getColor(color))
return icon return icon
} }

View File

@ -112,7 +112,6 @@ class PreferencesActivity :
pref.fragment!! pref.fragment!!
) )
fragment.arguments = args fragment.arguments = args
fragment.setTargetFragment(caller, 0)
supportFragmentManager.commit { supportFragmentManager.commit {
setCustomAnimations( setCustomAnimations(
R.anim.activity_open_enter, R.anim.activity_open_enter,

View File

@ -157,7 +157,7 @@ class AccountManager @Inject constructor(db: AppDatabase) {
it.defaultPostPrivacy = account.source?.privacy ?: Status.Visibility.PUBLIC it.defaultPostPrivacy = account.source?.privacy ?: Status.Visibility.PUBLIC
it.defaultPostLanguage = account.source?.language.orEmpty() it.defaultPostLanguage = account.source?.language.orEmpty()
it.defaultMediaSensitivity = account.source?.sensitive ?: false it.defaultMediaSensitivity = account.source?.sensitive ?: false
it.emojis = account.emojis.orEmpty() it.emojis = account.emojis
it.locked = account.locked it.locked = account.locked
Log.d(TAG, "updateActiveAccount: saving account with id " + it.id) Log.d(TAG, "updateActiveAccount: saving account with id " + it.id)

View File

@ -28,7 +28,6 @@ import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import androidx.core.os.BundleCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.DataSource
@ -39,6 +38,7 @@ import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.ViewMediaActivity import com.keylesspalace.tusky.ViewMediaActivity
import com.keylesspalace.tusky.databinding.FragmentViewImageBinding import com.keylesspalace.tusky.databinding.FragmentViewImageBinding
import com.keylesspalace.tusky.entity.Attachment import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.util.getParcelableCompat
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
@ -100,12 +100,8 @@ class ViewImageFragment : ViewMediaFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val arguments = this.requireArguments() val arguments = requireArguments()
val attachment = BundleCompat.getParcelable( val attachment = arguments.getParcelableCompat<Attachment>(ARG_ATTACHMENT)
arguments,
ARG_ATTACHMENT,
Attachment::class.java
)
this.shouldStartTransition = arguments.getBoolean(ARG_START_POSTPONED_TRANSITION) this.shouldStartTransition = arguments.getBoolean(ARG_START_POSTPONED_TRANSITION)
val url: String? val url: String?
var description: String? = null var description: String? = null
@ -231,7 +227,7 @@ class ViewImageFragment : ViewMediaFragment() {
} }
override fun onToolbarVisibilityChange(visible: Boolean) { override fun onToolbarVisibilityChange(visible: Boolean) {
if (!userVisibleHint) return if (view == null) return
isDescriptionVisible = showingDescription && visible isDescriptionVisible = showingDescription && visible
val alpha = if (isDescriptionVisible) 1.0f else 0.0f val alpha = if (isDescriptionVisible) 1.0f else 0.0f

View File

@ -100,6 +100,7 @@ abstract class ViewMediaFragment : Fragment() {
override fun onDestroyView() { override fun onDestroyView() {
toolbarVisibilityDisposable?.invoke() toolbarVisibilityDisposable?.invoke()
toolbarVisibilityDisposable = null
super.onDestroyView() super.onDestroyView()
} }
} }

View File

@ -52,6 +52,7 @@ import com.keylesspalace.tusky.ViewMediaActivity
import com.keylesspalace.tusky.databinding.FragmentViewVideoBinding import com.keylesspalace.tusky.databinding.FragmentViewVideoBinding
import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.Attachment import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.util.getParcelableCompat
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
@ -130,7 +131,7 @@ class ViewVideoFragment : ViewMediaFragment(), Injectable {
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val attachment = arguments?.getParcelable<Attachment>(ARG_ATTACHMENT) val attachment = arguments?.getParcelableCompat<Attachment>(ARG_ATTACHMENT)
?: throw IllegalArgumentException("attachment has to be set") ?: throw IllegalArgumentException("attachment has to be set")
val url = attachment.url val url = attachment.url
@ -377,7 +378,7 @@ class ViewVideoFragment : ViewMediaFragment(), Injectable {
} }
override fun onToolbarVisibilityChange(visible: Boolean) { override fun onToolbarVisibilityChange(visible: Boolean) {
if (!userVisibleHint) { if (view == null) {
return return
} }

View File

@ -29,6 +29,7 @@ import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.service.SendStatusService import com.keylesspalace.tusky.service.SendStatusService
import com.keylesspalace.tusky.service.StatusToSend import com.keylesspalace.tusky.service.StatusToSend
import com.keylesspalace.tusky.util.getSerializableExtraCompat
import com.keylesspalace.tusky.util.randomAlphanumericString import com.keylesspalace.tusky.util.randomAlphanumericString
import dagger.android.AndroidInjection import dagger.android.AndroidInjection
import javax.inject.Inject import javax.inject.Inject
@ -54,9 +55,8 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
NotificationHelper.KEY_SENDER_ACCOUNT_FULL_NAME NotificationHelper.KEY_SENDER_ACCOUNT_FULL_NAME
) )
val citedStatusId = intent.getStringExtra(NotificationHelper.KEY_CITED_STATUS_ID) val citedStatusId = intent.getStringExtra(NotificationHelper.KEY_CITED_STATUS_ID)
val visibility = intent.getSerializableExtra( val visibility =
NotificationHelper.KEY_VISIBILITY intent.getSerializableExtraCompat<Status.Visibility>(NotificationHelper.KEY_VISIBILITY)!!
) as Status.Visibility
val spoiler = intent.getStringExtra(NotificationHelper.KEY_SPOILER).orEmpty() val spoiler = intent.getStringExtra(NotificationHelper.KEY_SPOILER).orEmpty()
val mentions = intent.getStringArrayExtra(NotificationHelper.KEY_MENTIONS).orEmpty() val mentions = intent.getStringArrayExtra(NotificationHelper.KEY_MENTIONS).orEmpty()

View File

@ -31,7 +31,6 @@ import android.util.Log
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.ServiceCompat import androidx.core.app.ServiceCompat
import androidx.core.content.IntentCompat
import at.connyduck.calladapter.networkresult.fold import at.connyduck.calladapter.networkresult.fold
import com.keylesspalace.tusky.MainActivity import com.keylesspalace.tusky.MainActivity
import com.keylesspalace.tusky.R 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.ScheduledStatus
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.getParcelableExtraCompat
import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.unsafeLazy
import dagger.android.AndroidInjection import dagger.android.AndroidInjection
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
@ -102,7 +102,7 @@ class SendStatusService : Service(), Injectable {
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
if (intent.hasExtra(KEY_STATUS)) { 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") ?: throw IllegalStateException("SendStatusService started without $KEY_STATUS extra")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
@ -247,11 +247,11 @@ class SendStatusService : Service(), Injectable {
scheduledAt = statusToSend.scheduledAt, scheduledAt = statusToSend.scheduledAt,
poll = statusToSend.poll, poll = statusToSend.poll,
language = statusToSend.language, language = statusToSend.language,
mediaAttributes = media.map { media -> mediaAttributes = media.map { mediaItem ->
MediaAttribute( MediaAttribute(
id = media.id!!, id = mediaItem.id!!,
description = media.description, description = mediaItem.description,
focus = media.focus?.toMastodonApiString(), focus = mediaItem.focus?.toMastodonApiString(),
thumbnail = null thumbnail = null
) )
} }

View File

@ -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 <reified T : Parcelable> Bundle.getParcelableCompat(key: String?): T? =
BundleCompat.getParcelable(this, key, T::class.java)
inline fun <reified T : Serializable> Bundle.getSerializableCompat(key: String?): T? =
BundleCompat.getSerializable(this, key, T::class.java)
inline fun <reified T : Parcelable> Intent.getParcelableExtraCompat(key: String?): T? =
IntentCompat.getParcelableExtra(this, key, T::class.java)
inline fun <reified T : Serializable> Intent.getSerializableExtraCompat(key: String?): T? =
IntentCompat.getSerializableExtra(this, key, T::class.java)
inline fun <reified T : Parcelable> Intent.getParcelableArrayListExtraCompat(key: String?): ArrayList<T>? =
IntentCompat.getParcelableArrayListExtra(this, key, T::class.java)

View File

@ -22,13 +22,13 @@ import android.net.Uri
import androidx.activity.result.contract.ActivityResultContract import androidx.activity.result.contract.ActivityResultContract
class PickMediaFiles : ActivityResultContract<Boolean, List<Uri>>() { class PickMediaFiles : ActivityResultContract<Boolean, List<Uri>>() {
override fun createIntent(context: Context, allowMultiple: Boolean): Intent { override fun createIntent(context: Context, input: Boolean): Intent {
return Intent(Intent.ACTION_GET_CONTENT) return Intent(Intent.ACTION_GET_CONTENT)
.addCategory(Intent.CATEGORY_OPENABLE) .addCategory(Intent.CATEGORY_OPENABLE)
.setType("*/*") .setType("*/*")
.apply { .apply {
putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*", "video/*", "audio/*")) putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*", "video/*", "audio/*"))
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, allowMultiple) putExtra(Intent.EXTRA_ALLOW_MULTIPLE, input)
} }
} }

View File

@ -19,7 +19,6 @@ package com.keylesspalace.tusky.util
import android.content.Context import android.content.Context
import android.content.res.Configuration import android.content.res.Configuration
import android.graphics.Color import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.appcompat.app.AppCompatDelegate 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) { fun setDrawableTint(context: Context, drawable: Drawable, @AttrRes attribute: Int) {
drawable.setColorFilter( drawable.setTint(MaterialColors.getColor(context, attribute, Color.BLACK))
MaterialColors.getColor(context, attribute, Color.BLACK),
PorterDuff.Mode.SRC_IN
)
} }
fun setAppNightMode(flavor: String?) { fun setAppNightMode(flavor: String?) {

View File

@ -189,8 +189,8 @@ class MediaPreviewLayout(context: Context, attrs: AttributeSet? = null) :
val wrapper = getChildAt(index) val wrapper = getChildAt(index)
action( action(
index, index,
wrapper.findViewById(R.id.preview_image_view) as MediaPreviewImageView, wrapper.findViewById(R.id.preview_image_view),
wrapper.findViewById(R.id.preview_media_description_indicator) as TextView wrapper.findViewById(R.id.preview_media_description_indicator)
) )
} }
} }