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

Commit 1f921935 authored by Hasib Prince's avatar Hasib Prince
Browse files

Merge branch '2461-differentiate_releases' into 'main'

feat(updates): Differentiate between Gitlab releases (#2461)

See merge request !501
parents a79141bb 95a177a2
Loading
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
/*
 * 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/>.
 */

package foundation.e.apps.data.gitlab

import foundation.e.apps.data.gitlab.models.ReleaseInfo
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path

interface ReleaseInfoApi {

    companion object {
        const val BASE_URL =
            "${SystemAppDefinitionApi.BASE_URL}/api/v4/projects/"
    }

    @GET("{projectId}/releases")
    suspend fun getReleases(
        @Path("projectId") projectId: Int,
    ): Response<List<ReleaseInfo>>

}
+4 −5
Original line number Diff line number Diff line
@@ -20,19 +20,18 @@ package foundation.e.apps.data.gitlab
import foundation.e.apps.data.gitlab.models.SystemAppInfo
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Url

interface SystemAppDefinitionApi {

    companion object {
        const val BASE_URL =
            "https://gitlab.e.foundation/api/v4/projects/"
            "https://gitlab.e.foundation/"
    }

    @GET("{projectId}/releases/permalink/latest/downloads/json/{releaseType}.json")
    @GET
    suspend fun getSystemAppUpdateInfo(
        @Path("projectId") projectId: Int,
        @Path("releaseType") releaseType: String,
        @Url detailsUrl: String,
    ): Response<SystemAppInfo>

}
+35 −4
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.os.Build
import dagger.hilt.android.qualifiers.ApplicationContext
import foundation.e.apps.data.application.ApplicationDataManager
import foundation.e.apps.data.application.data.Application
import foundation.e.apps.data.gitlab.models.OsReleaseType
import foundation.e.apps.data.gitlab.models.SystemAppInfo
import foundation.e.apps.data.gitlab.models.SystemAppProject
import foundation.e.apps.data.gitlab.models.toApplication
@@ -39,6 +40,7 @@ class SystemAppsUpdatesRepository @Inject constructor(
    private val systemAppDefinitionApi: SystemAppDefinitionApi,
    private val applicationDataManager: ApplicationDataManager,
    private val appLoungePackageManager: AppLoungePackageManager,
    private val releaseInfoApi: ReleaseInfoApi,
) {

    private val systemAppProjectList = mutableListOf<SystemAppProject>()
@@ -93,9 +95,34 @@ class SystemAppsUpdatesRepository @Inject constructor(
        }
    }

    private suspend fun getReleaseDetailsUrl(
        projectId: Int,
        releaseType: OsReleaseType,
    ): String? {
        val releaseResponse = releaseInfoApi.getReleases(projectId)
        val releases = releaseResponse.body()

        if (!releaseResponse.isSuccessful || releases == null) {
            Timber.e("Failed to fetch releases for project id - $projectId")
            return null
        }

        val sortedReleases = releases.sortedByDescending {
            it.releasedAt
        }

        for (release in sortedReleases) {
            release.getAssetWebLink("${releaseType}.json")?.run {
                return this.removePrefix(SystemAppDefinitionApi.BASE_URL)
            }
        }

        return null
    }

    private suspend fun getSystemAppUpdateInfo(
        packageName: String,
        releaseType: String,
        releaseType: OsReleaseType,
        sdkLevel: Int,
        device: String,
    ): Application? {
@@ -103,7 +130,9 @@ class SystemAppsUpdatesRepository @Inject constructor(
        val projectId =
            systemAppProjectList.find { it.packageName == packageName }?.projectId ?: return null

        val response = systemAppDefinitionApi.getSystemAppUpdateInfo(projectId, releaseType)
        val detailsUrl = getReleaseDetailsUrl(projectId, releaseType) ?: return null

        val response = systemAppDefinitionApi.getSystemAppUpdateInfo(detailsUrl)
        val systemAppInfo = response.body()

        return if (systemAppInfo == null) {
@@ -129,8 +158,10 @@ class SystemAppsUpdatesRepository @Inject constructor(
        return SystemInfoProvider.getSystemProperty(SystemInfoProvider.KEY_LINEAGE_DEVICE) ?: ""
    }

    private fun getSystemReleaseType(): String {
        return SystemInfoProvider.getSystemProperty(SystemInfoProvider.KEY_LINEAGE_RELEASE_TYPE) ?: ""
    private fun getSystemReleaseType(): OsReleaseType {
        return SystemInfoProvider.getSystemProperty(SystemInfoProvider.KEY_LINEAGE_RELEASE_TYPE).let {
            OsReleaseType.get(it)
        }
    }

    suspend fun getSystemUpdates(): List<Application> {
+59 −0
Original line number Diff line number Diff line
/*
 * 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/>.
 */

package foundation.e.apps.data.gitlab.models

import com.squareup.moshi.Json

data class ReleaseInfo(
    val name: String,
    @Json(name = "released_at")
    val releasedAt: String,
    val assets: ReleaseAssets,
) {
    fun getAssetWebLink(assetName: String): String? {
        return assets.links.firstOrNull { it.name == assetName }?.directAssetUrl
    }
}

data class ReleaseAssets(
    val links: List<ReleaseLinks>,
)

data class ReleaseLinks(
    val name: String,
    @Json(name = "direct_asset_url")
    val directAssetUrl: String
)

enum class OsReleaseType {
    TEST,
    COMMUNITY,
    STABLE,
    UNKNOWN,
    ;

    override fun toString(): String {
        return this.name.lowercase()
    }

    companion object {
        fun get(value: String?): OsReleaseType {
            return OsReleaseType.values().find { it.name == value?.trim()?.uppercase() } ?: UNKNOWN
        }
    }
}
 No newline at end of file
+15 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import foundation.e.apps.data.cleanapk.CleanApkRetrofit
import foundation.e.apps.data.ecloud.EcloudApiInterface
import foundation.e.apps.data.exodus.ExodusTrackerApi
import foundation.e.apps.data.fdroid.FdroidApiInterface
import foundation.e.apps.data.gitlab.ReleaseInfoApi
import foundation.e.apps.data.gitlab.UpdatableSystemAppsApi
import foundation.e.apps.data.gitlab.SystemAppDefinitionApi
import foundation.e.apps.data.parentalcontrol.fdroid.FDroidMonitorApi
@@ -147,6 +148,20 @@ class RetrofitApiModule {
            .create(UpdatableSystemAppsApi::class.java)
    }

    @Singleton
    @Provides
    fun provideReleaseInfoApi(
        okHttpClient: OkHttpClient,
        moshi: Moshi,
    ): ReleaseInfoApi {
        return Retrofit.Builder()
            .baseUrl(ReleaseInfoApi.BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(MoshiConverterFactory.create(moshi))
            .build()
            .create(ReleaseInfoApi::class.java)
    }

    @Singleton
    @Provides
    fun provideSystemAppDefinitionApi(