Loading app/ui/legacy/build.gradle +4 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,10 @@ dependencies { implementation libs.fastadapter.extensions.drag implementation libs.fastadapter.extensions.utils implementation libs.circleimageview implementation libs.moshi implementation libs.moshi.kotlin implementation libs.gson implementation libs.androidx.datastore api libs.appauth implementation libs.commons.io Loading app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/EmailCache.kt 0 → 100644 +70 −0 Original line number Diff line number Diff line package com.fsck.k9.ui.messagelist import android.content.Context import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore import com.google.gson.Gson import com.google.gson.TypeAdapter import com.google.gson.reflect.TypeToken import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonToken import com.google.gson.stream.JsonWriter import com.squareup.moshi.Moshi import java.io.IOException import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.map import kotlinx.coroutines.runBlocking import timber.log.Timber class EmailCache constructor(private val context: Context, private val moshi: Moshi, private val gson: Gson) { companion object { private const val preferenceDataStoreName = "emailCache" private val Context.emailCacheDataStore by preferencesDataStore(preferenceDataStoreName) } private val MAIL_LIST_KEY = stringPreferencesKey("mail_list") suspend fun saveLatestMails(mailList: List<MessageListItem>) { // val type = Types.newParameterizedType(List::class.java, MessageListItem::class.java) // val adapter = moshi.adapter<List<MessageListItem>>(type) // val mailListJson = adapter.toJson(mailList) val listType = object : TypeToken<List<MessageListItem>>() {}.type val mailListJson = gson.toJson(mailList, listType) context.emailCacheDataStore.edit { it[MAIL_LIST_KEY] = mailListJson } } suspend fun getCachedMails(): List<MessageListItem>? { return runBlocking { val listType = object : TypeToken<List<MessageListItem>>() {}.type val mailListJson = context.emailCacheDataStore.data.map { it[MAIL_LIST_KEY] }.firstOrNull() Timber.d("email data: $mailListJson") gson.fromJson(mailListJson, listType) } } } internal class CharSequenceTypeAdapter : TypeAdapter<CharSequence?>() { @Throws(IOException::class) override fun write(out: JsonWriter, value: CharSequence?) { if (value == null) { out.nullValue() } else { // Assumes that value complies with CharSequence.toString() contract out.value(value.toString()) } } @Throws(IOException::class) override fun read(`in`: JsonReader): CharSequence? { return if (`in`.peek() === JsonToken.NULL) { // Skip the JSON null `in`.skipValue() null } else { `in`.nextString() } } } app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/KoinModule.kt +9 −1 Original line number Diff line number Diff line package com.fsck.k9.ui.messagelist import com.google.gson.Gson import com.google.gson.GsonBuilder import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import org.koin.android.ext.koin.androidContext import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.dsl.module Loading @@ -14,8 +19,11 @@ val messageListUiModule = module { messageHelper = get() ) } single { Moshi.Builder().add(KotlinJsonAdapterFactory()) .build() } single { GsonBuilder().registerTypeAdapter(CharSequence::class.java, CharSequenceTypeAdapter()).create() } single<EmailCache> { EmailCache(androidContext(), get(), get()) } factory { MessageListLiveDataFactory(messageListLoader = get(), preferences = get(), messageListRepository = get()) MessageListLiveDataFactory(messageListLoader = get(), preferences = get(), messageListRepository = get(), emailCache = get()) } single { SortTypeToastProvider() } } app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListLiveData.kt +7 −2 Original line number Diff line number Diff line Loading @@ -15,7 +15,8 @@ class MessageListLiveData( private val preferences: Preferences, private val messageListRepository: MessageListRepository, private val coroutineScope: CoroutineScope, val config: MessageListConfig val config: MessageListConfig, val emailCache: EmailCache ) : LiveData<MessageListInfo>() { private val messageListChangedListener = MessageListChangedListener { Loading @@ -24,10 +25,14 @@ class MessageListLiveData( private fun loadMessageListAsync() { coroutineScope.launch(Dispatchers.Main) { emailCache.getCachedMails()?.let { value = MessageListInfo(it, true) } val messageList = withContext(Dispatchers.IO) { messageListLoader.getMessageList(config) } value = messageList // value = messageList emailCache.saveLatestMails(messageList.messageListItems) } } Loading app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListLiveDataFactory.kt +3 −2 Original line number Diff line number Diff line Loading @@ -7,9 +7,10 @@ import kotlinx.coroutines.CoroutineScope class MessageListLiveDataFactory( private val messageListLoader: MessageListLoader, private val preferences: Preferences, private val messageListRepository: MessageListRepository private val messageListRepository: MessageListRepository, private val emailCache: EmailCache ) { fun create(coroutineScope: CoroutineScope, config: MessageListConfig): MessageListLiveData { return MessageListLiveData(messageListLoader, preferences, messageListRepository, coroutineScope, config) return MessageListLiveData(messageListLoader, preferences, messageListRepository, coroutineScope, config, emailCache) } } Loading
app/ui/legacy/build.gradle +4 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,10 @@ dependencies { implementation libs.fastadapter.extensions.drag implementation libs.fastadapter.extensions.utils implementation libs.circleimageview implementation libs.moshi implementation libs.moshi.kotlin implementation libs.gson implementation libs.androidx.datastore api libs.appauth implementation libs.commons.io Loading
app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/EmailCache.kt 0 → 100644 +70 −0 Original line number Diff line number Diff line package com.fsck.k9.ui.messagelist import android.content.Context import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore import com.google.gson.Gson import com.google.gson.TypeAdapter import com.google.gson.reflect.TypeToken import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonToken import com.google.gson.stream.JsonWriter import com.squareup.moshi.Moshi import java.io.IOException import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.map import kotlinx.coroutines.runBlocking import timber.log.Timber class EmailCache constructor(private val context: Context, private val moshi: Moshi, private val gson: Gson) { companion object { private const val preferenceDataStoreName = "emailCache" private val Context.emailCacheDataStore by preferencesDataStore(preferenceDataStoreName) } private val MAIL_LIST_KEY = stringPreferencesKey("mail_list") suspend fun saveLatestMails(mailList: List<MessageListItem>) { // val type = Types.newParameterizedType(List::class.java, MessageListItem::class.java) // val adapter = moshi.adapter<List<MessageListItem>>(type) // val mailListJson = adapter.toJson(mailList) val listType = object : TypeToken<List<MessageListItem>>() {}.type val mailListJson = gson.toJson(mailList, listType) context.emailCacheDataStore.edit { it[MAIL_LIST_KEY] = mailListJson } } suspend fun getCachedMails(): List<MessageListItem>? { return runBlocking { val listType = object : TypeToken<List<MessageListItem>>() {}.type val mailListJson = context.emailCacheDataStore.data.map { it[MAIL_LIST_KEY] }.firstOrNull() Timber.d("email data: $mailListJson") gson.fromJson(mailListJson, listType) } } } internal class CharSequenceTypeAdapter : TypeAdapter<CharSequence?>() { @Throws(IOException::class) override fun write(out: JsonWriter, value: CharSequence?) { if (value == null) { out.nullValue() } else { // Assumes that value complies with CharSequence.toString() contract out.value(value.toString()) } } @Throws(IOException::class) override fun read(`in`: JsonReader): CharSequence? { return if (`in`.peek() === JsonToken.NULL) { // Skip the JSON null `in`.skipValue() null } else { `in`.nextString() } } }
app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/KoinModule.kt +9 −1 Original line number Diff line number Diff line package com.fsck.k9.ui.messagelist import com.google.gson.Gson import com.google.gson.GsonBuilder import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import org.koin.android.ext.koin.androidContext import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.dsl.module Loading @@ -14,8 +19,11 @@ val messageListUiModule = module { messageHelper = get() ) } single { Moshi.Builder().add(KotlinJsonAdapterFactory()) .build() } single { GsonBuilder().registerTypeAdapter(CharSequence::class.java, CharSequenceTypeAdapter()).create() } single<EmailCache> { EmailCache(androidContext(), get(), get()) } factory { MessageListLiveDataFactory(messageListLoader = get(), preferences = get(), messageListRepository = get()) MessageListLiveDataFactory(messageListLoader = get(), preferences = get(), messageListRepository = get(), emailCache = get()) } single { SortTypeToastProvider() } }
app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListLiveData.kt +7 −2 Original line number Diff line number Diff line Loading @@ -15,7 +15,8 @@ class MessageListLiveData( private val preferences: Preferences, private val messageListRepository: MessageListRepository, private val coroutineScope: CoroutineScope, val config: MessageListConfig val config: MessageListConfig, val emailCache: EmailCache ) : LiveData<MessageListInfo>() { private val messageListChangedListener = MessageListChangedListener { Loading @@ -24,10 +25,14 @@ class MessageListLiveData( private fun loadMessageListAsync() { coroutineScope.launch(Dispatchers.Main) { emailCache.getCachedMails()?.let { value = MessageListInfo(it, true) } val messageList = withContext(Dispatchers.IO) { messageListLoader.getMessageList(config) } value = messageList // value = messageList emailCache.saveLatestMails(messageList.messageListItems) } } Loading
app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListLiveDataFactory.kt +3 −2 Original line number Diff line number Diff line Loading @@ -7,9 +7,10 @@ import kotlinx.coroutines.CoroutineScope class MessageListLiveDataFactory( private val messageListLoader: MessageListLoader, private val preferences: Preferences, private val messageListRepository: MessageListRepository private val messageListRepository: MessageListRepository, private val emailCache: EmailCache ) { fun create(coroutineScope: CoroutineScope, config: MessageListConfig): MessageListLiveData { return MessageListLiveData(messageListLoader, preferences, messageListRepository, coroutineScope, config) return MessageListLiveData(messageListLoader, preferences, messageListRepository, coroutineScope, config, emailCache) } }