1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.spa.network
18 
19 import android.app.Activity
20 import android.content.Context
21 import android.content.ContextWrapper
22 import android.os.Bundle
23 import androidx.annotation.VisibleForTesting
24 import androidx.compose.foundation.layout.Column
25 import androidx.compose.foundation.layout.padding
26 import androidx.compose.runtime.Composable
27 import androidx.compose.runtime.LaunchedEffect
28 import androidx.compose.ui.Modifier
29 import androidx.compose.ui.platform.LocalContext
30 import androidx.navigation.NavHostController
31 import androidx.navigation.NavType
32 import androidx.navigation.compose.NavHost
33 import androidx.navigation.compose.composable
34 import androidx.navigation.compose.rememberNavController
35 import androidx.navigation.navArgument
36 import com.android.settings.R
37 import com.android.settings.network.SimOnboardingActivity
38 import com.android.settings.network.SimOnboardingActivity.Companion.CallbackType
39 import com.android.settings.network.SimOnboardingService
40 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
41 import com.android.settingslib.spa.framework.common.SettingsPageProvider
42 import com.android.settingslib.spa.framework.common.createSettingsPage
43 import com.android.settingslib.spa.framework.compose.navigator
44 import com.android.settingslib.spa.framework.theme.SettingsDimension
45 import com.android.settingslib.spa.widget.preference.Preference
46 import com.android.settingslib.spa.widget.preference.PreferenceModel
47 import com.android.settingslib.spa.widget.ui.SettingsBody
48 
49 const val SUB_ID = "subId"
50 
51 enum class SimOnboardingScreen(val stringResId: Int) {
52     LabelSim(R.string.sim_onboarding_label_sim_title),
53     SelectSim(R.string.sim_onboarding_select_sim_title),
54     PrimarySim(R.string.sim_onboarding_primary_sim_title)
55 }
56 
57 /**
58  * Showing the sim onboarding which is the process flow of sim switching on.
59  */
60 object SimOnboardingPageProvider : SettingsPageProvider {
61     override val name = "SimOnboardingPageProvider"
62     override val parameter = listOf(
<lambda>null63         navArgument(SUB_ID) { type = NavType.IntType },
64     )
65 
66     private val owner = createSettingsPage()
67     @VisibleForTesting
68     var onboardingService: SimOnboardingService = SimOnboardingActivity.onboardingService
69 
buildInjectEntrynull70     fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = owner)
71         .setUiLayoutFn {
72             // never using
73             Preference(object : PreferenceModel {
74                 override val title = name
75                 override val onClick = navigator(getRoute(-1))
76             })
77         }
78 
79     @Composable
Pagenull80     override fun Page(arguments: Bundle?) {
81         PageImpl(onboardingService,rememberNavController())
82     }
83 
getRoutenull84     fun getRoute(
85         subId: Int
86     ): String = "${name}/$subId"
87 }
88 
89 fun Context.getActivity(): Activity? = when (this) {
90     is Activity -> this
91     is ContextWrapper -> baseContext.getActivity()
92     else -> null
93 }
94 
95 @Composable
PageImplnull96 fun PageImpl(onboardingService:SimOnboardingService,navHostController: NavHostController) {
97     val context = LocalContext.current
98     var finishOnboarding: () -> Unit = {
99         context.getActivity()?.finish()
100         onboardingService.callback(CallbackType.CALLBACK_FINISH)
101     }
102 
103     NavHost(
104         navController = navHostController,
105         startDestination = SimOnboardingScreen.LabelSim.name
106     ) {
107         composable(route = SimOnboardingScreen.LabelSim.name) {
108             val nextPage =
109                 if (onboardingService.isMultipleEnabledProfilesSupported
110                         && onboardingService.isAllOfSlotAssigned
111                         && !onboardingService.doesTargetSimActive) {
112                     SimOnboardingScreen.SelectSim.name
113                 } else {
114                     LaunchedEffect(Unit) {
115                         onboardingService.addCurrentItemForSelectedSim()
116                     }
117                     SimOnboardingScreen.PrimarySim.name
118                 }
119             SimOnboardingLabelSimImpl(
120                 nextAction = { navHostController.navigate(nextPage) },
121                 cancelAction = finishOnboarding,
122                 onboardingService = onboardingService
123             )
124         }
125         composable(route = SimOnboardingScreen.PrimarySim.name) {
126             SimOnboardingPrimarySimImpl(
127                 nextAction = {
128                     onboardingService.callback(CallbackType.CALLBACK_ONBOARDING_COMPLETE)
129                     context.getActivity()?.finish()
130                 },
131                 cancelAction = finishOnboarding,
132                 onboardingService = onboardingService
133             )
134         }
135         composable(route = SimOnboardingScreen.SelectSim.name) {
136             SimOnboardingSelectSimImpl(
137                 nextAction = { navHostController.navigate(SimOnboardingScreen.PrimarySim.name) },
138                 cancelAction = finishOnboarding,
139                 onboardingService = onboardingService
140             )
141         }
142     }
143 }
144 
145 @Composable
SimOnboardingMessagenull146 fun SimOnboardingMessage(text: String) {
147     Column(
148         Modifier.padding(
149             start = SettingsDimension.itemPaddingStart,
150             end = SettingsDimension.itemPaddingEnd,
151             bottom = SettingsDimension.paddingExtraLarge,
152         )
153     ) {
154         SettingsBody(text)
155     }
156 }
157