From 0c3b3e272b1421732eb40c81c4ff1fd1a40a9a1e Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sun, 27 Oct 2024 13:56:36 +0530 Subject: [PATCH] androidApp: Initial support for announcements Signed-off-by: Aayush Gupta --- .../ccip/android/ui/navigation/NavGraph.kt | 5 + .../ccip/android/ui/navigation/Screen.kt | 6 ++ .../announcement/AnnouncementScreen.kt | 100 ++++++++++++++++++ .../announcement/AnnouncementViewModel.kt | 31 ++++++ .../android/ui/screens/event/EventScreen.kt | 6 +- 5 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 androidApp/src/main/java/app/opass/ccip/android/ui/screens/announcement/AnnouncementScreen.kt create mode 100644 androidApp/src/main/java/app/opass/ccip/android/ui/screens/announcement/AnnouncementViewModel.kt diff --git a/androidApp/src/main/java/app/opass/ccip/android/ui/navigation/NavGraph.kt b/androidApp/src/main/java/app/opass/ccip/android/ui/navigation/NavGraph.kt index 1a9532f..bda5974 100644 --- a/androidApp/src/main/java/app/opass/ccip/android/ui/navigation/NavGraph.kt +++ b/androidApp/src/main/java/app/opass/ccip/android/ui/navigation/NavGraph.kt @@ -17,6 +17,7 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.toRoute +import app.opass.ccip.android.ui.screens.announcement.AnnouncementScreen import app.opass.ccip.android.ui.screens.event.EventScreen import app.opass.ccip.android.ui.screens.eventpreview.EventPreviewScreen import app.opass.ccip.android.ui.screens.schedule.ScheduleScreen @@ -56,6 +57,10 @@ fun SetupNavGraph(navHostController: NavHostController, startDestination: Screen composable { backStackEntry -> backStackEntry.toRoute().TicketScreen(navHostController) } + + composable { backStackEntry -> + backStackEntry.toRoute().AnnouncementScreen(navHostController) + } } } diff --git a/androidApp/src/main/java/app/opass/ccip/android/ui/navigation/Screen.kt b/androidApp/src/main/java/app/opass/ccip/android/ui/navigation/Screen.kt index 11d40cb..2eb79ee 100644 --- a/androidApp/src/main/java/app/opass/ccip/android/ui/navigation/Screen.kt +++ b/androidApp/src/main/java/app/opass/ccip/android/ui/navigation/Screen.kt @@ -42,4 +42,10 @@ sealed class Screen(@StringRes val title: Int, @DrawableRes val icon: Int) { title = R.string.ticket, icon = R.drawable.ic_ticket ) + + @Serializable + data class Announcement(val eventId: String, val token: String? = null) : Screen( + title = R.string.announcement, + icon = R.drawable.ic_announcement + ) } diff --git a/androidApp/src/main/java/app/opass/ccip/android/ui/screens/announcement/AnnouncementScreen.kt b/androidApp/src/main/java/app/opass/ccip/android/ui/screens/announcement/AnnouncementScreen.kt new file mode 100644 index 0000000..efb0dde --- /dev/null +++ b/androidApp/src/main/java/app/opass/ccip/android/ui/screens/announcement/AnnouncementScreen.kt @@ -0,0 +1,100 @@ +/* + * SPDX-FileCopyrightText: 2024 OPass + * SPDX-License-Identifier: GPL-3.0-only + */ + +package app.opass.ccip.android.ui.screens.announcement + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavHostController +import app.opass.ccip.android.R +import app.opass.ccip.android.ui.components.TopAppBar +import app.opass.ccip.android.ui.extensions.browse +import app.opass.ccip.android.ui.navigation.Screen +import app.opass.ccip.network.models.fastpass.Announcement + +@Composable +fun Screen.Announcement.AnnouncementScreen( + navHostController: NavHostController, + viewModel: AnnouncementViewModel = hiltViewModel() +) { + val context = LocalContext.current + val announcements by viewModel.announcements.collectAsStateWithLifecycle() + + LaunchedEffect(key1 = Unit) { + viewModel.getAnnouncements(this@AnnouncementScreen.eventId, this@AnnouncementScreen.token) + } + + Scaffold( + modifier = Modifier.fillMaxSize(), + topBar = { + TopAppBar( + title = stringResource(this.title), + navHostController = navHostController, + actions = { + IconButton( + onClick = { + viewModel.getAnnouncements( + this@AnnouncementScreen.eventId, + this@AnnouncementScreen.token, + true + ) + } + ) { + Icon( + painter = painterResource(id = R.drawable.ic_refresh), + contentDescription = null + ) + } + } + ) + } + ) { paddingValues -> + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), + contentPadding = PaddingValues(10.dp) + ) { + items(announcements) { announcement: Announcement -> + AnnouncementItem(announcement) { + context.browse(announcement.url) + } + } + } + } +} + +@Composable +fun AnnouncementItem(announcement: Announcement, onClicked: () -> Unit = {}) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 10.dp) + .clickable(enabled = announcement.url.isNotBlank()) { onClicked() } + ) { + Text(text = announcement.message, style = MaterialTheme.typography.bodyLarge) + } +} diff --git a/androidApp/src/main/java/app/opass/ccip/android/ui/screens/announcement/AnnouncementViewModel.kt b/androidApp/src/main/java/app/opass/ccip/android/ui/screens/announcement/AnnouncementViewModel.kt new file mode 100644 index 0000000..380a671 --- /dev/null +++ b/androidApp/src/main/java/app/opass/ccip/android/ui/screens/announcement/AnnouncementViewModel.kt @@ -0,0 +1,31 @@ +/* + * SPDX-FileCopyrightText: 2024 OPass + * SPDX-License-Identifier: GPL-3.0-only + */ + +package app.opass.ccip.android.ui.screens.announcement + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import app.opass.ccip.helpers.PortalHelper +import app.opass.ccip.network.models.fastpass.Announcement +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class AnnouncementViewModel @Inject constructor( + private val portalHelper: PortalHelper +): ViewModel() { + + private val _announcements: MutableStateFlow> = MutableStateFlow(emptyList()) + val announcements = _announcements.asStateFlow() + + fun getAnnouncements(eventId: String, token: String? = null, forceReload: Boolean = false) { + viewModelScope.launch { + _announcements.value = portalHelper.getAnnouncements(eventId, token, forceReload) + } + } +} diff --git a/androidApp/src/main/java/app/opass/ccip/android/ui/screens/event/EventScreen.kt b/androidApp/src/main/java/app/opass/ccip/android/ui/screens/event/EventScreen.kt index 2937e8c..740bf62 100644 --- a/androidApp/src/main/java/app/opass/ccip/android/ui/screens/event/EventScreen.kt +++ b/androidApp/src/main/java/app/opass/ccip/android/ui/screens/event/EventScreen.kt @@ -142,7 +142,11 @@ fun Screen.Event.EventScreen( FeatureItem( label = stringResource(id = R.string.announcement), iconRes = R.drawable.ic_announcement - ) + ) { + navHostController.navigate( + Screen.Announcement(this@EventScreen.id, attendee?.token) + ) + } } FeatureType.FAST_PASS -> {