Skip to content

Commit

Permalink
androidApp: SessionScreen: Initial support for viewing session inform…
Browse files Browse the repository at this point in the history
…ation

Signed-off-by: Aayush Gupta <[email protected]>
  • Loading branch information
theimpulson committed Oct 10, 2024
1 parent bea1047 commit ea6fe8c
Show file tree
Hide file tree
Showing 12 changed files with 283 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import androidx.navigation.NavHostController
@Composable
@OptIn(ExperimentalMaterial3Api::class)
fun TopAppBar(
title: String,
title: String = String(),
navHostController: NavHostController? = null,
navigationIcon: @Composable () -> Unit = { DefaultNavigationIcon(navHostController) },
actions: @Composable() (RowScope.() -> Unit) = {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.navigation.toRoute
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
import app.opass.ccip.android.ui.screens.session.SessionScreen

@Composable
fun SetupNavGraph(navHostController: NavHostController, startDestination: Screen) {
Expand All @@ -46,6 +47,10 @@ fun SetupNavGraph(navHostController: NavHostController, startDestination: Screen
backStackEntry.sharedViewModel(navHostController)
)
}

composable<Screen.Session> { backStackEntry ->
backStackEntry.toRoute<Screen.Session>().SessionScreen(navHostController)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,14 @@ sealed class Screen(@StringRes val title: Int, @DrawableRes val icon: Int) {
)

@Serializable
data class Schedule(val id: String) : Screen(
data class Schedule(val eventId: String) : Screen(
title = R.string.schedule,
icon = R.drawable.ic_schedule
)

@Serializable
data class Session(val eventId: String, val sessionId: String) : Screen(
title = R.string.session,
icon = R.drawable.ic_podium
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fun Screen.Schedule.ScheduleScreen(
val context = LocalContext.current
val schedule by viewModel.schedule.collectAsStateWithLifecycle()

LaunchedEffect(key1 = Unit) { viewModel.getSchedule(this@ScheduleScreen.id) }
LaunchedEffect(key1 = Unit) { viewModel.getSchedule(this@ScheduleScreen.eventId) }

@Composable
fun LoadSessionPreviewItems(
Expand Down Expand Up @@ -105,7 +105,11 @@ fun Screen.Schedule.ScheduleScreen(
DateUtils.FORMAT_SHOW_TIME
),
room = session.room
)
) {
navHostController.navigate(
Screen.Session(this@ScheduleScreen.eventId, session.id)
)
}
}
}
}
Expand Down Expand Up @@ -151,11 +155,10 @@ fun SessionPreviewItem(
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp)) {
Text(
text = room.ifBlank { stringResource(R.string.na) },
color = MaterialTheme.colorScheme.onPrimary,
fontSize = 12.sp,
modifier = Modifier
.clip(RoundedCornerShape(8.dp))
.background(color = MaterialTheme.colorScheme.primary)
.background(color = MaterialTheme.colorScheme.secondaryContainer)
.padding(horizontal = 10.dp)
.shimmer(isLoading),
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
* SPDX-FileCopyrightText: 2024 OPass
* SPDX-License-Identifier: GPL-3.0-only
*/

package app.opass.ccip.android.ui.screens.session

import android.text.format.DateUtils
import androidx.annotation.DrawableRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.FilterChip
import androidx.compose.material3.Icon
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.Alignment
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.compose.ui.util.fastForEach
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.navigation.Screen
import app.opass.ccip.network.models.schedule.Session

@Composable
fun Screen.Session.SessionScreen(
navHostController: NavHostController,
viewModel: SessionViewModel = hiltViewModel()
) {

val context = LocalContext.current
val session by viewModel.session.collectAsStateWithLifecycle()

LaunchedEffect(key1 = Unit) {
viewModel.getSession(this@SessionScreen.eventId, this@SessionScreen.sessionId)
}

Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = { TopAppBar(navHostController = navHostController) }
) { paddingValues ->
if (session != null) {
LoadSession(
session = session!!,
dateTime = DateUtils.formatDateRange(
context,
viewModel.sdf.parse(session!!.start)!!.time,
viewModel.sdf.parse(session!!.end)!!.time,
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_SHOW_TIME or DateUtils.FORMAT_ABBREV_ALL
),
modifier = Modifier.padding(paddingValues)
)
}
}
}

@Composable
fun LoadSession(session: Session, dateTime: String, modifier: Modifier) {
Column(
modifier = modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.padding(20.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
// Tags
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
session.tags?.fastForEach { tag ->
FilterChip(selected = true, onClick = {}, label = { Text(text = tag) })
}
}

// Title
Text(text = session.title, style = MaterialTheme.typography.headlineMedium)

// Type, Room, and Time
Card(
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceContainer
)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
session.type?.let { type ->
SessionInfoItem(
text = type.replaceFirstChar { it.titlecase() },
drawableRes = R.drawable.ic_info
)
}
SessionInfoItem(
text = session.room.ifBlank { stringResource(R.string.na) },
drawableRes = R.drawable.ic_location
)
SessionInfoItem(text = dateTime, drawableRes = R.drawable.ic_time)
SessionInfoItem(
text = session.speakers.joinToString(separator = ", ")
.ifBlank { stringResource(R.string.na) },
drawableRes = R.drawable.ic_podium
)
}
}
}
}

