Skip to content

Commit 9014e63

Browse files
fix: fixed upgrade item on SettingsFragment, moved upgrade popup to MainFragment (#438)
1 parent ddcb57d commit 9014e63

File tree

17 files changed

+146
-224
lines changed

17 files changed

+146
-224
lines changed

app/src/main/java/org/openedx/app/MainFragment.kt

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ package org.openedx.app
33
import android.os.Bundle
44
import android.view.Menu
55
import android.view.View
6+
import androidx.compose.foundation.layout.fillMaxWidth
7+
import androidx.compose.runtime.getValue
8+
import androidx.compose.runtime.livedata.observeAsState
9+
import androidx.compose.runtime.remember
10+
import androidx.compose.ui.Modifier
611
import androidx.core.os.bundleOf
712
import androidx.core.view.forEach
813
import androidx.fragment.app.Fragment
@@ -14,9 +19,14 @@ import org.koin.android.ext.android.inject
1419
import org.koin.androidx.viewmodel.ext.android.viewModel
1520
import org.openedx.app.databinding.FragmentMainBinding
1621
import org.openedx.app.deeplink.HomeTab
22+
import org.openedx.core.AppUpdateState
23+
import org.openedx.core.AppUpdateState.wasUpgradeDialogClosed
1724
import org.openedx.core.adapter.NavigationFragmentAdapter
25+
import org.openedx.core.presentation.dialog.appupgrade.AppUpgradeDialogFragment
26+
import org.openedx.core.presentation.global.appupgrade.AppUpgradeRecommendedBox
1827
import org.openedx.core.presentation.global.appupgrade.UpgradeRequiredFragment
1928
import org.openedx.core.presentation.global.viewBinding
29+
import org.openedx.core.system.notifier.app.AppUpgradeEvent
2030
import org.openedx.discovery.presentation.DiscoveryRouter
2131
import org.openedx.downloads.presentation.download.DownloadsFragment
2232
import org.openedx.learn.presentation.LearnFragment
@@ -45,6 +55,7 @@ class MainFragment : Fragment(R.layout.fragment_main) {
4555
handleArguments()
4656
setupBottomNavigation()
4757
setupViewPager()
58+
setupBottomPopup()
4859
observeViewModel()
4960
}
5061

@@ -186,6 +197,56 @@ class MainFragment : Fragment(R.layout.fragment_main) {
186197
}
187198
}
188199

