Commit 9bc304da authored by stopcovid@lunabee.com's avatar stopcovid@lunabee.com
Browse files

Update 1.1.2

parent 0793e6f8
......@@ -53,12 +53,12 @@ dependencies {
api 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
api 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
api "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0"
api "androidx.navigation:navigation-fragment-ktx:2.2.2"
api "androidx.navigation:navigation-ui-ktx:2.2.2"
api "androidx.navigation:navigation-fragment-ktx:2.3.0"
api "androidx.navigation:navigation-ui-ktx:2.3.0"
api 'androidx.preference:preference:1.1.1'
api 'androidx.recyclerview:recyclerview:1.1.0'
api 'androidx.emoji:emoji-appcompat:1.0.0'
api 'androidx.emoji:emoji-bundled:1.0.0'
api 'androidx.emoji:emoji-appcompat:1.1.0'
api 'androidx.emoji:emoji-bundled:1.1.0'
api 'com.google.android.material:material:1.2.0-beta01'
api 'com.google.code.gson:gson:2.8.6'
......
......@@ -10,7 +10,7 @@
<resources>
<color name="color_primary">#85BBFF</color>
<color name="color_on_primary">#00285A</color>
<color name="color_primary_light">#29394D</color>
<color name="color_primary_light">#2685BBFF</color>
<color name="color_on_primary_light">#FFFFFF</color>
<color name="color_error">#FF6F4D</color>
<color name="color_error_light">#331716</color>
......
......@@ -10,7 +10,7 @@
<resources>
<color name="color_primary">#000091</color>
<color name="color_on_primary">#FFFFFF</color>
<color name="color_primary_light">#E4ECF3</color>
<color name="color_primary_light">#1A000091</color>
<color name="color_on_primary_light">#000091</color>
<color name="color_error">#E2011C</color>
<color name="color_error_light">#FACDD2</color>
......
......@@ -16,7 +16,6 @@ import com.google.gson.GsonBuilder
import com.lunabeestudio.framework.BuildConfig
import okhttp3.CertificatePinner
import okhttp3.ConnectionSpec
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Interceptor
import okhttp3.OkHttpClient
......@@ -33,20 +32,18 @@ import java.util.concurrent.TimeUnit
object RetrofitClient {
internal fun <T> getService(context: Context, clazz: Class<T>,
httpUrl: HttpUrl): T {
internal fun <T> getService(context: Context, baseUrl: String, clazz: Class<T>): T {
return Retrofit.Builder()
.baseUrl(httpUrl)
.baseUrl(baseUrl.toHttpUrl())
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
.client(getDefaultOKHttpClient(context, BuildConfig.BASE_URL, BuildConfig.CERTIFICATE_SHA256))
.client(getDefaultOKHttpClient(context, baseUrl, BuildConfig.CERTIFICATE_SHA256))
.build().create(clazz)
}
internal fun <T> getFileService(context: Context, clazz: Class<T>,
httpUrl: HttpUrl): T {
internal fun <T> getFileService(context: Context, baseUrl: String, clazz: Class<T>): T {
return Retrofit.Builder()
.baseUrl(httpUrl)
.client(getFileOKHttpClient(context, BuildConfig.BASE_URL, BuildConfig.CERTIFICATE_SHA256))
.baseUrl(baseUrl.toHttpUrl())
.client(getFileOKHttpClient(context, baseUrl, BuildConfig.CERTIFICATE_SHA256))
.build().create(clazz)
}
......
......@@ -32,7 +32,6 @@ import com.lunabeestudio.robert.datasource.RemoteServiceDataSource
import com.lunabeestudio.robert.model.BackendException
import com.lunabeestudio.robert.model.RobertResult
import com.lunabeestudio.robert.model.RobertResultData
import okhttp3.HttpUrl.Companion.toHttpUrl
import retrofit2.HttpException
import retrofit2.Response
import timber.log.Timber
......@@ -40,8 +39,8 @@ import java.io.File
class ServiceDataSource(context: Context, baseUrl: String = BuildConfig.BASE_URL) : RemoteServiceDataSource {
private var api: StopCovidApi = RetrofitClient.getService(context, StopCovidApi::class.java, baseUrl.toHttpUrl())
private var fileApi: StopCovidApi = RetrofitClient.getFileService(context, StopCovidApi::class.java, baseUrl.toHttpUrl())
private var api: StopCovidApi = RetrofitClient.getService(context, baseUrl, StopCovidApi::class.java)
private var fileApi: StopCovidApi = RetrofitClient.getFileService(context, baseUrl, StopCovidApi::class.java)
override suspend fun generateCaptcha(apiVersion: String, type: String, language: String): RobertResultData<String> {
val result = tryCatchRequestData {
......
......@@ -24,7 +24,7 @@ interface RobertManager {
val isProximityActive: Boolean
val isAtRisk: Boolean
val isAtRisk: Boolean?
val atRiskLastRefresh: Long?
......
......@@ -70,7 +70,10 @@ class RobertManagerImpl(
private val localProximityRepository: LocalProximityRepository =
LocalProximityRepository(localLocalProximityDataSource)
private val remoteServiceRepository: RemoteServiceRepository =
RemoteServiceRepository(serviceDataSource, sharedCryptoDataSource, localKeystoreDataSource, configurationDataSource)
RemoteServiceRepository(serviceDataSource,
sharedCryptoDataSource,
localKeystoreDataSource,
configurationDataSource)
init {
if (isRegistered) {
......@@ -90,8 +93,8 @@ class RobertManagerImpl(
override val isProximityActive: Boolean
get() = keystoreRepository.proximityActive ?: false
override val isAtRisk: Boolean
get() = keystoreRepository.atRisk ?: false
override val isAtRisk: Boolean?
get() = keystoreRepository.atRisk
override val atRiskLastRefresh: Long?
get() = keystoreRepository.atRiskLastRefresh
......
......@@ -22,8 +22,8 @@ import androidx.work.WorkerParameters
import com.lunabeestudio.robert.RobertApplication
import com.lunabeestudio.robert.RobertConstant
import com.lunabeestudio.robert.RobertManager
import com.lunabeestudio.robert.model.TimeNotAlignedException
import com.lunabeestudio.robert.model.RobertResult
import com.lunabeestudio.robert.model.TimeNotAlignedException
import timber.log.Timber
import java.util.concurrent.TimeUnit
import kotlin.random.Random
......@@ -35,10 +35,10 @@ internal class StatusWorker(context: Context, workerParams: WorkerParameters) :
val robertManager: RobertManager = robertApplication.robertManager
Timber.d("Start updating status")
val wasAtRisk = robertManager.isAtRisk
val wasAtRisk = robertManager.isAtRisk == true
val result = robertManager.updateStatus(robertApplication)
if (!wasAtRisk && robertManager.isAtRisk) {
if (!wasAtRisk && robertManager.isAtRisk == true) {
(applicationContext as RobertApplication).atRiskDetected()
}
......
......@@ -42,13 +42,13 @@ android {
applicationId "fr.gouv.android.stopcovid"
minSdkVersion 21
targetSdkVersion 29
versionCode 39
versionName "1.1.1"
versionCode 41
versionName "1.1.2"
testInstrumentationRunner = 'com.lunabeestudio.stopcovid.TestRunner'
buildConfigField 'String', 'CAPTCHA_API_KEY', STOPCOVID_CAPTCHA_API_KEY
buildConfigField 'String', 'CAPTCHA_URL', STOPCOVID_CAPTCHA_URL
buildConfigField 'String', 'CAPTCHA_API_KEY', '"6LettPsUAAAAAHYaFdRBOilHUgmTMSIPKNZN4D7l"'
buildConfigField 'String', 'CAPTCHA_URL', '"https://stopcovid.gouv.fr"'
buildConfigField 'String', 'APP_MAINTENANCE_CERTIFICATE_SHA256', '"sha256/sXQojvwsiyblrpMQIVRXGC5u7AgknzTJm+VIK1kQmD8="'
buildConfigField 'String', 'APP_MAINTENANCE_URL', '"https://app.stopcovid.gouv.fr/maintenance/info-maintenance-v2.json"'
}
......@@ -71,7 +71,7 @@ android {
dependencies {
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.work:work-runtime-ktx:2.3.4'
implementation('com.journeyapps:zxing-android-embedded:4.1.0') { transitive = false }
......
......@@ -100,5 +100,14 @@
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
</intent-filter>
</receiver>
<receiver
android:name=".receiver.UpgradeReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
</application>
</manifest>
......@@ -29,7 +29,6 @@ object Constants {
}
object ServerConstant {
val ACCEPTED_REPORT_CODE_LENGTH: List<Int> = listOf(6, 36)
val MAX_GAP_DEVICE_SERVER: Long = TimeUnit.MINUTES.toMillis(2L)
}
}
......@@ -41,11 +41,9 @@ import com.lunabeestudio.framework.sharedcrypto.BouncyCastleCryptoDataSource
import com.lunabeestudio.robert.RobertApplication
import com.lunabeestudio.robert.RobertManager
import com.lunabeestudio.robert.RobertManagerImpl
import com.lunabeestudio.stopcovid.BuildConfig.APP_MAINTENANCE_URL
import com.lunabeestudio.stopcovid.activity.MainActivity
import com.lunabeestudio.stopcovid.coreui.UiConstants
import com.lunabeestudio.stopcovid.coreui.manager.StringsManager
import com.lunabeestudio.stopcovid.extension.robertManager
import com.lunabeestudio.stopcovid.manager.AppMaintenanceManager
import com.lunabeestudio.stopcovid.manager.ConfigDataSource
import com.lunabeestudio.stopcovid.manager.PrivacyManager
......@@ -100,7 +98,7 @@ class StopCovid : Application(), LifecycleObserver, RobertApplication {
AppMaintenanceManager.init(this,
R.drawable.maintenance,
R.drawable.maintenance,
APP_MAINTENANCE_URL)
BuildConfig.APP_MAINTENANCE_URL)
val config = BundledEmojiCompatConfig(this)
EmojiCompat.init(config)
startAppMaintenanceWorker(false)
......@@ -130,8 +128,8 @@ class StopCovid : Application(), LifecycleObserver, RobertApplication {
}
override fun atRiskDetected() {
val minHour = robertManager().atRiskMinHourContactNotif
val maxHour = robertManager().atRiskMaxHourContactNotif
val minHour = robertManager.atRiskMinHourContactNotif
val maxHour = robertManager.atRiskMaxHourContactNotif
val currentCal = Calendar.getInstance()
val hours = currentCal.get(Calendar.HOUR_OF_DAY)
......@@ -265,7 +263,7 @@ class StopCovid : Application(), LifecycleObserver, RobertApplication {
.enqueueUniquePeriodicWork(Constants.WorkerNames.TIME_CHANGED, policy, timeChangedWorkRequest)
}
fun refreshStatusIfNeeded() {
private fun refreshStatusIfNeeded() {
if (System.currentTimeMillis() - (robertManager.atRiskLastRefresh
?: 0L) > TimeUnit.HOURS.toMillis(robertManager.checkStatusFrequencyHour.toLong())) {
CoroutineScope(Dispatchers.IO).launch {
......
......@@ -13,7 +13,6 @@ package com.lunabeestudio.stopcovid.activity
import android.os.Bundle
import android.view.Menu
import android.view.accessibility.AccessibilityEvent
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.children
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
......@@ -25,7 +24,6 @@ import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.setupActionBarWithNavController
import com.google.android.material.snackbar.Snackbar
import com.lunabeestudio.robert.RobertManager
import com.lunabeestudio.stopcovid.NavMainDirections
import com.lunabeestudio.stopcovid.R
import com.lunabeestudio.stopcovid.coreui.extension.applyAndConsumeWindowInsetBottom
import com.lunabeestudio.stopcovid.coreui.extension.hideBottomSheet
......@@ -33,6 +31,7 @@ import com.lunabeestudio.stopcovid.coreui.extension.showSnackBar
import com.lunabeestudio.stopcovid.coreui.manager.StringsManager
import com.lunabeestudio.stopcovid.databinding.ActivityMainBinding
import com.lunabeestudio.stopcovid.extension.robertManager
import com.lunabeestudio.stopcovid.extension.safeNavigate
import com.lunabeestudio.stopcovid.fragment.IsSickFragmentDirections
class MainActivity : BaseActivity() {
......@@ -97,7 +96,7 @@ class MainActivity : BaseActivity() {
}
if (robertManager.isSick) {
navController.navigate(IsSickFragmentDirections.actionGlobalIsSickFragment())
navController.safeNavigate(IsSickFragmentDirections.actionGlobalIsSickFragment())
}
}
......
......@@ -15,7 +15,6 @@ import android.os.Bundle
import android.view.accessibility.AccessibilityEvent
import android.view.animation.DecelerateInterpolator
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
import androidx.navigation.NavController
......@@ -26,10 +25,10 @@ import com.lunabeestudio.stopcovid.R
import com.lunabeestudio.stopcovid.coreui.extension.applyAndConsumeWindowInsetBottom
import com.lunabeestudio.stopcovid.databinding.ActivityOnBoardingBinding
import com.lunabeestudio.stopcovid.extension.isOnBoardingDone
import com.lunabeestudio.stopcovid.extension.safeNavigate
import com.lunabeestudio.stopcovid.fragment.OnBoardingWelcomeFragmentDirections
import com.lunabeestudio.stopcovid.viewmodel.OnBoardingViewModel
import com.lunabeestudio.stopcovid.viewmodel.OnBoardingViewModelFactory
import timber.log.Timber
class OnBoardingActivity : BaseActivity() {
......@@ -64,12 +63,8 @@ class OnBoardingActivity : BaseActivity() {
when {
sharedPreferences.isOnBoardingDone() -> {
try {
navController.navigate(OnBoardingWelcomeFragmentDirections.actionOnBoardingWelcomeFragmentToMainActivity())
finishAndRemoveTask()
} catch (e: IllegalArgumentException) {
Timber.e(e)
}
navController.safeNavigate(OnBoardingWelcomeFragmentDirections.actionOnBoardingWelcomeFragmentToMainActivity())
finishAndRemoveTask()
}
savedInstanceState == null -> {
replaceSplashScreenLogo()
......
......@@ -11,7 +11,16 @@
package com.lunabeestudio.stopcovid.extension
import android.content.Context
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.lunabeestudio.robert.RobertApplication
import com.lunabeestudio.robert.RobertManager
fun Context.robertManager(): RobertManager = (applicationContext as RobertApplication).robertManager
\ No newline at end of file
fun Context.robertManager(): RobertManager = (applicationContext as RobertApplication).robertManager
fun Context.showInvalidCodeAlert(strings: Map<String, String>) {
MaterialAlertDialogBuilder(this)
.setTitle(strings["enterCodeController.alert.invalidCode.title"])
.setMessage(strings["enterCodeController.alert.invalidCode.message"])
.setPositiveButton(strings["common.ok"], null)
.show()
}
\ No newline at end of file
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Authors
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Created by Lunabee Studio / Date - 2020/15/07 - for the STOP-COVID project
*/
package com.lunabeestudio.stopcovid.extension
import android.os.Bundle
import androidx.annotation.IdRes
import androidx.navigation.NavController
import androidx.navigation.NavDirections
import androidx.navigation.NavOptions
fun NavController.safeNavigate(@IdRes resId: Int, args: Bundle?,
navOptions: NavOptions?) {
try {
navigate(resId, args, navOptions, null)
} catch (e: IllegalArgumentException) {
// back and button pressed quickly can trigger this exception.
}
}
fun NavController.safeNavigate(directions: NavDirections) {
try {
navigate(directions.actionId, directions.arguments)
} catch (e: IllegalArgumentException) {
// back and button pressed quickly can trigger this exception.
}
}
\ No newline at end of file
......@@ -16,6 +16,7 @@ import android.content.pm.ActivityInfo
import android.net.Uri
import android.widget.Toast
import timber.log.Timber
import java.util.regex.Pattern
fun String.openInChromeTab(context: Context) {
val intent = Intent(Intent.ACTION_VIEW)
......@@ -27,4 +28,8 @@ fun String.openInChromeTab(context: Context) {
Timber.e("No activity to open url")
Toast.makeText(context, "Unable to open url", Toast.LENGTH_SHORT).show()
}
}
fun String.isCodeValid(): Boolean {
return length == 6 || Pattern.matches("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}", this)
}
\ No newline at end of file
......@@ -11,8 +11,10 @@
package com.lunabeestudio.stopcovid.fastitem
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.lunabeestudio.stopcovid.R
import com.lunabeestudio.stopcovid.coreui.extension.safeEmojiSpanify
......@@ -33,6 +35,7 @@ class ContactItem : BaseItem<ContactItem.ViewHolder>(
holder.titleTextView.text = title.safeEmojiSpanify()
holder.captionTextView.text = caption.safeEmojiSpanify()
holder.moreTextView.text = more.safeEmojiSpanify()
holder.moreImageView.isVisible = false
holder.moreConstraintLayout.setOnClickListener(moreClickListener)
}
......@@ -42,6 +45,7 @@ class ContactItem : BaseItem<ContactItem.ViewHolder>(
val captionTextView: TextView = v.findViewById(R.id.captionTextView)
val moreConstraintLayout: ConstraintLayout = v.findViewById(R.id.linkLayout)
val moreTextView: TextView = v.findViewById(R.id.textView)
val moreImageView: ImageView = v.findViewById(R.id.leftIconImageView)
}
}
......
......@@ -18,6 +18,7 @@ import android.view.View
import androidx.navigation.fragment.findNavController
import androidx.navigation.navOptions
import com.lunabeestudio.stopcovid.R
import com.lunabeestudio.stopcovid.extension.safeNavigate
abstract class AboutMainFragment : MainFragment() {
......@@ -34,7 +35,7 @@ abstract class AboutMainFragment : MainFragment() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (item.itemId == R.id.item_text) {
findNavController().navigate(R.id.nav_about, null, navOptions {
findNavController().safeNavigate(R.id.nav_about, null, navOptions {
anim {
enter = R.anim.nav_default_enter_anim
popEnter = R.anim.nav_default_pop_enter_anim
......
......@@ -34,7 +34,6 @@ import com.lunabeestudio.stopcovid.fastitem.audioItem
import com.lunabeestudio.stopcovid.fastitem.editTextItem
import com.lunabeestudio.stopcovid.fastitem.imageItem
import com.lunabeestudio.stopcovid.fastitem.linkItem
import com.lunabeestudio.stopcovid.model.BackendException
import com.lunabeestudio.stopcovid.model.UnauthorizedException
import com.lunabeestudio.stopcovid.viewmodel.CaptchaViewModel
import com.lunabeestudio.stopcovid.viewmodel.CaptchaViewModelFactory
......@@ -80,7 +79,7 @@ class CaptchaFragment : MainFragment() {
findNavController().navigateUp()
}
viewModel.covidException.observe(viewLifecycleOwner) { error ->
if ((error is BackendException || error is UnauthorizedException) && viewModel.code.isNotBlank()) {
if (error is UnauthorizedException && viewModel.code.isNotBlank()) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(strings["captchaController.alert.invalidCode.title"])
.setMessage(strings["captchaController.alert.invalidCode.message"])
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment