Add BundleCompat to fix getSerializable

This commit is contained in:
Wolf-Martell Montwé 2024-02-09 10:39:48 +01:00
parent 32277205e5
commit d6955d0520
No known key found for this signature in database
GPG key ID: 6D45B21512ACBF72
5 changed files with 121 additions and 19 deletions

View file

@ -26,6 +26,7 @@ import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.commit import androidx.fragment.app.commit
import androidx.fragment.app.commitNow import androidx.fragment.app.commitNow
import app.k9mail.core.android.common.compat.BundleCompat
import app.k9mail.core.android.common.contact.CachingRepository import app.k9mail.core.android.common.contact.CachingRepository
import app.k9mail.core.android.common.contact.ContactRepository import app.k9mail.core.android.common.contact.ContactRepository
import app.k9mail.feature.launcher.FeatureLauncherActivity import app.k9mail.feature.launcher.FeatureLauncherActivity
@ -168,6 +169,7 @@ open class MessageList :
window.statusBarColor = Color.TRANSPARENT window.statusBarColor = Color.TRANSPARENT
val rootLayout = findViewById<View>(R.id.drawerLayout) val rootLayout = findViewById<View>(R.id.drawerLayout)
rootLayout.systemUiVisibility = rootLayout.systemUiVisibility or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or rootLayout.systemUiVisibility = rootLayout.systemUiVisibility or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
@ -301,8 +303,13 @@ open class MessageList :
} }
if (savedInstanceState != null) { if (savedInstanceState != null) {
val savedDisplayMode = savedInstanceState.getSerializable(STATE_DISPLAY_MODE) as DisplayMode val savedDisplayMode = BundleCompat.getSerializable(
if (savedDisplayMode != DisplayMode.SPLIT_VIEW) { savedInstanceState,
STATE_DISPLAY_MODE,
DisplayMode::class.java,
)
if (savedDisplayMode != null && savedDisplayMode != DisplayMode.SPLIT_VIEW) {
displayMode = savedDisplayMode displayMode = savedDisplayMode
return return
} }

View file

@ -9,6 +9,7 @@ import android.widget.TextView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder import androidx.recyclerview.widget.RecyclerView.ViewHolder
import app.k9mail.core.android.common.compat.BundleCompat
import com.fsck.k9.ui.R import com.fsck.k9.ui.R
import com.fsck.k9.ui.base.loader.observeLoading import com.fsck.k9.ui.base.loader.observeLoading
import de.cketti.changelog.ReleaseItem import de.cketti.changelog.ReleaseItem
@ -20,7 +21,9 @@ import org.koin.core.parameter.parametersOf
*/ */
class ChangelogFragment : Fragment() { class ChangelogFragment : Fragment() {
private val viewModel: ChangelogViewModel by viewModel { private val viewModel: ChangelogViewModel by viewModel {
val mode = arguments?.getSerializable(ARG_MODE) as? ChangeLogMode ?: error("Missing argument '$ARG_MODE'") val mode = arguments?.let {
BundleCompat.getSerializable(it, ARG_MODE, ChangeLogMode::class.java)
} ?: error("Missing argument '$ARG_MODE'")
parametersOf(mode) parametersOf(mode)
} }
@ -85,6 +88,7 @@ class ChangelogAdapter(releaseItems: List<ReleaseItem>) : RecyclerView.Adapter<V
viewHolder.versionName.text = context.getString(R.string.changelog_version_title, item.versionName) viewHolder.versionName.text = context.getString(R.string.changelog_version_title, item.versionName)
viewHolder.versionDate.text = item.date viewHolder.versionDate.text = item.date
} }
is String -> { is String -> {
val viewHolder = holder as ChangeItemViewHolder val viewHolder = holder as ChangeItemViewHolder
viewHolder.changeText.text = item viewHolder.changeText.text = item

View file

@ -5,19 +5,13 @@ import java.util.Map;
import android.os.Bundle; import android.os.Bundle;
import com.fsck.k9.DI; import app.k9mail.core.android.common.compat.BundleCompat;
import timber.log.Timber;
import com.fsck.k9.Account; import com.fsck.k9.Account;
import com.fsck.k9.Account.MessageFormat; import com.fsck.k9.Account.MessageFormat;
import com.fsck.k9.Account.QuoteStyle; import com.fsck.k9.Account.QuoteStyle;
import com.fsck.k9.DI;
import com.fsck.k9.activity.MessageCompose; import com.fsck.k9.activity.MessageCompose;
import com.fsck.k9.activity.MessageCompose.Action; import com.fsck.k9.activity.MessageCompose.Action;
import com.fsck.k9.message.extractors.BodyTextExtractor;
import com.fsck.k9.message.html.HtmlConverter;
import com.fsck.k9.message.quote.HtmlQuoteCreator;
import com.fsck.k9.message.quote.TextQuoteCreator;
import com.fsck.k9.message.signature.HtmlSignatureRemover;
import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.Part; import com.fsck.k9.mail.Part;
import com.fsck.k9.mail.internet.MessageExtractor; import com.fsck.k9.mail.internet.MessageExtractor;
@ -25,11 +19,17 @@ import com.fsck.k9.mail.internet.MimeUtility;
import com.fsck.k9.mailstore.AttachmentResolver; import com.fsck.k9.mailstore.AttachmentResolver;
import com.fsck.k9.mailstore.MessageViewInfo; import com.fsck.k9.mailstore.MessageViewInfo;
import com.fsck.k9.message.IdentityField; import com.fsck.k9.message.IdentityField;
import com.fsck.k9.message.quote.InsertableHtmlContent;
import com.fsck.k9.message.MessageBuilder; import com.fsck.k9.message.MessageBuilder;
import com.fsck.k9.message.QuotedTextMode; import com.fsck.k9.message.QuotedTextMode;
import com.fsck.k9.message.SimpleMessageFormat; import com.fsck.k9.message.SimpleMessageFormat;
import com.fsck.k9.message.extractors.BodyTextExtractor;
import com.fsck.k9.message.html.HtmlConverter;
import com.fsck.k9.message.quote.HtmlQuoteCreator;
import com.fsck.k9.message.quote.InsertableHtmlContent;
import com.fsck.k9.message.quote.TextQuoteCreator;
import com.fsck.k9.message.signature.HtmlSignatureRemover;
import com.fsck.k9.message.signature.TextSignatureRemover; import com.fsck.k9.message.signature.TextSignatureRemover;
import timber.log.Timber;
public class QuotedMessagePresenter { public class QuotedMessagePresenter {
@ -154,17 +154,31 @@ public class QuotedMessagePresenter {
} }
public void onRestoreInstanceState(Bundle savedInstanceState) { public void onRestoreInstanceState(Bundle savedInstanceState) {
quotedHtmlContent = (InsertableHtmlContent) savedInstanceState.getSerializable(STATE_KEY_HTML_QUOTE); quotedHtmlContent = BundleCompat.INSTANCE.getSerializable(
savedInstanceState,
STATE_KEY_HTML_QUOTE,
InsertableHtmlContent.class
);
quotedTextFormat = BundleCompat.getSerializable(
savedInstanceState,
STATE_KEY_QUOTED_TEXT_FORMAT,
SimpleMessageFormat.class
);
forcePlainText = savedInstanceState.getBoolean(STATE_KEY_FORCE_PLAIN_TEXT);
showOrHideQuotedText(
BundleCompat.getSerializable(
savedInstanceState,
STATE_KEY_QUOTED_TEXT_MODE,
QuotedTextMode.class
)
);
if (quotedHtmlContent != null && quotedHtmlContent.getQuotedContent() != null) { if (quotedHtmlContent != null && quotedHtmlContent.getQuotedContent() != null) {
// we don't have the part here, but inline-displayed images are cached by the webview // we don't have the part here, but inline-displayed images are cached by the webview
view.setQuotedHtml(quotedHtmlContent.getQuotedContent(), null); view.setQuotedHtml(quotedHtmlContent.getQuotedContent(), null);
} }
quotedTextFormat = (SimpleMessageFormat) savedInstanceState.getSerializable(
STATE_KEY_QUOTED_TEXT_FORMAT);
forcePlainText = savedInstanceState.getBoolean(STATE_KEY_FORCE_PLAIN_TEXT);
showOrHideQuotedText(
(QuotedTextMode) savedInstanceState.getSerializable(STATE_KEY_QUOTED_TEXT_MODE));
} }
public void processMessageToForward(MessageViewInfo messageViewInfo) throws MessagingException { public void processMessageToForward(MessageViewInfo messageViewInfo) throws MessagingException {

View file

@ -0,0 +1,22 @@
package app.k9mail.core.android.common.compat
import android.os.Build
import android.os.Bundle
import java.io.Serializable
// This class resolves a deprecation warning and issue with the Bundle.getSerializable method
// Fixes https://issuetracker.google.com/issues/314250395
// Could be removed once releases in androidx.core.os.BundleCompat
object BundleCompat {
@JvmStatic
fun <T : Serializable> getSerializable(bundle: Bundle, key: String?, clazz: Class<T>): T? = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> bundle.getSerializable(key, clazz)
else -> {
@Suppress("DEPRECATION")
val serializable = bundle.getSerializable(key)
@Suppress("UNCHECKED_CAST")
if (clazz.isInstance(serializable)) serializable as T else null
}
}
}

View file

@ -0,0 +1,55 @@
package app.k9mail.core.android.common.compat
import android.os.Bundle
import assertk.assertThat
import assertk.assertions.isEqualTo
import java.io.Serializable
import kotlin.test.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class BundleCompatTest {
@Test
fun `getSerializable returns Serializable`() {
val bundle = Bundle()
val key = "keySerializable"
val serializable = TestSerializable("value")
val clazz = TestSerializable::class.java
bundle.putSerializable(key, serializable)
val result = BundleCompat.getSerializable(bundle, key, clazz)
assertThat(result).isEqualTo(serializable)
}
@Test
fun `getSerializable returns null when class mismatch`() {
val bundle = Bundle()
val key = "keySerializable"
val serializable = TestSerializable("value")
val clazz = OtherTestSerializable::class.java
bundle.putSerializable(key, serializable)
val result = BundleCompat.getSerializable(bundle, key, clazz)
assertThat(result).isEqualTo(null)
}
internal class TestSerializable(
val value: String,
) : Serializable {
companion object {
private const val serialVersionUID = 1L
}
}
internal class OtherTestSerializable(
val value: String,
) : Serializable {
companion object {
private const val serialVersionUID = 2L
}
}
}