200+
private fun setupBottomPopup() {
201+
binding.composeBottomPopup.setContent {
202+
val appUpgradeEvent by viewModel.appUpgradeEvent.observeAsState()
203+
val wasUpgradeDialogClosed by remember { wasUpgradeDialogClosed }
204+
val appUpgradeParameters = AppUpdateState.AppUpgradeParameters(
205+
appUpgradeEvent = appUpgradeEvent,
206+
wasUpgradeDialogClosed = wasUpgradeDialogClosed,
207+
appUpgradeRecommendedDialog = {
208+
val dialog = AppUpgradeDialogFragment.newInstance()
209+
dialog.show(
210+
requireActivity().supportFragmentManager,
211+
AppUpgradeDialogFragment::class.simpleName
212+
)
213+
},
214+
onAppUpgradeRecommendedBoxClick = {
215+
AppUpdateState.openPlayMarket(requireContext())
216+
},
217+
onAppUpgradeRequired = {
218+
router.navigateToUpgradeRequired(
219+
requireActivity().supportFragmentManager
220+
)
221+
}
222+
)
223+
when (appUpgradeParameters.appUpgradeEvent) {
224+
is AppUpgradeEvent.UpgradeRecommendedEvent -> {
225+
if (appUpgradeParameters.wasUpgradeDialogClosed) {
226+
AppUpgradeRecommendedBox(
227+
modifier = Modifier.fillMaxWidth(),
228+
onClick = appUpgradeParameters.onAppUpgradeRecommendedBoxClick
229+
)
230+
} else {
231+
if (!AppUpdateState.wasUpdateDialogDisplayed) {
232+
AppUpdateState.wasUpdateDialogDisplayed = true
233+
appUpgradeParameters.appUpgradeRecommendedDialog()
234+
}
235+
}
236+
}
237+
238+
is AppUpgradeEvent.UpgradeRequiredEvent -> {
239+
if (!AppUpdateState.wasUpdateDialogDisplayed) {
240+
AppUpdateState.wasUpdateDialogDisplayed = true
241+
appUpgradeParameters.onAppUpgradeRequired()
242+
}
243+
}
244+
245+
else -> {}
246+
}
247+
}
248+
}
249+
189250
companion object {
190251
private const val ARG_COURSE_ID = "courseId"
191252
private const val ARG_INFO_TYPE = "info_type"

app/src/main/java/org/openedx/app/MainViewModel.kt

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,20 @@ import kotlinx.coroutines.flow.asSharedFlow
1010
import kotlinx.coroutines.flow.distinctUntilChanged
1111
import kotlinx.coroutines.flow.launchIn
1212
import kotlinx.coroutines.flow.onEach
13+
import kotlinx.coroutines.launch
1314
import org.openedx.core.config.Config
1415
import org.openedx.core.system.notifier.DiscoveryNotifier
1516
import org.openedx.core.system.notifier.NavigationToDiscovery
17+
import org.openedx.core.system.notifier.app.AppNotifier
18+
import org.openedx.core.system.notifier.app.AppUpgradeEvent
1619
import org.openedx.discovery.presentation.DiscoveryNavigator
1720
import org.openedx.foundation.presentation.BaseViewModel
1821

1922
class MainViewModel(
2023
private val config: Config,
2124
private val notifier: DiscoveryNotifier,
2225
private val analytics: AppAnalytics,
26+
private val appNotifier: AppNotifier,
2327
) : BaseViewModel() {
2428

2529
private val _isBottomBarEnabled = MutableLiveData(true)
@@ -30,21 +34,19 @@ class MainViewModel(
3034
val navigateToDiscovery: SharedFlow<Boolean>
3135
get() = _navigateToDiscovery.asSharedFlow()
3236

37+
private val _appUpgradeEvent = MutableLiveData<AppUpgradeEvent>()
38+
val appUpgradeEvent: LiveData<AppUpgradeEvent>
39+
get() = _appUpgradeEvent
40+
3341
val isDiscoveryTypeWebView get() = config.getDiscoveryConfig().isViewTypeWebView()
3442
val getDiscoveryFragment get() = DiscoveryNavigator(isDiscoveryTypeWebView).getDiscoveryFragment()
3543

3644
val isDownloadsFragmentEnabled get() = config.getDownloadsConfig().isEnabled
3745

3846
override fun onCreate(owner: LifecycleOwner) {
3947
super.onCreate(owner)
40-
notifier.notifier
41-
.onEach {
42-
if (it is NavigationToDiscovery) {
43-
_navigateToDiscovery.emit(true)
44-
}
45-
}
46-
.distinctUntilChanged()
47-
.launchIn(viewModelScope)
48+
collectDiscoveryEvents()
49+
collectAppUpgradeEvent()
4850
}
4951

5052
fun enableBottomBar(enable: Boolean) {
@@ -75,4 +77,28 @@ class MainViewModel(
7577
}
7678
)
7779
}
80+
81+
private fun collectDiscoveryEvents() {
82+
notifier.notifier
83+
.onEach {
84+
if (it is NavigationToDiscovery) {
85+
_navigateToDiscovery.emit(true)
86+
}
87+
}
88+
.distinctUntilChanged()
89+
.launchIn(viewModelScope)
90+
}
91+
92+
private fun collectAppUpgradeEvent() {
93+
viewModelScope.launch {
94+
appNotifier.notifier
95+
.onEach { event ->
96+
if (event is AppUpgradeEvent) {
97+
_appUpgradeEvent.value = event
98+
}
99+
}
100+
.distinctUntilChanged()
101+
.launchIn(viewModelScope)
102+
}
103+
}
78104
}

app/src/main/java/org/openedx/app/data/networking/AppUpgradeInterceptor.kt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import kotlinx.coroutines.runBlocking
44
import okhttp3.Interceptor
55
import okhttp3.Response
66
import org.openedx.app.BuildConfig
7+
import org.openedx.core.AppUpdateState
78
import org.openedx.core.system.notifier.app.AppNotifier
89
import org.openedx.core.system.notifier.app.AppUpgradeEvent
910
import org.openedx.core.utils.TimeUtils
@@ -17,23 +18,30 @@ class AppUpgradeInterceptor(
1718
val responseCode = response.code
1819
val latestAppVersion = response.header(HEADER_APP_LATEST_VERSION) ?: ""
1920
val lastSupportedDateString = response.header(HEADER_APP_VERSION_LAST_SUPPORTED_DATE) ?: ""
20-
val lastSupportedDateTime = TimeUtils.iso8601WithTimeZoneToDate(lastSupportedDateString)?.time ?: 0L
21+
val lastSupportedDateTime =
22+
TimeUtils.iso8601WithTimeZoneToDate(lastSupportedDateString)?.time ?: 0L
2123
runBlocking {
22-
when {
24+
val appUpgradeEvent = when {
2325
responseCode == 426 -> {
24-
appNotifier.send(AppUpgradeEvent.UpgradeRequiredEvent)
26+
AppUpgradeEvent.UpgradeRequiredEvent
2527
}
2628

2729
BuildConfig.VERSION_NAME != latestAppVersion && lastSupportedDateTime > Date().time -> {
28-
appNotifier.send(AppUpgradeEvent.UpgradeRecommendedEvent(latestAppVersion))
30+
AppUpgradeEvent.UpgradeRecommendedEvent(latestAppVersion)
2931
}
3032

3133
latestAppVersion.isNotEmpty() &&
3234
BuildConfig.VERSION_NAME != latestAppVersion &&
3335
lastSupportedDateTime < Date().time -> {
34-
appNotifier.send(AppUpgradeEvent.UpgradeRequiredEvent)
36+
AppUpgradeEvent.UpgradeRequiredEvent
37+
}
38+
39+
else -> {
40+
return@runBlocking
3541
}
3642
}
43+
AppUpdateState.lastAppUpgradeEvent = appUpgradeEvent
44+
appNotifier.send(appUpgradeEvent)
3745
}
3846
return response
3947
}

app/src/main/java/org/openedx/app/data/networking/HeadersInterceptor.kt

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package org.openedx.app.data.networking
22

3-
import android.content.Context
43
import okhttp3.Interceptor
54
import okhttp3.Response
6-
import org.openedx.app.BuildConfig
75
import org.openedx.core.config.Config
86
import org.openedx.core.data.storage.CorePreferences
7+
import org.openedx.core.presentation.global.AppData
98

109
class HeadersInterceptor(
11-
private val context: Context,
10+
private val appData: AppData,
1211
private val config: Config,
1312
private val preferencesManager: CorePreferences,
1413
) : Interceptor {
@@ -26,13 +25,7 @@ class HeadersInterceptor(
2625
addHeader("Accept", "application/json")
2726

2827
val httpAgent = System.getProperty("http.agent") ?: ""
29-
addHeader(
30-
"User-Agent",
31-
httpAgent + " " +
32-
context.getString(org.openedx.core.R.string.app_name) + "/" +
33-
BuildConfig.APPLICATION_ID + "/" +
34-
BuildConfig.VERSION_NAME
35-
)
28+
addHeader("User-Agent", "$httpAgent ${appData.versionName}")
3629
}.build()
3730
)
3831
}

app/src/main/java/org/openedx/app/di/ScreenModule.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ val screenModule = module {
9191
get(),
9292
)
9393
}
94-
viewModel { MainViewModel(get(), get(), get()) }
94+
viewModel { MainViewModel(get(), get(), get(), get()) }
9595

9696
factory { AuthRepository(get(), get(), get()) }
9797
factory { AuthInteractor(get()) }
@@ -148,7 +148,7 @@ val screenModule = module {
148148

149149
factory { DashboardRepository(get(), get(), get(), get()) }
150150
factory { DashboardInteractor(get()) }
151-
viewModel { DashboardListViewModel(get(), get(), get(), get(), get(), get(), get()) }
151+
viewModel { DashboardListViewModel(get(), get(), get(), get(), get(), get()) }
152152
viewModel { (windowSize: WindowSize) ->
153153
DashboardGalleryViewModel(
154154
get(),
@@ -169,7 +169,7 @@ val screenModule = module {
169169

170170
factory { DiscoveryRepository(get(), get(), get()) }
171171
factory { DiscoveryInteractor(get()) }
172-
viewModel { NativeDiscoveryViewModel(get(), get(), get(), get(), get(), get(), get()) }
172+
viewModel { NativeDiscoveryViewModel(get(), get(), get(), get(), get(), get()) }
173173
viewModel { (querySearch: String) ->
174174
WebViewDiscoveryViewModel(
175175
querySearch,

app/src/main/res/layout/fragment_main.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,11 @@
2727
app:layout_constraintHorizontal_bias="0.5"
2828
app:layout_constraintStart_toStartOf="parent" />
2929

30+
<androidx.compose.ui.platform.ComposeView
31+
android:id="@+id/compose_bottom_popup"
32+
android:layout_width="match_parent"
33+
android:layout_height="wrap_content"
34+
android:paddingBottom="24.dp"
35+
app:layout_constraintBottom_toBottomOf="@+id/view_pager" />
36+
3037
</androidx.constraintlayout.widget.ConstraintLayout>

core/src/main/java/org/openedx/core/AppUpdateState.kt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,37 @@ package org.openedx.core
33
import android.content.ActivityNotFoundException
44
import android.content.Context
55
import android.content.Intent
6-
import android.net.Uri
76
import androidx.compose.runtime.mutableStateOf
7+
import androidx.core.net.toUri
88
import org.openedx.core.system.notifier.app.AppUpgradeEvent
99

1010
object AppUpdateState {
1111
var wasUpdateDialogDisplayed = false
12-
var wasUpdateDialogClosed = mutableStateOf(false)
12+
var wasUpgradeDialogClosed = mutableStateOf(false)
13+
var lastAppUpgradeEvent: AppUpgradeEvent? = null
1314

1415
fun openPlayMarket(context: Context) {
1516
try {
16-
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=${context.packageName}")))
17+
context.startActivity(
18+
Intent(
19+
Intent.ACTION_VIEW,
20+
"market://details?id=${context.packageName}".toUri()
21+
)
22+
)
1723
} catch (e: ActivityNotFoundException) {
1824
e.printStackTrace()
1925
context.startActivity(
2026
Intent(
2127
Intent.ACTION_VIEW,
22-
Uri.parse("https://play.google.com/store/apps/details?id=${context.packageName}")
28+
"https://play.google.com/store/apps/details?id=${context.packageName}".toUri()
2329
)
2430
)
2531
}
2632
}
2733

2834
data class AppUpgradeParameters(
2935
val appUpgradeEvent: AppUpgradeEvent? = null,
30-
val wasUpdateDialogClosed: Boolean = AppUpdateState.wasUpdateDialogClosed.value,
36+
val wasUpgradeDialogClosed: Boolean = AppUpdateState.wasUpgradeDialogClosed.value,
3137
val appUpgradeRecommendedDialog: () -> Unit = {},
3238
val onAppUpgradeRecommendedBoxClick: () -> Unit = {},
3339
val onAppUpgradeRequired: () -> Unit = {},

core/src/main/java/org/openedx/core/presentation/dialog/appupgrade/AppUpgradeDialogFragment.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ class AppUpgradeDialogFragment : DialogFragment() {
3333
}
3434

3535
private fun onNotNowClick() {
36-
AppUpdateState.wasUpdateDialogClosed.value = true
36+
AppUpdateState.wasUpgradeDialogClosed.value = true
3737
dismiss()
3838
}
3939

4040
private fun onUpdateClick() {
41-
AppUpdateState.wasUpdateDialogClosed.value = true
41+
AppUpdateState.wasUpgradeDialogClosed.value = true
4242
dismiss()
4343
AppUpdateState.openPlayMarket(requireContext())
4444
}

0 commit comments

Comments
 (0)