From 709e0ec1ca2b79ba323df705303acbd8c2af0d2c Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 26 Nov 2025 16:06:58 +0800 Subject: [PATCH] compose: Migrate onboarding logic to compose * Still needs implementation for showing microG installation screen on huawei * No anonymous mode on huawei * Needs handling for showing permissions screen via settings Signed-off-by: Aayush Gupta --- .../view/ui/onboarding/MicroGFragment.kt | 164 ----------- .../view/ui/onboarding/OnboardingFragment.kt | 104 ------- .../store/compose/composable/LinkListItem.kt | 12 +- .../compose/composable/PermissionList.kt | 8 +- .../store/compose/navigation/NavDisplay.kt | 5 + .../aurora/store/compose/navigation/Screen.kt | 3 + .../ui/commons/PermissionRationaleScreen.kt | 7 +- .../compose/ui/onboarding/OnboardingScreen.kt | 139 ++++++++++ .../ui/onboarding/PermissionsScreen.kt | 91 +++++++ .../compose/ui/onboarding/WelcomeScreen.kt | 144 ++++++++++ .../ui/onboarding/navigation/ExtraScreen.kt | 27 ++ .../java/com/aurora/store/data/model/Dash.kt | 41 --- .../com/aurora/store/data/model/Permission.kt | 13 +- .../data/providers/PermissionProvider.kt | 30 +-- .../view/epoxy/views/preference/DashView.kt | 54 ---- .../epoxy/views/preference/PermissionView.kt | 65 ----- .../view/ui/details/DetailsMicroGFragment.kt | 203 -------------- .../BaseFlavouredOnboardingFragment.kt | 254 ------------------ .../view/ui/onboarding/PermissionsFragment.kt | 171 ------------ .../view/ui/onboarding/WelcomeFragment.kt | 105 -------- .../view/ui/preferences/SettingsFragment.kt | 4 +- .../ui/splash/BaseFlavouredSplashFragment.kt | 5 +- .../commons/PermissionRationaleViewModel.kt | 9 +- .../viewmodel/onboarding/OnboardingPage.kt | 7 - .../onboarding/OnboardingViewModel.kt | 81 +++++- app/src/main/res/drawable/ic_code.xml | 21 +- app/src/main/res/drawable/ic_faq.xml | 21 +- app/src/main/res/drawable/ic_license.xml | 21 +- app/src/main/res/drawable/ic_privacy.xml | 21 +- .../fragment_onboarding_microg.xml | 109 -------- .../fragment_onboarding_permissions.xml | 81 ------ .../fragment_onboarding_welcome.xml | 63 ----- .../res/layout/fragment_details_microg.xml | 110 -------- .../main/res/layout/fragment_onboarding.xml | 84 ------ .../res/layout/fragment_onboarding_microg.xml | 106 -------- .../fragment_onboarding_permissions.xml | 72 ----- .../layout/fragment_onboarding_welcome.xml | 59 ---- app/src/main/res/layout/view_dash.xml | 64 ----- app/src/main/res/layout/view_permission.xml | 54 ---- .../main/res/navigation/mobile_navigation.xml | 38 +-- .../view/ui/onboarding/OnboardingFragment.kt | 82 ------ .../view/ui/onboarding/OnboardingFragment.kt | 82 ------ 42 files changed, 527 insertions(+), 2307 deletions(-) delete mode 100644 app/src/huawei/java/com/aurora/store/view/ui/onboarding/MicroGFragment.kt delete mode 100644 app/src/huawei/java/com/aurora/store/view/ui/onboarding/OnboardingFragment.kt create mode 100644 app/src/main/java/com/aurora/store/compose/ui/onboarding/OnboardingScreen.kt create mode 100644 app/src/main/java/com/aurora/store/compose/ui/onboarding/PermissionsScreen.kt create mode 100644 app/src/main/java/com/aurora/store/compose/ui/onboarding/WelcomeScreen.kt create mode 100644 app/src/main/java/com/aurora/store/compose/ui/onboarding/navigation/ExtraScreen.kt delete mode 100644 app/src/main/java/com/aurora/store/data/model/Dash.kt delete mode 100644 app/src/main/java/com/aurora/store/view/epoxy/views/preference/DashView.kt delete mode 100644 app/src/main/java/com/aurora/store/view/epoxy/views/preference/PermissionView.kt delete mode 100644 app/src/main/java/com/aurora/store/view/ui/details/DetailsMicroGFragment.kt delete mode 100644 app/src/main/java/com/aurora/store/view/ui/onboarding/BaseFlavouredOnboardingFragment.kt delete mode 100644 app/src/main/java/com/aurora/store/view/ui/onboarding/PermissionsFragment.kt delete mode 100644 app/src/main/java/com/aurora/store/view/ui/onboarding/WelcomeFragment.kt delete mode 100644 app/src/main/java/com/aurora/store/viewmodel/onboarding/OnboardingPage.kt delete mode 100644 app/src/main/res/layout-land/fragment_onboarding_microg.xml delete mode 100644 app/src/main/res/layout-land/fragment_onboarding_permissions.xml delete mode 100644 app/src/main/res/layout-land/fragment_onboarding_welcome.xml delete mode 100644 app/src/main/res/layout/fragment_details_microg.xml delete mode 100644 app/src/main/res/layout/fragment_onboarding.xml delete mode 100644 app/src/main/res/layout/fragment_onboarding_microg.xml delete mode 100644 app/src/main/res/layout/fragment_onboarding_permissions.xml delete mode 100644 app/src/main/res/layout/fragment_onboarding_welcome.xml delete mode 100644 app/src/main/res/layout/view_dash.xml delete mode 100644 app/src/main/res/layout/view_permission.xml delete mode 100644 app/src/preload/java/com/aurora/store/view/ui/onboarding/OnboardingFragment.kt delete mode 100644 app/src/vanilla/java/com/aurora/store/view/ui/onboarding/OnboardingFragment.kt diff --git a/app/src/huawei/java/com/aurora/store/view/ui/onboarding/MicroGFragment.kt b/app/src/huawei/java/com/aurora/store/view/ui/onboarding/MicroGFragment.kt deleted file mode 100644 index b11ad4e9a..000000000 --- a/app/src/huawei/java/com/aurora/store/view/ui/onboarding/MicroGFragment.kt +++ /dev/null @@ -1,164 +0,0 @@ -package com.aurora.store.view.ui.onboarding - -import android.os.Bundle -import android.view.View -import androidx.fragment.app.activityViewModels -import androidx.lifecycle.lifecycleScope -import com.aurora.Constants.PACKAGE_NAME_GMS -import com.aurora.extensions.browse -import com.aurora.store.AuroraApp -import com.aurora.store.R -import com.aurora.store.data.event.Event -import com.aurora.store.data.event.InstallerEvent -import com.aurora.store.data.model.Dash -import com.aurora.store.data.model.DownloadStatus -import com.aurora.store.databinding.FragmentOnboardingMicrogBinding -import com.aurora.store.util.PackageUtil -import com.aurora.store.view.epoxy.views.EpoxyTextViewModel_ -import com.aurora.store.view.epoxy.views.preference.DashViewModel_ -import com.aurora.store.view.ui.commons.BaseFragment -import com.aurora.store.viewmodel.onboarding.MicroGViewModel -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.flow.filterNotNull -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch - -@AndroidEntryPoint -class MicroGFragment : BaseFragment() { - // Shared ViewModel - val microGViewModel: MicroGViewModel by activityViewModels() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - with(binding) { - // RecyclerView - epoxyRecycler.withModels { - setFilterDuplicates(true) - - add( - EpoxyTextViewModel_() - .id("microg_desc") - .title(getString(R.string.onboarding_gms_missing)) - .size(14) - .style(R.style.AuroraTextStyle) - ) - - add( - EpoxyTextViewModel_() - .id("microg_gms") - .title(getString(R.string.onboarding_gms_microg)) - .size(14) - .style(R.style.AuroraTextStyle) - ) - - - dashItems().forEach { - add( - DashViewModel_() - .id(it.id) - .dash(it) - .click { _ -> - requireContext().browse(it.url) - } - ) - } - } - - checkboxAgreement.setOnCheckedChangeListener { _, value -> - microGViewModel.markAgreement(value) - btnMicroG.isEnabled = value - } - - btnMicroG.setOnClickListener { microGViewModel.downloadMicroG() } - } - - microGViewModel.download.filterNotNull().onEach { - when (it.downloadStatus) { - DownloadStatus.DOWNLOADING -> updateProgressBar(visible = true, it.progress) - DownloadStatus.FAILED -> updateProgressBar(visible = false, 0) - DownloadStatus.QUEUED -> updateProgressBar(visible = true, -1) - DownloadStatus.COMPLETED -> updateProgressBar(visible = true, -1) - else -> {} - } - }.launchIn(viewLifecycleOwner.lifecycleScope) - - viewLifecycleOwner.lifecycleScope.launch { - AuroraApp.events.installerEvent.collect { onEvent(it) } - } - } - - private fun onEvent(event: Event) { - when (event) { - is InstallerEvent.Installed -> { - if (event.packageName == PACKAGE_NAME_GMS) { - microGViewModel.downloadCompanion() - } - - if (PackageUtil.isMicroGBundleInstalled(requireContext())) { - markInstallationComplete() - } - } - - is InstallerEvent.Failed -> markInstallationFailed() - else -> {} - } - } - - private fun updateProgressBar(visible: Boolean, downloadProgress: Int) { - with(binding.progressBar) { - if (visible) show() else hide() - isIndeterminate = downloadProgress == -1 - progress = downloadProgress - } - } - - private fun markInstallationComplete() { - with(binding) { - with(btnMicroG) { - isEnabled = false - text = getString(R.string.title_installed) - } - checkboxAgreement.isEnabled = false - progressBar.hide() - } - } - - private fun markInstallationFailed() { - with(binding) { - with(btnMicroG) { - isEnabled = false - text = getString(R.string.action_install) - } - checkboxAgreement.isChecked = false - progressBar.hide() - } - } - - private fun dashItems(): List { - return listOf( - Dash( - id = 2, - title = requireContext().getString(R.string.details_dev_website), - subtitle = requireContext().getString(R.string.microg_website), - icon = R.drawable.ic_network, - url = "https://microG.org" - ), - Dash( - id = 4, - title = requireContext().getString(R.string.privacy_policy_title), - subtitle = requireContext().getString(R.string.microg_privacy_policy), - icon = R.drawable.ic_privacy, - url = "https://microg.org/privacy.html" - ), - Dash( - id = 5, - title = requireContext().getString(R.string.menu_disclaimer), - subtitle = requireContext().getString(R.string.microg_license_agreement), - icon = R.drawable.ic_disclaimer, - url = "https://raw.githubusercontent.com/microg/GmsCore/refs/heads/master/LICENSE" - ) - ) - } -} \ No newline at end of file diff --git a/app/src/huawei/java/com/aurora/store/view/ui/onboarding/OnboardingFragment.kt b/app/src/huawei/java/com/aurora/store/view/ui/onboarding/OnboardingFragment.kt deleted file mode 100644 index 14e5d0f1d..000000000 --- a/app/src/huawei/java/com/aurora/store/view/ui/onboarding/OnboardingFragment.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.view.ui.onboarding - -import androidx.fragment.app.Fragment -import com.aurora.extensions.isHuawei -import com.aurora.store.data.providers.BlacklistProvider -import com.aurora.store.util.PackageUtil -import com.aurora.store.util.Preferences.PREFERENCE_AUTO_DELETE -import com.aurora.store.util.Preferences.PREFERENCE_DEFAULT_SELECTED_TAB -import com.aurora.store.util.Preferences.PREFERENCE_DISPENSER_URLS -import com.aurora.store.util.Preferences.PREFERENCE_FILTER_AURORA_ONLY -import com.aurora.store.util.Preferences.PREFERENCE_FILTER_FDROID -import com.aurora.store.util.Preferences.PREFERENCE_FOR_YOU -import com.aurora.store.util.Preferences.PREFERENCE_INSTALLER_ID -import com.aurora.store.util.Preferences.PREFERENCE_THEME_STYLE -import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_CHECK_INTERVAL -import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_EXTENDED -import com.aurora.store.util.Preferences.PREFERENCE_VENDING_VERSION -import com.aurora.store.util.save -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -class OnboardingFragment : BaseFlavouredOnboardingFragment() { - @Inject - lateinit var blacklistProvider: BlacklistProvider - - override fun loadDefaultPreferences() { - /*Filters*/ - save(PREFERENCE_FILTER_AURORA_ONLY, false) - save(PREFERENCE_FILTER_FDROID, true) - - /*Network*/ - save(PREFERENCE_DISPENSER_URLS, emptySet()) - save(PREFERENCE_VENDING_VERSION, 0) - - /*Customization*/ - save(PREFERENCE_THEME_STYLE, 0) - save(PREFERENCE_DEFAULT_SELECTED_TAB, 0) - save(PREFERENCE_FOR_YOU, true) - - /*Installer*/ - save(PREFERENCE_AUTO_DELETE, true) - save(PREFERENCE_INSTALLER_ID, 0) - - /*Updates*/ - save(PREFERENCE_UPDATES_EXTENDED, false) - save(PREFERENCE_UPDATES_CHECK_INTERVAL, 3) - } - - override fun onboardingPages(): List { - var pages = mutableListOf( - WelcomeFragment(), - PermissionsFragment.newInstance() - ) - - /** - * MicroG Fragment Preconditions: - * 1. It should be a Huawei device - * 2. Supported App Gallery should be available, i.e. v15.1.x or above - * 3. MicroG bundle should not be already installed - */ - if ( - isHuawei && - PackageUtil.hasSupportedAppGallery(requireContext()) && - !PackageUtil.isMicroGBundleInstalled(requireContext()) - ) { - pages.add(MicroGFragment()) - } - - return pages - } - - override fun setupAutoUpdates() { - super.setupAutoUpdates() - - // Remove super & implement variant logic here - } - - override fun finishOnboarding() { - blacklistProvider.blacklist("com.android.vending") - blacklistProvider.blacklist("com.google.android.gms") - - super.finishOnboarding() - } -} diff --git a/app/src/main/java/com/aurora/store/compose/composable/LinkListItem.kt b/app/src/main/java/com/aurora/store/compose/composable/LinkListItem.kt index a0103ca93..48b16134c 100644 --- a/app/src/main/java/com/aurora/store/compose/composable/LinkListItem.kt +++ b/app/src/main/java/com/aurora/store/compose/composable/LinkListItem.kt @@ -22,6 +22,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.dimensionResource @@ -41,7 +43,12 @@ import com.aurora.store.compose.preview.PreviewTemplate * @param onClick Callback when the composable is clicked */ @Composable -fun LinkListItem(modifier: Modifier = Modifier, link: Link, onClick: () -> Unit = {}) { +fun LinkListItem( + modifier: Modifier = Modifier, + link: Link, + onClick: () -> Unit = {}, + iconTint: Color? = null +) { Row( modifier = modifier .fillMaxWidth() @@ -58,7 +65,8 @@ fun LinkListItem(modifier: Modifier = Modifier, link: Link, onClick: () -> Unit contentScale = ContentScale.Crop, modifier = Modifier .requiredSize(dimensionResource(R.dimen.icon_size_default)) - .clip(CircleShape) + .clip(CircleShape), + colorFilter = if (iconTint != null) ColorFilter.tint(color = iconTint) else null ) VerticalDivider( modifier = Modifier diff --git a/app/src/main/java/com/aurora/store/compose/composable/PermissionList.kt b/app/src/main/java/com/aurora/store/compose/composable/PermissionList.kt index 0be93f483..58ed92d28 100644 --- a/app/src/main/java/com/aurora/store/compose/composable/PermissionList.kt +++ b/app/src/main/java/com/aurora/store/compose/composable/PermissionList.kt @@ -16,6 +16,7 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyItemScope import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -51,7 +52,8 @@ private const val TAG = "PermissionsScreen" @Composable fun PermissionList( modifier: Modifier = Modifier, - permissions: Set, + permissions: List, + header: (@Composable (LazyItemScope.(Int) -> Unit))? = null, onPermissionCallback: (type: PermissionType) -> Unit = {} ) { val context = LocalContext.current @@ -132,6 +134,8 @@ fun PermissionList( modifier = modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.margin_xxsmall)) ) { + if (header != null) stickyHeader(content = header) + permissions.sortedBy { it.optional } .groupBy { permission -> permission.optional } .forEach { (key, value) -> @@ -166,7 +170,7 @@ private fun PermissionListPreview() { optional = Random.nextBoolean(), isGranted = Random.nextBoolean() ) - }.toSet() + } PreviewTemplate { PermissionList(permissions = permissions) } diff --git a/app/src/main/java/com/aurora/store/compose/navigation/NavDisplay.kt b/app/src/main/java/com/aurora/store/compose/navigation/NavDisplay.kt index a373876fc..a2a23511a 100644 --- a/app/src/main/java/com/aurora/store/compose/navigation/NavDisplay.kt +++ b/app/src/main/java/com/aurora/store/compose/navigation/NavDisplay.kt @@ -26,6 +26,7 @@ import com.aurora.store.compose.ui.details.AppDetailsScreen import com.aurora.store.compose.ui.dev.DevProfileScreen import com.aurora.store.compose.ui.downloads.DownloadsScreen import com.aurora.store.compose.ui.favourite.FavouriteScreen +import com.aurora.store.compose.ui.onboarding.OnboardingScreen import com.aurora.store.compose.ui.search.SearchScreen /** @@ -119,6 +120,10 @@ fun NavDisplay(startDestination: NavKey) { } ) } + + entry { + OnboardingScreen() + } } ) } diff --git a/app/src/main/java/com/aurora/store/compose/navigation/Screen.kt b/app/src/main/java/com/aurora/store/compose/navigation/Screen.kt index d204598c7..72b5099c3 100644 --- a/app/src/main/java/com/aurora/store/compose/navigation/Screen.kt +++ b/app/src/main/java/com/aurora/store/compose/navigation/Screen.kt @@ -50,4 +50,7 @@ sealed class Screen : NavKey, Parcelable { @Serializable data object Favourite : Screen() + + @Serializable + data object Onboarding : Screen() } diff --git a/app/src/main/java/com/aurora/store/compose/ui/commons/PermissionRationaleScreen.kt b/app/src/main/java/com/aurora/store/compose/ui/commons/PermissionRationaleScreen.kt index 32b725bd6..5dcd3f69a 100644 --- a/app/src/main/java/com/aurora/store/compose/ui/commons/PermissionRationaleScreen.kt +++ b/app/src/main/java/com/aurora/store/compose/ui/commons/PermissionRationaleScreen.kt @@ -43,8 +43,7 @@ fun PermissionRationaleScreen( onNavigateUp = onNavigateUp, permissions = permissions .filter { it.type in requiredPermissions } - .map { permission -> permission.copy(optional = false) } - .toSet(), + .map { permission -> permission.copy(optional = false) }, onPermissionCallback = { type -> viewModel.refreshPermissionsList() onPermissionCallback(type) @@ -54,7 +53,7 @@ fun PermissionRationaleScreen( @Composable private fun ScreenContent( - permissions: Set = emptySet(), + permissions: List = emptyList(), onNavigateUp: () -> Unit = {}, onPermissionCallback: (type: PermissionType) -> Unit = {}, windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo() @@ -87,7 +86,7 @@ private fun PermissionsScreenPreview() { optional = Random.nextBoolean(), isGranted = Random.nextBoolean() ) - }.toSet() + } PreviewTemplate { ScreenContent(permissions = permissions) } diff --git a/app/src/main/java/com/aurora/store/compose/ui/onboarding/OnboardingScreen.kt b/app/src/main/java/com/aurora/store/compose/ui/onboarding/OnboardingScreen.kt new file mode 100644 index 000000000..21b9ea68f --- /dev/null +++ b/app/src/main/java/com/aurora/store/compose/ui/onboarding/OnboardingScreen.kt @@ -0,0 +1,139 @@ +/* + * SPDX-FileCopyrightText: 2025 The Calyx Institute + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package com.aurora.store.compose.ui.onboarding + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.material3.Button +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import com.aurora.store.R +import com.aurora.store.compose.composable.PageIndicator +import com.aurora.store.compose.preview.PreviewTemplate +import com.aurora.store.compose.ui.onboarding.navigation.ExtraScreen +import com.aurora.store.viewmodel.onboarding.OnboardingViewModel +import kotlinx.coroutines.launch + +@Composable +fun OnboardingScreen(viewModel: OnboardingViewModel = hiltViewModel()) { + val pages = listOfNotNull( + ExtraScreen.Welcome, + ExtraScreen.Permissions + ) + + ScreenContent( + pages = pages, + onFinishOnboarding = { viewModel.finishOnboarding() } + ) +} + +@Composable +private fun ScreenContent( + pages: List = emptyList(), + onFinishOnboarding: () -> Unit = {} +) { + val pagerState = rememberPagerState { pages.size } + val coroutineScope = rememberCoroutineScope() + + Scaffold( + topBar = { + TopAppBar( + title = { + PageIndicator(totalPages = pages.size, currentPage = pagerState.currentPage) + } + ) + } + ) { paddingValues -> + Column( + modifier = Modifier + .padding(paddingValues) + .fillMaxSize(), + verticalArrangement = Arrangement.SpaceBetween + ) { + HorizontalPager( + modifier = Modifier.weight(1F), + state = pagerState, + verticalAlignment = Alignment.Top + ) { page -> + when (pages[page]) { + ExtraScreen.Welcome -> WelcomeScreen() + ExtraScreen.Permissions -> PermissionsScreen() + } + } + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(dimensionResource(R.dimen.padding_medium)), + horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.padding_medium)) + ) { + TextButton( + modifier = Modifier.weight(1F), + enabled = pagerState.currentPage != 0, + onClick = { + coroutineScope.launch { + pagerState.animateScrollToPage(pagerState.currentPage - 1) + } + } + ) { + Text( + text = stringResource(R.string.action_back), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + + Button( + modifier = Modifier.weight(1F), + onClick = { + when { + pagerState.currentPage < (pagerState.pageCount - 1) -> { + coroutineScope.launch { + pagerState.animateScrollToPage(pagerState.currentPage + 1) + } + } + + else -> onFinishOnboarding() + } + } + ) { + Text( + text = stringResource(R.string.action_next), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } + } +} + +@Preview +@Composable +private fun OnboardingScreenPreview() { + PreviewTemplate { + ScreenContent( + pages = listOf(ExtraScreen.Welcome, ExtraScreen.Permissions) + ) + } +} diff --git a/app/src/main/java/com/aurora/store/compose/ui/onboarding/PermissionsScreen.kt b/app/src/main/java/com/aurora/store/compose/ui/onboarding/PermissionsScreen.kt new file mode 100644 index 000000000..e0479a90f --- /dev/null +++ b/app/src/main/java/com/aurora/store/compose/ui/onboarding/PermissionsScreen.kt @@ -0,0 +1,91 @@ +/* + * SPDX-FileCopyrightText: 2025 The Calyx Institute + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package com.aurora.store.compose.ui.onboarding + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.datasource.LoremIpsum +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.aurora.store.R +import com.aurora.store.compose.composable.PermissionList +import com.aurora.store.compose.preview.PreviewTemplate +import com.aurora.store.data.model.Permission +import com.aurora.store.data.model.PermissionType +import com.aurora.store.viewmodel.commons.PermissionRationaleViewModel +import kotlin.random.Random + +@Composable +fun PermissionsScreen(viewModel: PermissionRationaleViewModel = hiltViewModel()) { + val permissions by viewModel.permissions.collectAsStateWithLifecycle() + + ScreenContent( + permissions = permissions, + onPermissionCallback = { viewModel.refreshPermissionsList() } + ) +} + +@Composable +private fun ScreenContent( + permissions: List = emptyList(), + onPermissionCallback: (type: PermissionType) -> Unit = {} +) { + PermissionList( + modifier = Modifier.padding(horizontal = dimensionResource(R.dimen.padding_medium)), + permissions = permissions, + onPermissionCallback = onPermissionCallback, + header = { + Surface(modifier = Modifier.fillMaxWidth()) { + Column( + modifier = Modifier.padding(dimensionResource(R.dimen.padding_normal)) + ) { + Text( + text = stringResource(R.string.onboarding_title_permissions), + style = MaterialTheme.typography.headlineLargeEmphasized, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = stringResource(R.string.onboarding_permission_select), + style = MaterialTheme.typography.titleLarge, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + } + } + } + ) +} + +@Preview(showBackground = true) +@Composable +private fun PermissionsScreenPreview() { + val permissions = PermissionType.entries.map { type -> + Permission( + type = type, + title = LoremIpsum(3).values.first(), + subtitle = LoremIpsum(7).values.first(), + optional = Random.nextBoolean(), + isGranted = Random.nextBoolean() + ) + } + PreviewTemplate { + ScreenContent( + permissions = permissions + ) + } +} diff --git a/app/src/main/java/com/aurora/store/compose/ui/onboarding/WelcomeScreen.kt b/app/src/main/java/com/aurora/store/compose/ui/onboarding/WelcomeScreen.kt new file mode 100644 index 000000000..e9dca0e09 --- /dev/null +++ b/app/src/main/java/com/aurora/store/compose/ui/onboarding/WelcomeScreen.kt @@ -0,0 +1,144 @@ +/* + * SPDX-FileCopyrightText: 2025 The Calyx Institute + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package com.aurora.store.compose.ui.onboarding + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import com.aurora.extensions.browse +import com.aurora.store.R +import com.aurora.store.compose.composable.LinkListItem +import com.aurora.store.compose.preview.PreviewTemplate +import com.aurora.store.compose.ui.about.AboutDialog +import com.aurora.store.data.model.Link + +@Composable +fun WelcomeScreen() { + var shouldShowAboutDialog by rememberSaveable { mutableStateOf(false) } + + if (shouldShowAboutDialog) { + AboutDialog(onDismiss = { shouldShowAboutDialog = false }) + } + + ScreenContent(onAboutAurora = { shouldShowAboutDialog = true }) +} + +@Composable +private fun ScreenContent(onAboutAurora: () -> Unit = {}) { + val context = LocalContext.current + + val links = listOf( + Link( + id = 0, + title = stringResource(R.string.title_about), + subtitle = stringResource(R.string.about_aurora_store_subtitle), + icon = R.drawable.ic_menu_about, + url = "https://auroraoss.com/" + ), + Link( + id = 1, + title = stringResource(R.string.faqs_title), + subtitle = stringResource(R.string.faqs_subtitle), + icon = R.drawable.ic_faq, + url = "https://gitlab.com/AuroraOSS/AuroraStore/-/wikis/Frequently%20Asked%20Questions" + ), + Link( + id = 2, + title = stringResource(R.string.source_code_title), + subtitle = stringResource(R.string.source_code_subtitle), + icon = R.drawable.ic_code, + url = "https://gitlab.com/AuroraOSS/AuroraStore/" + ), + Link( + id = 3, + title = stringResource(R.string.menu_license), + subtitle = stringResource(R.string.license_subtitle), + icon = R.drawable.ic_license, + url = "https://gitlab.com/AuroraOSS/AuroraStore/-/blob/master/LICENSE" + ), + Link( + id = 4, + title = stringResource(R.string.privacy_policy_title), + subtitle = stringResource(R.string.privacy_policy_subtitle), + icon = R.drawable.ic_privacy, + url = "https://gitlab.com/AuroraOSS/AuroraStore/-/blob/master/POLICY.md" + ), + Link( + id = 5, + title = stringResource(R.string.menu_disclaimer), + subtitle = stringResource(R.string.disclaimer_subtitle), + icon = R.drawable.ic_disclaimer, + url = "https://gitlab.com/AuroraOSS/AuroraStore/-/blob/master/DISCLAIMER.md" + ) + ) + + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues(horizontal = dimensionResource(R.dimen.padding_medium)), + verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.margin_xxsmall)) + ) { + stickyHeader { + Surface(modifier = Modifier.fillMaxWidth()) { + Column( + modifier = Modifier.padding(dimensionResource(R.dimen.padding_normal)) + ) { + Text( + text = stringResource(R.string.onboarding_title_welcome), + style = MaterialTheme.typography.headlineLargeEmphasized, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = stringResource(R.string.onboarding_welcome_select), + style = MaterialTheme.typography.titleLarge, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } + + items(items = links, key = { item -> item.id }) { link -> + LinkListItem( + link = link, + onClick = { + when (link.id) { + 0 -> onAboutAurora() + else -> context.browse(link.url) + } + }, + iconTint = MaterialTheme.colorScheme.primary + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun WelcomeScreenPreview() { + PreviewTemplate { + ScreenContent() + } +} diff --git a/app/src/main/java/com/aurora/store/compose/ui/onboarding/navigation/ExtraScreen.kt b/app/src/main/java/com/aurora/store/compose/ui/onboarding/navigation/ExtraScreen.kt new file mode 100644 index 000000000..3b4406716 --- /dev/null +++ b/app/src/main/java/com/aurora/store/compose/ui/onboarding/navigation/ExtraScreen.kt @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2025 The Calyx Institute + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package com.aurora.store.compose.ui.onboarding.navigation + +import android.os.Parcelable +import androidx.navigation3.runtime.NavKey +import kotlinx.parcelize.Parcelize +import kotlinx.serialization.Serializable + +/** + * Extra destinations for onboarding + * + * All of these destinations are child destinations of onboarding screen are shown inside it. + */ +@Parcelize +@Serializable +sealed class ExtraScreen : NavKey, Parcelable { + + @Serializable + data object Welcome : ExtraScreen() + + @Serializable + data object Permissions : ExtraScreen() +} diff --git a/app/src/main/java/com/aurora/store/data/model/Dash.kt b/app/src/main/java/com/aurora/store/data/model/Dash.kt deleted file mode 100644 index 6893f339e..000000000 --- a/app/src/main/java/com/aurora/store/data/model/Dash.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.data.model - -import androidx.annotation.DrawableRes - -data class Dash( - var id: Int, - var title: String, - var subtitle: String, - @DrawableRes var icon: Int, - var url: String -) { - override fun equals(other: Any?): Boolean { - return when (other) { - is Dash -> other.id == id - else -> false - } - } - - override fun hashCode(): Int { - return id.hashCode() - } -} diff --git a/app/src/main/java/com/aurora/store/data/model/Permission.kt b/app/src/main/java/com/aurora/store/data/model/Permission.kt index ed9e0ce7c..1266fd6a1 100644 --- a/app/src/main/java/com/aurora/store/data/model/Permission.kt +++ b/app/src/main/java/com/aurora/store/data/model/Permission.kt @@ -25,15 +25,4 @@ data class Permission( val subtitle: String, val optional: Boolean = false, val isGranted: Boolean = false -) { - override fun equals(other: Any?): Boolean { - return when (other) { - is Permission -> other.type == type - else -> false - } - } - - override fun hashCode(): Int { - return type.hashCode() - } -} +) diff --git a/app/src/main/java/com/aurora/store/data/providers/PermissionProvider.kt b/app/src/main/java/com/aurora/store/data/providers/PermissionProvider.kt index bd31a1045..b639c4c29 100644 --- a/app/src/main/java/com/aurora/store/data/providers/PermissionProvider.kt +++ b/app/src/main/java/com/aurora/store/data/providers/PermissionProvider.kt @@ -93,20 +93,14 @@ class PermissionProvider(private val fragment: Fragment) : context.getString(R.string.onboarding_permission_installer_legacy_desc) }, optional = false, - isGranted = PermissionProvider.isGranted( - context, - PermissionType.INSTALL_UNKNOWN_APPS - ) + isGranted = isGranted(context, PermissionType.INSTALL_UNKNOWN_APPS) ), Permission( type = PermissionType.DOZE_WHITELIST, title = context.getString(R.string.onboarding_permission_doze), subtitle = context.getString(R.string.onboarding_permission_doze_desc), optional = true, - isGranted = PermissionProvider.isGranted( - context, - PermissionType.DOZE_WHITELIST - ) + isGranted = isGranted(context, PermissionType.DOZE_WHITELIST) ) ) @@ -117,10 +111,7 @@ class PermissionProvider(private val fragment: Fragment) : title = context.getString(R.string.onboarding_permission_esm), subtitle = context.getString(R.string.onboarding_permission_esa_desc), optional = false, - isGranted = PermissionProvider.isGranted( - context, - PermissionType.STORAGE_MANAGER - ) + isGranted = isGranted(context, PermissionType.STORAGE_MANAGER) ) ) } else { @@ -130,10 +121,7 @@ class PermissionProvider(private val fragment: Fragment) : title = context.getString(R.string.onboarding_permission_esa), subtitle = context.getString(R.string.onboarding_permission_esa_desc), optional = false, - isGranted = PermissionProvider.isGranted( - context, - PermissionType.EXTERNAL_STORAGE - ) + isGranted = isGranted(context, PermissionType.EXTERNAL_STORAGE) ) ) } @@ -145,10 +133,7 @@ class PermissionProvider(private val fragment: Fragment) : title = context.getString(R.string.onboarding_permission_notifications), subtitle = context.getString(R.string.onboarding_permission_notifications_desc), optional = true, - isGranted = PermissionProvider.isGranted( - context, - PermissionType.POST_NOTIFICATIONS - ) + isGranted = isGranted(context, PermissionType.POST_NOTIFICATIONS) ) ) } @@ -160,10 +145,7 @@ class PermissionProvider(private val fragment: Fragment) : title = context.getString(R.string.app_links_title), subtitle = context.getString(R.string.app_links_desc), optional = true, - isGranted = PermissionProvider.isGranted( - context, - PermissionType.APP_LINKS - ) + isGranted = isGranted(context, PermissionType.APP_LINKS) ), ) } diff --git a/app/src/main/java/com/aurora/store/view/epoxy/views/preference/DashView.kt b/app/src/main/java/com/aurora/store/view/epoxy/views/preference/DashView.kt deleted file mode 100644 index b49caa2fa..000000000 --- a/app/src/main/java/com/aurora/store/view/epoxy/views/preference/DashView.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.view.epoxy.views.preference - -import android.content.Context -import android.util.AttributeSet -import androidx.core.content.ContextCompat -import com.airbnb.epoxy.CallbackProp -import com.airbnb.epoxy.ModelProp -import com.airbnb.epoxy.ModelView -import com.aurora.store.data.model.Dash -import com.aurora.store.databinding.ViewDashBinding -import com.aurora.store.view.epoxy.views.BaseModel -import com.aurora.store.view.epoxy.views.BaseView - -@ModelView( - autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT, - baseModelClass = BaseModel::class -) -class DashView @JvmOverloads constructor( - context: Context?, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0 -) : BaseView(context, attrs, defStyleAttr) { - - @ModelProp - fun dash(dash: Dash) { - binding.line1.text = dash.title - binding.line2.text = dash.subtitle - binding.img.setImageDrawable(ContextCompat.getDrawable(context, dash.icon)) - } - - @CallbackProp - fun click(onClickListener: OnClickListener?) { - binding.root.setOnClickListener(onClickListener) - } -} diff --git a/app/src/main/java/com/aurora/store/view/epoxy/views/preference/PermissionView.kt b/app/src/main/java/com/aurora/store/view/epoxy/views/preference/PermissionView.kt deleted file mode 100644 index 4d5414aa1..000000000 --- a/app/src/main/java/com/aurora/store/view/epoxy/views/preference/PermissionView.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.view.epoxy.views.preference - -import android.content.Context -import android.util.AttributeSet -import androidx.core.content.ContextCompat -import com.airbnb.epoxy.CallbackProp -import com.airbnb.epoxy.ModelProp -import com.airbnb.epoxy.ModelView -import com.aurora.store.R -import com.aurora.store.data.model.Permission -import com.aurora.store.databinding.ViewPermissionBinding -import com.aurora.store.view.epoxy.views.BaseModel -import com.aurora.store.view.epoxy.views.BaseView - -@ModelView( - autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT, - baseModelClass = BaseModel::class -) -class PermissionView @JvmOverloads constructor( - context: Context?, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0 -) : BaseView(context, attrs, defStyleAttr) { - - @ModelProp - fun permission(installer: Permission) { - binding.line1.text = installer.title - binding.line2.text = installer.subtitle - } - - @ModelProp - fun isGranted(granted: Boolean) { - if (granted) { - binding.btnAction.isEnabled = false - binding.btnAction.text = ContextCompat.getString(context, R.string.action_granted) - } else { - binding.btnAction.isEnabled = true - binding.btnAction.text = ContextCompat.getString(context, R.string.action_grant) - } - } - - @CallbackProp - fun click(onClickListener: OnClickListener?) { - binding.btnAction.setOnClickListener(onClickListener) - } -} diff --git a/app/src/main/java/com/aurora/store/view/ui/details/DetailsMicroGFragment.kt b/app/src/main/java/com/aurora/store/view/ui/details/DetailsMicroGFragment.kt deleted file mode 100644 index 2c9df2fee..000000000 --- a/app/src/main/java/com/aurora/store/view/ui/details/DetailsMicroGFragment.kt +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.view.ui.details - -import android.os.Bundle -import android.view.View -import androidx.fragment.app.viewModels -import androidx.lifecycle.lifecycleScope -import androidx.navigation.fragment.findNavController -import com.aurora.extensions.browse -import com.aurora.store.AuroraApp -import com.aurora.store.R -import com.aurora.store.data.event.Event -import com.aurora.store.data.event.InstallerEvent -import com.aurora.store.data.model.Dash -import com.aurora.store.data.model.DownloadStatus -import com.aurora.store.databinding.FragmentDetailsMicrogBinding -import com.aurora.store.util.PackageUtil -import com.aurora.store.view.epoxy.views.EpoxyTextViewModel_ -import com.aurora.store.view.epoxy.views.preference.DashViewModel_ -import com.aurora.store.view.ui.commons.BaseFragment -import com.aurora.store.viewmodel.onboarding.MicroGViewModel -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.flow.filterNotNull -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch - -@AndroidEntryPoint -class DetailsMicroGFragment : BaseFragment() { - - val microGViewModel: MicroGViewModel by viewModels() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - // Toolbar - binding.toolbar.apply { - title = "" - setNavigationOnClickListener { findNavController().navigateUp() } - } - - with(binding) { - // RecyclerView - epoxyRecycler.withModels { - setFilterDuplicates(true) - - add( - EpoxyTextViewModel_() - .id("microg_title") - .title(getString(R.string.onboarding_title_gsf)) - .size(32) - .style(R.style.AuroraTextStyle) - ) - - add( - EpoxyTextViewModel_() - .id("microg_desc") - .title(getString(R.string.onboarding_title_gsf_desc)) - .size(18) - .style(R.style.AuroraTextStyle) - ) - - add( - EpoxyTextViewModel_() - .id("microg_desc") - .title(getString(R.string.onboarding_gms_missing)) - .size(14) - .style(R.style.AuroraTextStyle) - ) - - add( - EpoxyTextViewModel_() - .id("microg_gms") - .title(getString(R.string.onboarding_gms_microg)) - .size(14) - .style(R.style.AuroraTextStyle) - ) - - - dashItems().forEach { - add( - DashViewModel_() - .id(it.id) - .dash(it) - .click { _ -> - requireContext().browse(it.url) - } - ) - } - } - - checkboxAgreement.setOnCheckedChangeListener { _, value -> - microGViewModel.markAgreement(value) - btnMicroG.isEnabled = value - } - - btnMicroG.setOnClickListener { microGViewModel.downloadMicroG() } - btnSkip.setOnClickListener { findNavController().navigateUp() } - } - - microGViewModel.download.filterNotNull().onEach { - when (it.status) { - DownloadStatus.DOWNLOADING -> updateProgressBar(visible = true, it.progress) - DownloadStatus.FAILED -> updateProgressBar(visible = false, 0) - DownloadStatus.QUEUED -> updateProgressBar(visible = true, -1) - DownloadStatus.COMPLETED -> updateProgressBar(visible = true, -1) - else -> {} - } - }.launchIn(viewLifecycleOwner.lifecycleScope) - - viewLifecycleOwner.lifecycleScope.launch { - AuroraApp.events.installerEvent.collect { onEvent(it) } - } - } - - private fun onEvent(event: Event) { - when (event) { - is InstallerEvent.Installed -> { - if (PackageUtil.isMicroGBundleInstalled(requireContext())) { - markInstallationComplete() - } - } - - is InstallerEvent.Failed -> markInstallationFailed() - else -> {} - } - } - - private fun updateProgressBar(visible: Boolean, downloadProgress: Int) { - with(binding.progressBar) { - if (visible) show() else hide() - isIndeterminate = downloadProgress == -1 - progress = downloadProgress - } - } - - private fun markInstallationComplete() { - with(binding) { - with(btnMicroG) { - isEnabled = true - text = getString(R.string.action_finish) - setOnClickListener { findNavController().navigateUp() } - } - checkboxAgreement.isEnabled = false - progressBar.hide() - } - } - - private fun markInstallationFailed() { - with(binding) { - with(btnMicroG) { - isEnabled = false - text = getString(R.string.action_install) - } - checkboxAgreement.isChecked = false - progressBar.hide() - } - } - - private fun dashItems(): List { - return listOf( - Dash( - id = 2, - title = requireContext().getString(R.string.details_dev_website), - subtitle = requireContext().getString(R.string.microg_website), - icon = R.drawable.ic_network, - url = "https://microG.org" - ), - Dash( - id = 4, - title = requireContext().getString(R.string.privacy_policy_title), - subtitle = requireContext().getString(R.string.microg_privacy_policy), - icon = R.drawable.ic_privacy, - url = "https://microg.org/privacy.html" - ), - Dash( - id = 5, - title = requireContext().getString(R.string.menu_disclaimer), - subtitle = requireContext().getString(R.string.microg_license_agreement), - icon = R.drawable.ic_disclaimer, - url = "https://raw.githubusercontent.com/microg/GmsCore/refs/heads/master/LICENSE" - ) - ) - } -} diff --git a/app/src/main/java/com/aurora/store/view/ui/onboarding/BaseFlavouredOnboardingFragment.kt b/app/src/main/java/com/aurora/store/view/ui/onboarding/BaseFlavouredOnboardingFragment.kt deleted file mode 100644 index 565a2623f..000000000 --- a/app/src/main/java/com/aurora/store/view/ui/onboarding/BaseFlavouredOnboardingFragment.kt +++ /dev/null @@ -1,254 +0,0 @@ -package com.aurora.store.view.ui.onboarding - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.annotation.StringRes -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager -import androidx.fragment.app.activityViewModels -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.lifecycleScope -import androidx.viewpager2.adapter.FragmentStateAdapter -import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback -import com.aurora.extensions.areNotificationsEnabled -import com.aurora.extensions.isIgnoringBatteryOptimizations -import com.aurora.store.AuroraApp -import com.aurora.store.R -import com.aurora.store.data.event.Event -import com.aurora.store.data.event.InstallerEvent -import com.aurora.store.data.model.UpdateMode -import com.aurora.store.data.work.CacheWorker -import com.aurora.store.databinding.FragmentOnboardingBinding -import com.aurora.store.util.PackageUtil -import com.aurora.store.util.Preferences -import com.aurora.store.util.Preferences.PREFERENCE_DEFAULT -import com.aurora.store.util.Preferences.PREFERENCE_INTRO -import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_AUTO -import com.aurora.store.util.save -import com.aurora.store.view.ui.commons.BaseFragment -import com.aurora.store.viewmodel.onboarding.MicroGViewModel -import com.aurora.store.viewmodel.onboarding.OnboardingPage -import com.aurora.store.viewmodel.onboarding.OnboardingViewModel -import com.google.android.material.tabs.TabLayoutMediator -import com.jakewharton.processphoenix.ProcessPhoenix -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.launch - -abstract class BaseFlavouredOnboardingFragment : BaseFragment() { - // Shared ViewModels - val microGViewModel: MicroGViewModel by activityViewModels() - val onboardingViewModel: OnboardingViewModel by activityViewModels() - - var currentPage = 0 - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = FragmentOnboardingBinding.inflate(inflater, container, false) - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - // Adjust layout margins for edgeToEdge display - ViewCompat.setOnApplyWindowInsetsListener(binding.layoutBottom) { layout, windowInsets -> - val insets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars()) - layout.setPadding(0, 0, 0, insets.bottom) - WindowInsetsCompat.CONSUMED - } - - val isDefaultPrefLoaded = Preferences.getBoolean(requireContext(), PREFERENCE_DEFAULT) - - if (!isDefaultPrefLoaded) { - save(PREFERENCE_DEFAULT, true) - loadDefaultPreferences() - - // No onboarding for TV, proceed with defaults - if (PackageUtil.isTv(view.context)) finishOnboarding() - } - - val pages = onboardingPages() - - with(binding) { - // ViewPager2 - with(viewpager2) { - adapter = PagerAdapter( - childFragmentManager, - viewLifecycleOwner.lifecycle, - pages - ) - isUserInputEnabled = false - setCurrentItem(0, true) - registerOnPageChangeCallback(object : OnPageChangeCallback() { - override fun onPageSelected(position: Int) { - onboardingViewModel.setCurrentPage( - when (position) { - 0 -> OnboardingPage.WELCOME - 1 -> OnboardingPage.PERMISSIONS - 2 -> OnboardingPage.GSF - else -> OnboardingPage.WELCOME - } - ) - currentPage = position - } - }) - } - - TabLayoutMediator(tabLayout, viewpager2, true) { tab, position -> - tab.text = (position + 1).toString() - }.attach() - } - - updateBackwardButton(false) - updateForwardButton(true) - - viewLifecycleOwner.lifecycleScope.launch { - // Combine both relevant flows - combine( - microGViewModel.checked, - onboardingViewModel.currentPage - ) { isChecked, page -> isChecked to page }.collect { (isChecked, page) -> - when (page) { - OnboardingPage.WELCOME -> { - updateBackwardButton(enabled = false) - updateForwardButton(enabled = true) - } - - OnboardingPage.PERMISSIONS -> { - updateBackwardButton(enabled = true) - val isLastPage = pages.size == 2 - - updateForwardButton( - enabled = true, - resId = if (isLastPage) R.string.action_finish else R.string.action_next, - if (isLastPage) { - { finishOnboarding() } - } else { - null - } - ) - } - - OnboardingPage.GSF -> { - updateBackwardButton(enabled = true) - - if (isChecked) { - val isInstalled = PackageUtil.isMicroGBundleInstalled(requireContext()) - updateForwardButton( - enabled = isInstalled, - resId = R.string.action_finish, - action = if (isInstalled) { - { finishOnboarding() } - } else { - null - } - ) - } else { - updateForwardButton( - enabled = false, - resId = R.string.action_finish, - action = { finishOnboarding() } - ) - } - } - } - } - } - - viewLifecycleOwner.lifecycleScope.launch { - AuroraApp.events.installerEvent.collect { onEvent(it) } - } - } - - private fun updateBackwardButton( - enabled: Boolean = true - ) { - with(binding.btnBackward) { - isEnabled = enabled - text = getString(R.string.action_back) - setOnClickListener({ - binding.viewpager2.setCurrentItem(binding.viewpager2.currentItem - 1, true) - }) - } - } - - private fun updateForwardButton( - enabled: Boolean = true, - @StringRes resId: Int = R.string.action_next, - action: ((View) -> Unit)? = null - ) { - with(binding.btnForward) { - isEnabled = enabled - text = getString(resId) - setOnClickListener(action ?: { - binding.viewpager2.setCurrentItem(binding.viewpager2.currentItem + 1, true) - }) - } - } - - private fun onEvent(event: Event) { - when (event) { - is InstallerEvent.Installed -> { - if (PackageUtil.isMicroGBundleInstalled(requireContext())) { - with(binding.btnForward) { - isEnabled = true - text = getString(R.string.action_finish) - setOnClickListener { - finishOnboarding() - } - } - } - } - - else -> { - - } - } - } - - abstract fun loadDefaultPreferences() - - abstract fun onboardingPages(): List - - open fun finishOnboarding() { - setupAutoUpdates() - CacheWorker.scheduleAutomatedCacheCleanup(requireContext()) - Preferences.putBooleanNow(requireContext(), PREFERENCE_INTRO, true) - - // Restart the app to ensure all permissions are granted - ProcessPhoenix.triggerRebirth(context) - } - - open fun setupAutoUpdates() { - val updateMode = when { - requireContext().isIgnoringBatteryOptimizations() -> UpdateMode.CHECK_AND_INSTALL - requireContext().areNotificationsEnabled() -> UpdateMode.CHECK_AND_NOTIFY - else -> UpdateMode.DISABLED - } - - save(PREFERENCE_UPDATES_AUTO, updateMode.ordinal) - - onboardingViewModel.updateHelper.scheduleAutomatedCheck() - } - - internal class PagerAdapter( - fragmentManager: FragmentManager, - lifecycle: Lifecycle, - var items: List - ) : FragmentStateAdapter(fragmentManager, lifecycle) { - override fun createFragment(position: Int): Fragment { - return items[position] - } - - override fun getItemCount(): Int { - return items.size - } - } -} diff --git a/app/src/main/java/com/aurora/store/view/ui/onboarding/PermissionsFragment.kt b/app/src/main/java/com/aurora/store/view/ui/onboarding/PermissionsFragment.kt deleted file mode 100644 index ef927456a..000000000 --- a/app/src/main/java/com/aurora/store/view/ui/onboarding/PermissionsFragment.kt +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * Copyright (C) 2022, The Calyx Institute - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.view.ui.onboarding - -import android.os.Bundle -import android.view.View -import androidx.core.os.bundleOf -import androidx.core.view.isVisible -import androidx.navigation.fragment.findNavController -import androidx.navigation.fragment.navArgs -import com.aurora.extensions.isOAndAbove -import com.aurora.extensions.isRAndAbove -import com.aurora.extensions.isSAndAbove -import com.aurora.extensions.isTAndAbove -import com.aurora.store.R -import com.aurora.store.data.model.Permission -import com.aurora.store.data.model.PermissionType -import com.aurora.store.data.providers.PermissionProvider.Companion.isGranted -import com.aurora.store.databinding.FragmentOnboardingPermissionsBinding -import com.aurora.store.view.epoxy.views.TextDividerViewModel_ -import com.aurora.store.view.epoxy.views.preference.PermissionViewModel_ -import com.aurora.store.view.ui.commons.BaseFragment -import dagger.hilt.android.AndroidEntryPoint - -@AndroidEntryPoint -class PermissionsFragment : BaseFragment() { - - private val args: PermissionsFragmentArgs by navArgs() - - companion object { - fun newInstance(isOnboarding: Boolean = true): PermissionsFragment { - return PermissionsFragment().apply { - arguments = bundleOf("isOnboarding" to isOnboarding) - } - } - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - // Headers are only visible if we are onboarding - binding.title.isVisible = args.isOnboarding - binding.toolbar.apply { - isVisible = !args.isOnboarding - setNavigationOnClickListener { findNavController().navigateUp() } - } - - updateController() - } - - private fun permissionList(): List { - val permissions = mutableListOf( - Permission( - PermissionType.INSTALL_UNKNOWN_APPS, - getString(R.string.onboarding_permission_installer), - if (isOAndAbove) { - getString(R.string.onboarding_permission_installer_desc) - } else { - getString(R.string.onboarding_permission_installer_legacy_desc) - } - ), - Permission( - PermissionType.DOZE_WHITELIST, - getString(R.string.onboarding_permission_doze), - getString(R.string.onboarding_permission_doze_desc), - true - ) - ) - - if (isRAndAbove) { - permissions.add( - Permission( - PermissionType.STORAGE_MANAGER, - getString(R.string.onboarding_permission_esm), - getString(R.string.onboarding_permission_esa_desc), - false - ) - ) - } else { - permissions.add( - Permission( - PermissionType.EXTERNAL_STORAGE, - getString(R.string.onboarding_permission_esa), - getString(R.string.onboarding_permission_esa_desc), - false - ) - ) - } - - if (isTAndAbove) { - permissions.add( - Permission( - PermissionType.POST_NOTIFICATIONS, - getString(R.string.onboarding_permission_notifications), - getString(R.string.onboarding_permission_notifications_desc), - true - ) - ) - } - - if (isSAndAbove) { - permissions.add( - Permission( - PermissionType.APP_LINKS, - getString(R.string.app_links_title), - getString(R.string.app_links_desc), - optional = true - ), - ) - } - - return permissions - } - - private fun updateController() { - binding.epoxyRecycler.withModels { - setFilterDuplicates(true) - - add( - TextDividerViewModel_() - .id("required_divider") - .title(getString(R.string.item_required)) - ) - - permissionList() - .filterNot { it.optional } - .forEach { add(renderPermissionView(it)) } - - val optionalPermissions = permissionList().filter { it.optional } - if (optionalPermissions.isNotEmpty()) { - add( - TextDividerViewModel_() - .id("optional_divider") - .title(getString(R.string.item_optional)) - ) - - optionalPermissions.forEach { add(renderPermissionView(it)) } - } - } - } - - private fun renderPermissionView(permission: Permission): PermissionViewModel_ { - return PermissionViewModel_() - .id(permission.type.name) - .permission(permission) - .isGranted(isGranted(requireContext(), permission.type)) - .click { _ -> - permissionProvider.request(permission.type) { - if (it) updateController() - } - } - } -} diff --git a/app/src/main/java/com/aurora/store/view/ui/onboarding/WelcomeFragment.kt b/app/src/main/java/com/aurora/store/view/ui/onboarding/WelcomeFragment.kt deleted file mode 100644 index 39fd186a7..000000000 --- a/app/src/main/java/com/aurora/store/view/ui/onboarding/WelcomeFragment.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.view.ui.onboarding - -import android.os.Bundle -import android.view.View -import androidx.navigation.fragment.findNavController -import com.aurora.extensions.browse -import com.aurora.store.R -import com.aurora.store.data.model.Dash -import com.aurora.store.databinding.FragmentOnboardingWelcomeBinding -import com.aurora.store.view.epoxy.views.preference.DashViewModel_ -import com.aurora.store.view.ui.commons.BaseFragment -import dagger.hilt.android.AndroidEntryPoint - -@AndroidEntryPoint -class WelcomeFragment : BaseFragment() { - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - // RecyclerView - binding.epoxyRecycler.withModels { - setFilterDuplicates(true) - loadDashFromAssets().forEach { - add( - DashViewModel_() - .id(it.id) - .dash(it) - .click { _ -> - if (it.id == 0) { - findNavController().navigate(R.id.aboutDialog) - } else { - requireContext().browse(it.url) - } - } - ) - } - } - } - - private fun loadDashFromAssets(): List { - return listOf( - Dash( - id = 0, - title = requireContext().getString(R.string.title_about), - subtitle = requireContext().getString(R.string.about_aurora_store_subtitle), - icon = R.drawable.ic_menu_about, - url = "https://auroraoss.com/" - ), - Dash( - id = 1, - title = requireContext().getString(R.string.faqs_title), - subtitle = requireContext().getString(R.string.faqs_subtitle), - icon = R.drawable.ic_faq, - url = "https://gitlab.com/AuroraOSS/AuroraStore/-/wikis/Frequently%20Asked%20Questions" - ), - Dash( - id = 2, - title = requireContext().getString(R.string.source_code_title), - subtitle = requireContext().getString(R.string.source_code_subtitle), - icon = R.drawable.ic_code, - url = "https://gitlab.com/AuroraOSS/AuroraStore/" - ), - Dash( - id = 3, - title = requireContext().getString(R.string.menu_license), - subtitle = requireContext().getString(R.string.license_subtitle), - icon = R.drawable.ic_license, - url = "https://gitlab.com/AuroraOSS/AuroraStore/-/blob/master/LICENSE" - ), - Dash( - id = 4, - title = requireContext().getString(R.string.privacy_policy_title), - subtitle = requireContext().getString(R.string.privacy_policy_subtitle), - icon = R.drawable.ic_privacy, - url = "https://gitlab.com/AuroraOSS/AuroraStore/-/blob/master/POLICY.md" - ), - Dash( - id = 5, - title = requireContext().getString(R.string.menu_disclaimer), - subtitle = requireContext().getString(R.string.disclaimer_subtitle), - icon = R.drawable.ic_disclaimer, - url = "https://gitlab.com/AuroraOSS/AuroraStore/-/blob/master/DISCLAIMER.md" - ) - ) - } -} diff --git a/app/src/main/java/com/aurora/store/view/ui/preferences/SettingsFragment.kt b/app/src/main/java/com/aurora/store/view/ui/preferences/SettingsFragment.kt index a8c9ffc7c..312f8e81b 100644 --- a/app/src/main/java/com/aurora/store/view/ui/preferences/SettingsFragment.kt +++ b/app/src/main/java/com/aurora/store/view/ui/preferences/SettingsFragment.kt @@ -35,9 +35,7 @@ class SettingsFragment : PreferenceFragmentCompat() { setPreferencesFromResource(R.xml.preferences_settings, rootKey) findPreference("pref_perms")?.setOnPreferenceClickListener { - findNavController().navigate( - SettingsFragmentDirections.actionSettingsFragmentToPermissionsFragment(false) - ) + TODO() true } findPreference("pref_install")?.setOnPreferenceClickListener { diff --git a/app/src/main/java/com/aurora/store/view/ui/splash/BaseFlavouredSplashFragment.kt b/app/src/main/java/com/aurora/store/view/ui/splash/BaseFlavouredSplashFragment.kt index d2f4b1d8a..e0ec92113 100644 --- a/app/src/main/java/com/aurora/store/view/ui/splash/BaseFlavouredSplashFragment.kt +++ b/app/src/main/java/com/aurora/store/view/ui/splash/BaseFlavouredSplashFragment.kt @@ -70,9 +70,8 @@ abstract class BaseFlavouredSplashFragment : BaseFragment super.onViewCreated(view, savedInstanceState) if (!Preferences.getBoolean(requireContext(), PREFERENCE_INTRO)) { - findNavController().navigate( - SplashFragmentDirections.actionSplashFragmentToOnboardingFragment() - ) + requireContext().navigate(Screen.Onboarding) + activity?.finish() return } diff --git a/app/src/main/java/com/aurora/store/viewmodel/commons/PermissionRationaleViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/commons/PermissionRationaleViewModel.kt index 35b551200..9f17f63ea 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/commons/PermissionRationaleViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/commons/PermissionRationaleViewModel.kt @@ -24,10 +24,11 @@ class PermissionRationaleViewModel @Inject constructor( fun refreshPermissionsList() { _permissions.value = _permissions.value.map { permission -> - permission.copy(isGranted = PermissionProvider.isGranted( - context, - permission.type - ) + permission.copy( + isGranted = PermissionProvider.isGranted( + context, + permission.type + ) ) } } diff --git a/app/src/main/java/com/aurora/store/viewmodel/onboarding/OnboardingPage.kt b/app/src/main/java/com/aurora/store/viewmodel/onboarding/OnboardingPage.kt deleted file mode 100644 index 8386b6ccc..000000000 --- a/app/src/main/java/com/aurora/store/viewmodel/onboarding/OnboardingPage.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.aurora.store.viewmodel.onboarding - -enum class OnboardingPage { - WELCOME, - PERMISSIONS, - GSF, -} \ No newline at end of file diff --git a/app/src/main/java/com/aurora/store/viewmodel/onboarding/OnboardingViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/onboarding/OnboardingViewModel.kt index c6266be9c..5aab12238 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/onboarding/OnboardingViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/onboarding/OnboardingViewModel.kt @@ -5,24 +5,85 @@ package com.aurora.store.viewmodel.onboarding +import android.content.Context +import android.util.Log import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import com.aurora.Constants +import com.aurora.extensions.areNotificationsEnabled +import com.aurora.extensions.isIgnoringBatteryOptimizations import com.aurora.store.data.helper.UpdateHelper +import com.aurora.store.data.model.UpdateMode +import com.aurora.store.data.work.CacheWorker +import com.aurora.store.util.Preferences +import com.aurora.store.util.Preferences.PREFERENCE_AUTO_DELETE +import com.aurora.store.util.Preferences.PREFERENCE_DEFAULT_SELECTED_TAB +import com.aurora.store.util.Preferences.PREFERENCE_DISPENSER_URLS +import com.aurora.store.util.Preferences.PREFERENCE_FILTER_AURORA_ONLY +import com.aurora.store.util.Preferences.PREFERENCE_FILTER_FDROID +import com.aurora.store.util.Preferences.PREFERENCE_FOR_YOU +import com.aurora.store.util.Preferences.PREFERENCE_INSTALLER_ID +import com.aurora.store.util.Preferences.PREFERENCE_INTRO +import com.aurora.store.util.Preferences.PREFERENCE_THEME_STYLE +import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_AUTO +import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_CHECK_INTERVAL +import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_EXTENDED +import com.aurora.store.util.Preferences.PREFERENCE_VENDING_VERSION +import com.aurora.store.util.save +import com.jakewharton.processphoenix.ProcessPhoenix import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch +import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject @HiltViewModel -class OnboardingViewModel @Inject constructor(val updateHelper: UpdateHelper) : ViewModel() { +class OnboardingViewModel @Inject constructor( + val updateHelper: UpdateHelper, + @ApplicationContext private val context: Context +) : ViewModel() { - private val _page = MutableStateFlow(OnboardingPage.WELCOME) - val currentPage: StateFlow = _page + private val TAG = OnboardingViewModel::class.java.simpleName - fun setCurrentPage(page: OnboardingPage) { - viewModelScope.launch { - _page.emit(page) + fun finishOnboarding() { + Log.i(TAG, "Finishing onboarding with defaults") + context.saveDefaultPreferences() + setupAutoUpdates() + CacheWorker.scheduleAutomatedCacheCleanup(context) + Preferences.putBooleanNow(context, PREFERENCE_INTRO, true) + + // Restart the app to ensure all permissions are granted + ProcessPhoenix.triggerRebirth(context) + } + + private fun setupAutoUpdates() { + val updateMode = when { + context.isIgnoringBatteryOptimizations() -> UpdateMode.CHECK_AND_INSTALL + context.areNotificationsEnabled() -> UpdateMode.CHECK_AND_NOTIFY + else -> UpdateMode.DISABLED } + + context.save(PREFERENCE_UPDATES_AUTO, updateMode.ordinal) + context.save(PREFERENCE_UPDATES_CHECK_INTERVAL, 3) + updateHelper.scheduleAutomatedCheck() + } + + private fun Context.saveDefaultPreferences() { + /*Filters*/ + save(PREFERENCE_FILTER_AURORA_ONLY, false) + save(PREFERENCE_FILTER_FDROID, true) + + /*Network*/ + save(PREFERENCE_DISPENSER_URLS, setOf(Constants.URL_DISPENSER)) + save(PREFERENCE_VENDING_VERSION, 0) + + /*Customization*/ + save(PREFERENCE_THEME_STYLE, 0) + save(PREFERENCE_DEFAULT_SELECTED_TAB, 0) + save(PREFERENCE_FOR_YOU, true) + + /*Installer*/ + save(PREFERENCE_AUTO_DELETE, true) + save(PREFERENCE_INSTALLER_ID, 0) + + /*Updates*/ + save(PREFERENCE_UPDATES_EXTENDED, false) } } diff --git a/app/src/main/res/drawable/ic_code.xml b/app/src/main/res/drawable/ic_code.xml index 91f50493d..469500703 100644 --- a/app/src/main/res/drawable/ic_code.xml +++ b/app/src/main/res/drawable/ic_code.xml @@ -1,26 +1,11 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout-land/fragment_onboarding_permissions.xml b/app/src/main/res/layout-land/fragment_onboarding_permissions.xml deleted file mode 100644 index 4b588c455..000000000 --- a/app/src/main/res/layout-land/fragment_onboarding_permissions.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout-land/fragment_onboarding_welcome.xml b/app/src/main/res/layout-land/fragment_onboarding_welcome.xml deleted file mode 100644 index e3f9a99d0..000000000 --- a/app/src/main/res/layout-land/fragment_onboarding_welcome.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_details_microg.xml b/app/src/main/res/layout/fragment_details_microg.xml deleted file mode 100644 index 5a913e7fe..000000000 --- a/app/src/main/res/layout/fragment_details_microg.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_onboarding.xml b/app/src/main/res/layout/fragment_onboarding.xml deleted file mode 100644 index 326b56e01..000000000 --- a/app/src/main/res/layout/fragment_onboarding.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_onboarding_microg.xml b/app/src/main/res/layout/fragment_onboarding_microg.xml deleted file mode 100644 index 124aa2144..000000000 --- a/app/src/main/res/layout/fragment_onboarding_microg.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_onboarding_permissions.xml b/app/src/main/res/layout/fragment_onboarding_permissions.xml deleted file mode 100644 index ce8a56cde..000000000 --- a/app/src/main/res/layout/fragment_onboarding_permissions.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_onboarding_welcome.xml b/app/src/main/res/layout/fragment_onboarding_welcome.xml deleted file mode 100644 index 41ec33c87..000000000 --- a/app/src/main/res/layout/fragment_onboarding_welcome.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/view_dash.xml b/app/src/main/res/layout/view_dash.xml deleted file mode 100644 index d27df0ea6..000000000 --- a/app/src/main/res/layout/view_dash.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/view_permission.xml b/app/src/main/res/layout/view_permission.xml deleted file mode 100644 index 50910bf5a..000000000 --- a/app/src/main/res/layout/view_permission.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 8e4f619b4..e3ad54380 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -70,11 +70,7 @@ android:id="@+id/settingsFragment" android:name="com.aurora.store.view.ui.preferences.SettingsFragment" android:label="@string/title_settings" - tools:layout="@layout/fragment_setting"> - - + tools:layout="@layout/fragment_setting" /> - - - - - - - - - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.view.ui.onboarding - -import androidx.fragment.app.Fragment -import com.aurora.Constants -import com.aurora.store.util.Preferences.PREFERENCE_AUTO_DELETE -import com.aurora.store.util.Preferences.PREFERENCE_DEFAULT_SELECTED_TAB -import com.aurora.store.util.Preferences.PREFERENCE_DISPENSER_URLS -import com.aurora.store.util.Preferences.PREFERENCE_FILTER_AURORA_ONLY -import com.aurora.store.util.Preferences.PREFERENCE_FILTER_FDROID -import com.aurora.store.util.Preferences.PREFERENCE_FOR_YOU -import com.aurora.store.util.Preferences.PREFERENCE_INSTALLER_ID -import com.aurora.store.util.Preferences.PREFERENCE_THEME_STYLE -import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_CHECK_INTERVAL -import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_EXTENDED -import com.aurora.store.util.Preferences.PREFERENCE_VENDING_VERSION -import com.aurora.store.util.save -import dagger.hilt.android.AndroidEntryPoint - -@AndroidEntryPoint -class OnboardingFragment : BaseFlavouredOnboardingFragment() { - - override fun loadDefaultPreferences() { - /*Filters*/ - save(PREFERENCE_FILTER_AURORA_ONLY, false) - save(PREFERENCE_FILTER_FDROID, true) - - /*Network*/ - save(PREFERENCE_DISPENSER_URLS, setOf(Constants.URL_DISPENSER)) - save(PREFERENCE_VENDING_VERSION, 0) - - /*Customization*/ - save(PREFERENCE_THEME_STYLE, 0) - save(PREFERENCE_DEFAULT_SELECTED_TAB, 0) - save(PREFERENCE_FOR_YOU, true) - - /*Installer*/ - save(PREFERENCE_AUTO_DELETE, true) - save(PREFERENCE_INSTALLER_ID, 0) - - /*Updates*/ - save(PREFERENCE_UPDATES_EXTENDED, false) - save(PREFERENCE_UPDATES_CHECK_INTERVAL, 3) - } - - override fun onboardingPages(): List { - return listOf( - WelcomeFragment(), - PermissionsFragment.newInstance() - ) - } - - override fun setupAutoUpdates() { - super.setupAutoUpdates() - - // Remove super & implement variant logic here - } - - override fun finishOnboarding() { - super.finishOnboarding() - - // Remove super & implement variant logic here - } -} diff --git a/app/src/vanilla/java/com/aurora/store/view/ui/onboarding/OnboardingFragment.kt b/app/src/vanilla/java/com/aurora/store/view/ui/onboarding/OnboardingFragment.kt deleted file mode 100644 index b0aea999a..000000000 --- a/app/src/vanilla/java/com/aurora/store/view/ui/onboarding/OnboardingFragment.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.view.ui.onboarding - -import androidx.fragment.app.Fragment -import com.aurora.Constants -import com.aurora.store.util.Preferences.PREFERENCE_AUTO_DELETE -import com.aurora.store.util.Preferences.PREFERENCE_DEFAULT_SELECTED_TAB -import com.aurora.store.util.Preferences.PREFERENCE_DISPENSER_URLS -import com.aurora.store.util.Preferences.PREFERENCE_FILTER_AURORA_ONLY -import com.aurora.store.util.Preferences.PREFERENCE_FILTER_FDROID -import com.aurora.store.util.Preferences.PREFERENCE_FOR_YOU -import com.aurora.store.util.Preferences.PREFERENCE_INSTALLER_ID -import com.aurora.store.util.Preferences.PREFERENCE_THEME_STYLE -import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_CHECK_INTERVAL -import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_EXTENDED -import com.aurora.store.util.Preferences.PREFERENCE_VENDING_VERSION -import com.aurora.store.util.save -import dagger.hilt.android.AndroidEntryPoint - -@AndroidEntryPoint -class OnboardingFragment : BaseFlavouredOnboardingFragment() { - - override fun loadDefaultPreferences() { - /*Filters*/ - save(PREFERENCE_FILTER_AURORA_ONLY, false) - save(PREFERENCE_FILTER_FDROID, true) - - /*Network*/ - save(PREFERENCE_DISPENSER_URLS, setOf(Constants.URL_DISPENSER)) - save(PREFERENCE_VENDING_VERSION, 0) - - /*Customization*/ - save(PREFERENCE_THEME_STYLE, 0) - save(PREFERENCE_DEFAULT_SELECTED_TAB, 0) - save(PREFERENCE_FOR_YOU, true) - - /*Installer*/ - save(PREFERENCE_AUTO_DELETE, true) - save(PREFERENCE_INSTALLER_ID, 0) - - /*Updates*/ - save(PREFERENCE_UPDATES_EXTENDED, false) - save(PREFERENCE_UPDATES_CHECK_INTERVAL, 3) - } - - override fun onboardingPages(): List { - return listOf( - WelcomeFragment(), - PermissionsFragment.newInstance() - ) - } - - override fun setupAutoUpdates() { - super.setupAutoUpdates() - - // Remove super & implement variant logic here - } - - override fun finishOnboarding() { - super.finishOnboarding() - - // Remove super & implement variant logic here - } -}