Skip to content

Commit ad4dfaf

Browse files
feat: authorization request dialog
1 parent e465552 commit ad4dfaf

File tree

4 files changed

+340
-17
lines changed

4 files changed

+340
-17
lines changed

core/src/main/java/org/openedx/core/ui/ComposeCommon.kt

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,27 +1265,14 @@ fun AuthButtonsPanel(
12651265
showRegisterButton: Boolean,
12661266
) {
12671267
Row {
1268-
if (showRegisterButton) {
1269-
OpenEdXButton(
1270-
modifier = Modifier
1271-
.testTag("btn_register")
1272-
.width(0.dp)
1273-
.weight(1f),
1274-
text = stringResource(id = R.string.core_register),
1275-
textColor = MaterialTheme.appColors.primaryButtonText,
1276-
backgroundColor = MaterialTheme.appColors.secondaryButtonBackground,
1277-
onClick = { onRegisterClick() }
1278-
)
1279-
}
1280-
12811268
OpenEdXOutlinedButton(
12821269
modifier = Modifier
12831270
.testTag("btn_sign_in")
12841271
.then(
12851272
if (showRegisterButton) {
12861273
Modifier
12871274
.width(100.dp)
1288-
.padding(start = 16.dp)
1275+
.padding(end = 16.dp)
12891276
} else {
12901277
Modifier.weight(1f)
12911278
}
@@ -1296,6 +1283,18 @@ fun AuthButtonsPanel(
12961283
backgroundColor = MaterialTheme.appColors.secondaryButtonBorderedBackground,
12971284
borderColor = MaterialTheme.appColors.secondaryButtonBorder,
12981285
)
1286+
if (showRegisterButton) {
1287+
OpenEdXButton(
1288+
modifier = Modifier
1289+
.testTag("btn_register")
1290+
.width(0.dp)
1291+
.weight(1f),
1292+
text = stringResource(id = R.string.core_register),
1293+
textColor = MaterialTheme.appColors.primaryButtonText,
1294+
backgroundColor = MaterialTheme.appColors.secondaryButtonBackground,
1295+
onClick = { onRegisterClick() }
1296+
)
1297+
}
12991298
}
13001299
}
13011300

core/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,6 @@
187187
<string name="core_not_synced">Not Synced</string>
188188
<string name="core_syncing_to_calendar">Syncing to calendar…</string>
189189
<string name="core_next">Next</string>
190+
<string name="core_authorization">Authorization</string>
191+
<string name="core_authorization_request">Please enter the system to continue with course enrollment.</string>
190192
</resources>
Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
package org.openedx.discovery.presentation.detail
2+
3+
import android.content.res.Configuration
4+
import android.content.res.Configuration.UI_MODE_NIGHT_NO
5+
import android.content.res.Configuration.UI_MODE_NIGHT_YES
6+
import android.graphics.Color
7+
import android.graphics.drawable.ColorDrawable
8+
import android.os.Bundle
9+
import android.view.LayoutInflater
10+
import android.view.ViewGroup
11+
import androidx.compose.foundation.layout.Arrangement
12+
import androidx.compose.foundation.layout.Box
13+
import androidx.compose.foundation.layout.Column
14+
import androidx.compose.foundation.layout.Row
15+
import androidx.compose.foundation.layout.Spacer
16+
import androidx.compose.foundation.layout.fillMaxWidth
17+
import androidx.compose.foundation.layout.height
18+
import androidx.compose.foundation.layout.padding
19+
import androidx.compose.foundation.layout.size
20+
import androidx.compose.foundation.layout.width
21+
import androidx.compose.material.Card
22+
import androidx.compose.material.Icon
23+
import androidx.compose.material.IconButton
24+
import androidx.compose.material.MaterialTheme
25+
import androidx.compose.material.Text
26+
import androidx.compose.material.icons.Icons
27+
import androidx.compose.material.icons.automirrored.filled.Login
28+
import androidx.compose.material.icons.filled.Close
29+
import androidx.compose.runtime.Composable
30+
import androidx.compose.ui.Alignment
31+
import androidx.compose.ui.Modifier
32+
import androidx.compose.ui.draw.clip
33+
import androidx.compose.ui.platform.ComposeView
34+
import androidx.compose.ui.platform.LocalConfiguration
35+
import androidx.compose.ui.platform.ViewCompositionStrategy
36+
import androidx.compose.ui.res.stringResource
37+
import androidx.compose.ui.text.style.TextAlign
38+
import androidx.compose.ui.tooling.preview.Preview
39+
import androidx.compose.ui.unit.dp
40+
import androidx.core.os.bundleOf
41+
import androidx.fragment.app.DialogFragment
42+
import org.koin.android.ext.android.inject
43+
import org.openedx.core.ui.OpenEdXButton
44+
import org.openedx.core.ui.OpenEdXOutlinedButton
45+
import org.openedx.core.ui.theme.OpenEdXTheme
46+
import org.openedx.core.ui.theme.appColors
47+
import org.openedx.core.ui.theme.appShapes
48+
import org.openedx.core.ui.theme.appTypography
49+
import org.openedx.discovery.presentation.DiscoveryRouter
50+
import org.openedx.foundation.extension.setWidthPercent
51+
import org.openedx.core.R as coreR
52+
53+
class AuthorizationFragmentDialog : DialogFragment() {
54+
55+
private val router: DiscoveryRouter by inject()
56+
57+
override fun onResume() {
58+
super.onResume()
59+
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
60+
setWidthPercent(percentage = 66)
61+
}
62+
}
63+
64+
override fun onCreateView(
65+
inflater: LayoutInflater,
66+
container: ViewGroup?,
67+
savedInstanceState: Bundle?
68+
) = ComposeView(requireContext()).apply {
69+
if (dialog != null && dialog!!.window != null) {
70+
dialog!!.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
71+
}
72+
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
73+
setContent {
74+
OpenEdXTheme {
75+
val courseId = requireArguments().getString(ARG_COURSE_ID) ?: ""
76+
AuthorizationDialogView(
77+
onRegisterButtonClick = {
78+
dismiss()
79+
router.navigateToSignUp(requireActivity().supportFragmentManager, courseId)
80+
},
81+
onSignInButtonClick = {
82+
dismiss()
83+
router.navigateToSignIn(
84+
requireActivity().supportFragmentManager,
85+
courseId,
86+
null
87+
)
88+
},
89+
onCancelButtonClick = {
90+
dismiss()
91+
}
92+
)
93+
}
94+
}
95+
}
96+
97+
companion object {
98+
private const val ARG_COURSE_ID = "arg_course_id"
99+
fun newInstance(
100+
courseId: String,
101+
): AuthorizationFragmentDialog {
102+
val dialog = AuthorizationFragmentDialog()
103+
dialog.arguments = bundleOf(
104+
ARG_COURSE_ID to courseId,
105+
)
106+
return dialog
107+
}
108+
}
109+
}
110+
111+
@Composable
112+
private fun AuthorizationDialogView(
113+
onRegisterButtonClick: () -> Unit,
114+
onSignInButtonClick: () -> Unit,
115+
onCancelButtonClick: () -> Unit
116+
) {
117+
val configuration = LocalConfiguration.current
118+
if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
119+
AuthorizationDialogPortraitView(
120+
onRegisterButtonClick = onRegisterButtonClick,
121+
onSignInButtonClick = onSignInButtonClick,
122+
onCancelButtonClick = onCancelButtonClick
123+
)
124+
} else {
125+
AuthorizationDialogLandscapeView(
126+
onRegisterButtonClick = onRegisterButtonClick,
127+
onSignInButtonClick = onSignInButtonClick,
128+
onCancelButtonClick = onCancelButtonClick
129+
)
130+
}
131+
}
132+
133+
@Composable
134+
private fun AuthorizationDialogPortraitView(
135+
onRegisterButtonClick: () -> Unit,
136+
onSignInButtonClick: () -> Unit,
137+
onCancelButtonClick: () -> Unit
138+
) {
139+
Card(
140+
modifier = Modifier
141+
.fillMaxWidth(fraction = 0.95f)
142+
.clip(MaterialTheme.appShapes.courseImageShape),
143+
backgroundColor = MaterialTheme.appColors.background,
144+
shape = MaterialTheme.appShapes.courseImageShape
145+
) {
146+
Column(
147+
modifier = Modifier.padding(30.dp),
148+
horizontalAlignment = Alignment.CenterHorizontally
149+
) {
150+
Box(
151+
contentAlignment = Alignment.CenterEnd,
152+
modifier = Modifier.fillMaxWidth()
153+
) {
154+
IconButton(
155+
modifier = Modifier.size(24.dp),
156+
onClick = onCancelButtonClick
157+
) {
158+
Icon(
159+
imageVector = Icons.Filled.Close,
160+
contentDescription = stringResource(id = org.openedx.core.R.string.core_cancel),
161+
tint = MaterialTheme.appColors.primary
162+
)
163+
}
164+
}
165+
Icon(
166+
modifier = Modifier
167+
.width(76.dp)
168+
.height(72.dp),
169+
imageVector = Icons.AutoMirrored.Filled.Login,
170+
contentDescription = null,
171+
tint = MaterialTheme.appColors.onBackground
172+
)
173+
Spacer(Modifier.height(36.dp))
174+
Text(
175+
text = stringResource(id = coreR.string.core_authorization),
176+
color = MaterialTheme.appColors.textPrimary,
177+
style = MaterialTheme.appTypography.titleLarge
178+
)
179+
Spacer(Modifier.height(8.dp))
180+
Text(
181+
modifier = Modifier.fillMaxWidth(),
182+
text = stringResource(id = coreR.string.core_authorization_request),
183+
color = MaterialTheme.appColors.textFieldText,
184+
style = MaterialTheme.appTypography.titleSmall,
185+
textAlign = TextAlign.Center
186+
)
187+
Spacer(Modifier.height(42.dp))
188+
Row {
189+
OpenEdXOutlinedButton(
190+
modifier = Modifier.weight(1f),
191+
borderColor = MaterialTheme.appColors.primaryButtonBackground,
192+
textColor = MaterialTheme.appColors.primaryButtonBackground,
193+
text = stringResource(id = coreR.string.core_sign_in),
194+
onClick = onSignInButtonClick
195+
)
196+
Spacer(Modifier.width(16.dp))
197+
OpenEdXButton(
198+
modifier = Modifier.weight(1f),
199+
text = stringResource(id = coreR.string.core_register),
200+
onClick = onRegisterButtonClick
201+
)
202+
}
203+
}
204+
}
205+
}
206+
207+
@Composable
208+
private fun AuthorizationDialogLandscapeView(
209+
onRegisterButtonClick: () -> Unit,
210+
onSignInButtonClick: () -> Unit,
211+
onCancelButtonClick: () -> Unit
212+
) {
213+
Card(
214+
modifier = Modifier
215+
.fillMaxWidth()
216+
.clip(MaterialTheme.appShapes.courseImageShape),
217+
backgroundColor = MaterialTheme.appColors.background,
218+
shape = MaterialTheme.appShapes.courseImageShape
219+
) {
220+
Column(
221+
modifier = Modifier.padding(38.dp)
222+
) {
223+
Box(
224+
contentAlignment = Alignment.CenterEnd,
225+
modifier = Modifier
226+
.fillMaxWidth()
227+
.padding(bottom = 12.dp)
228+
) {
229+
IconButton(
230+
modifier = Modifier.size(24.dp),
231+
onClick = onCancelButtonClick
232+
) {
233+
Icon(
234+
imageVector = Icons.Filled.Close,
235+
contentDescription = stringResource(id = org.openedx.core.R.string.core_cancel),
236+
tint = MaterialTheme.appColors.primary
237+
)
238+
}
239+
}
240+
Row(
241+
verticalAlignment = Alignment.CenterVertically,
242+
horizontalArrangement = Arrangement.SpaceBetween
243+
) {
244+
Column(
245+
Modifier.weight(1f),
246+
horizontalAlignment = Alignment.CenterHorizontally
247+
) {
248+
Icon(
249+
modifier = Modifier
250+
.width(76.dp)
251+
.height(72.dp),
252+
imageVector = Icons.AutoMirrored.Filled.Login,
253+
contentDescription = null,
254+
tint = MaterialTheme.appColors.onBackground
255+
)
256+
Spacer(Modifier.height(36.dp))
257+
Text(
258+
modifier = Modifier.fillMaxWidth(),
259+
text = stringResource(id = coreR.string.core_authorization),
260+
color = MaterialTheme.appColors.textPrimary,
261+
style = MaterialTheme.appTypography.titleLarge,
262+
textAlign = TextAlign.Center
263+
)
264+
Spacer(Modifier.height(8.dp))
265+
Text(
266+
modifier = Modifier.fillMaxWidth(),
267+
text = stringResource(id = coreR.string.core_authorization_request),
268+
color = MaterialTheme.appColors.textFieldText,
269+
style = MaterialTheme.appTypography.titleSmall,
270+
textAlign = TextAlign.Center
271+
)
272+
}
273+
Spacer(Modifier.width(42.dp))
274+
Column(
275+
Modifier.weight(1f),
276+
horizontalAlignment = Alignment.CenterHorizontally
277+
) {
278+
OpenEdXOutlinedButton(
279+
borderColor = MaterialTheme.appColors.primaryButtonBackground,
280+
textColor = MaterialTheme.appColors.primaryButtonBackground,
281+
text = stringResource(id = coreR.string.core_sign_in),
282+
onClick = onSignInButtonClick,
283+
)
284+
Spacer(Modifier.height(16.dp))
285+
OpenEdXButton(
286+
text = stringResource(id = coreR.string.core_register),
287+
onClick = onRegisterButtonClick
288+
)
289+
}
290+
}
291+
}
292+
}
293+
}
294+
295+
@Preview(uiMode = UI_MODE_NIGHT_NO)
296+
@Preview(uiMode = UI_MODE_NIGHT_YES)
297+
@Composable
298+
fun AuthorizationDialogPortraitViewPreview() {
299+
OpenEdXTheme {
300+
AuthorizationDialogPortraitView(
301+
onSignInButtonClick = {},
302+
onRegisterButtonClick = {},
303+
onCancelButtonClick = {}
304+
)
305+
}
306+
}
307+
308+
@Preview(uiMode = UI_MODE_NIGHT_NO)
309+
@Preview(uiMode = UI_MODE_NIGHT_YES)
310+
@Composable
311+
fun AuthorizationDialogLandscapeViewPreview() {
312+
OpenEdXTheme {
313+
AuthorizationDialogLandscapeView(
314+
onSignInButtonClick = {},
315+
onRegisterButtonClick = {},
316+
onCancelButtonClick = {}
317+
)
318+
}
319+
}

discovery/src/main/java/org/openedx/discovery/presentation/detail/CourseDetailsFragment.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,12 @@ class CourseDetailsFragment : Fragment() {
154154
if (currentState is CourseDetailsUIState.CourseData) {
155155
when {
156156
(!currentState.isUserLoggedIn) -> {
157-
router.navigateToLogistration(
158-
parentFragmentManager,
159-
currentState.course.courseId
157+
val dialog = AuthorizationFragmentDialog.newInstance(
158+
viewModel.courseId
159+
)
160+
dialog.show(
161+
requireActivity().supportFragmentManager,
162+
AuthorizationFragmentDialog::class.simpleName
160163
)
161164
}
162165

0 commit comments

Comments
 (0)