Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dark theme (& Material You theming) for widget #8719

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
added new widget
vayun-mathur committed Jan 6, 2025
commit f91983db6fa9a381c7eb1298ef50065e8338e645
6 changes: 6 additions & 0 deletions feature/widget/message-list/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
plugins {
id(ThunderbirdPlugins.Library.android)
alias(libs.plugins.compose)
}

dependencies {
implementation(projects.legacy.ui.legacy)
implementation(projects.legacy.core)

implementation(libs.timber)
implementation(libs.androidx.glance.appwidget)
implementation(libs.androidx.glance.material3)
}

android {
buildFeatures {
compose = true
}
namespace = "app.k9mail.feature.widget.message.list"
}
9 changes: 9 additions & 0 deletions feature/widget/message-list/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -6,6 +6,15 @@
android:name=".MessageListWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS"
/>
<receiver android:name="MyAppWidgetReceiver"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename the class from MyAppWidgetReceiver to MessageListWidgetReceiver.

android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/my_app_widget_info" />
</receiver>

</application>
</manifest>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file should be renamed to MessageListWidget

Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package app.k9mail.feature.widget.message.list

import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.widget.LinearLayout
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.app.PendingIntentCompat
import androidx.glance.ColorFilter
import androidx.glance.GlanceComposable
import androidx.glance.GlanceId
import androidx.glance.GlanceModifier
import androidx.glance.GlanceTheme
import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.action.Action
import androidx.glance.action.clickable
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import androidx.glance.appwidget.components.CircleIconButton
import androidx.glance.appwidget.cornerRadius
import androidx.glance.appwidget.lazy.LazyColumn
import androidx.glance.appwidget.lazy.items
import androidx.glance.appwidget.provideContent
import androidx.glance.background
import androidx.glance.layout.Alignment
import androidx.glance.layout.Box
import androidx.glance.layout.Column
import androidx.glance.layout.Row
import androidx.glance.layout.Spacer
import androidx.glance.layout.fillMaxHeight
import androidx.glance.layout.fillMaxSize
import androidx.glance.layout.fillMaxWidth
import androidx.glance.layout.height
import androidx.glance.layout.padding
import androidx.glance.layout.width
import androidx.glance.layout.wrapContentHeight
import androidx.glance.material3.ColorProviders
import androidx.glance.text.Text
import androidx.glance.text.TextStyle
import app.k9mail.core.ui.legacy.designsystem.atom.icon.Icons
import app.k9mail.legacy.account.Account.SortType
import app.k9mail.legacy.message.controller.MessageReference
import app.k9mail.legacy.search.SearchAccount
import app.k9mail.legacy.search.SearchAccount.Companion.createUnifiedInboxAccount
import com.fsck.k9.CoreResourceProvider
import com.fsck.k9.K9
import com.fsck.k9.activity.MessageCompose
import com.fsck.k9.activity.MessageList.Companion.intentDisplaySearch
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename this class from MyAppWidgetReceiver to MessageListWidgetReceiver.

override val glanceAppWidget: GlanceAppWidget = MyAppWidget()
}



class MyAppWidget : GlanceAppWidget(), KoinComponent {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename this class from MyAppWidget to MessageListWidget.


private val messageListLoader: MessageListLoader by inject()
private val coreResourceProvider: CoreResourceProvider by inject()

override suspend fun provideGlance(context: Context, id: GlanceId) {

// In this method, load data needed to render the AppWidget.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this comment.

// Use `withContext` to switch to another thread for long running
// operations.

provideContent {
var mails by remember { mutableStateOf(emptyList<MessageListItem>()) }

LaunchedEffect(Unit) {
val unifiedInboxSearch = SearchAccount.createUnifiedInboxAccount(
unifiedInboxTitle = coreResourceProvider.searchUnifiedInboxTitle(),
unifiedInboxDetail = coreResourceProvider.searchUnifiedInboxDetail(),
).relatedSearch
val messageListConfig = MessageListConfig(
search = unifiedInboxSearch,
showingThreadedList = K9.isThreadedViewEnabled,
sortType = SortType.SORT_DATE,
sortAscending = false,
sortDateAscending = false,
)
mails = messageListLoader.getMessageList(messageListConfig)
}

GlanceTheme(GlanceTheme.colors) {
Column(GlanceModifier.fillMaxSize().background(GlanceTheme.colors.surface)) {
Row(
GlanceModifier.padding(horizontal = 8.dp, vertical = 12.dp).fillMaxWidth().background(GlanceTheme.colors.primaryContainer)
.clickable {
val unifiedInboxAccount = createUnifiedInboxAccount(
unifiedInboxTitle = coreResourceProvider.searchUnifiedInboxTitle(),
unifiedInboxDetail = coreResourceProvider.searchUnifiedInboxDetail(),
)
val intent = intentDisplaySearch(
context = context,
search = unifiedInboxAccount.relatedSearch,
noThreading = true,
newTask = true,
clearTop = true,
)
PendingIntentCompat.getActivity(context, -1, intent, PendingIntent.FLAG_UPDATE_CURRENT, false)!!.send()
}
) {
Text("Unified Inbox", style = TextStyle(color = GlanceTheme.colors.primary, fontSize = 20.sp))
Spacer(GlanceModifier.defaultWeight())
Image(ImageProvider(Icons.Outlined.Edit), null, GlanceModifier.padding(2.dp).padding(end = 6.dp).clickable {
val intent = Intent(context, MessageCompose::class.java).apply {
action = MessageCompose.ACTION_COMPOSE
}
PendingIntentCompat.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, false)!!.send()
}, colorFilter = ColorFilter.tint(GlanceTheme.colors.primary))
}
LazyColumn(GlanceModifier.fillMaxSize()) {
items(mails) {
Column {
ListItem(it)
Spacer(GlanceModifier.height(2.dp).fillMaxWidth().background(GlanceTheme.colors.surfaceVariant)
)
}
}
// ListItem(MessageListItem(
// "Wikipedia",
// "May 5",
// "Kinda long subject that should be long enough to exceed the available display space",
// "Towel Day is celebrated every year on 25 May as a tribute to the author Douglas Adams by his fans.",
// false,
// false,
// 1,
// Color.Blue.hashCode(),
// MessageReference("", 0, ""),
// 11,
// "",
// 1,
// 0,
// false,
// 0
// ))
}
}
}
}
}
}

@Composable
private fun ListItem(item: MessageListItem) {
Row(GlanceModifier.fillMaxWidth().wrapContentHeight()) {
Spacer(GlanceModifier.width(8.dp).background(Color(item.accountColor)))
Column(GlanceModifier.fillMaxWidth().padding(vertical = 4.dp, horizontal = 4.dp)) {
Row(GlanceModifier.fillMaxWidth()) {
Row(GlanceModifier.defaultWeight(), horizontalAlignment = Alignment.Start) {
Text(item.subject, style = TextStyle(color = GlanceTheme.colors.primary, fontSize = 16.sp), maxLines = 1)
}
Spacer(GlanceModifier.width(4.dp))
Row(horizontalAlignment = Alignment.End) {
Box(GlanceModifier.background(GlanceTheme.colors.primaryContainer).cornerRadius(8.dp).padding(2.dp)) {
Text(
item.threadCount.toString(),
style = TextStyle(color = GlanceTheme.colors.primary, fontSize = 13.sp)
)
}
Spacer(GlanceModifier.width(4.dp))
Text(item.displayDate, style = TextStyle(color = GlanceTheme.colors.primary))
}
}
Spacer(GlanceModifier.height(2.dp))
Row {
Text(item.displayName, style = TextStyle(color = GlanceTheme.colors.primary, fontSize = 15.sp), maxLines = 1)
}
Spacer(GlanceModifier.height(2.dp))
Row {
Text(item.preview, style = TextStyle(color = GlanceTheme.colors.primary, fontSize = 13.sp), maxLines = 1)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/glance_default_loading_layout"
android:minHeight="180dp"
android:minWidth="250dp"
android:minResizeWidth="110dp"
android:minResizeHeight="110dp"
android:previewImage="@drawable/message_list_widget_preview"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen|keyguard"
>
</appwidget-provider>
4 changes: 4 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ detektPlugin = "1.23.5"
detektPluginCompose = "0.4.18"
fastAdapter = "5.7.0"
forkhandlesBom = "2.20.0.0"
glanceMaterial3 = "1.1.1"
glide = "4.16.0"
gradle = "8.11.1"
http4kBom = "5.35.2.0"
@@ -99,6 +100,7 @@ tokenautocomplete = "4.0.0-beta01-k9mail02"
turbine = "1.2.0"
xmlpull = "1.0"
zxing = "3.5.3"
glanceAppwidget = "1.1.1"

[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
@@ -150,6 +152,7 @@ androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", versi
androidx-fragment = { module = "androidx.fragment:fragment", version.ref = "androidxFragment" }
androidx-fragment-compose = { module = "androidx.fragment:fragment-compose", version.ref = "androidxFragment" }
androidx-fragment-testing = { module = "androidx.fragment:fragment-testing", version.ref = "androidxFragment" }
androidx-glance-material3 = { module = "androidx.glance:glance-material3", version.ref = "glanceMaterial3" }
androidx-lifecycle-common = { module = "androidx.lifecycle:lifecycle-common", version.ref = "androidxLifecycle" }
androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidxLifecycle" }
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidxLifecycle" }
@@ -245,6 +248,7 @@ tokenautocomplete = { module = "de.cketti.temp:tokenautocomplete", version.ref =
turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" }
xmlpull = { module = "com.github.cketti:xmlpull-extracted-from-android", version.ref = "xmlpull" }
zxing = { module = "com.google.zxing:core", version.ref = "zxing" }
androidx-glance-appwidget = { group = "androidx.glance", name = "glance-appwidget", version.ref = "glanceAppwidget" }

[bundles]
shared-jvm-main = [