Merge pull request #6405 from thundernest/message_list_widget_module

Move the message list widget to its own module
This commit is contained in:
cketti 2022-10-19 10:46:56 +02:00 committed by GitHub
commit 8db1cd3a24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 195 additions and 117 deletions

View file

@ -7,6 +7,7 @@ if (rootProject.testCoverage) {
dependencies {
implementation project(":app:ui:legacy")
implementation project(":app:ui:message-list-widget")
implementation project(":app:core")
implementation project(":app:storage")
implementation project(":app:crypto-openpgp")

View file

@ -336,11 +336,6 @@
</intent-filter>
</receiver>
<service
android:name=".widget.list.MessageListWidgetService"
android:enabled="true"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<service
android:name=".notification.NotificationActionService"
android:enabled="true"/>

View file

@ -3,6 +3,7 @@ package com.fsck.k9
import android.app.Application
import android.content.res.Configuration
import android.content.res.Resources
import app.k9mail.ui.widget.list.MessageListWidgetProvider
import com.fsck.k9.activity.MessageCompose
import com.fsck.k9.controller.MessagingController
import com.fsck.k9.notification.NotificationChannelManager
@ -42,6 +43,7 @@ class App : Application() {
initializeAppLanguage()
updateNotificationChannelsOnAppLanguageChanges()
themeManager.init()
MessageListWidgetProvider.init(this)
messagingListenerProvider.listeners.forEach { listener ->
messagingController.addListener(listener)

View file

@ -1,5 +1,7 @@
package com.fsck.k9
import app.k9mail.ui.widget.list.MessageListWidgetUpdateListener
import app.k9mail.ui.widget.list.messageListWidgetModule
import com.fsck.k9.auth.createOAuthConfigurationProvider
import com.fsck.k9.backends.backendsModule
import com.fsck.k9.controller.ControllerExtension
@ -10,8 +12,7 @@ import com.fsck.k9.preferences.K9StoragePersister
import com.fsck.k9.preferences.StoragePersister
import com.fsck.k9.resources.resourcesModule
import com.fsck.k9.storage.storageModule
import com.fsck.k9.widget.list.MessageListWidgetUpdateListener
import com.fsck.k9.widget.list.messageListWidgetModule
import com.fsck.k9.widget.list.messageListWidgetConfigModule
import com.fsck.k9.widget.unread.UnreadWidgetUpdateListener
import com.fsck.k9.widget.unread.unreadWidgetModule
import org.koin.core.qualifier.named
@ -35,6 +36,7 @@ private val mainAppModule = module {
val appModules = listOf(
mainAppModule,
messageListWidgetConfigModule,
messageListWidgetModule,
unreadWidgetModule,
notificationModule,

View file

@ -1,8 +1,8 @@
package com.fsck.k9.widget.list
import app.k9mail.ui.widget.list.MessageListWidgetConfig
import org.koin.dsl.module
val messageListWidgetModule = module {
single { MessageListWidgetUpdateListener(context = get()) }
factory { MessageListLoader(preferences = get(), messageListRepository = get(), messageHelper = get()) }
val messageListWidgetConfigModule = module {
single<MessageListWidgetConfig> { K9MessageListWidgetConfig() }
}

View file

@ -1,104 +1,9 @@
package com.fsck.k9.widget.list
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.widget.RemoteViews
import com.fsck.k9.R
import com.fsck.k9.activity.MessageCompose
import com.fsck.k9.activity.MessageList
import com.fsck.k9.activity.MessageList.Companion.intentDisplaySearch
import com.fsck.k9.helper.PendingIntentCompat.FLAG_IMMUTABLE
import com.fsck.k9.helper.PendingIntentCompat.FLAG_MUTABLE
import com.fsck.k9.search.SearchAccount.Companion.createUnifiedInboxAccount
import app.k9mail.ui.widget.list.MessageListWidgetConfig
class MessageListWidgetProvider : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
class MessageListWidgetProvider : app.k9mail.ui.widget.list.MessageListWidgetProvider()
private fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
val views = RemoteViews(context.packageName, R.layout.message_list_widget_layout)
views.setTextViewText(R.id.folder, context.getString(com.fsck.k9.ui.R.string.integrated_inbox_title))
val intent = Intent(context, MessageListWidgetService::class.java).apply {
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
}
views.setRemoteAdapter(R.id.listView, intent)
val viewAction = viewActionTemplatePendingIntent(context)
views.setPendingIntentTemplate(R.id.listView, viewAction)
val composeAction = composeActionPendingIntent(context)
views.setOnClickPendingIntent(R.id.new_message, composeAction)
val headerClickAction = viewUnifiedInboxPendingIntent(context)
views.setOnClickPendingIntent(R.id.top_controls, headerClickAction)
appWidgetManager.updateAppWidget(appWidgetId, views)
}
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
if (intent.action == ACTION_UPDATE_MESSAGE_LIST) {
val appWidgetManager = AppWidgetManager.getInstance(context)
val appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.listView)
}
}
private fun viewActionTemplatePendingIntent(context: Context): PendingIntent {
val intent = Intent(context, MessageList::class.java).apply {
action = Intent.ACTION_VIEW
}
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or FLAG_MUTABLE)
}
private fun viewUnifiedInboxPendingIntent(context: Context): PendingIntent {
val unifiedInboxAccount = createUnifiedInboxAccount()
val intent = intentDisplaySearch(
context = context,
search = unifiedInboxAccount.relatedSearch,
noThreading = true,
newTask = true,
clearTop = true
)
return PendingIntent.getActivity(context, -1, intent, PendingIntent.FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
}
private fun composeActionPendingIntent(context: Context): PendingIntent {
val intent = Intent(context, MessageCompose::class.java).apply {
action = MessageCompose.ACTION_COMPOSE
}
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
}
companion object {
private const val ACTION_UPDATE_MESSAGE_LIST = "UPDATE_MESSAGE_LIST"
fun triggerMessageListWidgetUpdate(context: Context) {
val appContext = context.applicationContext
val widgetManager = AppWidgetManager.getInstance(appContext)
val widget = ComponentName(appContext, MessageListWidgetProvider::class.java)
val widgetIds = widgetManager.getAppWidgetIds(widget)
val intent = Intent(context, MessageListWidgetProvider::class.java).apply {
action = ACTION_UPDATE_MESSAGE_LIST
putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds)
}
context.sendBroadcast(intent)
}
}
internal class K9MessageListWidgetConfig : MessageListWidgetConfig {
override val providerClass = MessageListWidgetProvider::class.java
}

View file

@ -0,0 +1,44 @@
apply plugin: 'com.android.library'
apply plugin: 'org.jetbrains.kotlin.android'
dependencies {
implementation project(":app:ui:legacy")
implementation project(":app:core")
implementation "com.jakewharton.timber:timber:${versions.timber}"
}
android {
namespace 'app.k9mail.ui.widget.list'
compileSdkVersion buildConfig.compileSdk
buildToolsVersion buildConfig.buildTools
defaultConfig {
minSdkVersion buildConfig.minSdk
targetSdkVersion buildConfig.robolectricSdk
}
buildTypes {
debug {
manifestPlaceholders = ['appAuthRedirectScheme': 'FIXME: override this in your app project']
}
release {
manifestPlaceholders = ['appAuthRedirectScheme': 'FIXME: override this in your app project']
}
}
lintOptions {
abortOnError false
lintConfig file("$rootProject.projectDir/config/lint/lint.xml")
}
compileOptions {
sourceCompatibility javaVersion
targetCompatibility javaVersion
}
kotlinOptions {
jvmTarget = kotlinJvmVersion
}
}

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<service
android:name=".MessageListWidgetService"
android:enabled="true"
android:permission="android.permission.BIND_REMOTEVIEWS" />
</application>
</manifest>

View file

@ -0,0 +1,8 @@
package app.k9mail.ui.widget.list
import org.koin.dsl.module
val messageListWidgetModule = module {
single { MessageListWidgetUpdateListener(context = get()) }
factory { MessageListLoader(preferences = get(), messageListRepository = get(), messageHelper = get()) }
}

View file

@ -1,4 +1,4 @@
package com.fsck.k9.widget.list
package app.k9mail.ui.widget.list
import com.fsck.k9.Account.SortType
import com.fsck.k9.search.LocalSearch

View file

@ -1,4 +1,4 @@
package com.fsck.k9.widget.list
package app.k9mail.ui.widget.list
import android.net.Uri

View file

@ -1,4 +1,4 @@
package com.fsck.k9.widget.list
package app.k9mail.ui.widget.list
import android.net.Uri
import com.fsck.k9.Account

View file

@ -1,4 +1,4 @@
package com.fsck.k9.widget.list
package app.k9mail.ui.widget.list
import com.fsck.k9.Account
import com.fsck.k9.Account.SortType

View file

@ -1,4 +1,4 @@
package com.fsck.k9.widget.list
package app.k9mail.ui.widget.list
import android.content.Context
import android.content.Intent
@ -11,7 +11,6 @@ import android.widget.RemoteViewsService.RemoteViewsFactory
import androidx.core.content.ContextCompat
import com.fsck.k9.Account.SortType
import com.fsck.k9.K9
import com.fsck.k9.R
import com.fsck.k9.search.LocalSearch
import com.fsck.k9.search.SearchAccount
import org.koin.core.component.KoinComponent

View file

@ -0,0 +1,5 @@
package app.k9mail.ui.widget.list
interface MessageListWidgetConfig {
val providerClass: Class<out MessageListWidgetProvider>
}

View file

@ -0,0 +1,105 @@
package app.k9mail.ui.widget.list
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.widget.RemoteViews
import com.fsck.k9.activity.MessageCompose
import com.fsck.k9.activity.MessageList
import com.fsck.k9.activity.MessageList.Companion.intentDisplaySearch
import com.fsck.k9.helper.PendingIntentCompat.FLAG_IMMUTABLE
import com.fsck.k9.helper.PendingIntentCompat.FLAG_MUTABLE
import com.fsck.k9.search.SearchAccount.Companion.createUnifiedInboxAccount
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import com.fsck.k9.ui.R as UiR
open class MessageListWidgetProvider : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
private fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
val views = RemoteViews(context.packageName, R.layout.message_list_widget_layout)
views.setTextViewText(R.id.folder, context.getString(UiR.string.integrated_inbox_title))
val intent = Intent(context, MessageListWidgetService::class.java)
views.setRemoteAdapter(R.id.listView, intent)
val viewAction = viewActionTemplatePendingIntent(context)
views.setPendingIntentTemplate(R.id.listView, viewAction)
val composeAction = composeActionPendingIntent(context)
views.setOnClickPendingIntent(R.id.new_message, composeAction)
val headerClickAction = viewUnifiedInboxPendingIntent(context)
views.setOnClickPendingIntent(R.id.top_controls, headerClickAction)
appWidgetManager.updateAppWidget(appWidgetId, views)
}
private fun viewActionTemplatePendingIntent(context: Context): PendingIntent {
val intent = Intent(context, MessageList::class.java).apply {
action = Intent.ACTION_VIEW
}
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or FLAG_MUTABLE)
}
private fun viewUnifiedInboxPendingIntent(context: Context): PendingIntent {
val unifiedInboxAccount = createUnifiedInboxAccount()
val intent = intentDisplaySearch(
context = context,
search = unifiedInboxAccount.relatedSearch,
noThreading = true,
newTask = true,
clearTop = true
)
return PendingIntent.getActivity(context, -1, intent, PendingIntent.FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
}
private fun composeActionPendingIntent(context: Context): PendingIntent {
val intent = Intent(context, MessageCompose::class.java).apply {
action = MessageCompose.ACTION_COMPOSE
}
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
}
companion object : KoinComponent {
private val messageListWidgetConfig: MessageListWidgetConfig by inject()
fun init(context: Context) {
resetMessageListWidget(context)
}
private fun resetMessageListWidget(context: Context) {
val appWidgetManager = AppWidgetManager.getInstance(context)
val providerClass = messageListWidgetConfig.providerClass
val componentName = ComponentName(context, providerClass)
val appWidgetIds = appWidgetManager.getAppWidgetIds(componentName)
val intent = Intent(context, providerClass).apply {
action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)
}
context.sendBroadcast(intent)
}
fun triggerMessageListWidgetUpdate(context: Context) {
val appWidgetManager = AppWidgetManager.getInstance(context)
val providerClass = messageListWidgetConfig.providerClass
val componentName = ComponentName(context, providerClass)
val appWidgetIds = appWidgetManager.getAppWidgetIds(componentName)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.listView)
}
}
}

View file

@ -1,4 +1,4 @@
package com.fsck.k9.widget.list
package app.k9mail.ui.widget.list
import android.content.Intent
import android.widget.RemoteViewsService

View file

@ -1,4 +1,4 @@
package com.fsck.k9.widget.list
package app.k9mail.ui.widget.list
import android.content.Context
import com.fsck.k9.Account

View file

@ -2,6 +2,7 @@ include ':app:k9mail'
include ':app:ui:base'
include ':app:ui:setup'
include ':app:ui:legacy'
include ':app:ui:message-list-widget'
include ':app:core'
include ':app:storage'
include ':app:crypto-openpgp'