@Composable
private fun SessionInfoItem(text: String, @DrawableRes drawableRes: Int) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(5.dp)
) {
Icon(
painter = painterResource(drawableRes),
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
Text(text = text, style = MaterialTheme.typography.bodyLarge)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: 2024 OPass
* SPDX-License-Identifier: GPL-3.0-only
*/

package app.opass.ccip.android.ui.screens.session

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.opass.ccip.helpers.PortalHelper
import app.opass.ccip.network.models.schedule.Session
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import javax.inject.Inject

@HiltViewModel
class SessionViewModel @Inject constructor(
val sdf: SimpleDateFormat,
private val portalHelper: PortalHelper
): ViewModel() {

private val _session: MutableStateFlow<Session?> = MutableStateFlow(null)
val session = _session.asStateFlow()

fun getSession(eventId: String, sessionId: String) {
viewModelScope.launch {
val session = portalHelper.getSession(eventId, sessionId) ?: return@launch

// Resolve tags, speakers and session type to their original values
val queriedTags = session.tags?.map { portalHelper.getTag(eventId, it)!!.name }
val queriedSpeakers = session.speakers.map { portalHelper.getSpeaker(eventId, it)!!.name }
val queriedSessionType = if (session.type != null) {
portalHelper.getSessionType(eventId, session.type!!)!!.name
} else {
null
}

_session.value = session.copy(
type = queriedSessionType,
tags = queriedTags,
speakers = queriedSpeakers
)
}
}
}
14 changes: 14 additions & 0 deletions androidApp/src/main/res/drawable/ic_info.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: Material Design Authors / Google LLC
~ SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M440,680L520,680L520,440L440,440L440,680ZM480,360Q497,360 508.5,348.5Q520,337 520,320Q520,303 508.5,291.5Q497,280 480,280Q463,280 451.5,291.5Q440,303 440,320Q440,337 451.5,348.5Q463,360 480,360ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
</vector>
14 changes: 14 additions & 0 deletions androidApp/src/main/res/drawable/ic_location.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: Material Design Authors / Google LLC
~ SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M480,480Q513,480 536.5,456.5Q560,433 560,400Q560,367 536.5,343.5Q513,320 480,320Q447,320 423.5,343.5Q400,367 400,400Q400,433 423.5,456.5Q447,480 480,480ZM480,774Q602,662 661,570.5Q720,479 720,408Q720,299 650.5,229.5Q581,160 480,160Q379,160 309.5,229.5Q240,299 240,408Q240,479 299,570.5Q358,662 480,774ZM480,880Q319,743 239.5,625.5Q160,508 160,408Q160,258 256.5,169Q353,80 480,80Q607,80 703.5,169Q800,258 800,408Q800,508 720.5,625.5Q641,743 480,880ZM480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Q480,400 480,400Z"/>
</vector>
14 changes: 14 additions & 0 deletions androidApp/src/main/res/drawable/ic_podium.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: Material Design Authors / Google LLC
~ SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M500,180Q500,213 476.5,236.5Q453,260 420,260Q407,260 396,256.5Q385,253 374,245Q350,253 335.5,274Q321,295 321,320L840,320L800,600L604,600L604,520L731,520Q736,490 739.5,460Q743,430 748,400L212,400Q217,430 220.5,460Q224,490 229,520L356,520L356,600L160,600L120,320L240,320Q240,271 267,231Q294,191 340,172Q340,172 340,172Q340,172 340,172Q343,141 366,120.5Q389,100 420,100Q453,100 476.5,123.5Q500,147 500,180ZM391,760L569,760L592,520Q592,520 592,520Q592,520 592,520L368,520Q368,520 368,520Q368,520 368,520L391,760ZM320,840L290,528Q286,493 310,466.5Q334,440 369,440L591,440Q626,440 650,466.5Q674,493 670,528L640,840L320,840Z"/>
</vector>
14 changes: 14 additions & 0 deletions androidApp/src/main/res/drawable/ic_speaker.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: Material Design Authors / Google LLC
~ SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M234,684Q285,645 348,622.5Q411,600 480,600Q549,600 612,622.5Q675,645 726,684Q761,643 780.5,591Q800,539 800,480Q800,347 706.5,253.5Q613,160 480,160Q347,160 253.5,253.5Q160,347 160,480Q160,539 179.5,591Q199,643 234,684ZM480,520Q421,520 380.5,479.5Q340,439 340,380Q340,321 380.5,280.5Q421,240 480,240Q539,240 579.5,280.5Q620,321 620,380Q620,439 579.5,479.5Q539,520 480,520ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q533,800 580,784.5Q627,769 666,740Q627,711 580,695.5Q533,680 480,680Q427,680 380,695.5Q333,711 294,740Q333,769 380,784.5Q427,800 480,800ZM480,440Q506,440 523,423Q540,406 540,380Q540,354 523,337Q506,320 480,320Q454,320 437,337Q420,354 420,380Q420,406 437,423Q454,440 480,440ZM480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380ZM480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Z"/>
</vector>
14 changes: 14 additions & 0 deletions androidApp/src/main/res/drawable/ic_time.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: Material Design Authors / Google LLC
~ SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M612,668L668,612L520,464L520,280L440,280L440,496L612,668ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480ZM480,800Q613,800 706.5,706.5Q800,613 800,480Q800,347 706.5,253.5Q613,160 480,160Q347,160 253.5,253.5Q160,347 160,480Q160,613 253.5,706.5Q347,800 480,800Z"/>
</vector>
5 changes: 5 additions & 0 deletions androidApp/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,9 @@
<!-- ScheduleScreen -->
<string name="schedule">Schedule</string>
<string name="na" translatable="false">N/A</string>

<!-- SessionScreen -->
<string name="session">Session</string>
<string name="speakers">Speakers</string>
<string name="introduction">Session introduction</string>
</resources>

0 comments on commit ea6fe8c

Please sign in to comment.