Skip to content

Commit f695f76

Browse files
committed
feat(profile): Add navigation to Starred and Favourite repositories
This commit introduces the ability to navigate to Starred and Favourite repositories from the profile screen, including new UI components and navigation logic. - **feat(profile)**: Added `OnStarredReposClick` and `OnFavouriteReposClick` actions to `ProfileAction` and handled them in `ProfileViewModel` and `ProfileRoot`. - **feat(profile)**: Created `Options.kt` section containing cards for "Stars" (GitHub starred repos) and "Favourites" (locally saved repos). - **feat(profile)**: Integrated the new `options` section into `ProfileSection.kt`. - **feat(navigation)**: Updated `AppNavigation.kt` to handle navigation to `StarredReposScreen` and `FavouritesScreen`. - **style(profile)**: Adjusted spacing and layout constants in `ProfileRoot` for better visual consistency.
1 parent eef0e03 commit f695f76

6 files changed

Lines changed: 176 additions & 1 deletion

File tree

composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/AppNavigation.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,12 @@ fun AppNavigation(
216216
},
217217
onNavigateToAuthentication = {
218218
navController.navigate(GithubStoreGraph.AuthenticationScreen)
219+
},
220+
onNavigateToStarredRepos = {
221+
navController.navigate(GithubStoreGraph.StarredReposScreen)
222+
},
223+
onNavigateToFavouriteRepos = {
224+
navController.navigate(GithubStoreGraph.FavouritesScreen)
219225
}
220226
)
221227
}

feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileAction.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ sealed interface ProfileAction {
1010
data class OnDarkThemeChange(val isDarkTheme: Boolean?) : ProfileAction
1111
data object OnLogoutClick : ProfileAction
1212
data object OnLogoutConfirmClick : ProfileAction
13+
data object OnStarredReposClick : ProfileAction
14+
data object OnFavouriteReposClick : ProfileAction
1315
data object OnLogoutDismiss : ProfileAction
1416
data object OnHelpClick : ProfileAction
1517
data object OnLoginClick : ProfileAction

feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileRoot.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ import zed.rainxch.profile.presentation.components.sections.settings
5050
fun ProfileRoot(
5151
onNavigateBack: () -> Unit,
5252
onNavigateToAuthentication: () -> Unit,
53+
onNavigateToStarredRepos: () -> Unit,
54+
onNavigateToFavouriteRepos: () -> Unit,
5355
viewModel: ProfileViewModel = koinViewModel()
5456
) {
5557
val state by viewModel.state.collectAsStateWithLifecycle()
@@ -98,6 +100,14 @@ fun ProfileRoot(
98100
onNavigateToAuthentication()
99101
}
100102

103+
ProfileAction.OnFavouriteReposClick -> {
104+
onNavigateToFavouriteRepos()
105+
}
106+
107+
ProfileAction.OnStarredReposClick -> {
108+
onNavigateToStarredRepos()
109+
}
110+
101111
else -> {
102112
viewModel.onAction(action)
103113
}
@@ -152,7 +162,7 @@ fun ProfileScreen(
152162
)
153163

154164
item {
155-
Spacer(Modifier.height(24.dp))
165+
Spacer(Modifier.height(16.dp))
156166
}
157167

158168
settings(

feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileViewModel.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,14 @@ class ProfileViewModel(
197197
/* Handed in composable */
198198
}
199199

200+
ProfileAction.OnFavouriteReposClick -> {
201+
/* Handed in composable */
202+
}
203+
204+
ProfileAction.OnStarredReposClick -> {
205+
/* Handed in composable */
206+
}
207+
200208
is ProfileAction.OnFontThemeSelected -> {
201209
viewModelScope.launch {
202210
themesRepository.setFontTheme(action.fontTheme)
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package zed.rainxch.profile.presentation.components.sections
2+
3+
import androidx.compose.foundation.BorderStroke
4+
import androidx.compose.foundation.background
5+
import androidx.compose.foundation.layout.Arrangement
6+
import androidx.compose.foundation.layout.Column
7+
import androidx.compose.foundation.layout.Row
8+
import androidx.compose.foundation.layout.Spacer
9+
import androidx.compose.foundation.layout.height
10+
import androidx.compose.foundation.layout.padding
11+
import androidx.compose.foundation.layout.size
12+
import androidx.compose.foundation.lazy.LazyListScope
13+
import androidx.compose.foundation.shape.CircleShape
14+
import androidx.compose.foundation.shape.RoundedCornerShape
15+
import androidx.compose.material.icons.Icons
16+
import androidx.compose.material.icons.filled.Favorite
17+
import androidx.compose.material.icons.filled.Star
18+
import androidx.compose.material3.Card
19+
import androidx.compose.material3.CardDefaults
20+
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
21+
import androidx.compose.material3.Icon
22+
import androidx.compose.material3.MaterialTheme
23+
import androidx.compose.material3.Text
24+
import androidx.compose.runtime.Composable
25+
import androidx.compose.ui.Alignment
26+
import androidx.compose.ui.Modifier
27+
import androidx.compose.ui.draw.clip
28+
import androidx.compose.ui.graphics.Brush
29+
import androidx.compose.ui.graphics.vector.ImageVector
30+
import androidx.compose.ui.text.style.TextOverflow
31+
import androidx.compose.ui.unit.dp
32+
import zed.rainxch.profile.presentation.ProfileAction
33+
34+
fun LazyListScope.options(
35+
isUserLoggedIn: Boolean,
36+
onAction: (ProfileAction) -> Unit,
37+
) {
38+
item {
39+
OptionCard(
40+
icon = Icons.Default.Star,
41+
label = "Stars",
42+
description = "Your Starred Repositories from GitHub",
43+
onClick = {
44+
onAction(ProfileAction.OnStarredReposClick)
45+
},
46+
enabled = isUserLoggedIn
47+
)
48+
49+
Spacer(Modifier.height(4.dp))
50+
51+
OptionCard(
52+
icon = Icons.Default.Favorite,
53+
label = "Favourites",
54+
description = "Your Favourite Repositories saved locally",
55+
onClick = {
56+
onAction(ProfileAction.OnFavouriteReposClick)
57+
}
58+
)
59+
}
60+
}
61+
62+
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
63+
@Composable
64+
private fun OptionCard(
65+
icon: ImageVector,
66+
label: String,
67+
description: String,
68+
onClick: () -> Unit,
69+
modifier: Modifier = Modifier,
70+
enabled: Boolean = true
71+
) {
72+
Card(
73+
modifier = modifier,
74+
colors = CardDefaults.elevatedCardColors(
75+
containerColor = MaterialTheme.colorScheme.surfaceContainerLow,
76+
contentColor = MaterialTheme.colorScheme.onSurface,
77+
disabledContainerColor = MaterialTheme.colorScheme.surfaceContainerLow.copy(alpha = .7f),
78+
disabledContentColor = MaterialTheme.colorScheme.onSurface.copy(alpha = .7f),
79+
),
80+
onClick = onClick,
81+
shape = RoundedCornerShape(36.dp),
82+
border = BorderStroke(
83+
width = .5.dp,
84+
color = MaterialTheme.colorScheme.surface
85+
),
86+
enabled = enabled
87+
) {
88+
Row(
89+
modifier = Modifier.padding(horizontal = 12.dp),
90+
verticalAlignment = Alignment.CenterVertically,
91+
horizontalArrangement = Arrangement.spacedBy(8.dp)
92+
) {
93+
Icon(
94+
imageVector = icon,
95+
contentDescription = null,
96+
modifier = Modifier
97+
.size(36.dp)
98+
.clip(CircleShape)
99+
.background(
100+
Brush.linearGradient(
101+
listOf(
102+
MaterialTheme.colorScheme.primary,
103+
MaterialTheme.colorScheme.secondary,
104+
)
105+
)
106+
)
107+
.padding(6.dp),
108+
tint = MaterialTheme.colorScheme.onPrimary
109+
)
110+
111+
Column(
112+
modifier = Modifier
113+
.weight(1f)
114+
.padding(12.dp),
115+
verticalArrangement = Arrangement.Center,
116+
horizontalAlignment = Alignment.Start
117+
) {
118+
Text(
119+
text = label,
120+
maxLines = 1,
121+
style = MaterialTheme.typography.titleMedium,
122+
overflow = TextOverflow.Ellipsis,
123+
color = MaterialTheme.colorScheme.onSurface
124+
)
125+
126+
Text(
127+
text = description,
128+
maxLines = 2,
129+
style = MaterialTheme.typography.bodyLargeEmphasized,
130+
overflow = TextOverflow.Ellipsis,
131+
color = MaterialTheme.colorScheme.onSurfaceVariant
132+
)
133+
}
134+
}
135+
}
136+
}

feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/ProfileSection.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package zed.rainxch.profile.presentation.components.sections
22

3+
import androidx.compose.foundation.layout.Spacer
4+
import androidx.compose.foundation.layout.height
35
import androidx.compose.foundation.lazy.LazyListScope
6+
import androidx.compose.ui.Modifier
7+
import androidx.compose.ui.unit.dp
48
import zed.rainxch.profile.presentation.ProfileAction
59
import zed.rainxch.profile.presentation.ProfileState
610

@@ -12,4 +16,13 @@ fun LazyListScope.profile(
1216
state = state,
1317
onAction = onAction
1418
)
19+
20+
item {
21+
Spacer(Modifier.height(20.dp))
22+
}
23+
24+
options(
25+
isUserLoggedIn = state.isUserLoggedIn,
26+
onAction = onAction
27+
)
1528
}

0 commit comments

Comments
 (0)