diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/ads/build.gradle b/ads/build.gradle
index e279d01..ff843f9 100644
--- a/ads/build.gradle
+++ b/ads/build.gradle
@@ -1,14 +1,18 @@
apply plugin: 'com.android.dynamic-feature'
apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
android {
- compileSdkVersion 29
-
+ buildFeatures {
+ viewBinding true
+ dataBinding true
+ }
+
+ compileSdkVersion 30
defaultConfig {
- minSdkVersion 17
- targetSdkVersion 29
+ minSdkVersion 16
+ targetSdkVersion 30
versionCode 1
versionName "1.0"
}
@@ -37,7 +41,7 @@ dependencies {
implementation project(':app')
// https://firebase.google.com/docs/admob/android/quick-start#import_the_mobile_ads_sdk
- implementation 'com.google.firebase:firebase-ads:19.2.0'
+ implementation 'com.google.firebase:firebase-ads:19.6.0'
}
repositories {
mavenCentral()
diff --git a/app/build.gradle b/app/build.gradle
index 3db0149..53a82a8 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,7 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
-apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.mikepenz.aboutlibraries.plugin'
apply plugin: 'com.google.firebase.firebase-perf'
apply plugin: 'com.google.firebase.crashlytics'
@@ -32,16 +31,19 @@ def gitCommitHash = { ->
}
android {
- buildFeatures.viewBinding = true
- compileSdkVersion 29
+ buildFeatures {
+ viewBinding true
+ dataBinding true
+ }
+ compileSdkVersion 30
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.javinator9889.handwashingreminder"
- minSdkVersion 17
- targetSdkVersion 29
- versionCode 137
- versionName "1.2.0-${gitCommitHash}"
+ minSdkVersion 16
+ targetSdkVersion 30
+ versionCode 142
+ versionName "1.2.1-${gitCommitHash}"
multiDexEnabled true
resConfigs "en", "es"
vectorDrawables.useSupportLibrary = true
@@ -111,20 +113,22 @@ dependencies {
def room_version = "2.2.5"
implementation fileTree(dir: 'libs', include: ['*.jar'])
api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
- api 'androidx.appcompat:appcompat:1.1.0'
- api 'androidx.core:core-ktx:1.3.0'
+ api 'androidx.appcompat:appcompat:1.2.0'
+ api 'androidx.core:core-ktx:1.3.2'
api 'androidx.legacy:legacy-support-v4:1.0.0'
- api 'androidx.constraintlayout:constraintlayout:1.1.3'
- testImplementation 'junit:junit:4.13'
- androidTestImplementation 'androidx.test.ext:junit:1.1.1'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+ api 'androidx.constraintlayout:constraintlayout:2.0.4'
+ testImplementation 'junit:junit:4.13.1'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+ // https://stackoverflow.com/questions/64247956/why-does-im-getting-service-not-registered-exception-even-though-i-not-used
+ api 'com.google.android.gms:play-services-basement:17.5.0'
// https://github.com/Javinator9889/LocaleManager
api 'com.github.javinator9889:localemanager:1.1X'
// https://material.io/develop/android/docs/getting-started/
- api 'com.google.android.material:material:1.1.0'
+ api 'com.google.android.material:material:1.2.1'
// https://developers.google.com/android/guides/setup
- implementation 'com.google.android.gms:play-services-location:17.0.0'
+ implementation 'com.google.android.gms:play-services-location:17.1.0'
// https://developer.android.com/jetpack/androidx/releases/annotation
api 'androidx.annotation:annotation:1.1.0'
// https://developer.android.com/jetpack/androidx/releases/cardview
@@ -134,32 +138,32 @@ dependencies {
// https://developer.android.com/studio/build/multidex
api 'androidx.multidex:multidex:2.0.1'
// https://github.com/mikepenz/Android-Iconics
- api 'com.mikepenz:iconics-core:5.0.3'
- api 'com.mikepenz:iconics-views:5.0.3'
+ api 'com.mikepenz:iconics-core:5.2.1'
+ api 'com.mikepenz:iconics-views:5.2.1'
//noinspection GradleDependency
- api 'com.mikepenz:google-material-typeface:3.0.1.4.original-kotlin@aar'
- api 'com.mikepenz:ionicons-typeface:2.0.1.5-kotlin@aar'
+ api 'com.mikepenz:google-material-typeface:3.0.1.6.original-kotlin@aar'
+ api 'com.mikepenz:ionicons-typeface:2.0.1.7-kotlin@aar'
// https://github.com/mikepenz/AboutLibraries
implementation "com.mikepenz:aboutlibraries-core:$latestAboutLibsRelease"
implementation "com.mikepenz:aboutlibraries:$latestAboutLibsRelease"
// https://developer.android.com/kotlin/ktx#play-core
- api 'com.google.android.play:core:1.7.3'
- api 'com.google.android.play:core-ktx:1.7.0'
+ api 'com.google.android.play:core:1.9.0'
+ api 'com.google.android.play:core-ktx:1.8.1'
// https://developer.android.com/kotlin/ktx#collection
implementation 'androidx.collection:collection-ktx:1.1.0'
// https://kotlinlang.org/docs/reference/reflection.html
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
// https://firebase.google.com/docs/android/setup#add-sdks
- api 'com.google.firebase:firebase-common-ktx:19.3.0'
- api 'com.google.firebase:firebase-analytics:17.4.3'
- api 'com.google.firebase:firebase-crashlytics:17.1.0'
- api 'com.google.firebase:firebase-perf:19.0.7'
- implementation 'com.google.firebase:firebase-auth:19.3.1'
+ api 'com.google.firebase:firebase-common-ktx:19.4.0'
+ api 'com.google.firebase:firebase-analytics:18.0.0'
+ api 'com.google.firebase:firebase-crashlytics:17.3.0'
+ api 'com.google.firebase:firebase-perf:19.0.10'
+ implementation 'com.google.firebase:firebase-auth:20.0.1'
// http://airbnb.io/lottie/#/android?id=getting-started
- api 'com.airbnb.android:lottie:3.4.1'
+ api 'com.airbnb.android:lottie:3.5.0'
// https://firebase.google.com/docs/remote-config/use-config-android
- implementation 'com.google.firebase:firebase-config:19.1.4'
- implementation 'com.google.firebase:firebase-config-ktx:19.1.4'
+ implementation 'com.google.firebase:firebase-config:20.0.2'
+ implementation 'com.google.firebase:firebase-config-ktx:20.0.2'
// https://mvnrepository.com/artifact/androidx.emoji/emoji/
api 'androidx.emoji:emoji:1.1.0'
api 'androidx.emoji:emoji-appcompat:1.1.0'
@@ -184,16 +188,16 @@ dependencies {
// https://github.com/afollestad/material-dialogs/
implementation 'com.afollestad.material-dialogs:core:3.3.0'
// https://developer.android.com/google/play/billing/billing_library_overview
- implementation 'com.android.billingclient:billing:3.0.0'
- implementation 'com.android.billingclient:billing-ktx:3.0.0'
+ implementation 'com.android.billingclient:billing:3.0.2'
+ implementation 'com.android.billingclient:billing-ktx:3.0.2'
// https://github.com/cbeust/klaxon
- implementation 'com.beust:klaxon:5.2'
+ implementation 'com.beust:klaxon:5.4'
// https://github.com/SufficientlySecure/html-textview
- implementation 'org.sufficientlysecure:html-textview:3.9'
+ implementation 'org.sufficientlysecure:html-textview:4.0'
// https://github.com/square/okhttp/tree/okhttp_3.12.x
- implementation 'com.squareup.okhttp3:okhttp:3.12.11'
+ implementation 'com.squareup.okhttp3:okhttp:3.12.12'
// https://square.github.io/okio/#releases
- implementation 'com.squareup.okio:okio:2.6.0'
+ implementation 'com.squareup.okio:okio:2.9.0'
// https://github.com/deano2390/MaterialShowcaseView
implementation 'com.github.deano2390:MaterialShowcaseView:1.3.4'
// https://github.com/PhilJay/MPAndroidChart
@@ -202,6 +206,8 @@ dependencies {
implementation "androidx.room:room-ktx:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// https://coil-kt.github.io/coil/
- api "io.coil-kt:coil:0.11.0"
+ api "io.coil-kt:coil:1.1.0"
+ // https://developer.android.com/jetpack/androidx/releases/work#declaring_dependencies
+ implementation "androidx.work:work-runtime-ktx:2.4.0"
}
apply plugin: 'com.google.gms.google-services'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7558e6a..1cb8f50 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,9 +73,12 @@
+ android:enabled="true"
+ android:exported="true">
+
+
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/DynamicFeatureProgress.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/DynamicFeatureProgress.kt
index 0d5c794..dc32993 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/DynamicFeatureProgress.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/DynamicFeatureProgress.kt
@@ -36,14 +36,12 @@ import com.google.firebase.analytics.FirebaseAnalytics
import com.javinator9889.handwashingreminder.BuildConfig
import com.javinator9889.handwashingreminder.R
import com.javinator9889.handwashingreminder.activities.base.SplitCompatBaseActivity
-import com.javinator9889.handwashingreminder.utils.AndroidVersion
-import com.javinator9889.handwashingreminder.utils.CONFIRMATION_REQUEST_CODE
-import com.javinator9889.handwashingreminder.utils.filterNotEmpty
-import com.javinator9889.handwashingreminder.utils.isAtLeast
-import kotlinx.android.synthetic.main.dynamic_content_pb.*
+import com.javinator9889.handwashingreminder.databinding.DynamicContentPbBinding
+import com.javinator9889.handwashingreminder.utils.*
import timber.log.Timber
-class DynamicFeatureProgress : SplitCompatBaseActivity(),
+class DynamicFeatureProgress :
+ SplitCompatBaseActivity(),
SplitInstallStateUpdatedListener {
companion object {
const val MODULES = "modules"
@@ -60,10 +58,12 @@ class DynamicFeatureProgress : SplitCompatBaseActivity(),
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ val layout = inflateLayout()
splitInstallManager.registerListener(this)
with(FirebaseAnalytics.getInstance(this)) {
setCurrentScreen(
- this@DynamicFeatureProgress, "Dynamic module", null
+ "Dynamic module",
+ this@DynamicFeatureProgress::class
)
}
modules =
@@ -85,7 +85,7 @@ class DynamicFeatureProgress : SplitCompatBaseActivity(),
}
}
if (moduleCount > 0 && modules.isNotEmpty()) {
- setContentView(R.layout.dynamic_content_pb)
+ setContentView(layout.root)
overridePendingTransition(android.R.anim.fade_in, 0)
val installRequest = installRequestBuilder.build()
splitInstallManager.startInstall(installRequest)
@@ -114,8 +114,8 @@ class DynamicFeatureProgress : SplitCompatBaseActivity(),
}
@SuppressLint("SetTextI18n")
- override fun onStateUpdate(state: SplitInstallSessionState?) {
- when (state?.status()) {
+ override fun onStateUpdate(state: SplitInstallSessionState) {
+ when (state.status()) {
SplitInstallSessionStatus.FAILED -> {
Toast.makeText(
this, getString(
@@ -140,36 +140,36 @@ class DynamicFeatureProgress : SplitCompatBaseActivity(),
finish()
}
SplitInstallSessionStatus.PENDING -> {
- install_progress.isIndeterminate = true
- percentage.text = getString(R.string.preparing)
+ binding.installProgress.isIndeterminate = true
+ binding.percentage.text = getString(R.string.preparing)
}
SplitInstallSessionStatus.DOWNLOADING -> {
val downloadedBytes =
Formatter.formatFileSize(this, state.bytesDownloaded)
val bytesToDownload =
Formatter.formatFileSize(this, state.totalBytesToDownload)
- bytesInfo.text = "$downloadedBytes / $bytesToDownload"
- install_progress.isIndeterminate = false
- install_progress.max = state.totalBytesToDownload.toInt()
+ binding.bytesInfo.text = "$downloadedBytes / $bytesToDownload"
+ binding.installProgress.isIndeterminate = false
+ binding.installProgress.max = state.totalBytesToDownload.toInt()
val progress = state.bytesDownloaded.toInt()
if (isAtLeast(AndroidVersion.N))
- install_progress.setProgress(progress, true)
+ binding.installProgress.setProgress(progress, true)
else
- install_progress.progress = progress
+ binding.installProgress.progress = progress
val currentPercentage =
(state.bytesDownloaded * 100 / state.totalBytesToDownload)
.toInt()
- percentage.text = "$currentPercentage %"
+ binding.percentage.text = "$currentPercentage %"
}
SplitInstallSessionStatus.INSTALLING -> {
- install_progress.isIndeterminate = true
- bytesInfo.text = ""
- percentage.text = getString(R.string.installing)
+ binding.installProgress.isIndeterminate = true
+ binding.bytesInfo.text = ""
+ binding.percentage.text = getString(R.string.installing)
}
SplitInstallSessionStatus.INSTALLED -> {
SplitInstallHelper.updateAppInfo(this)
if (++currentModule >= moduleCount) {
- dynamic_content_title.text = getString(R.string.done)
+ binding.dynamicContentTitle.text = getString(R.string.done)
setResultWithIntent(Activity.RESULT_OK)
finish()
}
@@ -189,4 +189,7 @@ class DynamicFeatureProgress : SplitCompatBaseActivity(),
finish()
}
}
+
+ override fun inflateLayout(): DynamicContentPbBinding =
+ DynamicContentPbBinding.inflate(layoutInflater).also { binding = it }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/LauncherActivity.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/LauncherActivity.kt
index 915bbb2..18ab4d5 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/LauncherActivity.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/LauncherActivity.kt
@@ -21,10 +21,9 @@ package com.javinator9889.handwashingreminder.activities
import android.app.Activity
import android.content.Context
import android.content.Intent
-import android.os.Bundle
import android.view.animation.Animation
import android.view.animation.AnimationUtils
-import androidx.appcompat.app.AppCompatActivity
+import androidx.annotation.LayoutRes
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.whenCreated
import androidx.lifecycle.whenStarted
@@ -40,8 +39,10 @@ import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings
import com.google.firebase.remoteconfig.ktx.remoteConfig
import com.javinator9889.handwashingreminder.BuildConfig
import com.javinator9889.handwashingreminder.R
+import com.javinator9889.handwashingreminder.activities.base.BaseFragmentActivity
import com.javinator9889.handwashingreminder.application.HandwashingApplication
import com.javinator9889.handwashingreminder.data.UserProperties
+import com.javinator9889.handwashingreminder.databinding.SplashScreenBinding
import com.javinator9889.handwashingreminder.gms.activity.ActivityHandler
import com.javinator9889.handwashingreminder.gms.ads.AdLoader
import com.javinator9889.handwashingreminder.gms.ads.AdsEnabler
@@ -55,7 +56,6 @@ import com.javinator9889.handwashingreminder.utils.RemoteConfig.SPECIAL_EVENT
import com.javinator9889.handwashingreminder.utils.threading.await
import com.mikepenz.iconics.Iconics
import javinator9889.localemanager.utils.languagesupport.LanguagesSupport.Language
-import kotlinx.android.synthetic.main.splash_screen.*
import kotlinx.coroutines.*
import timber.log.Timber
import com.javinator9889.handwashingreminder.utils.Firebase as FirebaseConf
@@ -63,7 +63,7 @@ import com.javinator9889.handwashingreminder.utils.Firebase as FirebaseConf
internal const val FAST_START_KEY = "intent:fast_start"
internal const val PENDING_INTENT_CODE = 201
-class LauncherActivity : AppCompatActivity() {
+class LauncherActivity : BaseFragmentActivity() {
private val deferreds = mutableSetOf>()
private var launchOnInstall = false
private var launchFromNotification = false
@@ -73,6 +73,9 @@ class LauncherActivity : AppCompatActivity() {
private val dynamicFeatureDeferred = CompletableDeferred()
private val activityIntentDeferred = CompletableDeferred()
private val splitInstallManager = SplitInstallManagerFactory.create(app)
+ private lateinit var binding: SplashScreenBinding
+ @get:LayoutRes
+ override val layoutId: Int = R.layout.splash_screen
init {
lifecycleScope.launch {
@@ -82,7 +85,7 @@ class LauncherActivity : AppCompatActivity() {
deferreds.add(async { initVariables() })
}
whenStarted {
- progressBar.show()
+ binding.progressBar.show()
val welcomeScreenJob = showWelcomeScreenAsync()
deferreds.add(installRequiredModulesAsync())
activityIntentDeferred.await().run {
@@ -90,7 +93,9 @@ class LauncherActivity : AppCompatActivity() {
if (launchFromNotification)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TASK
+ Timber.d("Joining welcome screen...")
welcomeScreenJob.join()
+ Timber.d("Start")
startActivity(this)
overridePendingTransition(0, android.R.anim.fade_out)
finish()
@@ -99,17 +104,17 @@ class LauncherActivity : AppCompatActivity() {
}
}
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.splash_screen)
- }
+ override fun inflateLayout(): SplashScreenBinding =
+ SplashScreenBinding.inflate(layoutInflater).also { binding = it }
private fun showWelcomeScreenAsync() =
lifecycleScope.launch(Dispatchers.Main) {
+ Timber.d("Awaiting Firebase initialization...")
app.firebaseInitDeferred.await()
val isThereAnySpecialEvent = with(Firebase.remoteConfig) {
getBoolean(SPECIAL_EVENT) && !launchFromNotification
}
+ Timber.d("Is any special event? $isThereAnySpecialEvent")
var sleepDuration = 0L
val animationLoaded = CompletableDeferred()
val fadeInAnimation = AnimationUtils.loadAnimation(
@@ -119,24 +124,29 @@ class LauncherActivity : AppCompatActivity() {
fadeInAnimation.duration = 300L
fadeInAnimation.setAnimationListener(object :
Animation.AnimationListener {
- override fun onAnimationStart(animation: Animation?) {}
+ override fun onAnimationStart(animation: Animation?) {
+ Timber.d("Animation started!")
+ }
override fun onAnimationRepeat(animation: Animation?) {}
override fun onAnimationEnd(animation: Animation?) {
+ Timber.d("Animation is completed")
animationLoaded.complete(true)
- logo.playAnimation()
+ binding.logo.playAnimation()
}
})
- if (isThereAnySpecialEvent) {
- logo.setAnimation(AnimatedResources.STAY_SAFE_STAY_HOME.res)
- logo.addLottieOnCompositionLoadedListener {
- logo.startAnimation(fadeInAnimation)
- sleepDuration = logo.duration
+ if (isThereAnySpecialEvent && !isDebuggable()) {
+ Timber.d("Starting custom animation...")
+ binding.logo.setAnimation(AnimatedResources.STAY_SAFE_STAY_HOME.res)
+ binding.logo.addLottieOnCompositionLoadedListener {
+ Timber.d("Animation loaded!")
+ binding.logo.startAnimation(fadeInAnimation)
+ sleepDuration = binding.logo.duration
}
animationLoaded.await()
delay(sleepDuration)
} else {
- logo.setImageResource(R.drawable.handwashing_app_logo)
- logo.startAnimation(fadeInAnimation)
+ binding.logo.setImageResource(R.drawable.handwashing_app_logo)
+ binding.logo.startAnimation(fadeInAnimation)
}
}
@@ -173,7 +183,7 @@ class LauncherActivity : AppCompatActivity() {
}
Timber.d("Created launch intent $launchIntent")
activityIntentDeferred.complete(launchIntent)
- }
+ } ?: Timber.e("Data was empty!")
} else {
Timber.d("Created launch intent at MainActivity")
activityIntentDeferred.complete(
@@ -185,7 +195,7 @@ class LauncherActivity : AppCompatActivity() {
override fun finish() {
Timber.d("Calling finish")
- progressBar.hide()
+ binding.progressBar.hide()
runBlocking(Dispatchers.Default) { deferreds.awaitAll() }
super.finish()
}
@@ -299,13 +309,13 @@ class LauncherActivity : AppCompatActivity() {
Timber.d("Adding periodic notifications if not enqueued yet")
Timber.d("Creating alarms notification channels...")
for (alarm in Alarms.values()) {
- Timber.d("Creating notification channel for ${alarm.identifier}")
+ Timber.d("Creating notification channel for ${alarm.groupId}")
NotificationsHandler(
context = this,
channelId = alarm.channelId,
- channelName = getString(R.string.time_notification_channel_name),
- channelDesc = getString(R.string.time_notification_channel_desc),
- groupId = alarm.identifier,
+ channelName = getString(alarm.channelName),
+ channelDesc = getString(alarm.channelDesc),
+ groupId = alarm.groupId,
groupName = getString(alarm.groupName)
)
}
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/MainActivity.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/MainActivity.kt
index d5f91ba..c959732 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/MainActivity.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/MainActivity.kt
@@ -37,9 +37,9 @@ import com.javinator9889.handwashingreminder.activities.views.fragments.news.New
import com.javinator9889.handwashingreminder.activities.views.fragments.washinghands.WashingHandsFragment
import com.javinator9889.handwashingreminder.custom.libraries.AppRate
import com.javinator9889.handwashingreminder.data.MainActivityDataHandler
+import com.javinator9889.handwashingreminder.databinding.ActivityMainBinding
import com.javinator9889.handwashingreminder.firebase.Auth
-import kotlinx.android.synthetic.main.activity_main.*
-import kotlinx.android.synthetic.main.how_to_wash_hands_layout.*
+import com.javinator9889.handwashingreminder.utils.setCurrentScreen
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -48,7 +48,7 @@ import timber.log.Timber
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseSequence
-class MainActivity : ActionBarBase(),
+class MainActivity : ActionBarBase(),
BottomNavigationView.OnNavigationItemSelectedListener,
BottomNavigationView.OnNavigationItemReselectedListener {
override val layoutId: Int = R.layout.activity_main
@@ -60,9 +60,14 @@ class MainActivity : ActionBarBase(),
lifecycleScope.launch {
whenCreated {
with(Firebase.remoteConfig) { fetchAndActivate() }
- launch { dataHandler.setMenuIcons(menu, this@MainActivity) }
- menu.setOnNavigationItemSelectedListener(this@MainActivity)
- menu.setOnNavigationItemReselectedListener(this@MainActivity)
+ launch {
+ dataHandler.setMenuIcons(
+ binding.menu,
+ this@MainActivity
+ )
+ }
+ binding.menu.setOnNavigationItemSelectedListener(this@MainActivity)
+ binding.menu.setOnNavigationItemReselectedListener(this@MainActivity)
deferredShowcase = dataHandler.loadShowcaseAsync(
activity = this@MainActivity,
lifecycleOwner = this@MainActivity
@@ -74,7 +79,7 @@ class MainActivity : ActionBarBase(),
}
whenResumed {
with(FirebaseAnalytics.getInstance(this@MainActivity)) {
- setCurrentScreen(this@MainActivity, "Main view", null)
+ setCurrentScreen("Main view", this@MainActivity::class)
}
deferredShowcase.await()?.let {
withContext(Dispatchers.Main) {
@@ -136,15 +141,15 @@ class MainActivity : ActionBarBase(),
R.id.handwashing -> {
val washingHandsFragment =
dataHandler.activeFragment as WashingHandsFragment
- if (washingHandsFragment.pager.currentItem != 0)
- washingHandsFragment.pager.currentItem--
+ if (washingHandsFragment.binding.pager.currentItem != 0)
+ washingHandsFragment.binding.pager.currentItem--
else {
- menu.selectedItemId = R.id.diseases
+ binding.menu.selectedItemId = R.id.diseases
onItemSelected(R.id.diseases)
}
}
else -> {
- menu.selectedItemId = R.id.diseases
+ binding.menu.selectedItemId = R.id.diseases
onItemSelected(R.id.diseases)
}
}
@@ -159,7 +164,7 @@ class MainActivity : ActionBarBase(),
else -> "Main view"
}
with(FirebaseAnalytics.getInstance(this)) {
- setCurrentScreen(this@MainActivity, screenTitle, null)
+ setCurrentScreen(screenTitle, this@MainActivity::class)
}
return onItemSelected(item.itemId)
}
@@ -201,4 +206,7 @@ class MainActivity : ActionBarBase(),
disallowAddToBackStack()
}
}
+
+ override fun inflateLayout(): ActivityMainBinding =
+ ActivityMainBinding.inflate(layoutInflater).also { binding = it }
}
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/PrivacyTermsActivity.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/PrivacyTermsActivity.kt
index 11dfdfa..59afb11 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/PrivacyTermsActivity.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/PrivacyTermsActivity.kt
@@ -26,9 +26,10 @@ import com.google.firebase.analytics.FirebaseAnalytics
import com.javinator9889.handwashingreminder.R
import com.javinator9889.handwashingreminder.activities.support.ActionBarBase
import com.javinator9889.handwashingreminder.collections.PrivacyTermsCollectionAdapter
-import kotlinx.android.synthetic.main.disease_view_expanded.*
+import com.javinator9889.handwashingreminder.databinding.PrivacyTermsBinding
-class PrivacyTermsActivity : ActionBarBase() {
+
+class PrivacyTermsActivity : ActionBarBase() {
override val layoutId: Int = R.layout.privacy_terms
override fun onCreate(savedInstanceState: Bundle?) {
@@ -44,8 +45,11 @@ class PrivacyTermsActivity : ActionBarBase() {
}
val adapter = PrivacyTermsCollectionAdapter(this)
- pager.adapter = adapter
- TabLayoutMediator(diseaseInfoTab, pager) { tab, position ->
+ binding.pager.adapter = adapter
+ TabLayoutMediator(
+ binding.diseaseInfoTab,
+ binding.pager
+ ) { tab, position ->
when (position) {
0 -> tab.text = getString(R.string.privacy_policy_title)
1 -> tab.text = getString(R.string.tos_title)
@@ -57,4 +61,7 @@ class PrivacyTermsActivity : ActionBarBase() {
super.onBackPressed()
finish()
}
+
+ override fun inflateLayout(): PrivacyTermsBinding =
+ PrivacyTermsBinding.inflate(layoutInflater).also { binding = it }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/BaseFragmentActivity.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/BaseFragmentActivity.kt
index e25613d..ed65c80 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/BaseFragmentActivity.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/BaseFragmentActivity.kt
@@ -20,14 +20,16 @@ package com.javinator9889.handwashingreminder.activities.base
import android.os.Bundle
import androidx.annotation.LayoutRes
+import androidx.viewbinding.ViewBinding
import javinator9889.localemanager.fragment.BaseFragmentActivity
-abstract class BaseFragmentActivity : BaseFragmentActivity() {
+abstract class BaseFragmentActivity : BaseFragmentActivity(), ViewBindingInflater {
@get:LayoutRes
protected abstract val layoutId: Int
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(layoutId)
+ val layout = inflateLayout()
+ setContentView(layout.root)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/BaseFragmentView.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/BaseFragmentView.kt
index 5a72d86..3afde57 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/BaseFragmentView.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/BaseFragmentView.kt
@@ -23,11 +23,13 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
+import androidx.viewbinding.ViewBinding
import javinator9889.localemanager.fragment.BaseFragment
-abstract class BaseFragmentView : BaseFragment() {
+abstract class BaseFragmentView : BaseFragment() {
@get:LayoutRes
protected abstract val layoutId: Int
+ internal lateinit var binding: T
override fun onCreateView(
inflater: LayoutInflater,
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/SplitCompatBaseActivity.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/SplitCompatBaseActivity.kt
index 90f8850..bde451f 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/SplitCompatBaseActivity.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/SplitCompatBaseActivity.kt
@@ -20,13 +20,16 @@ package com.javinator9889.handwashingreminder.activities.base
import android.content.Context
import android.os.Bundle
+import androidx.viewbinding.ViewBinding
import com.google.android.play.core.splitcompat.SplitCompat
import com.google.android.play.core.splitinstall.SplitInstallManager
import com.google.android.play.core.splitinstall.SplitInstallManagerFactory
import javinator9889.localemanager.activity.BaseAppCompatActivity
-abstract class SplitCompatBaseActivity : BaseAppCompatActivity() {
+abstract class SplitCompatBaseActivity :
+ BaseAppCompatActivity(), ViewBindingInflater {
protected lateinit var splitInstallManager: SplitInstallManager
+ protected lateinit var binding: T
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/BaseVisibleFragmentView.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/ViewBindingInflater.kt
similarity index 81%
rename from app/src/main/java/com/javinator9889/handwashingreminder/activities/base/BaseVisibleFragmentView.kt
rename to app/src/main/java/com/javinator9889/handwashingreminder/activities/base/ViewBindingInflater.kt
index 113bf33..9881f57 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/BaseVisibleFragmentView.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/base/ViewBindingInflater.kt
@@ -14,10 +14,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*
- * Created by Javinator9889 on 11/06/20 - Handwashing reminder.
+ * Created by Javinator9889 on 7/12/20 - Handwashing reminder.
*/
package com.javinator9889.handwashingreminder.activities.base
-abstract class BaseVisibleFragmentView : BaseFragmentView() {
- abstract fun onVisibilityChanged(visibility: Int)
+import androidx.viewbinding.ViewBinding
+
+interface ViewBindingInflater {
+ fun inflateLayout(): T
}
\ No newline at end of file
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/support/ActionBarBase.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/support/ActionBarBase.kt
index 20e34f4..35b7b63 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/support/ActionBarBase.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/support/ActionBarBase.kt
@@ -20,16 +20,21 @@ package com.javinator9889.handwashingreminder.activities.support
import android.os.Bundle
import androidx.annotation.LayoutRes
+import androidx.viewbinding.ViewBinding
import com.javinator9889.handwashingreminder.R
+import com.javinator9889.handwashingreminder.activities.base.ViewBindingInflater
import javinator9889.localemanager.activity.BaseAppCompatActivity
-abstract class ActionBarBase : BaseAppCompatActivity() {
+abstract class ActionBarBase : BaseAppCompatActivity(),
+ ViewBindingInflater {
@get:LayoutRes
protected abstract val layoutId: Int
+ protected lateinit var binding: T
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(layoutId)
+ val layout = inflateLayout()
+ setContentView(layout.root)
setSupportActionBar(findViewById(R.id.toolbar))
}
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseDescriptionFragment.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseDescriptionFragment.kt
index 7630a49..c82cd00 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseDescriptionFragment.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseDescriptionFragment.kt
@@ -19,11 +19,14 @@
package com.javinator9889.handwashingreminder.activities.views.fragments.diseases
import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
import androidx.annotation.LayoutRes
import com.javinator9889.handwashingreminder.R
import com.javinator9889.handwashingreminder.activities.base.BaseFragmentView
import com.javinator9889.handwashingreminder.data.ParsedHTMLText
-import kotlinx.android.synthetic.main.disease_description.*
+import com.javinator9889.handwashingreminder.databinding.DiseaseDescriptionBinding
import kotlin.properties.Delegates
internal const val ARG_TITLE = "bundle:title"
@@ -34,7 +37,7 @@ internal const val ARG_WEBSITE = "bundle:website"
internal const val ARG_ANIMATION_ID = "bundle:animation:id"
internal const val ARG_HTML_TEXT = "bundle:text:html"
-class DiseaseDescriptionFragment : BaseFragmentView() {
+class DiseaseDescriptionFragment : BaseFragmentView() {
@get:LayoutRes
override val layoutId: Int = R.layout.disease_description
private lateinit var parsedHTMLText: ParsedHTMLText
@@ -45,13 +48,23 @@ class DiseaseDescriptionFragment : BaseFragmentView() {
retainInstance = true
}
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ val view = super.onCreateView(inflater, container, savedInstanceState)
+ binding = DiseaseDescriptionBinding.bind(view)
+ return view
+ }
+
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
- outState.putCharSequence(ARG_TITLE, title.text)
- outState.putCharSequence(ARG_SDESC, shortDescription.text)
- outState.putCharSequence(ARG_LDESC, longDescription.text)
- outState.putCharSequence(ARG_PROVIDER, provider.text)
- outState.putCharSequence(ARG_WEBSITE, website.text)
+ outState.putCharSequence(ARG_TITLE, binding.title.text)
+ outState.putCharSequence(ARG_SDESC, binding.shortDescription.text)
+ outState.putCharSequence(ARG_LDESC, binding.longDescription.text)
+ outState.putCharSequence(ARG_PROVIDER, binding.provider.text)
+ outState.putCharSequence(ARG_WEBSITE, binding.website.text)
outState.putParcelable(ARG_HTML_TEXT, parsedHTMLText)
outState.putInt(ARG_ANIMATION_ID, animId)
}
@@ -62,15 +75,15 @@ class DiseaseDescriptionFragment : BaseFragmentView() {
val data = (savedInstanceState ?: arguments)!!
parsedHTMLText = data.getParcelable(ARG_HTML_TEXT)!!
animId = data.getInt(ARG_ANIMATION_ID)
- animatedView.setAnimation(animId)
- title.text = data.getCharSequence(ARG_TITLE) ?: parsedHTMLText.name
- shortDescription.text = data.getCharSequence(ARG_SDESC)
+ binding.animatedView.setAnimation(animId)
+ binding.title.text = data.getCharSequence(ARG_TITLE) ?: parsedHTMLText.name
+ binding.shortDescription.text = data.getCharSequence(ARG_SDESC)
?: parsedHTMLText.shortDescription
- longDescription.text = data.getCharSequence(ARG_LDESC)
+ binding.longDescription.text = data.getCharSequence(ARG_LDESC)
?: parsedHTMLText.longDescription
- provider.text = data.getCharSequence(ARG_PROVIDER)
+ binding.provider.text = data.getCharSequence(ARG_PROVIDER)
?: getString(R.string.written_by, parsedHTMLText.provider)
- website.text = data.getCharSequence(ARG_WEBSITE)
+ binding.website.text = data.getCharSequence(ARG_WEBSITE)
?: getString(R.string.available_at, parsedHTMLText.website)
}
}
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseExpandedView.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseExpandedView.kt
index 026a918..f1548ef 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseExpandedView.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseExpandedView.kt
@@ -25,20 +25,20 @@ import com.javinator9889.handwashingreminder.R
import com.javinator9889.handwashingreminder.activities.support.ActionBarBase
import com.javinator9889.handwashingreminder.collections.DiseaseTextAdapter
import com.javinator9889.handwashingreminder.data.ParsedHTMLText
-import kotlinx.android.synthetic.main.disease_view_expanded.*
+import com.javinator9889.handwashingreminder.databinding.DiseaseViewExpandedBinding
import kotlin.properties.Delegates
internal const val ARG_ANIMATION = "card:animation"
internal const val ARG_PARSED_TEXT = "text:HTML:parsed"
-class DiseaseExpandedView : ActionBarBase() {
+class DiseaseExpandedView : ActionBarBase() {
override val layoutId: Int = R.layout.disease_view_expanded
private var animId by Delegates.notNull()
private var parsedHTMLText: ParsedHTMLText? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- toolbar.setTitleTextColor(Color.BLACK)
+ binding.toolbar.setTitleTextColor(Color.BLACK)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowTitleEnabled(true)
@@ -48,8 +48,11 @@ class DiseaseExpandedView : ActionBarBase() {
parsedHTMLText = data.getParcelable(ARG_PARSED_TEXT)
if (parsedHTMLText != null) {
val adapter = DiseaseTextAdapter(this, animId, parsedHTMLText!!)
- pager.adapter = adapter
- TabLayoutMediator(diseaseInfoTab, pager) { tab, position ->
+ binding.pager.adapter = adapter
+ TabLayoutMediator(
+ binding.diseaseInfoTab,
+ binding.pager
+ ) { tab, position ->
when (position) {
0 -> tab.text = getText(R.string.description)
1 -> tab.text = getText(R.string.symptoms)
@@ -70,4 +73,7 @@ class DiseaseExpandedView : ActionBarBase() {
super.onBackPressed()
finish()
}
+
+ override fun inflateLayout(): DiseaseViewExpandedBinding =
+ DiseaseViewExpandedBinding.inflate(layoutInflater).also { binding = it }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseExtraInformationFragment.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseExtraInformationFragment.kt
index f42e9e7..e1d0996 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseExtraInformationFragment.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseaseExtraInformationFragment.kt
@@ -19,18 +19,21 @@
package com.javinator9889.handwashingreminder.activities.views.fragments.diseases
import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
import androidx.annotation.LayoutRes
import com.javinator9889.handwashingreminder.R
import com.javinator9889.handwashingreminder.activities.base.BaseFragmentView
import com.javinator9889.handwashingreminder.data.ParsedHTMLText
-import kotlinx.android.synthetic.main.simple_text_view.*
+import com.javinator9889.handwashingreminder.databinding.SimpleTextViewBinding
import kotlin.properties.Delegates
internal const val ARG_SYMPTOMS = "bundle:symptoms"
internal const val ARG_PREVENTION = "bundle:prevention"
internal const val ARG_POSITION = "bundle:item:position"
-class DiseaseExtraInformationFragment : BaseFragmentView() {
+class DiseaseExtraInformationFragment : BaseFragmentView() {
@get:LayoutRes
override val layoutId: Int = R.layout.simple_text_view
private var position by Delegates.notNull()
@@ -41,12 +44,22 @@ class DiseaseExtraInformationFragment : BaseFragmentView() {
retainInstance = true
}
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ val view = super.onCreateView(inflater, container, savedInstanceState)
+ binding = SimpleTextViewBinding.bind(view)
+ return view
+ }
+
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
if (position == 1)
- outState.putCharSequence(ARG_SYMPTOMS, text.text)
+ outState.putCharSequence(ARG_SYMPTOMS, binding.text.text)
else if (position == 2)
- outState.putCharSequence(ARG_PREVENTION, text.text)
+ outState.putCharSequence(ARG_PREVENTION, binding.text.text)
outState.putInt(ARG_POSITION, position)
outState.putParcelable(ARG_HTML_TEXT, parsedHTMLText)
}
@@ -57,7 +70,7 @@ class DiseaseExtraInformationFragment : BaseFragmentView() {
val data = (savedInstanceState ?: arguments)!!
position = data.getInt(ARG_POSITION)
parsedHTMLText = data.getParcelable(ARG_HTML_TEXT)!!
- text.text = when (position) {
+ binding.text.text = when (position) {
1 -> data.getCharSequence(ARG_SYMPTOMS)
?: parsedHTMLText.symptoms
2 -> data.getCharSequence(ARG_PREVENTION)
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseasesFragment.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseasesFragment.kt
index b15d819..48d1726 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseasesFragment.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/diseases/DiseasesFragment.kt
@@ -20,7 +20,9 @@ package com.javinator9889.handwashingreminder.activities.views.fragments.disease
import android.content.Intent
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
+import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.annotation.StringRes
import androidx.core.app.ActivityCompat
@@ -48,6 +50,9 @@ import com.javinator9889.handwashingreminder.activities.views.viewmodels.SavedVi
import com.javinator9889.handwashingreminder.data.ParsedHTMLText
import com.javinator9889.handwashingreminder.data.room.entities.Handwashing
import com.javinator9889.handwashingreminder.data.viewmodels.HandwashingViewModel
+import com.javinator9889.handwashingreminder.databinding.HandwashCountBinding
+import com.javinator9889.handwashingreminder.databinding.LoadingRecyclerViewBinding
+import com.javinator9889.handwashingreminder.databinding.MainDiseaseViewBinding
import com.javinator9889.handwashingreminder.emoji.EmojiLoader
import com.javinator9889.handwashingreminder.utils.calendar.CalendarUtils
import com.javinator9889.handwashingreminder.utils.toBarEntry
@@ -55,17 +60,13 @@ import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.GenericItem
import com.mikepenz.fastadapter.adapters.ItemAdapter
import com.mikepenz.fastadapter.listeners.ClickEventHook
-import kotlinx.android.synthetic.main.handwash_count.*
-import kotlinx.android.synthetic.main.handwash_count.view.*
-import kotlinx.android.synthetic.main.loading_recycler_view.*
-import kotlinx.android.synthetic.main.loading_recycler_view.view.*
-import kotlinx.android.synthetic.main.main_disease_view.view.*
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.launch
import timber.log.Timber
-class DiseasesFragment : BaseFragmentView(), LayoutVisibilityChange,
+class DiseasesFragment : BaseFragmentView(),
+ LayoutVisibilityChange,
View.OnClickListener {
override val layoutId: Int = R.layout.main_disease_view
@@ -73,6 +74,8 @@ class DiseasesFragment : BaseFragmentView(), LayoutVisibilityChange,
private lateinit var fastAdapter: FastAdapter
private lateinit var emojiLoader: Deferred
private lateinit var behavior: BottomSheetBehavior
+ private lateinit var handwashBinding: HandwashCountBinding
+ private lateinit var loadingRecyclerViewBinding: LoadingRecyclerViewBinding
private val upperAdsAdapter: ItemAdapter = ItemAdapter()
private val lowerAdsAdapter: ItemAdapter = ItemAdapter()
private val diseasesAdapter: ItemAdapter = ItemAdapter()
@@ -84,8 +87,8 @@ class DiseasesFragment : BaseFragmentView(), LayoutVisibilityChange,
init {
lifecycleScope.launchWhenStarted {
- loading.visibility = View.VISIBLE
- countLoader.visibility = View.VISIBLE
+ loadingRecyclerViewBinding.loading.visibility = View.VISIBLE
+ handwashBinding.countLoader.visibility = View.VISIBLE
informationViewModel.parsedHTMLText.observe(viewLifecycleOwner) {
if (it.isEmpty())
return@observe
@@ -103,8 +106,8 @@ class DiseasesFragment : BaseFragmentView(), LayoutVisibilityChange,
if (diseasesAdapter.getAdapterPosition(disease) == -1)
diseasesAdapter.add(disease)
}
- loading.visibility = View.INVISIBLE
- container.visibility = View.VISIBLE
+ loadingRecyclerViewBinding.loading.visibility = View.INVISIBLE
+ loadingRecyclerViewBinding.container.visibility = View.VISIBLE
}
}
handwashingViewModel.allData.observe(viewLifecycleOwner) {
@@ -119,12 +122,12 @@ class DiseasesFragment : BaseFragmentView(), LayoutVisibilityChange,
valueFormatter = IntFormatter()
dataSet = this
}
- countChart.data = BarData(dataSet)
- countChart.notifyDataSetChanged()
- countChart.fitScreen()
- countChart.moveViewToX(0F)
- countChart.setVisibleXRangeMaximum(7F)
- countChart.invalidate()
+ handwashBinding.countChart.data = BarData(dataSet)
+ handwashBinding.countChart.notifyDataSetChanged()
+ handwashBinding.countChart.fitScreen()
+ handwashBinding.countChart.moveViewToX(0F)
+ handwashBinding.countChart.setVisibleXRangeMaximum(7F)
+ handwashBinding.countChart.invalidate()
val todayAmount =
handwashingViewModel.getAsync(CalendarUtils.today.time)
val weeklyAmount =
@@ -132,27 +135,39 @@ class DiseasesFragment : BaseFragmentView(), LayoutVisibilityChange,
val monthlyAmount =
handwashingViewModel.getMonthlyCountAsync()
setCountText(
- countDailyTextView,
+ handwashBinding.countDailyTextView,
R.string.today_washed,
todayAmount.await()?.amount ?: 0
)
setCountText(
- countWeeklyTextView,
+ handwashBinding.countWeeklyTextView,
R.string.week_washed,
weeklyAmount.await()
)
setCountText(
- countMonthlyTextView,
+ handwashBinding.countMonthlyTextView,
R.string.month_washed,
monthlyAmount.await()
)
- countLoader.visibility = View.INVISIBLE
- scrollView.visibility = View.VISIBLE
+ handwashBinding.countLoader.visibility = View.INVISIBLE
+ handwashBinding.scrollView.visibility = View.VISIBLE
}
}
}
}
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ val view = super.onCreateView(inflater, container, savedInstanceState)
+ binding = MainDiseaseViewBinding.bind(view)
+ handwashBinding = binding.handwashingCount
+ loadingRecyclerViewBinding = binding.lrv
+ return view
+ }
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
onViewCreatedAsync(view, savedInstanceState)
@@ -171,7 +186,7 @@ class DiseasesFragment : BaseFragmentView(), LayoutVisibilityChange,
}
}
try {
- container.adapter = null
+ loadingRecyclerViewBinding.container.adapter = null
diseasesAdapter.clear()
} catch (e: Exception) {
Timber.w(e, "Exception when calling 'onBackPressed'")
@@ -184,7 +199,7 @@ class DiseasesFragment : BaseFragmentView(), LayoutVisibilityChange,
override fun onClick(v: View?) {
when (v) {
- countUpButton -> lifecycleScope.launch {
+ handwashBinding.countUpButton -> lifecycleScope.launch {
val createdItem =
handwashingViewModel.getAsync(CalendarUtils.today.time)
.await()
@@ -196,11 +211,11 @@ class DiseasesFragment : BaseFragmentView(), LayoutVisibilityChange,
)
)
handwashingViewModel.increment(CalendarUtils.today.time)
- leaves.visibility = View.VISIBLE
- if (!leaves.isAnimating)
- leaves.playAnimation()
+ handwashBinding.leaves.visibility = View.VISIBLE
+ if (!handwashBinding.leaves.isAnimating)
+ handwashBinding.leaves.playAnimation()
}
- countDownButton -> lifecycleScope.launch {
+ handwashBinding.countDownButton -> lifecycleScope.launch {
val createdItem =
handwashingViewModel.getAsync(CalendarUtils.today.time)
.await()
@@ -240,52 +255,52 @@ class DiseasesFragment : BaseFragmentView(), LayoutVisibilityChange,
listOf(upperAdsAdapter, diseasesAdapter, lowerAdsAdapter)
fastAdapter = FastAdapter.with(adapters)
val rvManager = LinearLayoutManager(context)
- with(view.container) {
+ with(loadingRecyclerViewBinding.container) {
layoutManager = rvManager
adapter = fastAdapter
}
fastAdapter.addEventHook(DiseaseClickEventHook())
fastAdapter.withSavedInstanceState(savedInstanceState)
- behavior = BottomSheetBehavior.from(view.contentLayout)
+ behavior = BottomSheetBehavior.from(binding.contentLayout)
behavior.addBottomSheetCallback(BottomSheetStateCallback())
- view.countChart.setDrawGridBackground(false)
- view.countChart.axisLeft.apply {
+ handwashBinding.countChart.setDrawGridBackground(false)
+ handwashBinding.countChart.axisLeft.apply {
setDrawGridLines(false)
valueFormatter = IntFormatter()
isGranularityEnabled = true
granularity = 1F
axisMinimum = 0F
}
- view.countChart.axisRight.apply {
+ handwashBinding.countChart.axisRight.apply {
setDrawGridLines(false)
valueFormatter = IntFormatter()
isGranularityEnabled = true
granularity = 1F
axisMinimum = 0F
}
- view.countChart.xAxis.apply {
+ handwashBinding.countChart.xAxis.apply {
setDrawGridLines(false)
valueFormatter = IntFormatter()
isGranularityEnabled = true
granularity = 1F
axisMaximum = 0F
}
- view.countChart.setVisibleXRangeMaximum(7F)
- view.countChart.isAutoScaleMinMaxEnabled = true
- view.countChart.legend.isEnabled = false
- view.countChart.description.isEnabled = false
- view.countChart.invalidate()
- view.countUpButton.setOnClickListener(this@DiseasesFragment)
- view.countDownButton.setOnClickListener(this@DiseasesFragment)
+ handwashBinding.countChart.setVisibleXRangeMaximum(7F)
+ handwashBinding.countChart.isAutoScaleMinMaxEnabled = true
+ handwashBinding.countChart.legend.isEnabled = false
+ handwashBinding.countChart.description.isEnabled = false
+ handwashBinding.countChart.invalidate()
+ handwashBinding.countUpButton.setOnClickListener(this@DiseasesFragment)
+ handwashBinding.countDownButton.setOnClickListener(this@DiseasesFragment)
val countUpText = getText(R.string.add_another)
val countDownText = getText(R.string.reduce_count)
val emojiCompat = emojiLoader.await()
try {
- countUpButton.text = emojiCompat.process(countUpText)
- countDownButton.text = emojiCompat.process(countDownText)
+ handwashBinding.countUpButton.text = emojiCompat.process(countUpText)
+ handwashBinding.countDownButton.text = emojiCompat.process(countDownText)
} catch (_: IllegalStateException) {
- countUpButton.text = countUpText
- countDownButton.text = countDownText
+ handwashBinding.countUpButton.text = countUpText
+ handwashBinding.countDownButton.text = countDownText
}
}
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/news/NewsFragment.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/news/NewsFragment.kt
index aeebd52..94505b7 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/news/NewsFragment.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/news/NewsFragment.kt
@@ -21,7 +21,9 @@ package com.javinator9889.handwashingreminder.activities.views.fragments.news
import android.content.Intent
import android.net.Uri
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
+import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
@@ -31,6 +33,7 @@ import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSmoothScroller
import androidx.recyclerview.widget.RecyclerView
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.afollestad.materialdialogs.MaterialDialog
import com.javinator9889.handwashingreminder.R
import com.javinator9889.handwashingreminder.activities.base.BaseFragmentView
@@ -38,6 +41,8 @@ import com.javinator9889.handwashingreminder.activities.base.LayoutVisibilityCha
import com.javinator9889.handwashingreminder.activities.views.fragments.news.adapter.News
import com.javinator9889.handwashingreminder.activities.views.viewmodels.NewsViewModel
import com.javinator9889.handwashingreminder.data.UserProperties
+import com.javinator9889.handwashingreminder.databinding.LoadingRecyclerViewBinding
+import com.javinator9889.handwashingreminder.databinding.RefreshingLayoutBinding
import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.GenericItem
import com.mikepenz.fastadapter.adapters.GenericItemAdapter
@@ -45,17 +50,17 @@ import com.mikepenz.fastadapter.adapters.ItemAdapter
import com.mikepenz.fastadapter.listeners.ClickEventHook
import com.mikepenz.fastadapter.scroll.EndlessRecyclerOnScrollListener
import com.mikepenz.fastadapter.ui.items.ProgressItem
-import kotlinx.android.synthetic.main.loading_recycler_view.*
-import kotlinx.android.synthetic.main.loading_recycler_view.view.*
-import kotlinx.android.synthetic.main.refreshing_layout.*
import kotlinx.coroutines.launch
import timber.log.Timber
-class NewsFragment : BaseFragmentView(), LayoutVisibilityChange {
+class NewsFragment : BaseFragmentView(),
+ LayoutVisibilityChange, SwipeRefreshLayout.OnRefreshListener {
@LayoutRes
override val layoutId: Int = R.layout.refreshing_layout
private lateinit var fastAdapter: FastAdapter
private lateinit var footerAdapter: GenericItemAdapter
+ private lateinit var loadingRecyclerView: LoadingRecyclerViewBinding
+ private lateinit var scrollListener: EndlessRecyclerOnScrollListener
private var viewCreated = false
private val newsAdapter = ItemAdapter()
private val newsViewModel: NewsViewModel by viewModels()
@@ -64,17 +69,21 @@ class NewsFragment : BaseFragmentView(), LayoutVisibilityChange {
init {
lifecycleScope.launch {
whenStarted {
- loading.visibility = View.VISIBLE
- refreshLayout.isEnabled = false
- newsViewModel.newsData.observe(viewLifecycleOwner) {
+ loadingRecyclerView.loading.visibility = View.VISIBLE
+ binding.refreshLayout.isEnabled = false
+ newsViewModel.newsData.observe(owner = viewLifecycleOwner) {
if (::footerAdapter.isInitialized)
footerAdapter.clear()
if (it.hasError && newsAdapter.adapterItemCount == 0) {
- errorScreen.visibility = View.VISIBLE
- container.visibility = View.INVISIBLE
- refreshLayout.isEnabled = true
+ loadingRecyclerView.errorScreen.visibility = View.VISIBLE
+ loadingRecyclerView.container.visibility = View.INVISIBLE
+ loadingRecyclerView.loading.visibility = View.INVISIBLE
+ binding.refreshLayout.isEnabled = true
return@observe
- } else errorScreen.visibility = View.INVISIBLE
+ } else {
+ loadingRecyclerView.errorScreen.visibility = View.INVISIBLE
+ loadingRecyclerView.loading.visibility = View.VISIBLE
+ }
if (it.id !in activeItems) {
val newsObject = News(
title = it.title,
@@ -83,13 +92,14 @@ class NewsFragment : BaseFragmentView(), LayoutVisibilityChange {
discoverDate = it.discoverDate,
imageUrl = it.elements?.url,
website = it.website?.name,
+ websiteHostname = it.website?.hostName,
websiteImageUrl = it.website?.iconURL,
lifecycleOwner = this@NewsFragment
)
newsAdapter.add(newsObject)
- loading.visibility = View.INVISIBLE
- container.visibility = View.VISIBLE
- refreshLayout.isEnabled = true
+ loadingRecyclerView.loading.visibility = View.INVISIBLE
+ loadingRecyclerView.container.visibility = View.VISIBLE
+ binding.refreshLayout.isEnabled = true
activeItems.add(it.id)
}
}
@@ -97,15 +107,26 @@ class NewsFragment : BaseFragmentView(), LayoutVisibilityChange {
}
}
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ val view = super.onCreateView(inflater, container, savedInstanceState)
+ binding = RefreshingLayoutBinding.bind(view)
+ loadingRecyclerView = binding.loadingView
+ return view
+ }
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
footerAdapter = ItemAdapter.items()
fastAdapter = FastAdapter.with(listOf(newsAdapter, footerAdapter))
val rvManager = LinearLayoutManager(context)
- val scrollListener =
+ scrollListener =
object : EndlessRecyclerOnScrollListener(footerAdapter) {
override fun onLoadMore(currentPage: Int) {
- view.container.post {
+ loadingRecyclerView.container.post {
footerAdapter.clear()
Timber.d("Loading more")
val progressItem = ProgressItem()
@@ -121,7 +142,7 @@ class NewsFragment : BaseFragmentView(), LayoutVisibilityChange {
}
}
}
- with(view.container) {
+ with(loadingRecyclerView.container) {
layoutManager = rvManager
adapter = fastAdapter
itemAnimator = DefaultItemAnimator()
@@ -130,21 +151,9 @@ class NewsFragment : BaseFragmentView(), LayoutVisibilityChange {
fastAdapter.addEventHooks(listOf(NewsClickHook(), ShareClickHook()))
fastAdapter.withSavedInstanceState(savedInstanceState)
viewCreated = savedInstanceState == null
- refreshLayout.setOnRefreshListener {
- refreshLayout.isRefreshing = true
- newsAdapter.clear()
- activeItems.clear()
- footerAdapter.clear()
- scrollListener.disable()
- lifecycleScope.launch {
- newsViewModel.populateData(language = UserProperties.language)
- }.invokeOnCompletion {
- refreshLayout.isRefreshing = false
- scrollListener.enable()
- scrollListener.resetPageCount()
- }
- container.visibility = View.INVISIBLE
- errorScreen.visibility = View.INVISIBLE
+ binding.refreshLayout.setOnRefreshListener(this)
+ binding.loadingView.reloadText.setOnClickListener {
+ onRefresh()
}
}
@@ -158,7 +167,13 @@ class NewsFragment : BaseFragmentView(), LayoutVisibilityChange {
override fun getVerticalSnapPreference(): Int = SNAP_TO_START
}
smoothScroller.targetPosition = 0
- container.layoutManager?.startSmoothScroll(smoothScroller)
+ loadingRecyclerView.container.layoutManager?.let {
+ if (it.isSmoothScrolling)
+ it.scrollToPosition(0)
+ else
+ it.startSmoothScroll(smoothScroller)
+ }
+
}
private inner class NewsClickHook : ClickEventHook() {
@@ -229,4 +244,21 @@ class NewsFragment : BaseFragmentView(), LayoutVisibilityChange {
}
}
}
+
+ override fun onRefresh() {
+ binding.refreshLayout.isRefreshing = true
+ newsAdapter.clear()
+ activeItems.clear()
+ footerAdapter.clear()
+ scrollListener.disable()
+ lifecycleScope.launch {
+ newsViewModel.populateData(language = UserProperties.language)
+ }.invokeOnCompletion {
+ binding.refreshLayout.isRefreshing = false
+ scrollListener.enable()
+ scrollListener.resetPageCount()
+ }
+ loadingRecyclerView.container.visibility = View.INVISIBLE
+ loadingRecyclerView.errorScreen.visibility = View.INVISIBLE
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/news/adapter/News.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/news/adapter/News.kt
index 97e04a2..ce3ae42 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/news/adapter/News.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/news/adapter/News.kt
@@ -24,7 +24,7 @@ import android.widget.ImageView
import android.widget.TextView
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
-import coil.api.load
+import coil.load
import coil.size.Scale
import com.airbnb.lottie.LottieAnimationView
import com.google.android.material.card.MaterialCardView
@@ -44,6 +44,7 @@ data class News(
val discoverDate: Date?,
val imageUrl: String?,
val website: String?,
+ val websiteHostname: String?,
val websiteImageUrl: String?,
val lifecycleOwner: LifecycleOwner,
override val layoutRes: Int = R.layout.news_card_view,
@@ -82,9 +83,16 @@ data class News(
scale(Scale.FILL)
lifecycle(item.lifecycleOwner)
}
- } else websiteLogo.visibility = View.GONE
- websiteName.text = item.website
- ?: context.getString(R.string.no_website)
+ } else {
+ if (item.websiteHostname != null) {
+ websiteLogo.load("https://www.google.com/s2/favicons?domain=${item.websiteHostname}") {
+ scale(Scale.FILL)
+ lifecycle(item.lifecycleOwner)
+ }
+ } else websiteLogo.visibility = View.GONE
+ }
+ websiteName.text =
+ item.website ?: context.getString(R.string.no_website)
publishDate.text =
item.discoverDate?.let { formatter.format(it) }
?: context.getString(R.string.no_date)
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/settings/SettingsView.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/settings/SettingsView.kt
index 69e75e7..b6cdb7b 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/settings/SettingsView.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/settings/SettingsView.kt
@@ -40,7 +40,7 @@ class SettingsView : PreferenceFragmentCompat(),
lateinit var adsPreference: WeakReference
lateinit var donationsPreference: WeakReference
lateinit var billingService: BillingService
- private val loader = SettingsLoader(view = this, lifecycleOwner = this)
+ private val loader = SettingsLoader(view = this, lifecycleOwner = this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -57,6 +57,7 @@ class SettingsView : PreferenceFragmentCompat(),
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
billingService = BillingService(view.context)
+ savedInstanceState?.let { loader.loadViews() }
}
override fun onPreferenceChange(
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/settings/TimePickerPreference.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/settings/TimePickerPreference.kt
index f265205..b73e7a7 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/settings/TimePickerPreference.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/settings/TimePickerPreference.kt
@@ -26,6 +26,7 @@ import androidx.preference.EditTextPreference
import com.javinator9889.handwashingreminder.jobs.alarms.AlarmHandler
import com.javinator9889.handwashingreminder.jobs.alarms.Alarms
import com.javinator9889.handwashingreminder.utils.formatTime
+import timber.log.Timber
class TimePickerPreference : EditTextPreference,
TimePickerDialog.OnTimeSetListener {
@@ -55,6 +56,7 @@ class TimePickerPreference : EditTextPreference,
}
fun updateSummary(time: String? = null) {
+ Timber.d("Updating summary of $this to $time or $text")
setSummary(time ?: text)
}
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/FirstSlide.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/FirstSlide.kt
index 996c162..a6c4f44 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/FirstSlide.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/FirstSlide.kt
@@ -18,21 +18,36 @@
*/
package com.javinator9889.handwashingreminder.activities.views.fragments.washinghands
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
import com.javinator9889.handwashingreminder.R
import com.javinator9889.handwashingreminder.activities.base.BaseFragmentView
-import kotlinx.android.synthetic.main.wash_your_hands_first_slide.*
+import com.javinator9889.handwashingreminder.databinding.WashYourHandsFirstSlideBinding
-class FirstSlide : BaseFragmentView() {
+
+class FirstSlide : BaseFragmentView() {
override val layoutId: Int = R.layout.wash_your_hands_first_slide
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ val view = super.onCreateView(inflater, container, savedInstanceState)
+ binding = WashYourHandsFirstSlideBinding.bind(view)
+ return view
+ }
+
override fun onPause() {
super.onPause()
- animation.pauseAnimation()
+ binding.animation.pauseAnimation()
}
override fun onResume() {
super.onResume()
- animation.playAnimation()
- image.setImageResource(R.drawable.handwashing_app_logo)
+ binding.animation.playAnimation()
+ binding.image.setImageResource(R.drawable.handwashing_app_logo)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/SliderView.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/SliderView.kt
index 27dc1a3..2ff8a6b 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/SliderView.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/SliderView.kt
@@ -21,17 +21,19 @@ package com.javinator9889.handwashingreminder.activities.views.fragments.washing
import android.media.MediaPlayer
import android.net.Uri
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
+import android.view.ViewGroup
import androidx.core.view.doOnLayout
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.whenStarted
-import coil.api.load
+import coil.load
import com.javinator9889.handwashingreminder.R
import com.javinator9889.handwashingreminder.activities.base.BaseFragmentView
import com.javinator9889.handwashingreminder.activities.views.viewmodels.*
-import kotlinx.android.synthetic.main.wash_your_hands_demo.*
+import com.javinator9889.handwashingreminder.databinding.WashYourHandsDemoBinding
import kotlinx.coroutines.launch
import timber.log.Timber
import java.io.File
@@ -41,7 +43,7 @@ import kotlin.properties.Delegates
private const val WAITING_ITEMS_COUNT = 4
internal const val ARG_POSITION = "bundle:position"
-class SliderView : BaseFragmentView() {
+class SliderView : BaseFragmentView() {
override val layoutId: Int = R.layout.wash_your_hands_demo
private lateinit var videoURI: Uri
private var drawableId by Delegates.notNull()
@@ -59,7 +61,7 @@ class SliderView : BaseFragmentView() {
init {
lifecycleScope.launch {
whenStarted {
- loading.visibility = View.VISIBLE
+ binding.loading.visibility = View.VISIBLE
viewModel.videos.observe(viewLifecycleOwner, Observer {
with(File(requireContext().cacheDir, it)) {
videoURI = Uri.fromFile(this)
@@ -69,23 +71,23 @@ class SliderView : BaseFragmentView() {
})
washingHandsModel.image.observe(viewLifecycleOwner, Observer {
try {
- image.load(it)
+ binding.image.load(it)
} catch (e: Exception) {
Timber.e(e, "Error while loading Glide view")
- image.setImageResource(it)
+ binding.image.setImageResource(it)
}
drawableId = it
Timber.d("Image finished loading")
incrementCounter()
})
washingHandsModel.title.observe(viewLifecycleOwner, Observer {
- title.text = it
+ binding.title.text = it
Timber.d("Title finished loading")
incrementCounter()
})
washingHandsModel.description.observe(viewLifecycleOwner,
Observer {
- description.text = it
+ binding.description.text = it
Timber.d("Description finished loading")
incrementCounter()
})
@@ -93,6 +95,16 @@ class SliderView : BaseFragmentView() {
}
}
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ val view = super.onCreateView(inflater, container, savedInstanceState)
+ binding = WashYourHandsDemoBinding.bind(view)
+ return view
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val args = arguments ?: savedInstanceState ?: throw
@@ -104,8 +116,8 @@ class SliderView : BaseFragmentView() {
override fun onPause() {
Timber.d("Slide paused")
- video.requestFocus()
- video.pause()
+ binding.video.requestFocus()
+ binding.video.pause()
super.onPause()
}
@@ -119,20 +131,20 @@ class SliderView : BaseFragmentView() {
override fun onResume() {
Timber.d("Slide resumed")
- video.requestFocus()
- video.start()
+ binding.video.requestFocus()
+ binding.video.start()
try {
- image.load(drawableId)
+ binding.image.load(drawableId)
} catch (e: Exception) {
Timber.e(e, "Error while loading Glide view")
- image.setImageResource(drawableId)
+ binding.image.setImageResource(drawableId)
}
super.onResume()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- image.doOnLayout {
+ binding.image.doOnLayout {
washingHandsModel.setImageSize(it.measuredWidth, it.measuredHeight)
}
}
@@ -150,16 +162,16 @@ class SliderView : BaseFragmentView() {
}
private fun showContent() {
- loading.visibility = View.GONE
- video.setVideoURI(videoURI)
- title.visibility = View.VISIBLE
- video.visibility = View.VISIBLE
- video.requestFocus()
- video.start()
- video.setOnPreparedListener { mp: MediaPlayer? ->
+ binding.loading.visibility = View.GONE
+ binding.video.setVideoURI(videoURI)
+ binding.title.visibility = View.VISIBLE
+ binding.video.visibility = View.VISIBLE
+ binding.video.requestFocus()
+ binding.video.start()
+ binding.video.setOnPreparedListener { mp: MediaPlayer? ->
mp?.isLooping = true
}
- description.visibility = View.VISIBLE
- image.visibility = View.VISIBLE
+ binding.description.visibility = View.VISIBLE
+ binding.image.visibility = View.VISIBLE
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/WashingHandsFragment.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/WashingHandsFragment.kt
index f02bd10..9d422e9 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/WashingHandsFragment.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/fragments/washinghands/WashingHandsFragment.kt
@@ -19,7 +19,9 @@
package com.javinator9889.handwashingreminder.activities.views.fragments.washinghands
import android.os.Bundle
+import android.view.LayoutInflater
import android.view.View
+import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
@@ -28,51 +30,60 @@ import com.google.android.material.tabs.TabLayoutMediator
import com.javinator9889.handwashingreminder.R
import com.javinator9889.handwashingreminder.activities.base.BaseFragmentView
import com.javinator9889.handwashingreminder.activities.base.LayoutVisibilityChange
-import kotlinx.android.synthetic.main.how_to_wash_hands_layout.view.*
-import kotlinx.android.synthetic.main.privacy_terms.*
+import com.javinator9889.handwashingreminder.databinding.HowToWashHandsLayoutBinding
import timber.log.Timber
import java.lang.ref.WeakReference
internal const val NUM_PAGES = 8
-class WashingHandsFragment : BaseFragmentView(), LayoutVisibilityChange {
+class WashingHandsFragment : BaseFragmentView(), LayoutVisibilityChange {
override val layoutId: Int = R.layout.how_to_wash_hands_layout
private val items = arrayOfNulls>(NUM_PAGES)
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ val view = super.onCreateView(inflater, container, savedInstanceState)
+ binding = HowToWashHandsLayoutBinding.bind(view)
+ return view
+ }
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val adapter = FragmentAdapter(requireActivity())
- view.pager.adapter = adapter
- TabLayoutMediator(view.tabPager, view.pager) { _, _ -> }.attach()
- view.pager.registerOnPageChangeCallback(object :
+ binding.pager.adapter = adapter
+ TabLayoutMediator(binding.tabPager, binding.pager) { _, _ -> }.attach()
+ binding.pager.registerOnPageChangeCallback(object :
ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
Timber.d("Current position: $position")
when (position) {
0 -> {
- view.previousButton.visibility = View.INVISIBLE
- view.nextButton.visibility = View.VISIBLE
+ binding.previousButton.visibility = View.INVISIBLE
+ binding.nextButton.visibility = View.VISIBLE
}
NUM_PAGES - 1 -> {
- view.nextButton.visibility = View.INVISIBLE
- view.previousButton.visibility = View.VISIBLE
+ binding.nextButton.visibility = View.INVISIBLE
+ binding.previousButton.visibility = View.VISIBLE
}
else -> {
- view.previousButton.visibility = View.VISIBLE
- view.nextButton.visibility = View.VISIBLE
+ binding.previousButton.visibility = View.VISIBLE
+ binding.nextButton.visibility = View.VISIBLE
}
}
}
})
- view.previousButton.setOnClickListener { view.pager.currentItem-- }
- view.nextButton.setOnClickListener { view.pager.currentItem++ }
+ binding.previousButton.setOnClickListener { binding.pager.currentItem-- }
+ binding.nextButton.setOnClickListener { binding.pager.currentItem++ }
}
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
Timber.d("Visibility changed: $hidden")
- items[pager.currentItem]?.get()?.onHiddenChanged(hidden)
+ items[binding.pager.currentItem]?.get()?.onHiddenChanged(hidden)
}
private inner class FragmentAdapter(fa: FragmentActivity) :
@@ -86,7 +97,7 @@ class WashingHandsFragment : BaseFragmentView(), LayoutVisibilityChange {
with(SliderView()) {
val args = Bundle(1)
args.putInt(ARG_POSITION, position - 1)
- this.arguments = args
+ arguments = args
items[position] = WeakReference(this)
return this
}
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/viewmodels/NewsViewModel.kt b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/viewmodels/NewsViewModel.kt
index 5a0f430..74a24bf 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/viewmodels/NewsViewModel.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/activities/views/viewmodels/NewsViewModel.kt
@@ -50,7 +50,7 @@ class NewsViewModel : ViewModel() {
fieldConverter(KlaxonDate::class, dateConverter)
fieldConverter(KlaxonElements::class, elementConverter)
}
- var requestReader: Reader? = null
+ var requestReader: Reader?
Auth.init()
val token = Auth.token()
Timber.d("Auth token: $token")
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/application/HandwashingApplication.kt b/app/src/main/java/com/javinator9889/handwashingreminder/application/HandwashingApplication.kt
index ab2c123..ba1bf55 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/application/HandwashingApplication.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/application/HandwashingApplication.kt
@@ -51,7 +51,7 @@ class HandwashingApplication : BaseApplication() {
get() = instance.scope
}
- override fun attachBaseContext(base: Context?) {
+ override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(base)
SplitCompat.install(base)
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/data/SettingsLoader.kt b/app/src/main/java/com/javinator9889/handwashingreminder/data/SettingsLoader.kt
index 8892291..fc55104 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/data/SettingsLoader.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/data/SettingsLoader.kt
@@ -44,6 +44,7 @@ import com.javinator9889.handwashingreminder.application.HandwashingApplication
import com.javinator9889.handwashingreminder.emoji.EmojiLoader
import com.javinator9889.handwashingreminder.gms.ads.AdsEnabler
import com.javinator9889.handwashingreminder.gms.splitservice.SplitInstallService
+import com.javinator9889.handwashingreminder.jobs.alarms.AlarmHandler
import com.javinator9889.handwashingreminder.jobs.alarms.Alarms
import com.javinator9889.handwashingreminder.listeners.OnPurchaseFinishedListener
import com.javinator9889.handwashingreminder.utils.*
@@ -506,7 +507,7 @@ class SettingsLoader(
with(FirebaseAnalytics.getInstance(view.requireContext())) {
setAnalyticsCollectionEnabled(enabled)
if (!enabled)
- setCurrentScreen(view.requireActivity(), null, null)
+ setCurrentScreen(null, view.requireActivity()::class)
}
true
}
@@ -590,6 +591,12 @@ class SettingsLoader(
)
preference.summary =
view.getString(R.string.minimum_time_summ, minutes)
+
+ // Cancel the old alarm and schedule a new one with the updated
+ // time
+ with(AlarmHandler(view.requireContext())) {
+ scheduleAlarm(Alarms.PENDING_ACTIVITY_ALARM)
+ }
true
}.getOrElse { Timber.w(it); false }
else -> true
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/gms/activity/ActivityHandler.kt b/app/src/main/java/com/javinator9889/handwashingreminder/gms/activity/ActivityHandler.kt
index 47902c0..abdb126 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/gms/activity/ActivityHandler.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/gms/activity/ActivityHandler.kt
@@ -22,12 +22,14 @@ import android.app.PendingIntent
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.content.Context
import android.content.Intent
+import androidx.preference.PreferenceManager
import com.google.android.gms.location.ActivityRecognition
import com.google.android.gms.location.ActivityTransition
import com.google.android.gms.location.ActivityTransition.ACTIVITY_TRANSITION_EXIT
import com.google.android.gms.location.ActivityTransitionRequest
import com.google.android.gms.location.DetectedActivity
import com.google.android.gms.tasks.Task
+import com.javinator9889.handwashingreminder.utils.Preferences
import timber.log.Timber
internal const val ACTIVITY_REQUEST_CODE = 64
@@ -97,6 +99,11 @@ class ActivityHandler private constructor(private val context: Context) {
private fun createPendingIntent(): PendingIntent =
with(Intent(context, ActivityReceiver::class.java)) {
action = TRANSITIONS_RECEIVER_ACTION
+ val prefs = PreferenceManager.getDefaultSharedPreferences(context)
+ putExtra(
+ Preferences.ACTIVITY_MINIMUM_TIME,
+ prefs.getString(Preferences.ACTIVITY_MINIMUM_TIME, "15")!!.toInt()
+ )
PendingIntent.getBroadcast(
context,
ACTIVITY_REQUEST_CODE,
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/gms/activity/ActivityReceiver.kt b/app/src/main/java/com/javinator9889/handwashingreminder/gms/activity/ActivityReceiver.kt
index d7b2845..d176828 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/gms/activity/ActivityReceiver.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/gms/activity/ActivityReceiver.kt
@@ -18,17 +18,26 @@
*/
package com.javinator9889.handwashingreminder.gms.activity
+import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.annotation.StringRes
+import androidx.core.app.NotificationCompat
import androidx.emoji.text.EmojiCompat
-import androidx.preference.PreferenceManager
import com.google.android.gms.location.ActivityTransition
+import com.google.android.gms.location.ActivityTransitionEvent
import com.google.android.gms.location.ActivityTransitionResult
import com.google.android.gms.location.DetectedActivity
import com.javinator9889.handwashingreminder.R
import com.javinator9889.handwashingreminder.emoji.EmojiLoader
+import com.javinator9889.handwashingreminder.jobs.HANDS_WASHED_ACTION
+import com.javinator9889.handwashingreminder.jobs.HANDS_WASHED_CODE
+import com.javinator9889.handwashingreminder.jobs.HandsWashedReceiver
+import com.javinator9889.handwashingreminder.jobs.NOTIFICATION_ID_KEY
+import com.javinator9889.handwashingreminder.jobs.alarms.AlarmHandler
+import com.javinator9889.handwashingreminder.jobs.alarms.Alarms
+import com.javinator9889.handwashingreminder.notifications.Action
import com.javinator9889.handwashingreminder.notifications.NotificationsHandler
import com.javinator9889.handwashingreminder.utils.ACTIVITY_CHANNEL_ID
import com.javinator9889.handwashingreminder.utils.Preferences
@@ -38,11 +47,16 @@ import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import timber.log.Timber
-import java.io.*
import java.util.*
import java.util.concurrent.TimeUnit
class ActivityReceiver : BroadcastReceiver() {
+ companion object ReceiverData {
+ val pendingActivities: Deque = ArrayDeque()
+ var latestNotificationTime: Long = 0L
+ var alarmScheduled: Boolean = false
+ }
+
/**
* {@inheritDoc}
*/
@@ -66,14 +80,19 @@ class ActivityReceiver : BroadcastReceiver() {
),
context.getString(
R.string.activity_notification_channel_desc
+ ),
+ "alarms:pending_activities",
+ context.getString(
+ R.string.activity_notification_channel_name
)
)
goAsync {
putNotification(
notificationHandler,
emojiLoader,
- event.activityType,
- context
+ event,
+ context,
+ intent
)
}
break
@@ -85,29 +104,29 @@ class ActivityReceiver : BroadcastReceiver() {
private suspend fun putNotification(
notificationsHandler: NotificationsHandler,
emojiLoader: Deferred,
- detectedActivity: Int,
- context: Context
+ event: ActivityTransitionEvent,
+ context: Context,
+ intent: Intent
) {
- val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val timeInBetweenNotifications =
- prefs.getString(Preferences.ACTIVITY_MINIMUM_TIME, "15")!!.toInt()
- val timeFile = File(context.cacheDir, "activity.time")
- var latestNotificationTime = 0L
- withContext(Dispatchers.IO) {
- if (timeFile.exists()) {
- DataInputStream(FileInputStream(timeFile)).use {
- latestNotificationTime = it.readLong()
- }
- }
- }
+ intent.getIntExtra(Preferences.ACTIVITY_MINIMUM_TIME, 15)
val timeDifference = CalendarUtils.timeBetweenIn(
TimeUnit.MINUTES,
latestNotificationTime
)
Timber.d("$timeDifference - $timeInBetweenNotifications")
- if (timeDifference <= timeInBetweenNotifications)
+ if (timeDifference < timeInBetweenNotifications) {
+ pendingActivities.add(event)
+ if (!alarmScheduled) {
+ with(AlarmHandler(context)) {
+ scheduleAlarm(Alarms.PENDING_ACTIVITY_ALARM)
+ }
+ alarmScheduled = true
+ }
return
- val notificationContent = when (detectedActivity) {
+ }
+ latestNotificationTime = CalendarUtils.now
+ val notificationContent = when (event.activityType) {
DetectedActivity.WALKING ->
NotificationContent(
R.string.activity_notification_walk,
@@ -129,7 +148,7 @@ class ActivityReceiver : BroadcastReceiver() {
R.string.activity_notification_vehicle_content
)
else -> throw IllegalArgumentException(
- "Activity not recognized - $detectedActivity"
+ "Activity not recognized - $event"
)
}
var title = context.getText(notificationContent.title)
@@ -140,6 +159,15 @@ class ActivityReceiver : BroadcastReceiver() {
content = emojiCompat.process(content)
} catch (_: IllegalStateException) {
}
+ val washedPendingIntent = PendingIntent.getBroadcast(
+ context,
+ HANDS_WASHED_CODE,
+ Intent(context, HandsWashedReceiver::class.java).apply {
+ action = HANDS_WASHED_ACTION
+ putExtra(NOTIFICATION_ID_KEY, 2)
+ },
+ PendingIntent.FLAG_UPDATE_CURRENT
+ )
withContext(Dispatchers.Main) {
notificationsHandler.createNotification(
iconDrawable = R.drawable.ic_stat_handwashing,
@@ -147,14 +175,15 @@ class ActivityReceiver : BroadcastReceiver() {
title = title,
content = content,
longContent = content,
- notificationId = 2
+ notificationId = 2,
+ priority = NotificationCompat.PRIORITY_MAX,
+ action = Action(
+ R.drawable.ic_stat_handwashing,
+ context.getText(R.string.just_washed),
+ washedPendingIntent
+ )
)
}
- withContext(Dispatchers.IO) {
- DataOutputStream(FileOutputStream(timeFile)).use {
- it.writeLong(Calendar.getInstance().timeInMillis)
- }
- }
}
}
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/graphics/RecyclingImageView.kt b/app/src/main/java/com/javinator9889/handwashingreminder/graphics/RecyclingImageView.kt
index 64a3818..37b9915 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/graphics/RecyclingImageView.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/graphics/RecyclingImageView.kt
@@ -25,7 +25,7 @@ import android.util.AttributeSet
import android.view.View
import androidx.annotation.DrawableRes
import androidx.appcompat.widget.AppCompatImageView
-import coil.api.load
+import coil.load
class RecyclingImageView : AppCompatImageView {
constructor(context: Context) : super(context)
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/BootCompletedJob.kt b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/BootCompletedJob.kt
index b0ecbe3..a3d43ff 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/BootCompletedJob.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/BootCompletedJob.kt
@@ -27,11 +27,14 @@ import com.javinator9889.handwashingreminder.jobs.alarms.AlarmHandler
import com.javinator9889.handwashingreminder.utils.Preferences
import timber.log.Timber
+const val ACTION_QBP = "android.intent.action.QUICKBOOT_POWERON"
+
class BootCompletedJob : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
- if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
+ if (intent.action in setOf(Intent.ACTION_BOOT_COMPLETED, ACTION_QBP)) {
val activityHandler = ActivityHandler.getInstance(context)
- val preferences = PreferenceManager.getDefaultSharedPreferences(context)
+ val preferences =
+ PreferenceManager.getDefaultSharedPreferences(context)
if (preferences.getBoolean(
Preferences.ACTIVITY_TRACKING_ENABLED,
false
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/HandsWashedReceiver.kt b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/HandsWashedReceiver.kt
index 08b0fbd..40f3101 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/HandsWashedReceiver.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/HandsWashedReceiver.kt
@@ -36,6 +36,8 @@ import kotlinx.coroutines.withContext
internal const val HANDS_WASHED_CODE = 128
internal const val HANDS_WASHED_ACTION =
"com.javinator9889.handwashingreminder.HANDSWASHED_EVENT"
+internal const val NOTIFICATION_ID_KEY =
+ "com.javinator9889.handwashingreminder.NID"
class HandsWashedReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@@ -44,8 +46,11 @@ class HandsWashedReceiver : BroadcastReceiver() {
with(HandwashingDatabase.getDatabase(context).handwashingDao()) {
HandwashingRepository(this)
}
- with(NotificationManagerCompat.from(context)) {
- cancel(1)
+ intent.getIntExtra(NOTIFICATION_ID_KEY, -1).let {
+ if (it != -1)
+ with(NotificationManagerCompat.from(context)) {
+ cancel(it)
+ }
}
goAsync {
val createdItem = withContext(Dispatchers.IO) {
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/UpdateReceiver.kt b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/UpdateReceiver.kt
index 6627b93..7c747a1 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/UpdateReceiver.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/UpdateReceiver.kt
@@ -18,10 +18,15 @@
*/
package com.javinator9889.handwashingreminder.jobs
+import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
+import com.javinator9889.handwashingreminder.BuildConfig
import com.javinator9889.handwashingreminder.jobs.alarms.AlarmHandler
+import com.javinator9889.handwashingreminder.utils.ACTIVITY_CHANNEL_ID
+import com.javinator9889.handwashingreminder.utils.AndroidVersion
+import com.javinator9889.handwashingreminder.utils.isAtLeast
import timber.log.Timber
class UpdateReceiver : BroadcastReceiver() {
@@ -31,6 +36,27 @@ class UpdateReceiver : BroadcastReceiver() {
with(AlarmHandler(context)) {
scheduleAllAlarms()
}
+ // Here, we need to remove all the notifications channels
+ // previously created as they have changed
+ if (BuildConfig.VERSION_CODE in 141..142 && isAtLeast(AndroidVersion.O)) {
+ val notificationManager =
+ context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ for (id in setOf(
+ "notifications:breakfast",
+ "notifications:lunch",
+ "notifications:dinner",
+ ACTIVITY_CHANNEL_ID
+ )) {
+ notificationManager.deleteNotificationChannel(id)
+ }
+ for (id in setOf(
+ "alarms:breakfast",
+ "alarms:lunch",
+ "alarms:dinner"
+ )) {
+ notificationManager.deleteNotificationChannelGroup(id)
+ }
+ }
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/AlarmHandler.kt b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/AlarmHandler.kt
index e1c9da6..34f1282 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/AlarmHandler.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/AlarmHandler.kt
@@ -26,8 +26,11 @@ import android.content.Intent
import androidx.annotation.IntRange
import androidx.core.app.AlarmManagerCompat
import androidx.preference.PreferenceManager
+import com.javinator9889.handwashingreminder.utils.calendar.CalendarUtils
import com.javinator9889.handwashingreminder.utils.timeAt
import timber.log.Timber
+import java.util.*
+import java.util.concurrent.TimeUnit
internal const val IDENTIFIER = "intent:id"
@@ -74,6 +77,16 @@ class AlarmHandler(private val context: Context) {
private fun getTimeForAlarm(alarm: Alarms): ScheduleTimeData {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
+ if (alarm == Alarms.PENDING_ACTIVITY_ALARM) {
+ val elapsedTimeAlarm =
+ preferences.getString(alarm.preferenceKey, "15")!!.toInt()
+ val nextAlarm =
+ CalendarUtils.timeIn(elapsedTimeAlarm, TimeUnit.MINUTES)
+ return ScheduleTimeData(
+ nextAlarm[Calendar.HOUR_OF_DAY],
+ nextAlarm[Calendar.MINUTE]
+ )
+ }
val savedTime = preferences.getString(alarm.preferenceKey, "")
if (savedTime.isNullOrBlank())
throw IllegalStateException("Time value cannot be null")
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/AlarmReceiver.kt b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/AlarmReceiver.kt
index 70b6bfa..4058276 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/AlarmReceiver.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/AlarmReceiver.kt
@@ -24,6 +24,7 @@ import android.content.Intent
import com.javinator9889.handwashingreminder.jobs.workers.BreakfastNotificationWorker
import com.javinator9889.handwashingreminder.jobs.workers.DinnerNotificationWorker
import com.javinator9889.handwashingreminder.jobs.workers.LunchNotificationWorker
+import com.javinator9889.handwashingreminder.jobs.workers.PendingActivityAlarmWorker
import com.javinator9889.handwashingreminder.utils.goAsync
class AlarmReceiver : BroadcastReceiver() {
@@ -33,7 +34,7 @@ class AlarmReceiver : BroadcastReceiver() {
BreakfastNotificationWorker(context)
Alarms.LUNCH_ALARM.identifier -> LunchNotificationWorker(context)
Alarms.DINNER_ALARM.identifier -> DinnerNotificationWorker(context)
- else -> return
+ else -> PendingActivityAlarmWorker(context)
}
goAsync { worker.doWork() }
}
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/Alarms.kt b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/Alarms.kt
index 3e0593e..eee4ef6 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/Alarms.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/alarms/Alarms.kt
@@ -20,34 +20,57 @@ package com.javinator9889.handwashingreminder.jobs.alarms
import androidx.annotation.StringRes
import com.javinator9889.handwashingreminder.R
+import com.javinator9889.handwashingreminder.utils.ACTIVITY_CHANNEL_ID
import com.javinator9889.handwashingreminder.utils.Preferences
enum class Alarms(
val identifier: String,
val code: Int,
val preferenceKey: String,
+ val groupId: String,
@StringRes val groupName: Int,
- val channelId: String
+ val channelId: String,
+ @StringRes val channelName: Int,
+ @StringRes val channelDesc: Int
) {
BREAKFAST_ALARM(
"alarms:breakfast",
0,
Preferences.BREAKFAST_TIME,
+ "alarms:scheduled",
+ R.string.time_notification_channel_name,
+ "notifications:breakfast",
R.string.breakfast_notifications,
- "notifications:breakfast"
+ R.string.breakfast_description
),
LUNCH_ALARM(
"alarms:lunch",
1,
Preferences.LUNCH_TIME,
+ "alarms:scheduled",
+ R.string.time_notification_channel_name,
+ "notifications:lunch",
R.string.lunch_notifications,
- "notifications:lunch"
+ R.string.lunch_description
),
DINNER_ALARM(
"alarms:dinner",
2,
Preferences.DINNER_TIME,
+ "alarms:scheduled",
+ R.string.time_notification_channel_name,
+ "notifications:dinner",
R.string.dinner_notifications,
- "notifications:dinner"
+ R.string.dinner_description
+ ),
+ PENDING_ACTIVITY_ALARM(
+ "alarms:activities",
+ 3,
+ Preferences.ACTIVITY_MINIMUM_TIME,
+ "alarms:pending_activities",
+ R.string.activity_notification_channel_name,
+ ACTIVITY_CHANNEL_ID,
+ R.string.activity_notification_channel_name,
+ R.string.activity_notification_channel_desc
)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/workers/PendingActivityAlarmWorker.kt b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/workers/PendingActivityAlarmWorker.kt
new file mode 100644
index 0000000..b022c76
--- /dev/null
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/workers/PendingActivityAlarmWorker.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2020 - present | Handwashing reminder by Javinator9889
+ *
+ * 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/.
+ *
+ * Created by Javinator9889 on 10/12/20 - Handwashing reminder.
+ */
+package com.javinator9889.handwashingreminder.jobs.workers
+
+import android.content.Context
+import com.google.android.gms.location.DetectedActivity
+import com.javinator9889.handwashingreminder.R
+import com.javinator9889.handwashingreminder.gms.activity.ActivityReceiver
+import com.javinator9889.handwashingreminder.jobs.alarms.AlarmHandler
+import com.javinator9889.handwashingreminder.jobs.alarms.Alarms
+
+class PendingActivityAlarmWorker(context: Context) :
+ ScheduledNotificationWorker(context) {
+ private val notificationContent: Pair
+ get() = when (ActivityReceiver.pendingActivities.poll()?.activityType) {
+ DetectedActivity.WALKING ->
+ R.string.activity_notification_walk to R.string.activity_notification_walk_content
+ DetectedActivity.RUNNING ->
+ R.string.activity_notification_run to R.string.activity_notifications_run_content
+ DetectedActivity.ON_BICYCLE ->
+ R.string.activity_notification_cycling to R.string.activity_notification_cycling_content
+ DetectedActivity.IN_VEHICLE ->
+ R.string.activity_notification_vehicle to R.string.activity_notification_vehicle_content
+ else -> -1 to -1
+ }
+ override val alarm: Alarms = Alarms.PENDING_ACTIVITY_ALARM
+ override val titleRes: Int = notificationContent.first
+ override val contentsRes: Int = notificationContent.second
+
+ override fun onFinish(result: Result) {
+ with(AlarmHandler(context)) {
+ if (ActivityReceiver.pendingActivities.size == 0) cancelAlarm(alarm)
+ else scheduleAlarm(alarm)
+ ActivityReceiver.alarmScheduled =
+ ActivityReceiver.pendingActivities.size != 0
+ }
+ if (result.isFailure) {
+ super.onFinish(result)
+ }
+ }
+}
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/workers/ScheduledNotificationWorker.kt b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/workers/ScheduledNotificationWorker.kt
index ac7f67e..e4cf5ad 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/jobs/workers/ScheduledNotificationWorker.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/jobs/workers/ScheduledNotificationWorker.kt
@@ -30,6 +30,7 @@ import com.javinator9889.handwashingreminder.emoji.EmojiLoader
import com.javinator9889.handwashingreminder.jobs.HANDS_WASHED_ACTION
import com.javinator9889.handwashingreminder.jobs.HANDS_WASHED_CODE
import com.javinator9889.handwashingreminder.jobs.HandsWashedReceiver
+import com.javinator9889.handwashingreminder.jobs.NOTIFICATION_ID_KEY
import com.javinator9889.handwashingreminder.jobs.alarms.AlarmHandler
import com.javinator9889.handwashingreminder.jobs.alarms.Alarms
import com.javinator9889.handwashingreminder.notifications.Action
@@ -47,18 +48,20 @@ abstract class ScheduledNotificationWorker(context: Context) {
protected abstract val contentsRes: Int
suspend fun doWork() = coroutineScope {
+ var result: Result = Result.success(Unit)
try {
- val startTime = System.currentTimeMillis()
val emojiLoader = EmojiLoader.loadAsync(context)
val notificationsHandler = NotificationsHandler(
context = context,
channelId = alarm.channelId,
- channelName = getString(R.string.time_notification_channel_name),
- channelDesc = getString(R.string.time_notification_channel_desc),
- groupId = alarm.identifier,
+ channelName = getString(alarm.channelName),
+ channelDesc = getString(alarm.channelDesc),
+ groupId = alarm.groupId,
groupName = getString(alarm.groupName)
)
val emojiCompat = emojiLoader.await()
+ if (titleRes == -1 && contentsRes == -1)
+ return@coroutineScope
var title = getText(titleRes)
var content =
getStringArray(contentsRes).toList().random() as CharSequence
@@ -72,6 +75,7 @@ abstract class ScheduledNotificationWorker(context: Context) {
HANDS_WASHED_CODE,
Intent(context, HandsWashedReceiver::class.java).apply {
action = HANDS_WASHED_ACTION
+ putExtra(NOTIFICATION_ID_KEY, 1)
},
PendingIntent.FLAG_UPDATE_CURRENT
)
@@ -90,11 +94,7 @@ abstract class ScheduledNotificationWorker(context: Context) {
)
)
}
- Timber.d(
- "Posting a notification took: ${System
- .currentTimeMillis() - startTime}ms"
- )
- } catch (e: Exception) {
+ } catch (e: Throwable) {
with(HandwashingApplication.instance) {
// Don't use so much resources, wait at most half a second until
// Firebase initializes or continue with execution.
@@ -104,14 +104,23 @@ abstract class ScheduledNotificationWorker(context: Context) {
firebaseInitDeferred.await()
}
}
- Timber.e(e, "Unhandled exception on worker class")
+ result = Result.failure(e)
// We don't want to keep using CPU at this time if the request
// fails so schedule next execution
} finally {
+ onFinish(result)
+ }
+ }
+
+ protected open fun onFinish(result: Result) {
+ if (result.isSuccess) {
with(AlarmHandler(context)) {
scheduleAlarm(alarm)
}
- }
+ } else Timber.e(
+ result.exceptionOrNull(),
+ "Unhandled exception on worker class"
+ )
}
private fun getString(@StringRes resId: Int): String =
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/utils/Analytics.kt b/app/src/main/java/com/javinator9889/handwashingreminder/utils/Analytics.kt
new file mode 100644
index 0000000..7fb1ab7
--- /dev/null
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/utils/Analytics.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2020 - present | Handwashing reminder by Javinator9889
+ *
+ * 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/.
+ *
+ * Created by Javinator9889 on 10/12/20 - Handwashing reminder.
+ */
+package com.javinator9889.handwashingreminder.utils
+
+import android.os.Bundle
+import com.google.firebase.analytics.FirebaseAnalytics
+import kotlin.reflect.KClass
+
+
+fun FirebaseAnalytics.setCurrentScreen(name: String?, cls: KClass<*>?) {
+ with(Bundle(2)) {
+ putString(FirebaseAnalytics.Param.SCREEN_NAME, name)
+ putString(FirebaseAnalytics.Param.SCREEN_CLASS, cls?.simpleName)
+ logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, this)
+ }
+}
diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/utils/calendar/Calendar.kt b/app/src/main/java/com/javinator9889/handwashingreminder/utils/calendar/Calendar.kt
index 58f2a1d..eff8394 100644
--- a/app/src/main/java/com/javinator9889/handwashingreminder/utils/calendar/Calendar.kt
+++ b/app/src/main/java/com/javinator9889/handwashingreminder/utils/calendar/Calendar.kt
@@ -45,6 +45,9 @@ object CalendarUtils {
return aMonthAgo
}
+ val now: Long
+ get() = Calendar.getInstance().timeInMillis
+
fun timeBetweenIn(
unit: TimeUnit,
to: Long,
@@ -55,4 +58,17 @@ object CalendarUtils {
to: Long,
from: Long = today.timeInMillis
): Long = from - to
+
+ fun timeIn(amount: Int, unit: TimeUnit): Calendar =
+ with(Calendar.getInstance()) {
+ when (unit) {
+ TimeUnit.MILLISECONDS -> this[Calendar.MILLISECOND] += amount
+ TimeUnit.SECONDS -> this[Calendar.SECOND] += amount
+ TimeUnit.MINUTES -> this[Calendar.MINUTE] += amount
+ TimeUnit.HOURS -> this[Calendar.HOUR_OF_DAY] += amount
+ TimeUnit.DAYS -> this[Calendar.DAY_OF_MONTH] += amount
+ else -> Unit
+ }
+ this
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_update_black.xml b/app/src/main/res/drawable/ic_update_black.xml
new file mode 100644
index 0000000..fdb2fca
--- /dev/null
+++ b/app/src/main/res/drawable/ic_update_black.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/layout/loading_recycler_view.xml b/app/src/main/res/layout/loading_recycler_view.xml
index 800d5f7..6426737 100644
--- a/app/src/main/res/layout/loading_recycler_view.xml
+++ b/app/src/main/res/layout/loading_recycler_view.xml
@@ -47,11 +47,31 @@
android:text="@string/news_error"
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
android:textSize="18sp"
- app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintBottom_toTopOf="@+id/reloadText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/errorAnimation"
tools:text="Error while obtaining new data" />
+
+
-
+
@@ -64,7 +65,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
-
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/news_card_view.xml b/app/src/main/res/layout/news_card_view.xml
index 46e81a7..e4ab83e 100644
--- a/app/src/main/res/layout/news_card_view.xml
+++ b/app/src/main/res/layout/news_card_view.xml
@@ -96,8 +96,9 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/splash_screen.xml b/app/src/main/res/layout/splash_screen.xml
index b3e14dd..eda0a6e 100644
--- a/app/src/main/res/layout/splash_screen.xml
+++ b/app/src/main/res/layout/splash_screen.xml
@@ -19,7 +19,7 @@
Recordatorios en el desayuno
+ ¡Recibe una notificación cuando es la
+ hora del desayuno! ☕
Recordatorios en la comida
+ ¡Recibe una notificación cuando es
+ la hora de la comida! 🍱
Recordatorios en la cenas
+ ¡Recibe una notificación cuando es la hora
+ de la cena! 🥗
¡Hora de comer y lavarse las manos!
🍱
@@ -297,4 +303,5 @@
Ajustes de notificaciones
¡Acabo de lavarlas!
¡Yupiiii! 🙌😱
+ Pulsa aquà para intentarlo de nuevo
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5812a91..d257f50 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -70,6 +70,8 @@
hands 😉💦👏
Breakfast reminders
+ Get a notification when it\'s breakfast
+ time! ☕
Time to lunch and wash your hands!
🍱
@@ -81,6 +83,8 @@
wash your hands before having lunch 💦👏
Lunch reminders
+ Get a notification when it\'s lunch
+ time! 🍱
Let\'s have a clean dinner 🥗
- The day is finishing and you can do it fully by
@@ -91,6 +95,8 @@
more than 15 diseases? That\'s a lot 😮
Dinner reminders
+ Get a notification when it\'s dinner
+ time! 🥗
Let\'s learn how to wash
our hands
Join me in this trip
@@ -325,4 +331,5 @@
Edit notification settings
Just washed them!
Hurray! 🙌😱
+ Click here to try again
diff --git a/appintro/build.gradle b/appintro/build.gradle
index 9bfb7e5..e20781f 100644
--- a/appintro/build.gradle
+++ b/appintro/build.gradle
@@ -1,16 +1,19 @@
apply plugin: 'com.android.dynamic-feature'
apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
android {
- buildFeatures.viewBinding = true
- compileSdkVersion 29
+ buildFeatures {
+ viewBinding true
+ dataBinding true
+ }
+ compileSdkVersion 30
android.defaultConfig.vectorDrawables.useSupportLibrary = true
defaultConfig {
- minSdkVersion 17
- targetSdkVersion 29
+ minSdkVersion 16
+ targetSdkVersion 30
versionCode 1
versionName "1.0"
}
diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/IntroActivity.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/IntroActivity.kt
index 33c9e43..7f35f22 100644
--- a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/IntroActivity.kt
+++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/IntroActivity.kt
@@ -45,16 +45,12 @@ import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.perf.FirebasePerformance
import com.javinator9889.handwashingreminder.activities.MainActivity
import com.javinator9889.handwashingreminder.appintro.custom.SliderPageBuilder
-import com.javinator9889.handwashingreminder.appintro.fragments.AnimatedAppIntro
-import com.javinator9889.handwashingreminder.appintro.fragments.SlidePolicyFragment
-import com.javinator9889.handwashingreminder.appintro.fragments.TimeConfigIntroFragment
-import com.javinator9889.handwashingreminder.appintro.fragments.TimeContainer
+import com.javinator9889.handwashingreminder.appintro.fragments.*
import com.javinator9889.handwashingreminder.appintro.timeconfig.TimeConfigItem
import com.javinator9889.handwashingreminder.appintro.utils.AnimatedResources
import com.javinator9889.handwashingreminder.gms.activity.ActivityHandler
import com.javinator9889.handwashingreminder.jobs.alarms.AlarmHandler
import com.javinator9889.handwashingreminder.utils.*
-import kotlinx.android.synthetic.main.animated_intro.*
import kotlinx.coroutines.*
import timber.log.Timber
import com.javinator9889.handwashingreminder.appintro.R as RIntro
@@ -82,9 +78,10 @@ class IntroActivity : AppIntro2(),
with(FirebaseAnalytics.getInstance(this)) {
logEvent(FirebaseAnalytics.Event.TUTORIAL_BEGIN, null)
- setCurrentScreen(this@IntroActivity, "Intro", null)
+ setCurrentScreen("Intro", this@IntroActivity::class)
}
+ Timber.d("Creating slides...")
val firstSlide = SliderPageBuilder.Builder()
.title(getString(RIntro.string.first_slide_title))
.description(getString(RIntro.string.first_slide_desc))
@@ -149,6 +146,7 @@ class IntroActivity : AppIntro2(),
backButtonVisibilityWithDone = true
setIndicatorColor(Color.DKGRAY, Color.GRAY)
nextButton.setOnClickListener(this)
+ Timber.d("Finished activity creation")
}
override fun onSaveInstanceState(outState: Bundle) {
@@ -181,6 +179,7 @@ class IntroActivity : AppIntro2(),
sharedPreferences.edit {
timeConfigSlide.itemAdapter.adapterItems.forEach { item ->
val time = "${item.hours}:${item.minutes}"
+ Timber.d("Saving $item with ID ${item.id} and time $time")
when (item.id) {
TimeConfig.BREAKFAST_ID ->
putString(Preferences.BREAKFAST_TIME, time)
@@ -255,9 +254,8 @@ class IntroActivity : AppIntro2(),
)
if (!policySlide.firebaseAnalytics.isChecked) {
firebaseAnalytics.setCurrentScreen(
- this@IntroActivity,
null,
- null
+ this@IntroActivity::class
)
firebaseAnalytics.setAnalyticsCollectionEnabled(false)
}
@@ -334,7 +332,7 @@ class IntroActivity : AppIntro2(),
if (newFragment is AnimatedAppIntro ||
newFragment is SlidePolicyFragment
)
- newFragment.image.playAnimation()
+ (newFragment as ImageFragment).image.playAnimation()
super.onSlideChanged(oldFragment, newFragment)
}
diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/AnimatedAppIntro.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/AnimatedAppIntro.kt
index bf73b9e..e04ab3f 100644
--- a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/AnimatedAppIntro.kt
+++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/AnimatedAppIntro.kt
@@ -38,12 +38,14 @@ import com.github.paolorotolo.appintro.util.TypefaceContainer
import com.google.android.play.core.splitcompat.SplitCompat
import com.javinator9889.handwashingreminder.appintro.R
import com.javinator9889.handwashingreminder.appintro.custom.*
+import com.javinator9889.handwashingreminder.appintro.databinding.AnimatedIntroBinding
class AnimatedAppIntro :
Fragment(),
ISlideSelectionListener,
- ISlideBackgroundColorHolder/*,
- LottieOnCompositionLoadedListener*/ {
+ ISlideBackgroundColorHolder,
+ IFragmentBinder,
+ ImageFragment {
private var drawable = 0
private var bgColor = 0
private var titleColor = 0
@@ -52,6 +54,11 @@ class AnimatedAppIntro :
@get:LayoutRes
protected val layoutId: Int = R.layout.animated_intro
private var title: String? = null
+ override var _binding: AnimatedIntroBinding? = null
+ private lateinit var _image: LottieAnimationView
+ override var image: LottieAnimationView
+ get() = _image
+ set(value) {_image = value}
@RawRes
private var animatedDrawable: Int? = null
@@ -64,7 +71,7 @@ class AnimatedAppIntro :
override fun onAttach(context: Context) {
super.onAttach(context)
- SplitCompat.installActivity(activity)
+ activity?.let { SplitCompat.installActivity(it) }
}
override fun onCreate(savedInstanceState: Bundle?) {
@@ -125,12 +132,12 @@ class AnimatedAppIntro :
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(layoutId, container, false)
+ _binding = AnimatedIntroBinding.bind(view)
+ image = binding.image
val titleText = view.findViewById(R.id.title)
val descriptionText = view.findViewById(R.id.description)
val slideImage = view.findViewById(R.id.image)
mainLayout = view.findViewById(R.id.main)
-// slideImage.addLottieOnCompositionLoadedListener(this)
-// slideImage.enableMergePathsForKitKatAndAbove(true)
titleText.text = title
if (titleColor != 0) {
titleText.setTextColor(titleColor)
diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/IFragmentBinder.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/IFragmentBinder.kt
new file mode 100644
index 0000000..46d3cf6
--- /dev/null
+++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/IFragmentBinder.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2020 - present | Handwashing reminder by Javinator9889
+ *
+ * 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/.
+ *
+ * Created by Javinator9889 on 7/12/20 - Handwashing reminder.
+ */
+package com.javinator9889.handwashingreminder.appintro.fragments
+
+import androidx.viewbinding.ViewBinding
+
+interface IFragmentBinder {
+ var _binding: T?
+ val binding: T get() = _binding!!
+}
\ No newline at end of file
diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/ImageFragment.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/ImageFragment.kt
new file mode 100644
index 0000000..ad61de8
--- /dev/null
+++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/ImageFragment.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2020 - present | Handwashing reminder by Javinator9889
+ *
+ * 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/.
+ *
+ * Created by Javinator9889 on 7/12/20 - Handwashing reminder.
+ */
+package com.javinator9889.handwashingreminder.appintro.fragments
+
+import com.airbnb.lottie.LottieAnimationView
+
+interface ImageFragment {
+ var image: LottieAnimationView
+}
\ No newline at end of file
diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/SlidePolicyFragment.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/SlidePolicyFragment.kt
index 084e94d..92f437f 100644
--- a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/SlidePolicyFragment.kt
+++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/SlidePolicyFragment.kt
@@ -25,6 +25,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
+import com.airbnb.lottie.LottieAnimationView
import com.github.paolorotolo.appintro.AppIntroBaseFragment
import com.github.paolorotolo.appintro.ISlidePolicy
import com.google.android.material.checkbox.MaterialCheckBox
@@ -34,12 +35,13 @@ import com.google.android.play.core.splitcompat.SplitCompat
import com.javinator9889.handwashingreminder.activities.PrivacyTermsActivity
import com.javinator9889.handwashingreminder.appintro.R
import com.javinator9889.handwashingreminder.appintro.custom.ARG_ANIM_DRAWABLE
+import com.javinator9889.handwashingreminder.appintro.databinding.SlidePolicyBinding
import com.javinator9889.handwashingreminder.appintro.utils.AnimatedResources
import com.javinator9889.handwashingreminder.utils.notNull
-import kotlinx.android.synthetic.main.slide_policy.view.*
import com.javinator9889.handwashingreminder.R as RBase
-class SlidePolicyFragment : AppIntroBaseFragment(), ISlidePolicy {
+class SlidePolicyFragment : AppIntroBaseFragment(), ISlidePolicy,
+ IFragmentBinder, ImageFragment {
companion object {
const val FIREBASE_ANALYTICS_CHECKED = "switch:fa:status"
const val FIREBASE_PERFORMANCE_CHECKED = "switch:fp:status"
@@ -51,6 +53,11 @@ class SlidePolicyFragment : AppIntroBaseFragment(), ISlidePolicy {
lateinit var firebasePerformance: SwitchMaterial
private lateinit var slidePolicyCheckBox: MaterialCheckBox
private var wasPolicyActivityLaunched = false
+ override var _binding: SlidePolicyBinding? = null
+ private lateinit var _image: LottieAnimationView
+ override var image: LottieAnimationView
+ get() = _image
+ set(value) {_image = value}
var title: String? = null
var titleColor: Int? = null
var imageDrawable: Int? = null
@@ -60,7 +67,7 @@ class SlidePolicyFragment : AppIntroBaseFragment(), ISlidePolicy {
override fun onAttach(context: Context) {
super.onAttach(context)
- SplitCompat.installActivity(activity)
+ activity?.let { SplitCompat.installActivity(it) }
}
override fun onCreateView(
@@ -69,13 +76,15 @@ class SlidePolicyFragment : AppIntroBaseFragment(), ISlidePolicy {
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(layoutId, container, false)
- firebaseAnalytics = view.analyticsSwitch
- firebasePerformance = view.performanceSwitch
- slidePolicyCheckBox = view.policyCheckbox
- layout = view.main
+ _binding = SlidePolicyBinding.bind(view)
+ image = binding.image
+ firebaseAnalytics = binding.analyticsSwitch
+ firebasePerformance = binding.performanceSwitch
+ slidePolicyCheckBox = binding.policyCheckbox
+ layout = binding.main
- val image = view.image
- val title = view.title
+ val image = binding.image
+ val title = binding.title
this.title?.let { title.text = it }
this.titleColor?.let { title.setTextColor(it) }
bgColor?.let { layout.setBackgroundColor(it) }
diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/TimeConfigIntroFragment.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/TimeConfigIntroFragment.kt
index 0f6a5ef..64bef6e 100644
--- a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/TimeConfigIntroFragment.kt
+++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/TimeConfigIntroFragment.kt
@@ -34,6 +34,8 @@ import androidx.recyclerview.widget.RecyclerView
import com.github.paolorotolo.appintro.AppIntroBaseFragment
import com.javinator9889.handwashingreminder.appintro.R
import com.javinator9889.handwashingreminder.appintro.TIME_CONFIG_REQUEST_CODE
+import com.javinator9889.handwashingreminder.appintro.databinding.TimeCardViewBinding
+import com.javinator9889.handwashingreminder.appintro.databinding.TimeConfigBinding
import com.javinator9889.handwashingreminder.appintro.timeconfig.TimeConfigActivity
import com.javinator9889.handwashingreminder.appintro.timeconfig.TimeConfigItem
import com.javinator9889.handwashingreminder.utils.AndroidVersion
@@ -43,8 +45,6 @@ import com.javinator9889.handwashingreminder.utils.isViewVisible
import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.adapters.ItemAdapter
import com.mikepenz.fastadapter.listeners.ClickEventHook
-import kotlinx.android.synthetic.main.time_card_view.view.*
-import kotlinx.android.synthetic.main.time_config.view.*
class TimeConfigIntroFragment : AppIntroBaseFragment() {
var bgColor: Int = Color.WHITE
@@ -53,6 +53,7 @@ class TimeConfigIntroFragment : AppIntroBaseFragment() {
lateinit var recyclerView: RecyclerView
lateinit var fastAdapter: FastAdapter
lateinit var itemAdapter: ItemAdapter
+ internal lateinit var binding: TimeConfigBinding
init {
propertyContainer[TimeConfig.BREAKFAST_ID.toInt()] = TimeContainer()
@@ -95,13 +96,17 @@ class TimeConfigIntroFragment : AppIntroBaseFragment() {
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
- ): View = inflater.inflate(layoutId, container, false)
+ ): View {
+ val view = inflater.inflate(layoutId, container, false)
+ binding = TimeConfigBinding.bind(view)
+ return view
+ }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val manager = LinearLayoutManager(context)
fastAdapter = FastAdapter.with(itemAdapter)
- recyclerView = view.cardsView.apply {
+ recyclerView = binding.cardsView.apply {
setHasFixedSize(true)
layoutManager = manager
adapter = fastAdapter
@@ -120,15 +125,21 @@ class TimeConfigIntroFragment : AppIntroBaseFragment() {
item: TimeConfigItem
) {
val intent = Intent(context, TimeConfigActivity::class.java)
+ val cardBinding = TimeCardViewBinding.bind(v)
val options = if (isAtLeast(AndroidVersion.LOLLIPOP)) {
val pairs = mutableListOf>()
val items = HashMap(6).apply {
- this[TimeConfigActivity.VIEW_TITLE_NAME] = v.title
- this[TimeConfigActivity.INFO_IMAGE_NAME] = v.infoImage
- this[TimeConfigActivity.USER_TIME_ICON] = v.clockIcon
- this[TimeConfigActivity.USER_TIME_HOURS] = v.hours
- this[TimeConfigActivity.USER_DDOT] = v.ddot
- this[TimeConfigActivity.USER_TIME_MINUTES] = v.minutes
+ this[TimeConfigActivity.VIEW_TITLE_NAME] =
+ cardBinding.title
+ this[TimeConfigActivity.INFO_IMAGE_NAME] =
+ cardBinding.infoImage
+ this[TimeConfigActivity.USER_TIME_ICON] =
+ cardBinding.clockIcon
+ this[TimeConfigActivity.USER_TIME_HOURS] =
+ cardBinding.hours
+ this[TimeConfigActivity.USER_DDOT] = cardBinding.ddot
+ this[TimeConfigActivity.USER_TIME_MINUTES] =
+ cardBinding.minutes
}
items.onEach {
if (it.value.isViewVisible(recyclerView))
@@ -142,9 +153,9 @@ class TimeConfigIntroFragment : AppIntroBaseFragment() {
null
}
intent.apply {
- putExtra("title", v.title.text)
- putExtra("hours", v.hours.text)
- putExtra("minutes", v.minutes.text)
+ putExtra("title", cardBinding.title.text)
+ putExtra("hours", cardBinding.hours.text)
+ putExtra("minutes", cardBinding.minutes.text)
putExtra("id", item.id)
putExtra("position", position)
}
@@ -160,5 +171,3 @@ class TimeConfigIntroFragment : AppIntroBaseFragment() {
override fun getLayoutId(): Int = R.layout.time_config
}
-
-data class TimeContainer(val hours: String? = "", val minutes: String? = "")
\ No newline at end of file
diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/TimeContainer.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/TimeContainer.kt
new file mode 100644
index 0000000..05ac05a
--- /dev/null
+++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/TimeContainer.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright © 2020 - present | Handwashing reminder by Javinator9889
+ *
+ * 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/.
+ *
+ * Created by Javinator9889 on 7/12/20 - Handwashing reminder.
+ */
+package com.javinator9889.handwashingreminder.appintro.fragments
+
+data class TimeContainer(val hours: String? = "", val minutes: String? = "")
diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigActivity.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigActivity.kt
index 865c61f..e35e3d3 100644
--- a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigActivity.kt
+++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigActivity.kt
@@ -30,10 +30,11 @@ import android.widget.TextView
import android.widget.TimePicker
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.ViewCompat
-import coil.api.load
+import coil.load
import com.google.android.play.core.splitcompat.SplitCompat
import com.javinator9889.handwashingreminder.activities.support.ActionBarBase
import com.javinator9889.handwashingreminder.appintro.R
+import com.javinator9889.handwashingreminder.appintro.databinding.TimeCardViewExpandedBinding
import com.javinator9889.handwashingreminder.utils.AndroidVersion
import com.javinator9889.handwashingreminder.utils.TimeConfig
import com.javinator9889.handwashingreminder.utils.formatTime
@@ -43,7 +44,7 @@ import java.util.*
import kotlin.properties.Delegates
class TimeConfigActivity :
- ActionBarBase(),
+ ActionBarBase(),
View.OnClickListener,
TimePickerDialog.OnTimeSetListener {
companion object Transitions {
@@ -95,22 +96,28 @@ class TimeConfigActivity :
ddot.setOnClickListener(this)
minutes.setOnClickListener(this)
clockIcon.setOnClickListener(this)
- ViewCompat.setTransitionName(title,
+ ViewCompat.setTransitionName(
+ title,
VIEW_TITLE_NAME
)
- ViewCompat.setTransitionName(image,
+ ViewCompat.setTransitionName(
+ image,
INFO_IMAGE_NAME
)
- ViewCompat.setTransitionName(hours,
+ ViewCompat.setTransitionName(
+ hours,
USER_TIME_HOURS
)
- ViewCompat.setTransitionName(ddot,
+ ViewCompat.setTransitionName(
+ ddot,
USER_DDOT
)
- ViewCompat.setTransitionName(minutes,
+ ViewCompat.setTransitionName(
+ minutes,
USER_TIME_MINUTES
)
- ViewCompat.setTransitionName(clockIcon,
+ ViewCompat.setTransitionName(
+ clockIcon,
USER_TIME_ICON
)
@@ -207,4 +214,8 @@ class TimeConfigActivity :
hours.text = formatTime(hourOfDay)
minutes.text = formatTime(minute)
}
+
+ override fun inflateLayout(): TimeCardViewExpandedBinding =
+ TimeCardViewExpandedBinding.inflate(layoutInflater)
+ .also { binding = it }
}
\ No newline at end of file
diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigItem.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigItem.kt
index 59016de..a08a715 100644
--- a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigItem.kt
+++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigItem.kt
@@ -23,7 +23,7 @@ import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.LayoutRes
import androidx.cardview.widget.CardView
-import coil.api.load
+import coil.load
import com.javinator9889.handwashingreminder.appintro.R
import com.javinator9889.handwashingreminder.utils.TimeConfig
import com.javinator9889.handwashingreminder.utils.notNull
diff --git a/appintro/src/main/res/layout/time_card_view.xml b/appintro/src/main/res/layout/time_card_view.xml
index 9b95689..77f3007 100644
--- a/appintro/src/main/res/layout/time_card_view.xml
+++ b/appintro/src/main/res/layout/time_card_view.xml
@@ -1,152 +1,146 @@
-
+ android:layout_margin="8dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginLeft="8dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginRight="8dp"
+ android:checkable="true"
+ android:clickable="true"
+ android:focusable="true"
+ android:minHeight="0dp"
+ android:padding="8dp"
+ android:visibility="visible"
+ app:cardCornerRadius="16dp"
+ app:cardElevation="4dp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.0"
+ app:layout_constraintStart_toStartOf="parent">
-
+ android:layout_height="wrap_content">
+
+
-
+ android:layout_height="match_parent"
+ android:layout_marginStart="8dp"
+ android:layout_marginLeft="8dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginRight="8dp"
+ android:layout_marginBottom="16dp"
+ android:orientation="horizontal"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/title">
-
+
+
+ android:layout_marginRight="16dp"
+ android:gravity="center_vertical">
-
-
-
-
-
-
-
+ android:layout_marginEnd="8dp"
+ android:tint="@color/dkgray"
+ app:iiv_color="@color/dkgray"
+ app:iiv_icon="ion_android_time"
+ app:iiv_size="16dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/hours"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
-
-
-
+
-
-
+
-
+
+
-
+
-
+
-
+
diff --git a/build.gradle b/build.gradle
index 68d64ad..0d21a1e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,23 +1,26 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = '1.3.72'
- ext.latestAboutLibsRelease = '8.2.0'
- ext.latestFastAdapterRelease = '5.1.0'
+ ext.kotlin_version = '1.4.21'
+ ext.latestAboutLibsRelease = '8.6.3'
+ ext.latestFastAdapterRelease = '5.3.2'
repositories {
google()
jcenter()
maven {
url 'https://maven.fabric.io/public'
}
+ maven {
+ url "https://plugins.gradle.org/m2/"
+ }
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.0.0'
+ classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${latestAboutLibsRelease}"
- classpath 'com.google.gms:google-services:4.3.3'
- classpath 'com.google.firebase:firebase-crashlytics-gradle:2.2.0'
- classpath 'com.google.firebase:perf-plugin:1.3.1' // Performance Monitoring plugin
+ classpath 'com.google.gms:google-services:4.3.4'
+ classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1'
+ classpath 'com.google.firebase:perf-plugin:1.3.4' // Performance Monitoring plugin
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
diff --git a/bundledemoji/build.gradle b/bundledemoji/build.gradle
index 51644f3..51a3752 100644
--- a/bundledemoji/build.gradle
+++ b/bundledemoji/build.gradle
@@ -1,14 +1,19 @@
apply plugin: 'com.android.dynamic-feature'
apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
android {
- compileSdkVersion 29
+ buildFeatures {
+ viewBinding true
+ dataBinding true
+ }
+
+ compileSdkVersion 30
defaultConfig {
- minSdkVersion 17
- targetSdkVersion 29
+ minSdkVersion 16
+ targetSdkVersion 30
versionCode 1
versionName "1.0"
diff --git a/extras/23920-error-state-dog.json b/extras/23920-error-state-dog.json
new file mode 100644
index 0000000..08f89b7
--- /dev/null
+++ b/extras/23920-error-state-dog.json
@@ -0,0 +1 @@
+{"v":"5.2.1","fr":60,"ip":0,"op":360,"w":1080,"h":1080,"nm":"Dog swimming","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Dog swimming Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[540,516,0],"ix":2},"a":{"a":0,"k":[540,540,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[-8.06,11.343],[-11.941,-35.223],[-16.119,-22.985],[28.488,-33.207],[17.611,8.657],[-5.075,48.953],[4.528,38.096]],"o":[[8.955,0.298],[11.939,35.222],[16.119,22.983],[-9.371,10.923],[-17.612,-8.656],[5.074,-48.954],[-3.178,-26.736]],"v":[[-39.699,-119.399],[9.852,-85.967],[47.163,-2.089],[47.163,91.937],[9.809,104.369],[-7.623,40.432],[-34.236,-72.736]],"c":true}],"e":[{"i":[[5.991,-0.491],[-11.941,-35.223],[-16.119,-22.985],[-3.121,-28.827],[-1.816,19.539],[36.665,51.678],[13.478,41.397]],"o":[[8.955,0.298],[11.939,35.222],[16.119,22.983],[4.709,43.498],[0.233,-2.509],[-8.038,-4.369],[-9.432,-28.969]],"v":[[-39.699,-119.399],[9.852,-85.967],[47.163,-2.089],[79.663,70.687],[38.559,92.869],[14.627,13.932],[-6.736,-71.236]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[5.991,-0.491],[-11.941,-35.223],[-16.119,-22.985],[-3.121,-28.827],[-1.816,19.539],[36.665,51.678],[13.478,41.397]],"o":[[8.955,0.298],[11.939,35.222],[16.119,22.983],[4.709,43.498],[0.233,-2.509],[-8.038,-4.369],[-9.432,-28.969]],"v":[[-39.699,-119.399],[9.852,-85.967],[47.163,-2.089],[79.663,70.687],[38.559,92.869],[14.627,13.932],[-6.736,-71.236]],"c":true}],"e":[{"i":[[-8.06,11.343],[-11.941,-35.223],[-16.119,-22.985],[28.488,-33.207],[17.611,8.657],[-5.075,48.953],[4.528,38.096]],"o":[[8.955,0.298],[11.939,35.222],[16.119,22.983],[-9.371,10.923],[-17.612,-8.656],[5.074,-48.954],[-3.178,-26.736]],"v":[[-39.699,-119.399],[9.852,-85.967],[47.163,-2.089],[47.163,91.937],[9.809,104.369],[-7.623,40.432],[-34.236,-72.736]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.552999997606,0.463000009574,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[659.708,424.639],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 14","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[-18.507,15.785],[-12.701,0],[-6.895,-8.738],[29.619,0]],"o":[[6.23,-5.313],[12.7,0],[6.895,8.738],[-29.619,0]],"v":[[-63.756,-6.071],[-23.114,-10.863],[21.519,-1.561],[-20.348,16.48]],"c":true}],"e":[{"i":[[-35.58,30.35],[-24.418,0],[-13.255,-16.801],[56.945,0]],"o":[[11.977,-10.215],[24.417,0],[13.256,16.8],[-56.945,0]],"v":[[-78.101,-17.058],[0.037,-26.271],[85.847,-8.386],[5.355,26.298]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[-35.58,30.35],[-24.418,0],[-13.255,-16.801],[56.945,0]],"o":[[11.977,-10.215],[24.417,0],[13.256,16.8],[-56.945,0]],"v":[[-78.101,-17.058],[0.037,-26.271],[85.847,-8.386],[5.355,26.298]],"c":true}],"e":[{"i":[[-18.508,15.785],[-12.701,0],[-6.895,-8.738],[29.619,0]],"o":[[6.23,-5.313],[12.7,0],[6.895,8.738],[-29.619,0]],"v":[[-63.756,-6.071],[-23.114,-10.863],[21.519,-1.561],[-20.348,16.48]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.6,0.677999997606,0.976000019148,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[872.896,754.863],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":60,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[5.44,10.815]],"o":[[0,0],[0,0]],"v":[[-0.026,10.194],[-2.72,-10.195]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.992156922583,0.580392156863,0.20000001496,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":7,"ix":5},"lc":2,"lj":1,"ml":10,"ml2":{"a":0,"k":10,"ix":8},"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[660.225,621.047],"e":[735.225,602.047],"to":[12.5,-3.16666674613953],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[735.225,602.047],"e":[660.225,621.047],"to":[0,0],"ti":[12.5,-3.16666674613953]},{"t":359}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[5.439,10.814]],"o":[[0,0],[0,0]],"v":[[-1.759,11.392],[-2.719,-11.393]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.992156922583,0.6,0.231372563979,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":7,"ix":5},"lc":2,"lj":1,"ml":10,"ml2":{"a":0,"k":10,"ix":8},"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[623.612,624.245],"e":[701.612,604.245],"to":[13,-3.33333325386047],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[701.612,604.245],"e":[623.612,624.245],"to":[0,0],"ti":[13,-3.33333325386047]},{"t":359}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[-8.523,10.648]],"o":[[0,0],[0,0]],"v":[[-10.026,18.194],[-4.22,-6.195]],"c":false}],"e":[{"i":[[0,0],[5.439,10.815]],"o":[[0,0],[0,0]],"v":[[-0.026,10.194],[-2.72,-10.195]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[0,0],[5.439,10.815]],"o":[[0,0],[0,0]],"v":[[-0.026,10.194],[-2.72,-10.195]],"c":false}],"e":[{"i":[[0,0],[-8.523,10.648]],"o":[[0,0],[0,0]],"v":[[-10.026,18.194],[-4.22,-6.195]],"c":false}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.992156922817,0.580392181873,0.200000017881,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":7,"ix":5},"lc":2,"lj":1,"ml":10,"ml2":{"a":0,"k":10,"ix":8},"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[457.742,613.547],"e":[515.242,603.047],"to":[9.58333301544189,-1.75],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[515.242,603.047],"e":[457.742,613.547],"to":[0,0],"ti":[9.58333301544189,-1.75]},{"t":359}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[-7.409,10.147]],"o":[[0,0],[0,0]],"v":[[-69.76,13.392],[-65.72,-8.893]],"c":false}],"e":[{"i":[[0,0],[5.44,10.814]],"o":[[0,0],[0,0]],"v":[[-1.76,11.392],[-2.72,-11.393]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[0,0],[5.44,10.814]],"o":[[0,0],[0,0]],"v":[[-1.76,11.392],[-2.72,-11.393]],"c":false}],"e":[{"i":[[0,0],[-7.409,10.147]],"o":[[0,0],[0,0]],"v":[[-69.76,13.392],[-65.72,-8.893]],"c":false}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.992156922817,0.580392181873,0.200000017881,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":7,"ix":5},"lc":2,"lj":1,"ml":10,"ml2":{"a":0,"k":10,"ix":8},"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[481.629,604.245],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":2,"cix":2,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[2.194,-16.08]],"o":[[0,0],[0,0]],"v":[[-101.191,1.64],[-102.597,32.36]],"c":false}],"e":[{"i":[[0,0],[2.194,-16.08]],"o":[[0,0],[0,0]],"v":[[0.309,-15.36],[-1.097,15.36]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[0,0],[2.194,-16.08]],"o":[[0,0],[0,0]],"v":[[0.309,-15.36],[-1.097,15.36]],"c":false}],"e":[{"i":[[0,0],[2.194,-16.08]],"o":[[0,0],[0,0]],"v":[[-101.191,1.64],[-102.597,32.36]],"c":false}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.109999997008,0.19199999641,0.46699999641,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":7,"ix":5},"lc":2,"lj":1,"ml":10,"ml2":{"a":0,"k":10,"ix":8},"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[627.113,496.521],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 6","np":2,"cix":2,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[-2.399,14.16],[-3.32,-7.2],[10.559,0]],"o":[[0.916,-5.401],[3.321,7.2],[-10.561,0]],"v":[[-121.101,-5.74],[-78.821,-5.74],[-96.38,19.94]],"c":true}],"e":[{"i":[[-2.399,14.16],[-3.32,-7.2],[10.559,0]],"o":[[0.916,-5.401],[3.321,7.2],[-10.561,0]],"v":[[-21.601,-9.24],[20.679,-9.24],[3.12,16.44]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[-2.399,14.16],[-3.32,-7.2],[10.559,0]],"o":[[0.916,-5.401],[3.321,7.2],[-10.561,0]],"v":[[-21.601,-9.24],[20.679,-9.24],[3.12,16.44]],"c":true}],"e":[{"i":[[-2.399,14.16],[-3.32,-7.2],[10.559,0]],"o":[[0.916,-5.401],[3.321,7.2],[-10.561,0]],"v":[[-121.101,-5.74],[-78.821,-5.74],[-96.38,19.94]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109999997008,0.19199999641,0.46699999641,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[623.29,480.081],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 7","np":2,"cix":2,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0.603,4.731],[5.963,2.379],[1.536,-7.998],[-5.111,0.295]],"o":[[-0.549,-4.31],[-5.962,-2.379],[-1.537,7.999],[5.111,-0.295]],"v":[[-44.114,3.099],[-61.539,-5.873],[-76.655,0.409],[-58.093,10.788]],"c":true}],"e":[{"i":[[-0.429,4.75],[5.311,3.607],[3.221,-7.48],[-5.055,-0.812]],"o":[[0.391,-4.327],[-5.31,-3.606],[-3.222,7.481],[5.055,0.812]],"v":[[17.016,5.899],[1.93,-6.612],[-14.184,-3.732],[1.709,10.399]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[-0.429,4.75],[5.311,3.607],[3.221,-7.48],[-5.055,-0.812]],"o":[[0.391,-4.327],[-5.31,-3.606],[-3.222,7.481],[5.055,0.812]],"v":[[17.016,5.899],[1.93,-6.612],[-14.184,-3.732],[1.709,10.399]],"c":true}],"e":[{"i":[[0.603,4.731],[5.963,2.379],[1.536,-7.998],[-5.111,0.295]],"o":[[-0.549,-4.31],[-5.962,-2.379],[-1.537,7.999],[5.111,-0.295]],"v":[[-44.114,3.099],[-61.539,-5.873],[-76.655,0.409],[-58.093,10.788]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.552999997606,0.463000009574,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[639.903,387.207],"e":[640.403,398.707],"to":[0.08333333581686,1.91666662693024],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":190,"s":[640.403,398.707],"e":[639.903,387.207],"to":[0,0],"ti":[0.08333333581686,1.91666662693024]},{"t":200}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 8","np":2,"cix":2,"ix":9,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[-0.898,5.186],[-7.112,1.874],[-1.489,-9.099],[6.003,0.992]],"o":[[0.818,-4.724],[7.112,-1.874],[1.489,9.1],[-6.005,-0.992]],"v":[[-86.955,3.485],[-66.089,-4.233],[-48.546,4.721],[-70.807,13.858]],"c":true}],"e":[{"i":[[1.06,5.155],[-5.935,4.344],[-4.713,-7.924],[5.95,-1.273]],"o":[[-0.966,-4.696],[5.934,-4.345],[4.714,7.925],[-5.952,1.273]],"v":[[-19.974,7.833],[-3.376,-6.981],[16.226,-5.064],[-1.151,11.582]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[1.06,5.155],[-5.935,4.344],[-4.713,-7.924],[5.95,-1.273]],"o":[[-0.966,-4.696],[5.934,-4.345],[4.714,7.925],[-5.952,1.273]],"v":[[-19.974,7.833],[-3.376,-6.981],[16.226,-5.064],[-1.151,11.582]],"c":true}],"e":[{"i":[[-0.898,5.186],[-7.112,1.874],[-1.489,-9.099],[6.003,0.992]],"o":[[0.818,-4.724],[7.112,-1.874],[1.489,9.1],[-6.005,-0.992]],"v":[[-86.955,3.485],[-66.089,-4.233],[-48.546,4.721],[-70.807,13.858]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.552999997606,0.463000009574,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[538.372,387.533],"e":[538.372,401.033],"to":[0,2.25],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":190,"s":[538.372,401.033],"e":[538.372,387.533],"to":[0,0],"ti":[0,2.25]},{"t":200}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 9","np":2,"cix":2,"ix":10,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,-7.158],[7.158,0],[0,7.158],[-7.157,0]],"o":[[0,7.158],[-7.157,0],[0,-7.158],[7.158,0]],"v":[[-59.54,-3],[-72.5,9.96],[-85.46,-3],[-72.5,-15.96]],"c":true}],"e":[{"i":[[0,-7.158],[7.158,0],[0,7.158],[-7.157,0]],"o":[[0,7.158],[-7.157,0],[0,-7.158],[7.158,0]],"v":[[12.96,0],[0,12.96],[-12.96,0],[0,-12.96]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[0,-7.158],[7.158,0],[0,7.158],[-7.157,0]],"o":[[0,7.158],[-7.157,0],[0,-7.158],[7.158,0]],"v":[[12.96,0],[0,12.96],[-12.96,0],[0,-12.96]],"c":true}],"e":[{"i":[[0,-7.158],[7.158,0],[0,7.158],[-7.157,0]],"o":[[0,7.158],[-7.157,0],[0,-7.158],[7.158,0]],"v":[[-59.54,-3],[-72.5,9.96],[-85.46,-3],[-72.5,-15.96]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109999997008,0.19199999641,0.46699999641,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[643.97,428.281],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":180,"s":[100,100],"e":[100,0]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":190,"s":[100,0],"e":[100,100]},{"t":200}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 10","np":2,"cix":2,"ix":11,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,-7.158],[7.158,0],[0,7.158],[-7.157,0]],"o":[[0,7.158],[-7.157,0],[0,-7.158],[7.158,0]],"v":[[-51.54,-3.5],[-64.5,9.46],[-77.46,-3.5],[-64.5,-16.46]],"c":true}],"e":[{"i":[[0,-7.158],[7.158,0],[0,7.158],[-7.157,0]],"o":[[0,7.158],[-7.157,0],[0,-7.158],[7.158,0]],"v":[[12.96,0],[0,12.96],[-12.96,0],[0,-12.96]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[0,-7.158],[7.158,0],[0,7.158],[-7.157,0]],"o":[[0,7.158],[-7.157,0],[0,-7.158],[7.158,0]],"v":[[12.96,0],[0,12.96],[-12.96,0],[0,-12.96]],"c":true}],"e":[{"i":[[0,-7.158],[7.158,0],[0,7.158],[-7.157,0]],"o":[[0,7.158],[-7.157,0],[0,-7.158],[7.158,0]],"v":[[-51.54,-3.5],[-64.5,9.46],[-77.46,-3.5],[-64.5,-16.46]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109999997008,0.19199999641,0.46699999641,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[538.689,427.781],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":180,"s":[100,100],"e":[100,0]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":190,"s":[100,0],"e":[100,100]},{"t":200}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 11","np":2,"cix":2,"ix":12,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[-11.81,22.259],[12.801,-37.76],[14.09,-26.593],[-18.19,-34.801],[-18.911,9.216],[-36.25,82.919],[1.92,28.8]],"o":[[-9.6,0.32],[-12.8,37.76],[-16.69,31.499],[8.201,15.69],[27.089,-13.201],[14.535,-33.249],[-1.919,-28.8]],"v":[[42.56,-128],[4.94,-76.66],[-15.06,-2.24],[-29.06,98.56],[9.161,111.46],[31,16.84],[37,-72.44]],"c":true}],"e":[{"i":[[8.641,12.16],[12.801,-37.76],[17.28,-24.64],[-34.88,-31.36],[-18.88,9.28],[5.44,52.48],[1.92,28.8]],"o":[[-9.6,0.32],[-12.8,37.76],[-17.279,24.64],[34.881,31.36],[18.879,-9.28],[-5.44,-52.48],[-1.919,-28.8]],"v":[[42.56,-128],[-10.56,-92.16],[-50.56,-2.24],[-50.56,98.56],[44.161,112.96],[80,35.84],[56,-77.44]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[8.641,12.16],[12.801,-37.76],[17.28,-24.64],[-34.88,-31.36],[-18.88,9.28],[5.44,52.48],[1.92,28.8]],"o":[[-9.6,0.32],[-12.8,37.76],[-17.279,24.64],[34.881,31.36],[18.879,-9.28],[-5.44,-52.48],[-1.919,-28.8]],"v":[[42.56,-128],[-10.56,-92.16],[-50.56,-2.24],[-50.56,98.56],[44.161,112.96],[80,35.84],[56,-77.44]],"c":true}],"e":[{"i":[[-11.81,22.259],[12.801,-37.76],[14.09,-26.593],[-18.19,-34.801],[-18.911,9.216],[-36.25,82.919],[1.92,28.8]],"o":[[-9.6,0.32],[-12.8,37.76],[-16.69,31.499],[8.201,15.69],[27.089,-13.201],[14.535,-33.249],[-1.919,-28.8]],"v":[[42.56,-128],[4.94,-76.66],[-15.06,-2.24],[-29.06,98.56],[9.161,111.46],[31,16.84],[37,-72.44]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.552999997606,0.463000009574,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[398.25,433.241],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 12","np":2,"cix":2,"ix":13,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[-44.209,1.799],[-17.28,-23.52],[-21.45,-57.281],[-1.39,-13.853],[59.37,-8.121],[6.971,4.199],[43.044,16.239],[-9.269,19.759],[-21.515,28.482]],"o":[[46.707,-1.901],[17.281,23.52],[6.024,16.085],[6.05,60.279],[-29.418,4.024],[-15.529,1.199],[-49.729,-18.761],[19.22,-40.97],[35.723,-9.784]],"v":[[-28.268,-140.65],[61.177,-106.789],[103.698,-23.609],[121.698,37.831],[33.378,141.23],[-35.223,129.91],[-121.023,137.62],[-135.483,28.85],[-123.443,-116.65]],"c":true}],"e":[{"i":[[-44.209,1.799],[-17.28,-23.52],[-2.16,-17.04],[-8.16,-11.28],[16.08,-24.96],[27.84,13.68],[45.36,7.68],[11.054,77.374],[-21.515,28.482]],"o":[[46.707,-1.901],[17.281,23.52],[2.16,17.04],[8.749,12.095],[-16.081,24.96],[-28.08,11.04],[-45.359,-7.68],[-6.399,-44.8],[35.723,-9.784]],"v":[[-28.268,-140.65],[73.677,-101.289],[103.198,-3.609],[121.198,33.831],[128.878,108.23],[58.777,125.91],[-38.523,134.87],[-138.483,11.35],[-123.443,-116.65]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[-44.209,1.799],[-17.28,-23.52],[-2.16,-17.04],[-8.16,-11.28],[16.08,-24.96],[27.84,13.68],[45.36,7.68],[11.054,77.374],[-21.515,28.482]],"o":[[46.707,-1.901],[17.281,23.52],[2.16,17.04],[8.749,12.095],[-16.081,24.96],[-28.08,11.04],[-45.359,-7.68],[-6.399,-44.8],[35.723,-9.784]],"v":[[-28.268,-140.65],[73.677,-101.289],[103.198,-3.609],[121.198,33.831],[128.878,108.23],[58.777,125.91],[-38.523,134.87],[-138.483,11.35],[-123.443,-116.65]],"c":true}],"e":[{"i":[[-44.209,1.799],[-17.28,-23.52],[-21.45,-57.281],[-1.39,-13.853],[59.37,-8.121],[6.971,4.199],[43.044,16.239],[-9.269,19.759],[-21.515,28.482]],"o":[[46.707,-1.901],[17.281,23.52],[6.024,16.085],[6.05,60.279],[-29.418,4.024],[-15.529,1.199],[-49.729,-18.761],[19.22,-40.97],[35.723,-9.784]],"v":[[-28.268,-140.65],[61.177,-106.789],[103.698,-23.609],[121.698,37.831],[33.378,141.23],[-35.223,129.91],[-121.023,137.62],[-135.483,28.85],[-123.443,-116.65]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.995999983245,0.760999971278,0.447000002394,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[564.252,421.89],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 13","np":2,"cix":2,"ix":14,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[-61.7,32.678],[0,0]],"o":[[0,0],[-24.913,-44.001],[0,0]],"v":[[-61.944,3.971],[-1.556,21.48],[-34.147,-23.348]],"c":true}],"e":[{"i":[[0,0],[-61.7,32.678],[0,0]],"o":[[0,0],[-24.913,-44.001],[0,0]],"v":[[-71.488,-15.773],[8.894,20.108],[-48.691,-62.092]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":38,"s":[{"i":[[0,0],[-61.7,32.678],[0,0]],"o":[[0,0],[-24.913,-44.001],[0,0]],"v":[[-71.488,-15.773],[8.894,20.108],[-48.691,-62.092]],"c":true}],"e":[{"i":[[0,0],[-61.7,32.678],[0,0]],"o":[[0,0],[-24.913,-44.001],[0,0]],"v":[[-47.944,-9.029],[47.944,14.98],[-20.147,-36.348]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[0,0],[-61.7,32.678],[0,0]],"o":[[0,0],[-24.913,-44.001],[0,0]],"v":[[-47.944,-9.029],[47.944,14.98],[-20.147,-36.348]],"c":true}],"e":[{"i":[[0,0],[-61.7,32.678],[0,0]],"o":[[0,0],[-24.913,-44.001],[0,0]],"v":[[-61.944,3.971],[-1.556,21.48],[-34.147,-23.348]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.996078491211,0.678431372549,0.337254901961,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[489.267,540.931],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 15","np":2,"cix":2,"ix":15,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[12.086,-16.079],[-11.965,-11.502],[-20.626,2.179],[5.38,41.823],[0,0]],"o":[[0,0],[-8.157,10.853],[11.965,11.502],[11.845,-1.251],[1.38,-22.677],[0,0]],"v":[[-57.6,-20],[-79.775,7.038],[-80.107,45.994],[-13.535,68.21],[3.93,17.636],[-0.32,-18.74]],"c":true}],"e":[{"i":[[0,0],[9.129,-15.522],[-12.749,-10.222],[-18.974,5.164],[9.108,37.182],[0,0]],"o":[[0,0],[-6.03,11.399],[12.749,10.223],[12.047,-4.432],[-5.465,-23.7],[0,0]],"v":[[-63.6,-66],[-71.581,7.68],[-68.465,45.91],[-1.22,61.816],[8.573,8.745],[-10.264,-55.234]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":38,"s":[{"i":[[0,0],[9.129,-15.522],[-12.749,-10.222],[-18.974,5.164],[9.108,37.182],[0,0]],"o":[[0,0],[-6.03,11.399],[12.749,10.223],[12.047,-4.432],[-5.465,-23.7],[0,0]],"v":[[-63.6,-66],[-71.581,7.68],[-68.465,45.91],[-1.22,61.816],[8.573,8.745],[-10.264,-55.234]],"c":true}],"e":[{"i":[[0,0],[-1.92,-13.44],[-15.68,-5.44],[-12.8,16.32],[23.039,19.839],[0,0]],"o":[[0,0],[1.92,13.44],[15.68,5.44],[12.8,-16.32],[-31.041,-27.52],[0,0]],"v":[[-57.6,-20],[-40.96,10.08],[-24.96,45.6],[44.8,37.92],[25.921,-24.48],[-40.32,-54.24]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[0,0],[-1.92,-13.44],[-15.68,-5.44],[-12.8,16.32],[23.039,19.839],[0,0]],"o":[[0,0],[1.92,13.44],[15.68,5.44],[12.8,-16.32],[-31.041,-27.52],[0,0]],"v":[[-57.6,-20],[-40.96,10.08],[-24.96,45.6],[44.8,37.92],[25.921,-24.48],[-40.32,-54.24]],"c":true}],"e":[{"i":[[0,0],[12.086,-16.079],[-11.965,-11.502],[-20.626,2.179],[5.38,41.823],[0,0]],"o":[[0,0],[-8.157,10.853],[11.965,11.502],[11.845,-1.251],[1.38,-22.677],[0,0]],"v":[[-57.6,-20],[-79.775,7.038],[-80.107,45.994],[-13.535,68.21],[3.93,17.636],[-0.32,-18.74]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.995999983245,0.760999971278,0.447000002394,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[483.69,570.041],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 16","np":2,"cix":2,"ix":16,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[12.819,24.122],[6.525,8.762],[0,0],[-0.759,-6.557]],"o":[[0,0],[-7.046,-13.258],[-50.502,2.503],[0,0],[0.82,7.085]],"v":[[-80.019,35.909],[-0.49,19.04],[-24.311,-13.48],[-81.671,11.35],[-79.856,24.697]],"c":true}],"e":[{"i":[[0,0],[12.819,24.122],[6.525,8.762],[0,0],[-0.759,-6.557]],"o":[[0,0],[-7.046,-13.258],[-50.502,2.503],[0,0],[0.82,7.085]],"v":[[-49.17,32.086],[31.212,15.583],[-8.157,-23.448],[-50.517,6.187],[-48.763,20.631]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":84,"s":[{"i":[[0,0],[12.819,24.122],[6.525,8.762],[0,0],[-0.759,-6.557]],"o":[[0,0],[-7.046,-13.258],[-50.502,2.503],[0,0],[0.82,7.085]],"v":[[-49.17,32.086],[31.212,15.583],[-8.157,-23.448],[-50.517,6.187],[-48.763,20.631]],"c":true}],"e":[{"i":[[0,0],[12.819,24.122],[13.172,6.655],[0,0],[-0.759,-6.557]],"o":[[0,0],[-7.046,-13.258],[-50.502,2.503],[0,0],[0.82,7.085]],"v":[[-13.767,28.38],[67.443,11.731],[7.792,-31.623],[-29.817,0.682],[-18.624,16.689]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[0,0],[12.819,24.122],[13.172,6.655],[0,0],[-0.759,-6.557]],"o":[[0,0],[-7.046,-13.258],[-50.502,2.503],[0,0],[0.82,7.085]],"v":[[-13.767,28.38],[67.443,11.731],[7.792,-31.623],[-29.817,0.682],[-18.624,16.689]],"c":true}],"e":[{"i":[[0,0],[12.819,24.122],[6.525,8.762],[0,0],[-0.759,-6.557]],"o":[[0,0],[-7.046,-13.258],[-50.502,2.503],[0,0],[0.82,7.085]],"v":[[-49.17,32.086],[31.212,15.583],[-8.157,-23.448],[-50.517,6.187],[-48.763,20.631]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":272,"s":[{"i":[[0,0],[12.819,24.122],[6.525,8.762],[0,0],[-0.759,-6.557]],"o":[[0,0],[-7.046,-13.258],[-50.502,2.503],[0,0],[0.82,7.085]],"v":[[-49.17,32.086],[31.212,15.583],[-8.157,-23.448],[-50.517,6.187],[-48.763,20.631]],"c":true}],"e":[{"i":[[0,0],[12.819,24.122],[6.525,8.762],[0,0],[-0.759,-6.557]],"o":[[0,0],[-7.046,-13.258],[-50.502,2.503],[0,0],[0.82,7.085]],"v":[[-80.019,35.909],[-0.49,19.04],[-24.311,-13.48],[-81.671,11.35],[-79.856,24.697]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.996078491211,0.678431372549,0.337254901961,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[676.036,548.968],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 17","np":2,"cix":2,"ix":17,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[10.787,-21.621],[-15.68,-5.44],[-12.799,16.32],[12.407,32.439],[0,0]],"o":[[0,0],[-6.061,12.148],[15.679,5.44],[12.8,-16.32],[-19.093,-41.561],[0,0]],"v":[[-57.6,-20],[-61.959,27.08],[-45.959,62.6],[23.8,54.92],[28.921,-1.48],[-16.32,-59.24]],"c":true}],"e":[{"i":[[0,0],[-1.92,-13.44],[-15.68,-5.44],[-12.799,16.32],[23.04,19.839],[0,0]],"o":[[0,0],[1.92,13.44],[15.679,5.44],[12.8,-16.32],[-31.041,-27.52],[0,0]],"v":[[-57.6,-20],[-40.959,10.08],[-24.959,45.6],[44.8,37.92],[25.921,-24.48],[-40.32,-54.24]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[0,0],[-1.92,-13.44],[-15.68,-5.44],[-12.799,16.32],[23.04,19.839],[0,0]],"o":[[0,0],[1.92,13.44],[15.679,5.44],[12.8,-16.32],[-31.041,-27.52],[0,0]],"v":[[-57.6,-20],[-40.959,10.08],[-24.959,45.6],[44.8,37.92],[25.921,-24.48],[-40.32,-54.24]],"c":true}],"e":[{"i":[[0,0],[10.787,-21.621],[-15.68,-5.44],[-12.799,16.32],[12.407,32.439],[0,0]],"o":[[0,0],[-6.061,12.148],[15.679,5.44],[12.8,-16.32],[-19.093,-41.561],[0,0]],"v":[[-57.6,-20],[-61.959,27.08],[-45.959,62.6],[23.8,54.92],[28.921,-1.48],[-16.32,-59.24]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.995999983245,0.760999971278,0.447000002394,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[651.672,580.041],"e":[703.672,570.041],"to":[8.66666698455811,-1.66666662693024],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[703.672,570.041],"e":[651.672,580.041],"to":[0,0],"ti":[8.66666698455811,-1.66666662693024]},{"t":359}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 18","np":2,"cix":2,"ix":18,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-38.631],[150.325,0],[0,38.63],[-150.325,0]],"o":[[0,38.63],[-150.325,0],[0,-38.631],[150.325,0]],"v":[[228.96,0],[-2.087,69.947],[-228.96,0],[-2.087,-69.947]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.886274569642,0.792156922583,0.925490255917,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[544.33,539.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":70,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 19","np":2,"cix":2,"ix":19,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"n":"0p667_1_0p167_0p167","t":0,"s":[{"i":[[0,0],[8.637,-160.553],[0,0],[-64.287,88.691],[-23.216,-2.405],[-74.974,-110.169],[3.114,11.391],[72.038,22.96],[0,0],[0,0],[21.175,-3.413],[0,0]],"o":[[0,0],[86.979,67.305],[0,0],[25.386,0.821],[98.964,10.251],[38.02,-41.759],[-12.841,-21.255],[-52.56,-12.96],[0,0],[0,0],[-16.918,7.478],[0,0]],"v":[[-131.05,-94.547],[-295.654,109.668],[-98.734,173.487],[-44.479,-83.844],[58.779,-85.268],[282.997,72.442],[300.23,-32.745],[191.787,-112.796],[102.622,-143.052],[-215.112,-122.818],[-243.595,-113.668],[-260.797,-107.167]],"c":true}],"e":[{"i":[[0,0],[8.637,-160.553],[0,0],[-64.287,88.691],[-20.53,-0.521],[-74.835,-109.965],[3.114,11.391],[72.038,22.96],[0,0],[0,0],[17.24,-6.036],[0,0]],"o":[[0,0],[91.888,44.724],[0,0],[25.586,0.827],[86.669,2.198],[5.129,-19.177],[-12.841,-21.255],[-52.559,-12.96],[0,0],[0,0],[-20.237,8.642],[0,0]],"v":[[-131.05,-94.547],[-212.69,152.868],[55.903,165.633],[26.212,-104.462],[94.965,-103.048],[305.579,19.424],[300.23,-32.745],[191.787,-112.796],[102.622,-143.052],[-232.058,-116.778],[-271.401,-100.686],[-301.84,-85.542]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"n":"0p833_0p833_0p333_0","t":180,"s":[{"i":[[0,0],[8.637,-160.553],[0,0],[-64.287,88.691],[-20.53,-0.521],[-74.835,-109.965],[3.114,11.391],[72.038,22.96],[0,0],[0,0],[17.24,-6.036],[0,0]],"o":[[0,0],[91.888,44.724],[0,0],[25.586,0.827],[86.669,2.198],[5.129,-19.177],[-12.841,-21.255],[-52.559,-12.96],[0,0],[0,0],[-20.237,8.642],[0,0]],"v":[[-131.05,-94.547],[-212.69,152.868],[55.903,165.633],[26.212,-104.462],[94.965,-103.048],[305.579,19.424],[300.23,-32.745],[191.787,-112.796],[102.622,-143.052],[-232.058,-116.778],[-271.401,-100.686],[-301.84,-85.542]],"c":true}],"e":[{"i":[[0,0],[8.637,-160.553],[0,0],[-64.287,88.691],[-23.216,-2.405],[-74.974,-110.169],[3.114,11.391],[72.038,22.96],[0,0],[0,0],[21.175,-3.413],[0,0]],"o":[[0,0],[86.979,67.305],[0,0],[25.386,0.821],[98.964,10.251],[38.02,-41.759],[-12.841,-21.255],[-52.56,-12.96],[0,0],[0,0],[-16.918,7.478],[0,0]],"v":[[-131.05,-94.547],[-295.654,109.668],[-98.734,173.487],[-44.479,-83.844],[58.779,-85.268],[282.997,72.442],[300.23,-32.745],[191.787,-112.796],[102.622,-143.052],[-215.112,-122.818],[-243.595,-113.668],[-260.797,-107.167]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.960784373564,0.831372608858,0.925490255917,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[570.474,595.717],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 20","np":2,"cix":2,"ix":20,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-78.933],[265.27,-18.473],[0,78.933],[-218.692,0]],"o":[[0,78.933],[-218.164,15.193],[0,-78.933],[218.692,0]],"v":[[333.09,0],[-4.508,170.902],[-333.089,0],[-3.035,-142.92]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.941000007181,0.964999988032,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[544.329,597.681],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 21","np":2,"cix":2,"ix":21,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[67.975,-10.303],[-17.942,-26.69],[-29.782,-25.833],[22,-45.116],[-84.02,-12.631],[-185.573,-11.427],[-55.1,88.31],[97.238,38.459]],"o":[[0,0],[-41.762,6.33],[11.837,17.608],[29.782,25.832],[-12.356,25.339],[90.091,13.544],[82.174,5.06],[28.285,-45.333],[-151.821,-30.93]],"v":[[-154.897,-113.926],[-238.614,-107.75],[-297.989,-55.035],[-223.645,-4.175],[-275.76,80.579],[-166.787,140.15],[114.122,120.731],[328.584,127.573],[175.078,-9.212]],"c":true}],"e":[{"i":[[0,0],[67.975,-10.303],[-3.782,-31.937],[-29.782,-25.833],[28.065,-41.615],[-131.167,-8.582],[-185.573,-11.427],[-186.663,33.328],[97.238,38.459]],"o":[[0,0],[-41.762,6.33],[5.54,46.783],[29.782,25.832],[-28.065,41.616],[90.909,5.948],[82.174,5.06],[129.755,-23.167],[-151.821,-30.93]],"v":[[-154.897,-113.926],[-287.705,-119.531],[-380.461,-72.708],[-249.172,-0.248],[-340.56,92.361],[-211.95,199.059],[127.868,173.75],[452.293,239.5],[247.733,6.497]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[0,0],[67.975,-10.303],[-3.782,-31.937],[-29.782,-25.833],[28.065,-41.615],[-131.167,-8.582],[-185.573,-11.427],[-186.663,33.328],[97.238,38.459]],"o":[[0,0],[-41.762,6.33],[5.54,46.783],[29.782,25.832],[-28.065,41.616],[90.909,5.948],[82.174,5.06],[129.755,-23.167],[-151.821,-30.93]],"v":[[-154.897,-113.926],[-287.705,-119.531],[-380.461,-72.708],[-249.172,-0.248],[-340.56,92.361],[-211.95,199.059],[127.868,173.75],[452.293,239.5],[247.733,6.497]],"c":true}],"e":[{"i":[[0,0],[67.975,-10.303],[-17.942,-26.69],[-29.782,-25.833],[22,-45.116],[-84.02,-12.631],[-185.573,-11.427],[-55.1,88.31],[97.238,38.459]],"o":[[0,0],[-41.762,6.33],[11.837,17.608],[29.782,25.832],[-12.356,25.339],[90.091,13.544],[82.174,5.06],[28.285,-45.333],[-151.821,-30.93]],"v":[[-154.897,-113.926],[-238.614,-107.75],[-297.989,-55.035],[-223.645,-4.175],[-275.76,80.579],[-166.787,140.15],[114.122,120.731],[328.584,127.572],[175.078,-9.212]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.6,0.677999997606,0.976000019148,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[417.716,703.099],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 22","np":2,"cix":2,"ix":22,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[-17.076,-2.883],[19.016,-22.102],[79.816,0]],"o":[[0,0],[17.075,2.883],[-19.016,22.102],[13.671,-43.836]],"v":[[-31.792,-43.208],[32.631,-39.312],[52.422,6.67],[-74.569,26.194]],"c":true}],"e":[{"i":[[0,0],[-31.68,-5.349],[35.281,-41.005],[148.079,0]],"o":[[0,0],[31.679,5.349],[-35.28,41.006],[25.363,-81.327]],"v":[[-56.079,-66.772],[63.442,-59.544],[100.161,25.766],[-135.442,61.987]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[0,0],[-31.68,-5.349],[35.281,-41.005],[148.079,0]],"o":[[0,0],[31.679,5.349],[-35.28,41.006],[25.363,-81.327]],"v":[[-56.079,-66.772],[63.442,-59.544],[100.161,25.766],[-135.442,61.987]],"c":true}],"e":[{"i":[[0,0],[-17.076,-2.883],[19.016,-22.102],[79.816,0]],"o":[[0,0],[17.075,2.883],[-19.016,22.102],[13.671,-43.836]],"v":[[-31.792,-43.208],[32.631,-39.312],[52.422,6.67],[-74.569,26.194]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.6,0.677999997606,0.976000019148,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[889.848,627.082],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 23","np":2,"cix":2,"ix":23,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[-16.14,13.767],[-11.077,0],[-6.013,-7.621],[25.832,0]],"o":[[5.433,-4.634],[11.076,0],[6.013,7.621],[-25.832,0]],"v":[[-77.904,-12.821],[-42.459,-17],[-3.533,-8.888],[-40.046,6.846]],"c":true}],"e":[{"i":[[-35.58,30.349],[-24.418,0],[-13.255,-16.8],[56.945,0]],"o":[[11.977,-10.216],[24.417,0],[13.256,16.8],[-56.945,0]],"v":[[-78.101,-17.057],[0.037,-26.27],[85.847,-8.386],[5.355,26.298]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":180,"s":[{"i":[[-35.58,30.349],[-24.418,0],[-13.255,-16.8],[56.945,0]],"o":[[11.977,-10.216],[24.417,0],[13.256,16.8],[-56.945,0]],"v":[[-78.101,-17.057],[0.037,-26.27],[85.847,-8.386],[5.355,26.298]],"c":true}],"e":[{"i":[[-16.14,13.767],[-11.077,0],[-6.013,-7.621],[25.832,0]],"o":[[5.433,-4.634],[11.076,0],[6.013,7.621],[-25.832,0]],"v":[[-77.904,-12.821],[-42.459,-17],[-3.533,-8.888],[-40.046,6.846]],"c":true}]},{"t":359}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.6,0.677999997606,0.976000019148,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[239.047,528.05],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":60,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 24","np":2,"cix":2,"ix":24,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":368,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index a89146e..94605a8 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -12,8 +12,8 @@
# org.gradle.parallel=true
#Thu Jun 04 12:03:50 CEST 2020
android.enableJetifier=true
-android.enableR8.fullMode=true
android.useAndroidX=true
+android.enableR8.fullMode=true
kotlin.code.style=official
org.gradle.caching=true
org.gradle.jvmargs=-Xms512M -Xmx2048M -XX\:MaxPermSize\=512M -XX\:MaxMetaspaceSize\=512M -Dkotlin.daemon.jvm.options\="-Xmx2048M"