Commit fe80a4c9 authored by Aayush Gupta's avatar Aayush Gupta Committed by Romain Hunault
Browse files

Apps: Upstream, Cleanup and CI

parent d957da8d
image: "registry.gitlab.e.foundation:5000/e/apps/docker-android-apps-cicd:latest"
stages:
- build
- debug
- release
before_script:
- export GRADLE_USER_HOME=$(pwd)/.gradle
- chmod +x ./gradlew
build:
stage: build
# Debug build related jobs
buildDebug:
stage: debug
script:
- ./gradlew build
- ./gradlew assembleDebug
artifacts:
paths:
- app/build/outputs/apk/
- app/build/reports/
\ No newline at end of file
- app/build/outputs/apk/
# Default lint configuration for debug builds
# Manual as we don't want to run them generally for debug builds
.lintDebugDefault:
stage: debug
when: manual
allow_failure: true
lintDebug:
extends: .lintDebugDefault
script:
- ./gradlew lintDebug
artifacts:
paths:
- app/build/reports/
ktlintDebug:
extends: .lintDebugDefault
script:
- ./gradlew app:ktlintCheck --info
artifacts:
paths:
- app/build/reports/ktlint/
# Release build related jobs
# Default configuration for release builds
# Only on "master" and "merge_request_event"
.releaseDefault:
stage: release
allow_failure: false
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
when: always
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always
buildRelease:
extends: .releaseDefault
script:
- ./gradlew assembleRelease
artifacts:
paths:
- app/build/outputs/apk/
lintRelease:
extends: .releaseDefault
script:
- ./gradlew lintRelease
artifacts:
paths:
- app/build/reports/
ktlintRelease:
extends: .releaseDefault
script:
- ./gradlew app:ktlintCheck --info
artifacts:
paths:
- app/build/reports/ktlint/
\ No newline at end of file
......@@ -3,6 +3,7 @@ plugins {
id 'kotlin-android'
id 'kotlin-kapt'
id 'kotlin-parcelize'
id "org.jlleitschuh.gradle.ktlint" version "10.1.0"
}
android {
......@@ -30,26 +31,18 @@ android {
buildTypes {
debug {
applicationIdSuffix ".debug"
signingConfig signingConfigs.config
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
platform {
signingConfig signingConfigs.config
}
}
buildFeatures {
viewBinding true
}
lintOptions {
lintConfig file("lint.xml")
disable 'MissingTranslation'
disable 'NullSafeMutableLiveData'
}
aaptOptions {
additionalParameters '-I', 'app/e-ui-sdk.jar'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
......@@ -60,21 +53,22 @@ android {
}
}
ktlint {
disabledRules = ["no-wildcard-imports"]
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.3.0-rc01'
implementation "com.google.android.material:material:1.3.0"
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation "com.google.android.material:material:1.4.0"
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation fileTree(include: ['*.jar'], dir: 'libs')
// eOS
compileOnly files("e-ui-sdk.jar")
// Preference
implementation "androidx.preference:preference-ktx:1.1.1"
......@@ -82,13 +76,13 @@ dependencies {
implementation 'org.bouncycastle:bcpg-jdk15on:1.60'
// GSON
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.google.code.gson:gson:2.8.7'
// PhotoView
implementation "com.github.chrisbanes:PhotoView:2.3.0"
// RecyclerView
implementation 'androidx.recyclerview:recyclerview:1.2.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
// WorkManager
implementation 'androidx.work:work-runtime-ktx:2.5.0'
......@@ -110,7 +104,7 @@ dependencies {
implementation "com.trello.rxlifecycle3:rxlifecycle-components-preference:$rxlifecycle_version"
// Jackson
def jackson_version = "2.12.2"
def jackson_version = "2.12.3"
implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version"
implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
......
......@@ -2,4 +2,6 @@
<issue id="InvalidPackage">
<ignore path="**/org.bouncycastle*.jar"/>
</issue>
<issue id="NullSafeMutableLiveData" severity="warning"/>
<issue id="MissingTranslation" severity="warning"/>
</lint>
\ No newline at end of file
......@@ -70,7 +70,7 @@
android:name=".pwa.PwaInstaller"
android:theme="@style/FullScreenTheme" />
<activity
android:name=".XAPK.InstallSplitApksActivity"
android:name=".xapk.InstallSplitApksActivity"
android:configChanges="screenSize|orientation|keyboardHidden"
android:launchMode="singleInstance"
android:theme="@style/AppTheme1"
......
......@@ -17,8 +17,6 @@
package foundation.e.apps
import android.annotation.SuppressLint
import android.content.*
import android.content.pm.PackageManager
......@@ -26,6 +24,7 @@ import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.MenuItem
import android.widget.Toast
import androidx.annotation.ColorRes
......@@ -37,7 +36,6 @@ import androidx.preference.PreferenceManager
import com.google.android.material.bottomnavigation.BottomNavigationItemView
import com.google.android.material.bottomnavigation.BottomNavigationMenuView
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomnavigation.LabelVisibilityMode
import com.google.android.material.snackbar.Snackbar
import foundation.e.apps.applicationmanager.ApplicationManager
import foundation.e.apps.applicationmanager.ApplicationManagerServiceConnection
......@@ -48,14 +46,15 @@ import foundation.e.apps.home.HomeFragment
import foundation.e.apps.search.SearchFragment
import foundation.e.apps.settings.SettingsFragment
import foundation.e.apps.updates.UpdatesFragment
import foundation.e.apps.updates.UpdatesManager
import foundation.e.apps.utils.Common
import foundation.e.apps.utils.Constants
import foundation.e.apps.utils.Constants.CURRENTLY_SELECTED_FRAGMENT_KEY
import kotlin.properties.Delegates
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener,
ApplicationManagerServiceConnectionCallback {
class MainActivity :
AppCompatActivity(),
BottomNavigationView.OnNavigationItemSelectedListener,
ApplicationManagerServiceConnectionCallback {
private lateinit var binding: ActivityMainBinding
private var currentFragmentId = 0
......@@ -63,9 +62,9 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
private val searchFragment = SearchFragment()
private val updatesFragment = UpdatesFragment()
private val applicationManagerServiceConnection =
ApplicationManagerServiceConnection(this)
ApplicationManagerServiceConnection(this)
private val codeRequestPermissions = 9527
var doubleBackToExitPressedOnce = false;
var doubleBackToExitPressedOnce = false
private var isReceiverRegistered = false
private var accentColorOS by Delegates.notNull<Int>()
......@@ -77,7 +76,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
private var instance: MainActivity? = null
lateinit var mActivity: MainActivity
var sharedPreferences : SharedPreferences?=null
var sharedPreferences: SharedPreferences? = null
val sharedPrefFile = "kotlinsharedpreference"
/*
......@@ -89,8 +88,6 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
}
}
override fun onCreate(savedInstanceState: Bundle?) {
binding = ActivityMainBinding.inflate(layoutInflater)
......@@ -102,9 +99,8 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
mActivity = this
disableCategoryIfOpenSource()
binding.bottomNavigationView.setOnNavigationItemSelectedListener{
if (selectFragment(it.itemId,it)) {
binding.bottomNavigationView.setOnNavigationItemSelectedListener {
if (selectFragment(it.itemId, it)) {
disableCategoryIfOpenSource()
currentFragmentId = it.itemId
return@setOnNavigationItemSelectedListener true
......@@ -112,14 +108,14 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
return@setOnNavigationItemSelectedListener false
}
disableShiftingOfNabBarItems()
Common.updateMicroGStatus(this)
// Show the home fragment by default
currentFragmentId = if (savedInstanceState != null &&
savedInstanceState.containsKey(CURRENTLY_SELECTED_FRAGMENT_KEY)) {
savedInstanceState.containsKey(CURRENTLY_SELECTED_FRAGMENT_KEY)
) {
savedInstanceState.getInt(CURRENTLY_SELECTED_FRAGMENT_KEY)
} else if (intent.hasExtra(Constants.UPDATES_NOTIFICATION_CLICK_EXTRA)) {
R.id.menu_updates
......@@ -139,32 +135,38 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
}
private fun openSearchFragment() {
if (intent.getBooleanExtra(Constants.OPEN_SEARCH,false)) {
if (intent.getBooleanExtra(Constants.OPEN_SEARCH, false)) {
currentFragmentId = R.id.menu_search
val bundle = Bundle()
bundle.putString(Constants.MICROG_QUERY,"microg")
searchFragment.arguments= bundle
bundle.putString(Constants.MICROG_QUERY, "microg")
searchFragment.arguments = bundle
}
}
private fun bottom_navigation_view_color() {
val iconsColorStates =
ColorStateList(arrayOf(intArrayOf(-android.R.attr.state_checked),
intArrayOf(android.R.attr.state_checked)), intArrayOf(
Color.parseColor("#C4CFD9"),
accentColorOS
))
val textColorStates = ColorStateList(arrayOf(intArrayOf(-android.R.attr.state_checked), intArrayOf(android.R.attr.state_checked)), intArrayOf(
ColorStateList(
arrayOf(
intArrayOf(-android.R.attr.state_checked),
intArrayOf(android.R.attr.state_checked)
),
intArrayOf(
Color.parseColor("#C4CFD9"),
accentColorOS
)
)
val textColorStates = ColorStateList(
arrayOf(intArrayOf(-android.R.attr.state_checked), intArrayOf(android.R.attr.state_checked)),
intArrayOf(
Color.parseColor("#C4CFD9"),
accentColorOS
))
)
)
binding.bottomNavigationView.setItemIconTintList(iconsColorStates)
binding.bottomNavigationView.setItemTextColor(textColorStates)
}
override fun onServiceBind(applicationManager: ApplicationManager) {
......@@ -179,7 +181,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
if (selectFragment(item.itemId,item)) {
if (selectFragment(item.itemId, item)) {
currentFragmentId = item.itemId
return true
}
......@@ -205,7 +207,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
val normalDrawable = item.icon
val wrapDrawable = DrawableCompat.wrap(normalDrawable)
DrawableCompat.setTint(wrapDrawable, ContextCompat.getColor(context, color))//context.resources.getColor(color))
DrawableCompat.setTint(wrapDrawable, ContextCompat.getColor(context, color)) // context.resources.getColor(color))
item.icon = wrapDrawable
}
......@@ -226,7 +228,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
return true
}
R.id.menu_search -> {
item?.setIcon(lineageos.platform.R.drawable.ic_search)
item?.setIcon(R.drawable.ic_search)
showFragment(searchFragment)
return true
}
......@@ -236,7 +238,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
return true
}
R.id.menu_settings -> {
item?.setIcon(lineageos.platform.R.drawable.ic_settings)
item?.setIcon(R.drawable.ic_settings)
showFragment(SettingsFragment())
return true
}
......@@ -253,7 +255,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
}
val filter = IntentFilter(Intent.ACTION_LOCALE_CHANGED)
registerReceiver(mLangReceiver, filter)
isReceiverRegistered = true;
isReceiverRegistered = true
}
return mLangReceiver
}
......@@ -261,9 +263,9 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
private fun showFragment(fragment: Fragment) {
binding.bottomNavigationView.menu.findItem(currentFragmentId).isChecked = true
supportFragmentManager
.beginTransaction()
.replace(R.id.frame_layout, fragment)
.commitAllowingStateLoss();
.beginTransaction()
.replace(R.id.frame_layout, fragment)
.commitAllowingStateLoss()
}
@SuppressLint("RestrictedApi")
......@@ -282,23 +284,34 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
for (i in 0 until menuView.childCount) {
val itemView = menuView.getChildAt(i) as BottomNavigationItemView
itemView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED); itemView.setChecked(itemView.itemData.isChecked)
itemView.setLabelVisibilityMode(BottomNavigationView.LABEL_VISIBILITY_LABELED)
itemView.itemData?.isChecked?.let {
itemView.setChecked(
it
)
}
}
}
private fun disableCategoryIfOpenSource(){
if(showApplicationTypePreference()=="open") {
private fun disableCategoryIfOpenSource() {
if (showApplicationTypePreference() == "open") {
binding.bottomNavigationView.menu.removeItem(R.id.menu_categories)
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>,
grantResults: IntArray) {
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == Constants.STORAGE_PERMISSION_REQUEST_CODE &&
grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_DENIED) {
Snackbar.make(binding.container, R.string.error_storage_permission_denied,
Snackbar.LENGTH_LONG).show()
grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_DENIED
) {
Snackbar.make(
binding.container, R.string.error_storage_permission_denied,
Snackbar.LENGTH_LONG
).show()
}
}
......@@ -325,13 +338,16 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
return
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, R.string.exit, Toast.LENGTH_SHORT).show();
this.doubleBackToExitPressedOnce = true
Toast.makeText(this, R.string.exit, Toast.LENGTH_SHORT).show()
Handler().postDelayed(Runnable() {
run {
doubleBackToExitPressedOnce = false;
}
}, 2000)
Handler(Looper.getMainLooper()).postDelayed(
Runnable() {
run {
doubleBackToExitPressedOnce = false
}
},
2000
)
}
}
......@@ -34,7 +34,6 @@ package foundation.e.apps.api
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import android.content.Context
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
......@@ -57,7 +56,7 @@ class AllAppsSearchRequest(private val keyword: String, private val page: Int, p
fun request(callback: (Error?, SearchResult?) -> Unit) {
try {
var appType =mActivity.showApplicationTypePreference()
var appType = mActivity.showApplicationTypePreference()
val url = Constants.BASE_URL + "apps?action=search&type=$appType&source=$appType&keyword=${URLEncoder.encode(keyword, "utf-8")}&page=$page&nres=$resultsPerPage"
val urlConnection = Common.createConnection(url, Constants.REQUEST_METHOD_GET)
val result = reader.readValue<SearchResult>(urlConnection.inputStream)
......@@ -76,6 +75,3 @@ class AllAppsSearchRequest(private val keyword: String, private val page: Int, p
}
}
}
......@@ -54,14 +54,11 @@ class AppDetailRequest(private val id: String) {
val result = reader.readValue<Result>(urlConnection.inputStream)
urlConnection.disconnect()
callback.invoke(null, result.app)
} catch (e: Exception) {
callback.invoke(Error.findError(e), null)
}
}
fun Pwarequest(callback: (Error?, PwaFullData?) -> Unit) {
try {
val url = Constants.BASE_URL + "apps?action=app_detail&id=$id&architectures=[$sb"
......@@ -69,7 +66,6 @@ class AppDetailRequest(private val id: String) {
val PwaResult = Pwareader.readValue<PwaResult>(urlConnection.inputStream)
urlConnection.disconnect()
callback.invoke(null, PwaResult.app)
} catch (e: Exception) {
callback.invoke(Error.findError(e), null)
}
......@@ -81,5 +77,3 @@ class AppDetailRequest(private val id: String) {
class PwaResult @JsonCreator
constructor(@JsonProperty("app") val app: PwaFullData)
}
......@@ -22,10 +22,8 @@ import foundation.e.apps.utils.Constants
import foundation.e.apps.utils.Error
import java.util.*
class FDroidAppExistsRequest(private val keyword: String) {
fun request(callback: (Error?, ArrayList<Int?>) -> Unit) {
try {
val l1 = ArrayList<Int?>()
......@@ -40,5 +38,4 @@ class FDroidAppExistsRequest(private val keyword: String) {
callback.invoke(Error.findError(e), ArrayList())
}
}
}
\ No newline at end of file
}
......@@ -27,21 +27,21 @@ import foundation.e.apps.applicationmanager.ApplicationManager
import foundation.e.apps.utils.*
import java.io.InputStreamReader
class GitlabDataRequest {
fun requestGmsCoreRelease(callback: (Error?, GitlabDataResult?) -> Unit) = try {
val url = Constants.RELEASE_API + Constants.MICROG_ID + Constants.RELEASE_ENDPOINT
val urlConnection = Common.createConnection(url, Constants.REQUEST_METHOD_GET)
val isr = InputStreamReader(urlConnection.inputStream)
val element = parseReader(isr)
val releaseList: List<ReleaseData> = Gson().fromJson(element.toString(),
Array<ReleaseData>::class.java).toList()
val releaseList: List<ReleaseData> = Gson().fromJson(
element.toString(),
Array<ReleaseData>::class.java
).toList()
urlConnection.disconnect()
val osReleaseType = OsInfo().getOSReleaseType()
val osReleaseType = OsInfo.getOSReleaseType()
var releaseUrl = ""
releaseList[0].assets.links.forEach {
......@@ -50,9 +50,15 @@ class GitlabDataRequest {
}
}
callback.invoke(null, GitlabDataResult(SystemAppDataSource.createDataSource(Constants.MICROG_ID.toString(),
releaseList[0].tag_name, Constants.MICROG_ICON_URI, releaseUrl)))
callback.invoke(
null,
GitlabDataResult(
SystemAppDataSource.createDataSource(
Constants.MICROG_ID.toString(),
releaseList[0].tag_name, Constants.MICROG_ICON_URI, releaseUrl
)
)
)
} catch (e: Exception) {
callback.invoke(Error.findError(e), null)
}
......@@ -62,6 +68,4 @@ class GitlabDataRequest {
return ApplicationParser.parseSystemAppData(applicationManager, context, data)
}
}
}
......@@ -49,20 +49,19 @@ class HomePwaRequest {
}
}
data class Result(val success: Boolean, val home: Home)
data class Home(
@JsonProperty("headings")
val headings: Map<String, String>?,
@JsonProperty(BANNER_APPS_KEY)
val bannerApps: List<PwasBasicData>,
@JsonProperty(POPULAR_APPS_KEY)
val topUpdatedApps: List<PwasBasicData>,
@JsonProperty(POPULAR_GAMES_KEY)
val topUpdatedGames: List<PwasBasicData>,
@JsonProperty(DISCOVER_KEY)
val discover: List<PwasBasicData>
@JsonProperty("headings")
val headings: Map<String, String>?,
@JsonProperty(BANNER_APPS_KEY)
val bannerApps: List<PwasBasicData>,
@JsonProperty(POPULAR_APPS_KEY)
val topUpdatedApps: