diff --git a/Jetchat/README.md b/Jetchat/README.md
index 992389bdb5..0433a4585d 100644
--- a/Jetchat/README.md
+++ b/Jetchat/README.md
@@ -25,6 +25,10 @@ This sample showcases:
+
+
+
+
### Status: 🚧 In progress
Jetchat is still in under development, and some features are not yet implemented.
diff --git a/Jetchat/app/build.gradle.kts b/Jetchat/app/build.gradle.kts
index f23f12439e..4972acab23 100644
--- a/Jetchat/app/build.gradle.kts
+++ b/Jetchat/app/build.gradle.kts
@@ -87,6 +87,8 @@ dependencies {
implementation(composeBom)
androidTestImplementation(composeBom)
+ implementation(libs.androidx.glance.appwidget)
+ implementation(libs.androidx.glance.material3)
implementation(libs.kotlin.stdlib)
implementation(libs.kotlinx.coroutines.android)
diff --git a/Jetchat/app/src/main/AndroidManifest.xml b/Jetchat/app/src/main/AndroidManifest.xml
index 602380c02e..064d10dd21 100644
--- a/Jetchat/app/src/main/AndroidManifest.xml
+++ b/Jetchat/app/src/main/AndroidManifest.xml
@@ -35,6 +35,14 @@
-
+
+
+
+
+
+
diff --git a/Jetchat/app/src/main/java/com/example/compose/jetchat/components/JetchatDrawer.kt b/Jetchat/app/src/main/java/com/example/compose/jetchat/components/JetchatDrawer.kt
index 5a5d11e482..8081baa1d4 100644
--- a/Jetchat/app/src/main/java/com/example/compose/jetchat/components/JetchatDrawer.kt
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/components/JetchatDrawer.kt
@@ -16,6 +16,11 @@
package com.example.compose.jetchat.components
+import android.appwidget.AppWidgetManager
+import android.content.ComponentName
+import android.content.Context
+import android.os.Build
+import android.widget.Toast
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -44,13 +49,16 @@ import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.compose.jetchat.R
import com.example.compose.jetchat.data.colleagueProfile
import com.example.compose.jetchat.data.meProfile
import com.example.compose.jetchat.theme.JetchatTheme
+import com.example.compose.jetchat.widget.WidgetReceiver
@Composable
fun JetchatDrawerContent(
@@ -73,9 +81,13 @@ fun JetchatDrawerContent(
ProfileItem("Taylor Brooks", colleagueProfile.photo) {
onProfileClicked(colleagueProfile.userId)
}
+ DividerItem(modifier = Modifier.padding(horizontal = 28.dp))
+ DrawerItemHeader("Settings")
+ WidgetDiscoverability()
}
}
+
@Composable
private fun DrawerHeader() {
Row(modifier = Modifier.padding(16.dp), verticalAlignment = CenterVertically) {
@@ -90,6 +102,7 @@ private fun DrawerHeader() {
)
}
}
+
@Composable
private fun DrawerItemHeader(text: String) {
Box(
@@ -199,6 +212,7 @@ fun DrawerPreview() {
}
}
}
+
@Composable
@Preview
fun DrawerPreviewDark() {
@@ -210,3 +224,50 @@ fun DrawerPreviewDark() {
}
}
}
+
+
+@Composable
+private fun WidgetDiscoverability() {
+ val context = LocalContext.current
+ Row(
+ modifier = Modifier
+ .height(56.dp)
+ .fillMaxWidth()
+ .padding(horizontal = 12.dp)
+ .clip(CircleShape)
+ .clickable(onClick = {
+ addWidgetToHomeScreen(context)
+ }),
+ verticalAlignment = CenterVertically
+ ) {
+ Text(
+ stringResource(id = R.string.add_widget_to_home_page),
+ style = MaterialTheme.typography.bodyMedium,
+ color = MaterialTheme.colorScheme.onSurface,
+ modifier = Modifier.padding(start = 12.dp)
+ )
+ }
+}
+
+private fun addWidgetToHomeScreen(context: Context) {
+ val appWidgetManager = AppWidgetManager.getInstance(context)
+ val myProvider = ComponentName(context, WidgetReceiver::class.java)
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ if (appWidgetManager.isRequestPinAppWidgetSupported) {
+ appWidgetManager.requestPinAppWidget(myProvider, null, null)
+ } else {
+ Toast.makeText(
+ context,
+ "Unable to add widget, please add from home screen",
+ Toast.LENGTH_LONG
+ ).show()
+ }
+ } else {
+ Toast.makeText(
+ context,
+ "Unable to add widget, please add from home screen",
+ Toast.LENGTH_LONG
+ ).show()
+ }
+}
diff --git a/Jetchat/app/src/main/java/com/example/compose/jetchat/conversation/ConversationUiState.kt b/Jetchat/app/src/main/java/com/example/compose/jetchat/conversation/ConversationUiState.kt
index 452e4eeb41..edd61c738d 100644
--- a/Jetchat/app/src/main/java/com/example/compose/jetchat/conversation/ConversationUiState.kt
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/conversation/ConversationUiState.kt
@@ -39,5 +39,5 @@ data class Message(
val content: String,
val timestamp: String,
val image: Int? = null,
- val authorImage: Int = if (author == "me") R.drawable.ali else R.drawable.someone_else
+ val authorImage: Int = if (author == "me") R.drawable.ali else R.drawable.someone_else,
)
diff --git a/Jetchat/app/src/main/java/com/example/compose/jetchat/data/FakeData.kt b/Jetchat/app/src/main/java/com/example/compose/jetchat/data/FakeData.kt
index 1c996a40d3..a37b493349 100644
--- a/Jetchat/app/src/main/java/com/example/compose/jetchat/data/FakeData.kt
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/data/FakeData.kt
@@ -64,6 +64,58 @@ private val initialMessages = listOf(
"8:03 PM"
)
)
+val unreadMessages = listOf(
+ Message(
+ "Taylor Brooks",
+ "You can use all the same stuff",
+ "8:05 PM"
+ ),
+ Message(
+ "Taylor Brooks",
+ "@aliconors Take a look at the `Flow.collectAsStateWithLifecycle()` APIs",
+ "8:05 PM"
+ ),
+ Message(
+ "Taylor Brooks",
+ "You can use all the same stuff",
+ "8:05 PM"
+ ),
+ Message(
+ "Taylor Brooks",
+ "@aliconors Take a look at the `Flow.collectAsStateWithLifecycle()` APIs",
+ "8:05 PM"
+ ),
+ Message(
+ "Taylor Brooks",
+ "You can use all the same stuff",
+ "8:05 PM"
+ ),
+ Message(
+ "Taylor Brooks",
+ "@aliconors Take a look at the `Flow.collectAsStateWithLifecycle()` APIs",
+ "8:05 PM"
+ ),
+ Message(
+ "Taylor Brooks",
+ "You can use all the same stuff",
+ "8:05 PM"
+ ),
+ Message(
+ "Taylor Brooks",
+ "@aliconors Take a look at the `Flow.collectAsStateWithLifecycle()` APIs",
+ "8:05 PM"
+ ),
+ Message(
+ "Taylor Brooks",
+ "You can use all the same stuff",
+ "8:05 PM"
+ ),
+ Message(
+ "Taylor Brooks",
+ "@aliconors Take a look at the `Flow.collectAsStateWithLifecycle()` APIs",
+ "8:05 PM"
+ ),
+)
val exampleUiState = ConversationUiState(
initialMessages = initialMessages,
diff --git a/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/JetChatWidget.kt b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/JetChatWidget.kt
new file mode 100644
index 0000000000..747db7cf8e
--- /dev/null
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/JetChatWidget.kt
@@ -0,0 +1,19 @@
+package com.example.compose.jetchat.widget
+
+import android.content.Context
+import androidx.glance.GlanceId
+import androidx.glance.GlanceTheme
+import androidx.glance.appwidget.GlanceAppWidget
+import androidx.glance.appwidget.provideContent
+import com.example.compose.jetchat.widget.composables.MessagesWidget
+
+class JetChatWidget : GlanceAppWidget() {
+
+ override suspend fun provideGlance(context: Context, id: GlanceId) {
+ provideContent {
+ GlanceTheme {
+ MessagesWidget()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/WidgetReceiver.kt b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/WidgetReceiver.kt
new file mode 100644
index 0000000000..e96306395c
--- /dev/null
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/WidgetReceiver.kt
@@ -0,0 +1,11 @@
+package com.example.compose.jetchat.widget
+
+import androidx.glance.appwidget.GlanceAppWidget
+import androidx.glance.appwidget.GlanceAppWidgetReceiver
+
+class WidgetReceiver : GlanceAppWidgetReceiver() {
+
+ override val glanceAppWidget: GlanceAppWidget
+ get() = JetChatWidget()
+
+}
\ No newline at end of file
diff --git a/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/composables/MessagesWidget.kt b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/composables/MessagesWidget.kt
new file mode 100644
index 0000000000..db42c8d57c
--- /dev/null
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/composables/MessagesWidget.kt
@@ -0,0 +1,60 @@
+package com.example.compose.jetchat.widget.composables
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.unit.dp
+import androidx.glance.GlanceModifier
+import androidx.glance.ImageProvider
+import androidx.glance.LocalContext
+import androidx.glance.action.actionStartActivity
+import androidx.glance.action.clickable
+import androidx.glance.appwidget.components.Scaffold
+import androidx.glance.appwidget.components.TitleBar
+import androidx.glance.appwidget.lazy.LazyColumn
+import androidx.glance.layout.Column
+import androidx.glance.layout.Spacer
+import androidx.glance.layout.fillMaxWidth
+import androidx.glance.layout.height
+import androidx.glance.text.FontWeight
+import androidx.glance.text.Text
+import androidx.glance.text.TextStyle
+import com.example.compose.jetchat.NavActivity
+import com.example.compose.jetchat.R
+import com.example.compose.jetchat.conversation.Message
+import com.example.compose.jetchat.data.unreadMessages
+
+@Composable
+fun MessagesWidget() {
+ Scaffold(titleBar = {
+ TitleBar(
+ startIcon = ImageProvider(R.drawable.ic_jetchat),
+ iconColor = null,
+ title = LocalContext.current.getString(R.string.app_name_unreads),
+ )
+ }) {
+ val unreadMessage = unreadMessages
+ LazyColumn(modifier = GlanceModifier.fillMaxWidth()) {
+ unreadMessage.forEach {
+ item {
+ Column(modifier = GlanceModifier.fillMaxWidth()) {
+ MessageItem(it)
+ Spacer(modifier = GlanceModifier.height(10.dp))
+ }
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun MessageItem(message: Message) {
+ Column(modifier = GlanceModifier.clickable(actionStartActivity()).fillMaxWidth()) {
+ Text(
+ text = message.author,
+ style = TextStyle(fontWeight = FontWeight.Bold)
+ )
+ Text(
+ text = message.content,
+ style = TextStyle(fontWeight = FontWeight.Normal)
+ )
+ }
+}
\ No newline at end of file
diff --git a/Jetchat/app/src/main/res/drawable/widget_icon.png b/Jetchat/app/src/main/res/drawable/widget_icon.png
new file mode 100644
index 0000000000..70d386ee16
Binary files /dev/null and b/Jetchat/app/src/main/res/drawable/widget_icon.png differ
diff --git a/Jetchat/app/src/main/res/layout/widget_error_layout.xml b/Jetchat/app/src/main/res/layout/widget_error_layout.xml
new file mode 100644
index 0000000000..dceb0aa87c
--- /dev/null
+++ b/Jetchat/app/src/main/res/layout/widget_error_layout.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Jetchat/app/src/main/res/layout/widget_loading_layout.xml b/Jetchat/app/src/main/res/layout/widget_loading_layout.xml
new file mode 100644
index 0000000000..baa2d8ac39
--- /dev/null
+++ b/Jetchat/app/src/main/res/layout/widget_loading_layout.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Jetchat/app/src/main/res/values/strings.xml b/Jetchat/app/src/main/res/values/strings.xml
index aae598c1fe..020432ab25 100644
--- a/Jetchat/app/src/main/res/values/strings.xml
+++ b/Jetchat/app/src/main/res/values/strings.xml
@@ -67,5 +67,8 @@
More options
Touch and hold to record
Record voice message
+ Cannot load Widget
+ JetChat (Un-Reads)
+ Add Widget to Home Page
diff --git a/Jetchat/app/src/main/res/xml/my_app_widget_info.xml b/Jetchat/app/src/main/res/xml/my_app_widget_info.xml
new file mode 100644
index 0000000000..dd3ae12af4
--- /dev/null
+++ b/Jetchat/app/src/main/res/xml/my_app_widget_info.xml
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/Jetchat/screenshots/widget.png b/Jetchat/screenshots/widget.png
new file mode 100644
index 0000000000..7a3cf48e39
Binary files /dev/null and b/Jetchat/screenshots/widget.png differ
diff --git a/Jetchat/screenshots/widget_discoverability.png b/Jetchat/screenshots/widget_discoverability.png
new file mode 100644
index 0000000000..a59e4d5b09
Binary files /dev/null and b/Jetchat/screenshots/widget_discoverability.png differ