1
1
package org.oppia.android.app.devoptions.featureflags
2
2
3
- import android.app.AlertDialog
4
3
import android.content.Intent
5
4
import android.view.LayoutInflater
6
5
import android.view.View
@@ -12,8 +11,8 @@ import androidx.fragment.app.Fragment
12
11
import androidx.recyclerview.widget.LinearLayoutManager
13
12
import org.oppia.android.app.databinding.databinding.FeatureFlagsFragmentBinding
14
13
import org.oppia.android.app.databinding.databinding.FeatureFlagsItemBinding
15
- import org.oppia.android.app.databinding.databinding.PendingChangesDialogFragmentBinding
16
14
import org.oppia.android.app.devoptions.AppRestartDialogFragment
15
+ import org.oppia.android.app.devoptions.PendingChangesDialogFragment
17
16
import org.oppia.android.app.fragment.FragmentScope
18
17
import org.oppia.android.app.model.FeatureFlagId
19
18
import org.oppia.android.app.model.OverriddenFeatureFlag
@@ -31,6 +30,9 @@ import kotlin.system.exitProcess
31
30
/* * Tag for displaying [AppRestartDialogFragment]. */
32
31
const val TAG_FEATURE_FLAG_RESTART_DIALOG = " FEATURE_FLAG_RESTART_DIALOG_TAG"
33
32
33
+ /* * Tag for displaying [PendingChangesDialogFragment]. */
34
+ const val TAG_FEATURE_FLAG_PENDING_CHANGES_DIALOG = " FEATURE_FLAG_PENDING_CHANGES_DIALOG_TAG"
35
+
34
36
/* * The presenter for [FeatureFlagsFragment]. */
35
37
@FragmentScope
36
38
class FeatureFlagsFragmentPresenter @Inject constructor(
@@ -44,7 +46,6 @@ class FeatureFlagsFragmentPresenter @Inject constructor(
44
46
private lateinit var binding: FeatureFlagsFragmentBinding
45
47
private lateinit var linearLayoutManager: LinearLayoutManager
46
48
private lateinit var bindingAdapter: BindableAdapter <FeatureFlagItemViewModel >
47
- private var restartRequired: Boolean = false
48
49
49
50
/* * Called when [FeatureFlagsFragment] is created. Handles UI for the fragment. */
50
51
fun handleCreateView (
@@ -58,13 +59,6 @@ class FeatureFlagsFragmentPresenter @Inject constructor(
58
59
container,
59
60
/* attachToRoot= */ false
60
61
)
61
- binding.featureFlagsToolbar.setNavigationOnClickListener {
62
- onBackNavigation()
63
- }
64
- binding.saveButton.setOnClickListener {
65
- val overriddenFlags = computeOverriddenFlags()
66
- savePendingFeatureFlags(overriddenFlags)
67
- }
68
62
69
63
activity.onBackPressedDispatcher.addCallback(
70
64
fragment,
@@ -82,16 +76,23 @@ class FeatureFlagsFragmentPresenter @Inject constructor(
82
76
featureFlagsViewModel.resetFlags.value = resetFlags.toMutableMap()
83
77
}
84
78
85
- binding.apply {
86
- this .lifecycleOwner = fragment
87
- this .viewModel = featureFlagsViewModel
88
- }
89
-
90
79
linearLayoutManager = LinearLayoutManager (activity.applicationContext)
91
80
bindingAdapter = createRecyclerViewAdapter()
92
- binding.featureFlagsRecyclerView.apply {
93
- layoutManager = linearLayoutManager
94
- adapter = bindingAdapter
81
+
82
+ binding.apply {
83
+ lifecycleOwner = fragment
84
+ viewModel = featureFlagsViewModel
85
+ saveButton.setOnClickListener {
86
+ val overriddenFlags = computeOverriddenFlags()
87
+ savePendingFeatureFlags(overriddenFlags)
88
+ }
89
+ featureFlagsToolbar.setNavigationOnClickListener {
90
+ onBackNavigation()
91
+ }
92
+ featureFlagsRecyclerView.apply {
93
+ layoutManager = linearLayoutManager
94
+ adapter = bindingAdapter
95
+ }
95
96
}
96
97
97
98
return binding.root
@@ -111,33 +112,15 @@ class FeatureFlagsFragmentPresenter @Inject constructor(
111
112
val resetFlags = getResetFeatureFlags()
112
113
113
114
if (overriddenFlags.isNotEmpty() || resetFlags.isNotEmpty()) {
114
- showPendingChangesDialog(overriddenFlags )
115
+ showPendingChangesDialog()
115
116
} else {
116
117
activity.finish()
117
118
}
118
119
}
119
120
120
- private fun showPendingChangesDialog (overriddenFlags : List <OverriddenFeatureFlag >) {
121
- val dialogBinding = PendingChangesDialogFragmentBinding .inflate(
122
- LayoutInflater .from(activity),
123
- /* root= */ null ,
124
- /* attachToRoot= */ false
125
- )
126
- val dialog = AlertDialog .Builder (activity)
127
- .setView(dialogBinding.root)
128
- .create()
129
-
130
- dialogBinding.saveButton.setOnClickListener {
131
- dialog.dismiss()
132
- savePendingFeatureFlags(overriddenFlags)
133
- }
134
-
135
- dialogBinding.discardButton.setOnClickListener {
136
- dialog.dismiss()
137
- activity.finish()
138
- }
139
-
140
- dialog.show()
121
+ private fun showPendingChangesDialog () {
122
+ val dialog = PendingChangesDialogFragment .newInstance()
123
+ dialog.showNow(fragment.childFragmentManager, TAG_FEATURE_FLAG_PENDING_CHANGES_DIALOG )
141
124
}
142
125
143
126
private fun savePendingFeatureFlags (overriddenFlags : List <OverriddenFeatureFlag >) {
@@ -190,7 +173,6 @@ class FeatureFlagsFragmentPresenter @Inject constructor(
190
173
.observe(fragment) { result ->
191
174
when (result) {
192
175
is AsyncResult .Success -> {
193
- restartRequired = true
194
176
val dialog = AppRestartDialogFragment .newInstance()
195
177
dialog.showNow(fragment.childFragmentManager, TAG_FEATURE_FLAG_RESTART_DIALOG )
196
178
}
@@ -273,21 +255,15 @@ class FeatureFlagsFragmentPresenter @Inject constructor(
273
255
}
274
256
}
275
257
276
- /* *
277
- * Called when [FeatureFlagsFragment] is destroyed.
278
- * Performs a fresh restart of the app to load any updated feature flag states, if required.
279
- */
280
- fun handleOnDestroy () {
281
- if (restartRequired) {
282
- val intent = Intent (activity, SplashActivity ::class .java).also {
283
- it.action = Intent .ACTION_MAIN
284
- it.addCategory(Intent .CATEGORY_LAUNCHER )
285
- }
286
- activity.startActivity(intent)
287
- // App is terminated to ensure a fresh restart and kill all the current process
288
- // so that ProcessState can be reinitialised on the fresh restart.
289
- exitProcess(0 )
290
- }
258
+ /* * Called when user opts to save changes in [PendingChangesDialogFragment]. */
259
+ fun savePendingChanges () {
260
+ val overriddenFlags = computeOverriddenFlags()
261
+ savePendingFeatureFlags(overriddenFlags)
262
+ }
263
+
264
+ /* * Called when user opts to discard changes in [PendingChangesDialogFragment]. */
265
+ fun discardPendingChanges () {
266
+ activity.finish()
291
267
}
292
268
293
269
/* *
@@ -309,4 +285,20 @@ class FeatureFlagsFragmentPresenter @Inject constructor(
309
285
fun getFeatureFlagStates (): Map <FeatureFlagId , Boolean > {
310
286
return featureFlagsViewModel.featureFlagStates.value ? : mapOf ()
311
287
}
288
+
289
+ /* *
290
+ * Performs a fresh restart of the app to reload feature flag states and reinitialize
291
+ * the app processState.
292
+ */
293
+ fun restartApp () {
294
+ val intent = Intent (activity, SplashActivity ::class .java).also {
295
+ it.action = Intent .ACTION_MAIN
296
+ it.addCategory(Intent .CATEGORY_LAUNCHER )
297
+ }
298
+ activity.finishAffinity()
299
+ activity.startActivity(intent)
300
+ // App is terminated to ensure a fresh restart and kill all the current process
301
+ // so that ProcessState can be reinitialised on the fresh restart.
302
+ exitProcess(0 )
303
+ }
312
304
}
0 commit comments