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
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

View File

@ -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<ComposeActivity.ComposeOptions>(COMPOSE_OPTIONS)
val composeIntent = if (composeOptions != null) {
ComposeActivity.startIntent(this, composeOptions)

View File

@ -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 {

View File

@ -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

View File

@ -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<Emoji> customEmojis, @NonNull StatusDisplayOptions statusDisplayOptions) {
protected void setDisplayName(@NonNull String name, @NonNull List<Emoji> 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()) &&

View File

@ -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;

View File

@ -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<Type>(EXTRA_TYPE)!!
val id: String? = intent.getStringExtra(EXTRA_ID)
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.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)
}
)
}

View File

@ -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<Uri>(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<Uri>(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 {

View File

@ -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<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.
Glide.with(this)

View File

@ -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.

View File

@ -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(

View File

@ -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<LoginData, LoginResult>() {
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<LoginData, LoginResult>() {
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 {

View File

@ -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
)
}
)

View File

@ -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
}

View File

@ -112,7 +112,6 @@ class PreferencesActivity :
pref.fragment!!
)
fragment.arguments = args
fragment.setTargetFragment(caller, 0)
supportFragmentManager.commit {
setCustomAnimations(
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.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)

View File

@ -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<Attachment>(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

View File

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

View File

@ -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<Attachment>(ARG_ATTACHMENT)
val attachment = arguments?.getParcelableCompat<Attachment>(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
}

View File

@ -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<Status.Visibility>(NotificationHelper.KEY_VISIBILITY)!!
val spoiler = intent.getStringExtra(NotificationHelper.KEY_SPOILER).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.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
)
}

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
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)
.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)
}
}

View File

@ -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?) {

View File

@ -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)
)
}
}