Skip to content

Commit

Permalink
Commented code
Browse files Browse the repository at this point in the history
  • Loading branch information
ntissieres authored and Greenade committed May 30, 2024
1 parent 38c04a0 commit cd4a3b3
Show file tree
Hide file tree
Showing 19 changed files with 315 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,32 +37,39 @@ import com.github.swent.echo.data.model.Association
import com.github.swent.echo.data.model.Event
import com.github.swent.echo.data.model.Tag

// This Composable function displays the details of an association.
@Composable
fun AssociationDetails(
association: Association,
isFollowed: Boolean,
follow: (Association) -> Unit,
events: List<Event>,
isOnline: Boolean,
refreshEvents: () -> Unit,
onTagPressed: (Tag) -> Unit = {},
association: Association, // The association to display
isFollowed: Boolean, // Whether the association is followed by the user
follow: (Association) -> Unit, // Function to follow/unfollow the association
events: List<Event>, // List of events related to the association
isOnline: Boolean, // Whether the user is online
refreshEvents: () -> Unit, // Function to refresh the list of events
onTagPressed: (Tag) -> Unit = {}, // Function to handle tag press events
) {
// Define layout parameters
val paddingValues = 10.dp
val phoneHorizontalCenter = (LocalConfiguration.current.screenWidthDp / 2).dp
val followWidth = 150.dp
val followHeight = 40.dp
val followSpaceInside = 5.dp
val verticalSpace = 12.dp

// Start of the layout
Column(
modifier = Modifier.fillMaxSize().padding(paddingValues).testTag("association_details")
) {
// Association name and follow/unfollow button
Box(modifier = Modifier.fillMaxWidth()) {
// Association name
Text(
association.name,
modifier =
Modifier.align(Alignment.CenterStart).widthIn(max = phoneHorizontalCenter),
style = MaterialTheme.typography.titleLarge
)
// Follow/unfollow button
Button(
enabled = isOnline,
onClick = { follow(association) },
Expand All @@ -72,11 +79,13 @@ fun AssociationDetails(
.height(followHeight)
.testTag("association_details_follow_button")
) {
// Icon for follow/unfollow
Icon(
if (isFollowed) Icons.Filled.Clear else Icons.Filled.Add,
"Follow/Unfollow association"
)
Spacer(modifier = Modifier.padding(followSpaceInside))
// Text for follow/unfollow
Text(
if (isFollowed) stringResource(R.string.association_details_unfollow)
else stringResource(R.string.association_details_follow),
Expand All @@ -85,6 +94,7 @@ fun AssociationDetails(
}
}
Spacer(modifier = Modifier.height(verticalSpace))
// Pager for association description and events
Pager(
listOf(
Pair(stringResource(R.string.association_details_description)) {
Expand All @@ -98,20 +108,26 @@ fun AssociationDetails(
}
}

// This Composable function displays the description of an association.
@Composable
fun AssociationDescription(
association: Association,
verticalSpace: Dp,
onTagPressed: (Tag) -> Unit
association: Association, // The association to display
verticalSpace: Dp, // The vertical space to use in the layout
onTagPressed: (Tag) -> Unit // Function to handle tag press events
) {
// Convert the set of related tags to a list
val tags = association.relatedTags.toList()
val spaceBetweenTagChips = 6.dp

// Start of the layout
Column {
// Display the related tags in a horizontal scrollable row
LazyRow(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(spaceBetweenTagChips)
) {
items(tags) { tag ->
// Each tag is displayed as a chip
AssistChip(
onClick = { onTagPressed(tag) },
label = { Text(tag.name) },
Expand All @@ -128,7 +144,9 @@ fun AssociationDescription(
)
}
}
// Display the association description
Text(association.description)
// If the association has a URL, display it as a hyperlink
if (association.url != null) {
Spacer(modifier = Modifier.height(verticalSpace))
Text(
Expand All @@ -141,7 +159,9 @@ fun AssociationDescription(
}
}

// This Composable function displays the events of an association.
@Composable
fun AssociationEvents(events: List<Event>, isOnline: Boolean, refreshEvents: () -> Unit) {
// Use a ListDrawer to display the events
ListDrawer(events, isOnline, refreshEvents)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,57 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.github.swent.echo.data.model.Association

/** A screen which displays a list of associations */
/**
* A screen which displays a list of associations. This Composable function takes a list of
* associations and a function to handle row clicks. It uses a LazyColumn to efficiently display a
* potentially large list of associations.
*/
@Composable
fun AssociationListScreen(
associationList: List<Association>,
onRowClicked: (Association) -> Unit = {},
associationList: List<Association>, // The list of associations to display
onRowClicked: (Association) -> Unit = {}, // Function to handle row clicks
) {
// LazyColumn is a vertically scrolling list that only composes and lays out the currently
// visible items
LazyColumn(modifier = Modifier.testTag("association_list_screen")) {
// For each association in the list, create an AssociationListElement
items(associationList.size) { index ->
AssociationListElement(
association = associationList[index],
onRowClicked = onRowClicked
association = associationList[index], // The association to display
onRowClicked = onRowClicked // The function to call when the row is clicked
)
}
}
}

/** An element in the association list */
/**
* An element in the association list. This Composable function takes an association and a function
* to handle clicks. It uses a ListItem to display the association's name and handle click events.
*/
@Composable
fun AssociationListElement(
association: Association,
onRowClicked: (Association) -> Unit,
association: Association, // The association to display
onRowClicked: (Association) -> Unit, // The function to call when the row is clicked
) {
val boxInsidePadding = 5.dp
val tonalElevation = 5.dp
val boxInsidePadding = 5.dp // The padding inside the box
val tonalElevation = 5.dp // The elevation of the box

// ListItem is a Material Design implementation of [list
// items](https://material.io/components/lists)
ListItem(
headlineContent = {
// Display the association's name
Text(
text = association.name,
textAlign = TextAlign.Center,
text = association.name, // The association's name
textAlign = TextAlign.Center, // Center the text
modifier =
Modifier.padding(boxInsidePadding)
.testTag("association_name_button_${association.name}")
Modifier.padding(boxInsidePadding) // Add padding
.testTag("association_name_button_${association.name}") // Add a test tag
)
},
modifier =
Modifier.clickable { onRowClicked(association) }
.testTag("association_list_${association.name}"),
tonalElevation = tonalElevation,
Modifier.clickable { onRowClicked(association) } // Make the ListItem clickable
.testTag("association_list_${association.name}"), // Add a test tag
tonalElevation = tonalElevation, // Set the elevation
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,52 @@ import com.github.swent.echo.ui.navigation.NavigationActions
import com.github.swent.echo.ui.navigation.Routes
import com.github.swent.echo.viewmodels.association.AssociationViewModel

/**
* A screen which displays associations. This Composable function takes an AssociationViewModel and
* NavigationActions. It uses a Scaffold to provide a layout structure for the screen.
*/
@Composable
fun AssociationScreen(associationViewModel: AssociationViewModel, navActions: NavigationActions) {
fun AssociationScreen(
associationViewModel:
AssociationViewModel, // The ViewModel that provides the data for the screen
navActions: NavigationActions // The actions that can be performed for navigation
) {
// Collect the state of followed associations, committee associations, and all associations
val followedAssociations by associationViewModel.followedAssociations.collectAsState()
val committeeAssociations by associationViewModel.committeeAssociations.collectAsState()
val showAllAssociations by associationViewModel.showAllAssociations.collectAsState()

// Create a list of pages for the Pager
val pages =
listOf(
Pair("Followed Associations", followedAssociations),
Pair("Committee Associations", committeeAssociations),
Pair("All Associations", showAllAssociations)
)

// Collect the state of the current association page and the initial page
val currentAssociationPage by associationViewModel.currentAssociationPage.collectAsState()
val initialPage by associationViewModel.initialPage.collectAsState()

// Collect the state of the searched text
val searched by associationViewModel.searched.collectAsState()

// Collect the state of the online status
val isOnline by associationViewModel.isOnline.collectAsState()

// Define the space between the search bar and the pages
val spaceBetweenSearchAndPages = 8.dp

// Scaffold provides a framework for material design surfaces
Scaffold(
topBar = {
// Display the title and back button
EventTitleAndBackButton(stringResource(R.string.hamburger_associations)) {
if (currentAssociationPage == Association.EMPTY) {
// Navigate to the map if the current association page is empty
navActions.navigateTo(Routes.MAP)
} else {
// Set the current association page to empty
associationViewModel.setCurrentAssociationPage(Association.EMPTY)
}
}
Expand All @@ -60,13 +79,17 @@ fun AssociationScreen(associationViewModel: AssociationViewModel, navActions: Na
modifier = Modifier.padding(paddingValues),
horizontalAlignment = Alignment.CenterHorizontally
) {
// Check if the current association page is empty, which means we must display the
// default screen
if (currentAssociationPage == Association.EMPTY) {
// Display the search bar
SearchBar(
stringResource(R.string.associations_categories),
searched,
associationViewModel::setSearched
)
Spacer(modifier = Modifier.height(spaceBetweenSearchAndPages))
// Display the pager with the list of pages
Pager(
pages.mapIndexed { id, page ->
Pair(page.first) {
Expand All @@ -80,6 +103,7 @@ fun AssociationScreen(associationViewModel: AssociationViewModel, navActions: Na
initialPage
)
} else {
// Display the association details
AssociationDetails(
currentAssociationPage,
followedAssociations.contains(currentAssociationPage),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,36 +23,50 @@ import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp

/**
* A Composable function that creates a dropdown menu. This function takes a title, a list of items,
* a selected item index, and a callback function.
*/
@Composable
fun Dropdown(
title: String,
items: List<String>,
selectedItem: Int,
callback: (Int) -> Unit,
title: String, // The title of the dropdown
items: List<String>, // The list of items to be displayed in the dropdown
selectedItem: Int, // The index of the selected item
callback: (Int) -> Unit, // The callback function to be called when an item is selected
) {
// Define the dimensions and states for the dropdown
val width = 170.dp
val itemsHeight = 40.dp
var expanded by remember { mutableStateOf(false) }
var expanded by remember {
mutableStateOf(false)
} // The state of the dropdown (expanded or not)
val verticalMaxSize = (LocalConfiguration.current.screenHeightDp / 4).dp
val cornerRadius = 5.dp

// Create a Box layout to contain the dropdown
Box {
// Create a Button that expands or collapses the dropdown when clicked
Button(
onClick = { expanded = true },
modifier = Modifier.width(width).height(itemsHeight).testTag("dropdown_button"),
shape = RoundedCornerShape(cornerRadius),
) {
// Display the selected item or the title if no item is selected
Text(if (selectedItem < 0) title else items[selectedItem])
// Display an arrow icon indicating the state of the dropdown
Icon(
if (!expanded) Icons.Filled.KeyboardArrowDown else Icons.Filled.KeyboardArrowUp,
contentDescription = "arrow"
)
}
// Create a DropdownMenu that displays the items
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
modifier =
Modifier.width(width).heightIn(max = verticalMaxSize).testTag("dropdown_menu")
) {
// Create a DropdownMenuItem for the null item
DropdownMenuItem(
onClick = {
callback(-1)
Expand All @@ -61,6 +75,7 @@ fun Dropdown(
text = { Text("---") },
modifier = Modifier.height(itemsHeight).testTag("dropdown_item_null")
)
// Create a DropdownMenuItem for each item in the list
items.forEachIndexed { id, item ->
DropdownMenuItem(
onClick = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,6 @@ fun HamburgerMenuDrawerSheet(
selectedIcon = Icons.Filled.DateRange,
navOnClick = { navActions.navigateTo(Routes.MY_EVENTS) }
),
/*
NavigationItem(
title = stringResource(id = R.string.hamburger_friends),
selectedIcon = Icons.Filled.Face,
),
NavigationItem(
title = stringResource(id = R.string.hamburger_settings),
selectedIcon = Icons.Filled.Settings,
),
*/
NavigationItem(
title = stringResource(id = R.string.hamburger_create_event),
selectedIcon = Icons.Filled.AddCircle,
Expand All @@ -91,12 +80,6 @@ fun HamburgerMenuDrawerSheet(
navActions.navigateTo(Routes.CREATE_EVENT.build(encodedMapCenter))
}
),
/*
NavigationItem(
title = stringResource(id = R.string.hamburger_add_friends),
selectedIcon = Icons.Filled.Add,
),
*/
NavigationItem(
title = stringResource(R.string.hamburger_associations),
selectedIcon = Icons.Filled.Star,
Expand Down Expand Up @@ -125,14 +108,12 @@ fun HamburgerMenuDrawerSheet(
Column(
modifier = Modifier.align(Alignment.TopStart).padding(8.dp).testTag("profile_sheet")
) {
// TO-DO: Replace with actual profile picture
Image(
modifier = Modifier.testTag("profile_picture"),
painter = painterResource(id = R.drawable.ic_launcher_foreground),
contentDescription = "profile picture"
)
Row(modifier = Modifier.padding(8.dp).testTag("profile_info")) {
// TO-DO: Replace with actual name and class
Text(
text = profileName,
modifier = Modifier.testTag("profile_name"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ private fun Content(
}
}

// Colors for the epfl/section/class tags
val colorEpfl = Color.Red.copy(0.6f)
val colorSection = Color.Blue.copy(0.6f)
val colorClass = Color.Green.copy(0.6f)
Loading

0 comments on commit cd4a3b3

Please sign in to comment.