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..b4ea01d944 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..1a78f008c1 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,7 +16,13 @@
package com.example.compose.jetchat.components
+import android.appwidget.AppWidgetManager
+import android.content.ComponentName
+import android.content.Context
+import android.os.Build
+import androidx.annotation.ChecksSdkIntAtLeast
import androidx.annotation.DrawableRes
+import androidx.annotation.RequiresApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -33,7 +39,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.windowInsetsTopHeight
import androidx.compose.foundation.shape.CircleShape
-import androidx.compose.material3.Divider
+import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
@@ -44,13 +50,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,6 +82,11 @@ fun JetchatDrawerContent(
ProfileItem("Taylor Brooks", colleagueProfile.photo) {
onProfileClicked(colleagueProfile.userId)
}
+ if (widgetAddingIsSupported(LocalContext.current)) {
+ DividerItem(modifier = Modifier.padding(horizontal = 28.dp))
+ DrawerItemHeader("Settings")
+ WidgetDiscoverability()
+ }
}
}
@@ -90,6 +104,7 @@ private fun DrawerHeader() {
)
}
}
+
@Composable
private fun DrawerItemHeader(text: String) {
Box(
@@ -182,7 +197,7 @@ private fun ProfileItem(text: String, @DrawableRes profilePic: Int?, onProfileCl
@Composable
fun DividerItem(modifier: Modifier = Modifier) {
- Divider(
+ HorizontalDivider(
modifier = modifier,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f)
)
@@ -199,6 +214,7 @@ fun DrawerPreview() {
}
}
}
+
@Composable
@Preview
fun DrawerPreviewDark() {
@@ -210,3 +226,42 @@ fun DrawerPreviewDark() {
}
}
}
+
+@RequiresApi(Build.VERSION_CODES.O)
+@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)
+ )
+ }
+}
+
+@RequiresApi(Build.VERSION_CODES.O)
+private fun addWidgetToHomeScreen(context: Context) {
+ val appWidgetManager = AppWidgetManager.getInstance(context)
+ val myProvider = ComponentName(context, WidgetReceiver::class.java)
+ if (widgetAddingIsSupported(context)) {
+ appWidgetManager.requestPinAppWidget(myProvider, null, null)
+ }
+}
+
+@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.O)
+private fun widgetAddingIsSupported(context: Context): Boolean {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
+ AppWidgetManager.getInstance(context).isRequestPinAppWidgetSupported
+}
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..102930dd64 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
@@ -26,7 +26,7 @@ import com.example.compose.jetchat.data.EMOJIS.EMOJI_PINK_HEART
import com.example.compose.jetchat.data.EMOJIS.EMOJI_POINTS
import com.example.compose.jetchat.profile.ProfileScreenState
-private val initialMessages = listOf(
+val initialMessages = listOf(
Message(
"me",
"Check it out!",
@@ -62,9 +62,26 @@ private val initialMessages = listOf(
"loading but haven’t found any good ones $EMOJI_MELTING $EMOJI_CLOUDS. " +
"What’s the recommended way to load async data and emit composable widgets?",
"8:03 PM"
- )
+ ),
+ Message(
+ "Shangeeth Sivan",
+ "Does anyone know about Glance Widgets its the new way to build widgets in Android!",
+ "8:08 PM"
+ ),
+ Message(
+ "Taylor Brooks",
+ "Wow! I never knew about Glance Widgets when was this added to the android ecosystem",
+ "8:10 PM"
+ ),
+ Message(
+ "John Glenn",
+ "Yeah its seems to be pretty new!",
+ "8:12 PM"
+ ),
)
+val unreadMessages = initialMessages.filter { it.author != "me" }
+
val exampleUiState = ConversationUiState(
initialMessages = initialMessages,
channelName = "#composers",
diff --git a/Jetchat/app/src/main/java/com/example/compose/jetchat/theme/Themes.kt b/Jetchat/app/src/main/java/com/example/compose/jetchat/theme/Themes.kt
index 667ef184f8..8fce79255d 100644
--- a/Jetchat/app/src/main/java/com/example/compose/jetchat/theme/Themes.kt
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/theme/Themes.kt
@@ -28,7 +28,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
-private val JetchatDarkColorScheme = darkColorScheme(
+val JetchatDarkColorScheme = darkColorScheme(
primary = Blue80,
onPrimary = Blue20,
primaryContainer = Blue30,
@@ -57,7 +57,7 @@ private val JetchatDarkColorScheme = darkColorScheme(
outline = BlueGrey60
)
-private val JetchatLightColorScheme = lightColorScheme(
+val JetchatLightColorScheme = lightColorScheme(
primary = Blue40,
onPrimary = Color.White,
primaryContainer = Blue90,
@@ -83,7 +83,7 @@ private val JetchatLightColorScheme = lightColorScheme(
inverseOnSurface = Grey95,
surfaceVariant = BlueGrey90,
onSurfaceVariant = BlueGrey30,
- outline = BlueGrey50
+ outline = BlueGrey50,
)
@SuppressLint("NewApi")
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..437309351f
--- /dev/null
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/JetChatWidget.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+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.data.unreadMessages
+import com.example.compose.jetchat.widget.composables.MessagesWidget
+
+class JetChatWidget : GlanceAppWidget() {
+
+ override suspend fun provideGlance(context: Context, id: GlanceId) {
+ provideContent {
+ GlanceTheme {
+ MessagesWidget(unreadMessages.toList())
+ }
+ }
+ }
+}
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..ad67c3d170
--- /dev/null
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/WidgetReceiver.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+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()
+}
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..0f6c4ea1a9
--- /dev/null
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/composables/MessagesWidget.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.compose.jetchat.widget.composables
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.tooling.preview.Preview
+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.Text
+import com.example.compose.jetchat.NavActivity
+import com.example.compose.jetchat.R
+import com.example.compose.jetchat.conversation.Message
+import com.example.compose.jetchat.widget.theme.JetChatGlanceTextStyles
+import com.example.compose.jetchat.widget.theme.JetchatGlanceColorScheme
+
+@Composable
+fun MessagesWidget(messages: List) {
+ Scaffold(titleBar = {
+ TitleBar(
+ startIcon = ImageProvider(R.drawable.ic_jetchat),
+ iconColor = null,
+ title = LocalContext.current.getString(R.string.messages_widget_title),
+ )
+ }, backgroundColor = JetchatGlanceColorScheme.colors.background) {
+ LazyColumn(modifier = GlanceModifier.fillMaxWidth()) {
+ messages.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 = JetChatGlanceTextStyles.titleMedium
+ )
+ Text(
+ text = message.content,
+ style = JetChatGlanceTextStyles.bodyMedium,
+ )
+ }
+}
+
+@Preview
+@Composable
+fun MessageItemPreview() {
+ MessageItem(Message("John", "This is a preview of the message Item", "8:02PM"))
+}
+
+@Preview
+@Composable
+fun WidgetPreview() {
+ MessagesWidget(listOf(Message("John", "This is a preview of the message Item", "8:02PM")))
+}
diff --git a/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/theme/Theme.kt b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/theme/Theme.kt
new file mode 100644
index 0000000000..12a7199a95
--- /dev/null
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/theme/Theme.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.compose.jetchat.widget.theme
+
+import androidx.glance.material3.ColorProviders
+import com.example.compose.jetchat.theme.JetchatDarkColorScheme
+import com.example.compose.jetchat.theme.JetchatLightColorScheme
+
+object JetchatGlanceColorScheme {
+ val colors = ColorProviders(
+ light = JetchatLightColorScheme,
+ dark = JetchatDarkColorScheme,
+ )
+}
diff --git a/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/theme/Type.kt b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/theme/Type.kt
new file mode 100644
index 0000000000..99b1b4183e
--- /dev/null
+++ b/Jetchat/app/src/main/java/com/example/compose/jetchat/widget/theme/Type.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.compose.jetchat.widget.theme
+
+import androidx.compose.ui.unit.sp
+import androidx.glance.text.FontWeight
+import androidx.glance.text.TextStyle
+
+object JetChatGlanceTextStyles {
+
+ val titleMedium = TextStyle(
+ fontSize = 16.sp,
+ color = JetchatGlanceColorScheme.colors.onSurfaceVariant,
+ fontWeight = FontWeight.Bold
+ )
+ val bodyMedium = TextStyle(
+ fontSize = 16.sp,
+ color = JetchatGlanceColorScheme.colors.onSurfaceVariant,
+ fontWeight = FontWeight.Normal
+ )
+}
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/values/strings.xml b/Jetchat/app/src/main/res/values/strings.xml
index aae598c1fe..bc04038a7a 100644
--- a/Jetchat/app/src/main/res/values/strings.xml
+++ b/Jetchat/app/src/main/res/values/strings.xml
@@ -67,5 +67,7 @@
More options
Touch and hold to record
Record voice message
+ JetChat unread messages
+ Add Widget to Home Page
diff --git a/Jetchat/app/src/main/res/xml/widget_unread_messages_info.xml b/Jetchat/app/src/main/res/xml/widget_unread_messages_info.xml
new file mode 100644
index 0000000000..69ea543dc8
--- /dev/null
+++ b/Jetchat/app/src/main/res/xml/widget_unread_messages_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