Skip to content

Commit 4dbff8b

Browse files
feat: authorization request dialog (#431)
1 parent 19eb8e3 commit 4dbff8b

File tree

4 files changed

+339
-17
lines changed

4 files changed

+339
-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: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
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 AuthorizationDialogFragment : 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 = LANDSCAPE_WIDTH_PERCENT)
61+
}
62+
}
63+
64+
override fun onCreateView(
65+
inflater: LayoutInflater,
66+
container: ViewGroup?,
67+
savedInstanceState: Bundle?
68+
) = ComposeView(requireContext()).apply {
69+
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
70+
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
71+
setContent {
72+
OpenEdXTheme {
73+
val courseId = requireArguments().getString(ARG_COURSE_ID) ?: ""
74+
AuthorizationDialogView(
75+
onRegisterButtonClick = {
76+
router.navigateToSignUp(requireActivity().supportFragmentManager, courseId)
77+
dismiss()
78+
},
79+
onSignInButtonClick = {
80+
router.navigateToSignIn(
81+
requireActivity().supportFragmentManager,
82+
courseId,
83+
null
84+
)
85+
dismiss()
86+
},
87+
onCancelButtonClick = {
88+
dismiss()
89+
}
90+
)
91+
}
92+
}
93+
}
94+
95+
companion object {
96+
private const val ARG_COURSE_ID = "arg_course_id"
97+
private const val LANDSCAPE_WIDTH_PERCENT = 66
98+
fun newInstance(
99+
courseId: String,
100+
): AuthorizationDialogFragment {
101+
val dialog = AuthorizationDialogFragment()
102+
dialog.arguments = bundleOf(
103+
ARG_COURSE_ID to courseId,
104+
)
105+
return dialog
106+
}
107+
}
108+
}
109+
110+
@Composable
111+
private fun AuthorizationDialogView(
112+
onRegisterButtonClick: () -> Unit,
113+
onSignInButtonClick: () -> Unit,
114+
onCancelButtonClick: () -> Unit
115+
) {
116+
val configuration = LocalConfiguration.current
117+
if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
118+
AuthorizationDialogPortraitView(
119+
onRegisterButtonClick = onRegisterButtonClick,
120+
onSignInButtonClick = onSignInButtonClick,
121+
onCancelButtonClick = onCancelButtonClick
122+
)
123+
} else {
124+
AuthorizationDialogLandscapeView(
125+
onRegisterButtonClick = onRegisterButtonClick,
126+
onSignInButtonClick = onSignInButtonClick,
127+
onCancelButtonClick = onCancelButtonClick
128+
)
129+
}
130+
}
131+
132+
@Composable
133+
private fun AuthorizationDialogPortraitView(
134+
onRegisterButtonClick: () -> Unit,
135+
onSignInButtonClick: () -> Unit,
136+
onCancelButtonClick: () -> Unit
137+
) {
138+
Card(
139+
modifier = Modifier
140+
.fillMaxWidth(fraction = 0.95f)
141+
.clip(MaterialTheme.appShapes.courseImageShape),
142+
backgroundColor = MaterialTheme.appColors.background,
143+
shape = MaterialTheme.appShapes.courseImageShape
144+
) {
145+
Column(
146+
modifier = Modifier.padding(30.dp),
147+
horizontalAlignment = Alignment.CenterHorizontally
148+
) {
149+
Box(
150+
contentAlignment = Alignment.CenterEnd,
151+
modifier = Modifier.fillMaxWidth()
152+
) {
153+
IconButton(
154+
modifier = Modifier.size(24.dp),
155+
onClick = onCancelButtonClick
156+
) {
157+
Icon(
158+
imageVector = Icons.Filled.Close,
159+
contentDescription = stringResource(id = coreR.string.core_cancel),
160+
tint = MaterialTheme.appColors.primary
161+
)
162+
}
163+
}
164+
Icon(
165+
modifier = Modifier
166+
.width(76.dp)
167+
.height(72.dp),
168+
imageVector = Icons.AutoMirrored.Filled.Login,
169+
contentDescription = null,
170+
tint = MaterialTheme.appColors.onBackground
171+
)
172+
Spacer(Modifier.height(36.dp))
173+
Text(
174+
text = stringResource(id = coreR.string.core_authorization),
175+
color = MaterialTheme.appColors.textPrimary,
176+
style = MaterialTheme.appTypography.titleLarge
177+
)
178+
Spacer(Modifier.height(8.dp))
179+
Text(
180+
modifier = Modifier.fillMaxWidth(),
181+
text = stringResource(id = coreR.string.core_authorization_request),
182+
color = MaterialTheme.appColors.textFieldText,
183+
style = MaterialTheme.appTypography.titleSmall,
184+
textAlign = TextAlign.Center
185+
)
186+
Spacer(Modifier.height(42.dp))
187+
Row {
188+
OpenEdXOutlinedButton(
189+
modifier = Modifier.weight(1f),
190+
borderColor = MaterialTheme.appColors.primaryButtonBackground,
191+
textColor = MaterialTheme.appColors.primaryButtonBackground,
192+
text = stringResource(id = coreR.string.core_sign_in),
193+
onClick = onSignInButtonClick
194+
)
195+
Spacer(Modifier.width(16.dp))
196+
OpenEdXButton(
197+
modifier = Modifier.weight(1f),
198+
text = stringResource(id = coreR.string.core_register),
199+
onClick = onRegisterButtonClick
200+
)
201+
}
202+
}
203+
}
204+
}
205+
206+
@Composable
207+
private fun AuthorizationDialogLandscapeView(
208+
onRegisterButtonClick: () -> Unit,
209+
onSignInButtonClick: () -> Unit,
210+
onCancelButtonClick: () -> Unit
211+
) {
212+
Card(
213+
modifier = Modifier
214+
.fillMaxWidth()
215+
.clip(MaterialTheme.appShapes.courseImageShape),
216+
backgroundColor = MaterialTheme.appColors.background,
217+
shape = MaterialTheme.appShapes.courseImageShape
218+
) {
219+
Column(
220+
modifier = Modifier.padding(38.dp)
221+
) {
222+
Box(
223+
contentAlignment = Alignment.CenterEnd,
224+
modifier = Modifier
225+
.fillMaxWidth()
226+
.padding(bottom = 12.dp)
227+
) {
228+
IconButton(
229+
modifier = Modifier.size(24.dp),
230+
onClick = onCancelButtonClick
231+
) {
232+
Icon(
233+
imageVector = Icons.Filled.Close,
234+
contentDescription = stringResource(id = coreR.string.core_cancel),
235+
tint = MaterialTheme.appColors.primary
236+
)
237+
}
238+
}
239+
Row(
240+
verticalAlignment = Alignment.CenterVertically,
241+
horizontalArrangement = Arrangement.SpaceBetween
242+
) {
243+
Column(
244+
Modifier.weight(1f),
245+
horizontalAlignment = Alignment.CenterHorizontally
246+
) {
247+
Icon(
248+
modifier = Modifier
249+
.width(76.dp)
250+
.height(72.dp),
251+
imageVector = Icons.AutoMirrored.Filled.Login,
252+
contentDescription = null,
253+
tint = MaterialTheme.appColors.onBackground
254+
)
255+
Spacer(Modifier.height(36.dp))
256+
Text(
257+
modifier = Modifier.fillMaxWidth(),
258+
text = stringResource(id = coreR.string.core_authorization),
259+
color = MaterialTheme.appColors.textPrimary,
260+
style = MaterialTheme.appTypography.titleLarge,
261+
textAlign = TextAlign.Center
262+
)
263+
Spacer(Modifier.height(8.dp))
264+
Text(
265+
modifier = Modifier.fillMaxWidth(),
266+
text = stringResource(id = coreR.string.core_authorization_request),
267+
color = MaterialTheme.appColors.textFieldText,
268+
style = MaterialTheme.appTypography.titleSmall,
269+
textAlign = TextAlign.Center
270+
)
271+
}
272+
Spacer(Modifier.width(42.dp))
273+
Column(
274+
Modifier.weight(1f),
275+
horizontalAlignment = Alignment.CenterHorizontally
276+
) {
277+
OpenEdXOutlinedButton(
278+
borderColor = MaterialTheme.appColors.primaryButtonBackground,
279+
textColor = MaterialTheme.appColors.primaryButtonBackground,
280+
text = stringResource(id = coreR.string.core_sign_in),
281+
onClick = onSignInButtonClick,
282+
)
283+
Spacer(Modifier.height(16.dp))
284+
OpenEdXButton(
285+
text = stringResource(id = coreR.string.core_register),
286+
onClick = onRegisterButtonClick
287+
)
288+
}
289+
}
290+
}
291+
}
292+
}
293+
294+
@Preview(uiMode = UI_MODE_NIGHT_NO)
295+
@Preview(uiMode = UI_MODE_NIGHT_YES)
296+
@Composable
297+
private fun AuthorizationDialogPortraitViewPreview() {
298+
OpenEdXTheme {
299+
AuthorizationDialogPortraitView(
300+
onSignInButtonClick = {},
301+
onRegisterButtonClick = {},
302+
onCancelButtonClick = {}
303+
)
304+
}
305+
}
306+
307+
@Preview(uiMode = UI_MODE_NIGHT_NO)
308+
@Preview(uiMode = UI_MODE_NIGHT_YES)
309+
@Composable
310+
private fun AuthorizationDialogLandscapeViewPreview() {
311+
OpenEdXTheme {
312+
AuthorizationDialogLandscapeView(
313+
onSignInButtonClick = {},
314+
onRegisterButtonClick = {},
315+
onCancelButtonClick = {}
316+
)
317+
}
318+
}

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 = AuthorizationDialogFragment.newInstance(
158+
viewModel.courseId
159+
)
160+
dialog.show(
161+
requireActivity().supportFragmentManager,
162+
AuthorizationDialogFragment::class.simpleName
160163
)
161164
}
162165

0 commit comments

Comments
 (0)