Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1040b69 authored by Fahim M. Choudhury's avatar Fahim M. Choudhury
Browse files

Merge branch '1844-add-ignore-functionality' into 'main'

Add functionality to ignore refresh session popup during an app session

See merge request !429
parents de5c63cd 61108d10
Loading
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -254,4 +254,8 @@ dependencies {

    // elib
    implementation 'foundation.e:elib:0.0.1-alpha11'

    // androidx.activity
    def activity_version = "1.6.1"
    implementation("androidx.activity:activity-ktx:$activity_version")
}
+19 −1
Original line number Diff line number Diff line
<?xml version="1.0" ?>
<!--
  ~ Copyright (C) 2021-2024 MURENA SAS
  ~
  ~ This program 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 3 of the License, or
  ~ (at your option) any later version.
  ~
  ~ This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
  ~
  -->

<SmellBaseline>
  <ManuallySuppressedIssues></ManuallySuppressedIssues>
  <CurrentIssues>
@@ -19,7 +37,7 @@
    <ID>LongParameterList:CleanApkRetrofit.kt$CleanApkRetrofit$( @Query("keyword") keyword: String, @Query("source") source: String = APP_SOURCE_FOSS, @Query("type") type: String = APP_TYPE_ANY, @Query("nres") nres: Int = 20, @Query("page") page: Int = 1, @Query("by") by: String? = null, )</ID>
    <ID>LongParameterList:EglExtensionProvider.kt$EglExtensionProvider$( egl10: EGL10, eglDisplay: EGLDisplay, eglConfig: EGLConfig?, ai: IntArray, ai1: IntArray?, set: MutableSet&lt;String&gt; )</ID>
    <ID>LongParameterList:FusedManagerImpl.kt$FusedManagerImpl$( @Named("cacheDir") private val cacheDir: String, private val downloadManager: DownloadManager, private val notificationManager: NotificationManager, private val fusedDownloadRepository: FusedDownloadRepository, private val pwaManager: PWAManager, private val appLoungePackageManager: AppLoungePackageManager, @Named("download") private val downloadNotificationChannel: NotificationChannel, @Named("update") private val updateNotificationChannel: NotificationChannel, @ApplicationContext private val context: Context )</ID>
    <ID>LongParameterList:MainActivityViewModel.kt$MainActivityViewModel$( private val appLoungeDataStore: AppLoungeDataStore, private val applicationRepository: ApplicationRepository, private val fusedManagerRepository: FusedManagerRepository, private val appLoungePackageManager: AppLoungePackageManager, private val pwaManager: PWAManager, private val ecloudRepository: EcloudRepository, private val blockedAppRepository: BlockedAppRepository, private val appInstallProcessor: AppInstallProcessor )</ID>
    <ID>LongParameterList:MainActivityViewModel.kt$MainActivityViewModel$( private val appLoungeDataStore: AppLoungeDataStore, private val applicationRepository: ApplicationRepository, private val fusedManagerRepository: FusedManagerRepository, private val appLoungePackageManager: AppLoungePackageManager, private val pwaManager: PWAManager, private val ecloudRepository: EcloudRepository, private val blockedAppRepository: BlockedAppRepository, private val appInstallProcessor: AppInstallProcessor, private val sessionPreference: SessionPreference )</ID>
    <ID>LongParameterList:UpdatesManagerImpl.kt$UpdatesManagerImpl$( @ApplicationContext private val context: Context, private val appLoungePackageManager: AppLoungePackageManager, private val applicationRepository: ApplicationRepository, private val faultyAppRepository: FaultyAppRepository, private val appLoungePreference: AppLoungePreference, private val fdroidRepository: FdroidRepository, private val blockedAppRepository: BlockedAppRepository, )</ID>
    <ID>LongParameterList:UpdatesWorker.kt$UpdatesWorker$( @Assisted private val context: Context, @Assisted private val params: WorkerParameters, private val updatesManagerRepository: UpdatesManagerRepository, private val dataStoreManager: DataStoreManager, private val authenticatorRepository: AuthenticatorRepository, private val appInstallProcessor: AppInstallProcessor, private val blockedAppRepository: BlockedAppRepository, )</ID>
    <ID>MagicNumber:AnonymousLoginManager.kt$AnonymousLoginManager$200</ID>
+21 −1
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2021-2024 MURENA SAS
  ~
  ~ This program 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 3 of the License, or
  ~ (at your option) any later version.
  ~
  ~ This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
  ~
  -->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

@@ -42,7 +60,9 @@
        android:restoreNeedsApplication="true"
        android:supportsRtl="true"
        android:theme="@style/Theme.Apps"
        android:usesCleartextTraffic="true">
        android:enableOnBackInvokedCallback="true"
        android:usesCleartextTraffic="true"
        tools:targetApi="tiramisu">

        <activity
            android:name=".MainActivity"
