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

Commit 860958b8 authored by Hasib Prince's avatar Hasib Prince
Browse files

App Lounge: Resolved Conflict: mergin main -> 5051-logging_class

parents 2f326309 a1736527
Loading
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -43,13 +43,15 @@ ktlintDebug:
# Release build related jobs

# Default configuration for release builds
# Only on "master" and "merge_request_event"
# Only on "master", "merge_request_event" and protected branches
buildRelease:
  stage: release
  allow_failure: false
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: always
    - if: '$CI_COMMIT_REF_PROTECTED == "true"'
      when: always
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
      when: always
  script:
@@ -69,6 +71,8 @@ buildRelease:
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
      when: always
    - if: '$CI_COMMIT_REF_PROTECTED == "true"'
      when: always

buildReleaseDev:
  extends: .releaseSigned
+7 −1
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ plugins {
}

def versionMajor = 2
def versionMinor = 2
def versionMinor = 3
def versionPatch = 0

android {
@@ -66,6 +66,12 @@ android {
            signingConfig signingConfigs.releaseStableConfig
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }

        applicationVariants.all { variant ->
            variant.outputs.all { output ->
                outputFileName = "AppLounge-${variant.versionName}-${variant.buildType.name}.apk"
            }
        }
    }
    buildFeatures {
        viewBinding true
+16 −4
Original line number Diff line number Diff line
@@ -19,15 +19,19 @@ class AppProgressViewModel @Inject constructor(
    suspend fun calculateProgress(
        fusedApp: FusedApp?,
        progress: DownloadProgress
    ): Pair<Long, Long> {
    ): Int {
        fusedApp?.let { app ->
            val appDownload = fusedManagerRepository.getDownloadList()
                .singleOrNull { it.id.contentEquals(app._id) && it.packageName.contentEquals(app.package_name) }
                ?: return Pair(1, 0)
                ?: return 0

            if (!appDownload.id.contentEquals(app._id) || !appDownload.packageName.contentEquals(app.package_name)) {
                return@let
            }

            if (!isProgressValidForApp(fusedApp, progress)) {
                return -1
            }
            val downloadingMap = progress.totalSizeBytes.filter { item ->
                appDownload.downloadIdMap.keys.contains(item.key)
            }
@@ -36,8 +40,16 @@ class AppProgressViewModel @Inject constructor(
                appDownload.downloadIdMap.keys.contains(item.key)
            }.values.sum()

            return Pair(totalSizeBytes, downloadedSoFar)
            return ((downloadedSoFar / totalSizeBytes.toDouble()) * 100).toInt()
        }
        return Pair(1, 0)
        return 0
    }

    private suspend fun isProgressValidForApp(
        fusedApp: FusedApp,
        downloadProgress: DownloadProgress
    ): Boolean {
        val download = fusedManagerRepository.getFusedDownload(downloadProgress.downloadId)
        return download.id == fusedApp._id
    }
}
+15 −48
Original line number Diff line number Diff line
@@ -44,9 +44,8 @@ import foundation.e.apps.purchase.AppPurchaseFragmentDirections
import foundation.e.apps.setup.signin.SignInViewModel
import foundation.e.apps.updates.UpdatesNotifier
import foundation.e.apps.utils.enums.Status
import foundation.e.apps.utils.enums.User
import foundation.e.apps.utils.parentFragment.TimeoutFragment
import foundation.e.apps.utils.modules.CommonUtilsModule
import foundation.e.apps.utils.parentFragment.TimeoutFragment
import kotlinx.coroutines.launch
import timber.log.Timber
import java.io.File
@@ -54,6 +53,7 @@ import java.util.UUID

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private lateinit var signInViewModel: SignInViewModel
    private lateinit var binding: ActivityMainBinding
    private val TAG = MainActivity::class.java.simpleName
    private lateinit var viewModel: MainActivityViewModel
@@ -72,7 +72,7 @@ class MainActivity : AppCompatActivity() {
        var hasInternet = true

        viewModel = ViewModelProvider(this)[MainActivityViewModel::class.java]
        val signInViewModel = ViewModelProvider(this)[SignInViewModel::class.java]
        signInViewModel = ViewModelProvider(this)[SignInViewModel::class.java]

        // navOptions and activityNavController for TOS and SignIn Fragments
        val navOptions = NavOptions.Builder()
@@ -86,30 +86,6 @@ class MainActivity : AppCompatActivity() {
            }
        }

        fun generateAuthDataBasedOnUserType(user: String) {
            if (user.isNotBlank() && viewModel.tocStatus.value == true) {
                when (User.valueOf(user)) {
                    User.ANONYMOUS -> {
                        if (viewModel.authDataJson.value.isNullOrEmpty() && !viewModel.authRequestRunning) {
                            Timber.d( "Fetching new authentication data")
                            viewModel.setFirstTokenFetchTime()
                            viewModel.getAuthData()
                        }
                    }
                    User.UNAVAILABLE -> {
                        viewModel.destroyCredentials(null)
                    }
                    User.GOOGLE -> {
                        if (viewModel.authData.value == null && !viewModel.authRequestRunning) {
                            Timber.d( "Fetching new authentication data")
                            viewModel.setFirstTokenFetchTime()
                            signInViewModel.fetchAuthData()
                        }
                    }
                }
            }
        }

        viewModel.internetConnection.observe(this) { isInternetAvailable ->
            hasInternet = isInternetAvailable
            if (isInternetAvailable) {
@@ -117,7 +93,7 @@ class MainActivity : AppCompatActivity() {
                binding.fragment.visibility = View.VISIBLE

                viewModel.userType.observe(this) { user ->
                    generateAuthDataBasedOnUserType(user)
                    viewModel.handleAuthDataJson()
                }

                signInViewModel.authLiveData.observe(this) {
@@ -126,34 +102,25 @@ class MainActivity : AppCompatActivity() {

                // Watch and refresh authentication data
                viewModel.authDataJson.observe(this) {
                    if (!it.isNullOrEmpty()) {
                        viewModel.generateAuthData()
                        Timber.d( "Authentication data is available!")
                    }
                    viewModel.handleAuthDataJson()
                }
            }
        }

        viewModel.authValidity.observe(this) {
            if (it != true) {
                Timber.d( "Authentication data validation failed!")
                viewModel.destroyCredentials { user ->
                    if (viewModel.isTimeEligibleForTokenRefresh()) {
                        generateAuthDataBasedOnUserType(user)
                    } else {
                        Timber.d( "Timeout validating auth data!")
            viewModel.handleAuthValidity(it) {
                Log.d(TAG, "Timeout validating auth data!")
                val lastFragment = navHostFragment.childFragmentManager.fragments[0]
                if (lastFragment is TimeoutFragment) {
                            Timber.d( "Displaying timeout from MainActivity on fragment: "
                                    + lastFragment::class.java.name)
                    Log.d(
                        TAG,
                        "Displaying timeout from MainActivity on fragment: " +
                            lastFragment::class.java.name
                    )
                    lastFragment.onTimeout()
                }
            }
        }
            } else {
                Timber.d( "Authentication data is valid!")
            }
        }

        navController.addOnDestinationChangedListener { _, destination, _ ->
            if (!hasInternet) {
+114 −9
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@

package foundation.e.apps

import android.app.Activity
import android.content.Context
import android.graphics.Bitmap
import android.os.Build
@@ -41,13 +40,12 @@ import com.google.gson.Gson
import dagger.hilt.android.lifecycle.HiltViewModel
import foundation.e.apps.api.cleanapk.blockedApps.BlockedAppRepository
import foundation.e.apps.api.ecloud.EcloudRepository
import foundation.e.apps.api.fused.FusedAPIImpl
import foundation.e.apps.api.fused.FusedAPIRepository
import foundation.e.apps.api.fused.data.FusedApp
import foundation.e.apps.api.gplay.utils.AC2DMTask
import foundation.e.apps.manager.database.fusedDownload.FusedDownload
import foundation.e.apps.manager.fused.FusedManagerRepository
import foundation.e.apps.manager.pkg.PkgManagerModule
import foundation.e.apps.manager.workmanager.InstallWorkManager
import foundation.e.apps.utils.enums.Origin
import foundation.e.apps.utils.enums.Status
import foundation.e.apps.utils.enums.Type
@@ -56,6 +54,7 @@ import foundation.e.apps.utils.modules.CommonUtilsModule.timeoutDurationInMillis
import foundation.e.apps.utils.modules.DataStoreModule
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import ru.beryukhov.reactivenetwork.ReactiveNetwork
import timber.log.Timber
import java.io.ByteArrayOutputStream
@@ -70,6 +69,7 @@ class MainActivityViewModel @Inject constructor(
    private val pkgManagerModule: PkgManagerModule,
    private val ecloudRepository: EcloudRepository,
    private val blockedAppRepository: BlockedAppRepository,
    private val aC2DMTask: AC2DMTask,
) : ViewModel() {

    val authDataJson: LiveData<String> = dataStoreModule.authData.asLiveData()
@@ -93,6 +93,8 @@ class MainActivityViewModel @Inject constructor(
     */
    var firstAuthDataFetchTime = 0L

    var isTokenValidationCompletedOnce = false

    // Downloads
    val downloadList = fusedManagerRepository.getDownloadLiveList()
    var installInProgress = false
@@ -107,15 +109,16 @@ class MainActivityViewModel @Inject constructor(

    companion object {
        private const val TAG = "MainActivityViewModel"
        private var isGoogleLoginRunning = false
    }

    fun setFirstTokenFetchTime() {
    private fun setFirstTokenFetchTime() {
        if (firstAuthDataFetchTime == 0L) {
            firstAuthDataFetchTime = SystemClock.uptimeMillis()
        }
    }

    fun isTimeEligibleForTokenRefresh(): Boolean {
    private fun isTimeEligibleForTokenRefresh(): Boolean {
        return (SystemClock.uptimeMillis() - firstAuthDataFetchTime) <= timeoutDurationInMillis
    }

@@ -198,13 +201,116 @@ class MainActivityViewModel @Inject constructor(
    }

    fun generateAuthData() {
        val data = gson.fromJson(authDataJson.value, AuthData::class.java)
        val data = jsonToAuthData()
        _authData.value = data
    }

    private fun jsonToAuthData() = gson.fromJson(authDataJson.value, AuthData::class.java)

    fun validateAuthData() {
        viewModelScope.launch {
            authValidity.postValue(isAuthValid(data))
            jsonToAuthData()?.let {
                val isAuthValid = isAuthValid(it)
                authValidity.postValue(isAuthValid)
                authRequestRunning = false
            }
        }
    }

    fun handleAuthDataJson() {
        val user = userType.value
        val json = authDataJson.value

        if (user == null || json == null) {
            return
        }

        if (!isUserLoggedIn(user, json)) {
            generateAuthDataBasedOnUserType(user)
        } else if (isEligibleToValidateJson(json)) {
            validateAuthData()
            Log.d(TAG, ">>> Authentication data is available!")
        }
    }

    private fun isUserLoggedIn(user: String, json: String) =
        user.isNotEmpty() && !user.contentEquals(User.UNAVAILABLE.name) && json.isNotEmpty()

    private fun isEligibleToValidateJson(authDataJson: String?) =
        !authDataJson.isNullOrEmpty() && !userType.value.isNullOrEmpty() && !userType.value.contentEquals(
            User.UNAVAILABLE.name
        )

    fun handleAuthValidity(isValid: Boolean, handleTimeoOut: () -> Unit) {
        if (isGoogleLoginRunning) {
            return
        }
        isTokenValidationCompletedOnce = true
        if (isValid) {
            Log.d(TAG, "Authentication data is valid!")
            generateAuthData()
            return
        }
        Log.d(TAG, ">>> Authentication data validation failed!")
        destroyCredentials { user ->
            if (isTimeEligibleForTokenRefresh()) {
                generateAuthDataBasedOnUserType(user)
            } else {
                handleTimeoOut()
            }
        }
    }

    private fun generateAuthDataBasedOnUserType(user: String) {
        if (user.isEmpty() || tocStatus.value == false || isGoogleLoginRunning) {
            return
        }
        when (User.valueOf(user)) {
            User.ANONYMOUS -> {
                if (authDataJson.value.isNullOrEmpty() && !authRequestRunning) {
                    Log.d(TAG, ">>> Fetching new authentication data")
                    setFirstTokenFetchTime()
                    getAuthData()
                }
            }
            User.UNAVAILABLE -> {
                destroyCredentials(null)
            }
            User.GOOGLE -> {
                if (authData.value == null && !authRequestRunning) {
                    Log.d(TAG, ">>> Fetching new authentication data")
                    setFirstTokenFetchTime()
                    doFetchAuthData()
                }
            }
        }
    }

    private suspend fun doFetchAuthData(email: String, oauthToken: String) {
        var responseMap: Map<String, String>
        withContext(Dispatchers.IO) {
            val response = aC2DMTask.getAC2DMResponse(email, oauthToken)
            responseMap = response
            responseMap["Token"]?.let {
                if (fusedAPIRepository.fetchAuthData(email, it) == null) {
                    dataStoreModule.clearUserType()
                    _errorMessageStringResource.value = R.string.unknown_error
                }
            }
        }
    }

    private fun doFetchAuthData() {
        viewModelScope.launch {
            isGoogleLoginRunning = true
            val email = dataStoreModule.getEmail()
            val oauthToken = dataStoreModule.getAASToken()
            if (email.isNotEmpty() && oauthToken.isNotEmpty()) {
                doFetchAuthData(email, oauthToken)
            }
            isGoogleLoginRunning = false
        }
    }

    private suspend fun isAuthValid(authData: AuthData): Boolean {
        return fusedAPIRepository.validateAuthData(authData)
@@ -385,7 +491,6 @@ class MainActivityViewModel @Inject constructor(
            val fusedDownload =
                fusedManagerRepository.getFusedDownload(packageName = app.package_name)
            fusedManagerRepository.cancelDownload(fusedDownload)
            InstallWorkManager.cancelWork(app.name)
        }
    }

Loading