+5 −5
Original line number Diff line number Diff line
/*
 * Apps  Quickly and easily install Android apps onto your device!
 * Copyright (C) 2021  E FOUNDATION
 * Copyright (C) 2021-2024 MURENA SAS
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
@@ -14,6 +13,7 @@
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package foundation.e.apps
@@ -29,8 +29,8 @@ import dagger.hilt.android.HiltAndroidApp
import foundation.e.apps.data.Constants.TAG_AUTHDATA_DUMP
import foundation.e.apps.data.preference.AppLoungeDataStore
import foundation.e.apps.data.preference.AppLoungePreference
import foundation.e.apps.install.pkg.PkgManagerBR
import foundation.e.apps.install.pkg.AppLoungePackageManager
import foundation.e.apps.install.pkg.PkgManagerBR
import foundation.e.apps.install.updates.UpdatesWorkManager
import foundation.e.apps.install.workmanager.InstallWorkManager
import foundation.e.apps.ui.setup.tos.TOS_VERSION
@@ -38,13 +38,13 @@ import foundation.e.apps.utils.CustomUncaughtExceptionHandler
import foundation.e.lib.telemetry.Telemetry
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import timber.log.Timber
import timber.log.Timber.Forest.plant
import java.util.concurrent.Executors
import javax.inject.Inject
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking

@HiltAndroidApp
@DelicateCoroutinesApi
+75 −13
Original line number Diff line number Diff line
/*
 * Apps  Quickly and easily install Android apps onto your device!
 * Copyright (C) 2021  E FOUNDATION
 * Copyright (C) 2021-2024 MURENA SAS
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
@@ -14,13 +13,16 @@
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package foundation.e.apps

import android.os.Build
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.os.Bundle
import android.view.View
import android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
@@ -43,7 +45,6 @@ import foundation.e.apps.data.login.AuthObject
import foundation.e.apps.data.login.LoginViewModel
import foundation.e.apps.data.login.PlayStoreAuthenticator
import foundation.e.apps.data.login.exceptions.GPlayValidationException
import foundation.e.apps.data.preference.AppLoungePreference
import foundation.e.apps.databinding.ActivityMainBinding
import foundation.e.apps.install.updates.UpdatesNotifier
import foundation.e.apps.ui.MainActivityViewModel
@@ -59,23 +60,25 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private lateinit var signInViewModel: SignInViewModel
    private lateinit var loginViewModel: LoginViewModel
    private lateinit var binding: ActivityMainBinding
    private val TAG = MainActivity::class.java.simpleName
    private lateinit var viewModel: MainActivityViewModel

    @Inject
    lateinit var appLoungePreference: AppLoungePreference
    companion object {
        private val TAG = MainActivity::class.java.simpleName
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)

        setupBackPressHandlingForTiramisuAndAbove()

        setContentView(binding.root)

        val (bottomNavigationView, navController) = setupBootomNav()
@@ -88,7 +91,7 @@ class MainActivity : AppCompatActivity() {
            bottomNavigationView.selectedItemId = R.id.updatesFragment
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        if (VERSION.SDK_INT >= VERSION_CODES.O) {
            viewModel.createNotificationChannels()
        }

@@ -120,6 +123,54 @@ class MainActivity : AppCompatActivity() {
        observeEvents()
    }

    override fun onStart() {
        super.onStart()
        checkSessionRefresh()
    }

    private fun checkSessionRefresh() {
        if (viewModel.shouldRefreshSession()) {
            refreshSession()
        }
    }

    private fun refreshSession() {
        loginViewModel.startLoginFlow(listOf(PlayStoreAuthenticator::class.java.simpleName))
    }

    // In Android 12 (API level 32) and lower, onBackPressed is always called,
    // regardless of any registered instances of OnBackPressedCallback.
    // https://developer.android.com/guide/navigation/navigation-custom-back#onbackpressed
    @Deprecated("Deprecated in Java")
    override fun onBackPressed() {
        if (isInitialScreen()) {
            resetIgnoreStatusForSessionRefresh()
        }
        super.onBackPressed()
    }

    private fun isInitialScreen(): Boolean {
        val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.fragment) as NavHostFragment

        val navController = navHostFragment.navController

        return navController.currentDestination?.id == navController.graph.startDestinationId
    }

    private fun resetIgnoreStatusForSessionRefresh() {
        viewModel.updateIgnoreRefreshPreference(ignore = false)
    }

    @Suppress("DEPRECATION")
    private fun setupBackPressHandlingForTiramisuAndAbove() {
        if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
            onBackInvokedDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT) {
                resetIgnoreStatusForSessionRefresh()
                super.onBackPressed() // Deprecated for Android 13+
            }
        }
    }

    private fun setupNavigations(navController: NavController) {
        val navOptions = NavOptions.Builder()
@@ -355,14 +406,25 @@ class MainActivity : AppCompatActivity() {
        EventBus.events.filter { appEvent ->
            appEvent is AppEvent.TooManyRequests
        }.collectLatest {
            val shouldShowDialog = viewModel.shouldRefreshSession()
            if (shouldShowDialog) {
                binding.sessionErrorLayout.visibility = View.VISIBLE
            binding.retrySessionButton.setOnClickListener {
                binding.sessionErrorLayout.visibility = View.GONE
                loginViewModel.startLoginFlow(listOf(PlayStoreAuthenticator::class.java.simpleName))
                binding.retrySessionButton.setOnClickListener { onRefreshSessionClick() }
                binding.ignoreSessionButton.setOnClickListener { onIgnoreSessionClick() }
            }
        }
    }

    private fun onIgnoreSessionClick() {
        viewModel.updateIgnoreRefreshPreference(true)
        binding.sessionErrorLayout.visibility = View.GONE
    }

    private fun onRefreshSessionClick() {
        binding.sessionErrorLayout.visibility = View.GONE
        refreshSession()
    }

    private fun setupBottomNavItemSelectedListener(
        bottomNavigationView: BottomNavigationView,
        navHostFragment: NavHostFragment,
Loading