From 6cd9d490e7c3e6b34ec0dd4ca23cd064de2439f6 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 27 Aug 2019 10:09:01 +0200 Subject: [PATCH 001/122] Optimize gradle properties --- gradle.properties | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/gradle.properties b/gradle.properties index c625a275..d7477703 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,26 +1,16 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html +android.useAndroidX=true -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m +# Use R8 in full mode instead of ProGuard compatibility mode. +android.enableR8.fullMode=true -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -android.useAndroidX=true -android.enableJetifier=true +# Enable rudimentary R class namespacing where each library only contains +# references to the resources it declares instead of declarations plus all +# transitive dependency references. +android.namespacedRClass=true -# define kotlin style guide when importing project -kotlin.code.style=official +# Only keep the single relevant constructor for types mentioned in XML files +# instead of using a parameter wildcard which keeps them all. +android.useMinimalKeepRules=true -# enable more aggressive R8 optimizations -android.enableR8.fullMode=true -android.useMinimalKeepRules=true \ No newline at end of file +# Set the build VMs heap size. +org.gradle.jvmargs=-Xmx1536m From f89e10496278f8425b75ebffd3edb83848f6d993 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 27 Aug 2019 11:57:45 +0200 Subject: [PATCH 002/122] Remove core ktx --- app/build.gradle | 1 - build.gradle | 1 - 2 files changed, 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 1bab2780..bcff7c42 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -76,7 +76,6 @@ dependencies { // AndroidX implementation "androidx.appcompat:appcompat:$appcompatVersion" - implementation "androidx.core:core-ktx:$coreKtxVersion" implementation "androidx.activity:activity:$activityVersion" implementation "androidx.recyclerview:recyclerview:$recyclerviewVersion" implementation "androidx.constraintlayout:constraintlayout:$constraintlayoutVersion" diff --git a/build.gradle b/build.gradle index 4922c7c1..9a26c3cc 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,6 @@ buildscript { kotlinVersion = '1.3.50' coroutinesVersion = '1.3.0' appcompatVersion = '1.1.0-rc01' - coreKtxVersion = '1.2.0-alpha03' activityVersion = '1.1.0-alpha02' materialVersion = '1.1.0-alpha09' recyclerviewVersion = '1.1.0-beta03' From dbb24b33b5511f3d4d8df4561a5fb2835cbe1b58 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 27 Aug 2019 12:01:52 +0200 Subject: [PATCH 003/122] Revert "Remove core ktx" This reverts commit f89e10496278f8425b75ebffd3edb83848f6d993. --- app/build.gradle | 1 + build.gradle | 1 + 2 files changed, 2 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index bcff7c42..1bab2780 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -76,6 +76,7 @@ dependencies { // AndroidX implementation "androidx.appcompat:appcompat:$appcompatVersion" + implementation "androidx.core:core-ktx:$coreKtxVersion" implementation "androidx.activity:activity:$activityVersion" implementation "androidx.recyclerview:recyclerview:$recyclerviewVersion" implementation "androidx.constraintlayout:constraintlayout:$constraintlayoutVersion" diff --git a/build.gradle b/build.gradle index 9a26c3cc..4922c7c1 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,7 @@ buildscript { kotlinVersion = '1.3.50' coroutinesVersion = '1.3.0' appcompatVersion = '1.1.0-rc01' + coreKtxVersion = '1.2.0-alpha03' activityVersion = '1.1.0-alpha02' materialVersion = '1.1.0-alpha09' recyclerviewVersion = '1.1.0-beta03' From 9059c8456df946a517a806e5d548047f0a670e8c Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 27 Aug 2019 15:23:35 +0200 Subject: [PATCH 004/122] Reenable jetifier to fix build --- gradle.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gradle.properties b/gradle.properties index d7477703..19e41955 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,8 @@ android.useAndroidX=true +# Enable jetifier, currently only because dagger still uses android.support.annotation +android.enableJetifier=true + # Use R8 in full mode instead of ProGuard compatibility mode. android.enableR8.fullMode=true From 7f8b8b683e7445cb499d7d15c761d1c46ece38b7 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 27 Aug 2019 15:41:44 +0200 Subject: [PATCH 005/122] Set execution flag --- gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From a30cb553f0be6de60626457d8ce840f35f52b739 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 27 Aug 2019 21:48:44 +0200 Subject: [PATCH 006/122] Correctly set new layout params --- .../com/g00fy2/developerwidget/ktx/ViewGroupExtensions.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewGroupExtensions.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewGroupExtensions.kt index f3e054ff..6323312e 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewGroupExtensions.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewGroupExtensions.kt @@ -10,7 +10,7 @@ import com.g00fy2.developerwidget.R fun ViewGroup.expand(fade: Boolean = false, easing: TimeInterpolator? = null) = this.apply { val params = layoutParams as ViewGroup.MarginLayoutParams params.topMargin = -height - requestLayout() + layoutParams = params if (fade) alpha = 0f visibility = View.VISIBLE @@ -19,9 +19,9 @@ fun ViewGroup.expand(fade: Boolean = false, easing: TimeInterpolator? = null) = addUpdateListener { (it.animatedValue as Int).let { value -> params.topMargin = value + layoutParams = params if (fade) alpha = (viewHeight + value) / viewHeight.toFloat() } - requestLayout() } easing?.let { easing -> interpolator = easing } duration = resources.getInteger(R.integer.animation_duration).toLong() @@ -31,7 +31,7 @@ fun ViewGroup.expand(fade: Boolean = false, easing: TimeInterpolator? = null) = fun ViewGroup.collapse(fade: Boolean = false, easing: TimeInterpolator? = null) = this.apply { val params = layoutParams as ViewGroup.MarginLayoutParams params.topMargin = 0 - requestLayout() + layoutParams = params if (fade) alpha = 1f visibility = View.VISIBLE @@ -40,9 +40,9 @@ fun ViewGroup.collapse(fade: Boolean = false, easing: TimeInterpolator? = null) addUpdateListener { (it.animatedValue as Int).let { value -> params.topMargin = value + layoutParams = params if (fade) alpha = (viewHeight + value) / viewHeight.toFloat() } - requestLayout() } easing?.let { easing -> interpolator = easing } duration = resources.getInteger(R.integer.animation_duration).toLong() From ae2d59af4834c3ad27ab3f65b507eb5e1427e533 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 27 Aug 2019 21:48:58 +0200 Subject: [PATCH 007/122] Update android studio --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4922c7c1..2733915a 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '3.6.0-alpha07' + androidGradleVersion = '3.6.0-alpha08' gradleScanVersion = '2.3' versioningPluginVersion = '1.0.0' From e27faf1fc0c3db65a0e825e297381dd658e4c8e9 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 28 Aug 2019 10:59:13 +0200 Subject: [PATCH 008/122] Update gradle --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 28f3cbe6..584a7b51 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip From 8acb5cfcd102623a364d280e0a16997729518ae7 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 29 Aug 2019 22:38:06 +0200 Subject: [PATCH 009/122] Update android studio --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2733915a..3a3d5a6f 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '3.6.0-alpha08' + androidGradleVersion = '3.6.0-alpha09' gradleScanVersion = '2.3' versioningPluginVersion = '1.0.0' From f57f63a2d564121804fb7dbc1016e766e3fd2afe Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Fri, 30 Aug 2019 17:28:36 +0200 Subject: [PATCH 010/122] Optimize custom views --- .../about/views/AboutHeaderLayout.kt | 13 +++++----- .../activities/about/views/AboutItemLayout.kt | 25 ++++++++----------- app/src/main/res/layout/about_item.xml | 5 ++-- app/src/main/res/layout/about_item_header.xml | 4 +-- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutHeaderLayout.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutHeaderLayout.kt index d32ebe15..0f506918 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutHeaderLayout.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutHeaderLayout.kt @@ -2,18 +2,19 @@ package com.g00fy2.developerwidget.activities.about.views import android.content.Context import android.util.AttributeSet -import android.view.LayoutInflater import android.widget.FrameLayout import androidx.annotation.StringRes import com.g00fy2.developerwidget.R import kotlinx.android.synthetic.main.about_item_header.view.* -class AboutHeaderLayout : FrameLayout { +class AboutHeaderLayout @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : FrameLayout(context, attrs, defStyleAttr) { - constructor(context: Context) : this(context, null) - constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) - constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { - LayoutInflater.from(context).inflate(R.layout.about_item_header, this, true) + init { + inflate(context, R.layout.about_item_header, this) } fun title(@StringRes titleRes: Int): AboutHeaderLayout { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt index 6b1396ce..85ff699e 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt @@ -2,8 +2,6 @@ package com.g00fy2.developerwidget.activities.about.views import android.content.Context import android.util.AttributeSet -import android.view.LayoutInflater -import android.view.View import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.constraintlayout.widget.ConstraintLayout @@ -12,50 +10,49 @@ import androidx.core.view.isVisible import com.g00fy2.developerwidget.R import kotlinx.android.synthetic.main.about_item.view.* -class AboutItemLayout : ConstraintLayout { +class AboutItemLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : + ConstraintLayout(context, attrs, defStyleAttr) { - constructor(context: Context) : this(context, null) - constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) - constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { - LayoutInflater.from(context).inflate(R.layout.about_item, this, true) + init { + inflate(context, R.layout.about_item, this) } override fun setEnabled(enabled: Boolean) { super.setEnabled(enabled) - for (child in constraint_layout.children) child.isEnabled = enabled + for (child in children) child.isEnabled = enabled } fun icon(@DrawableRes iconRes: Int): AboutItemLayout { icon_imageview.setImageResource(iconRes) - icon_imageview.visibility = View.VISIBLE + icon_imageview.isVisible = true return this } fun title(@StringRes titleRes: Int): AboutItemLayout { title_textview.setText(titleRes) - title_textview.visibility = View.VISIBLE + title_textview.isVisible = true return this } fun description(@StringRes descriptionRes: Int): AboutItemLayout { description_textview.setText(descriptionRes) - description_textview.visibility = View.VISIBLE + description_textview.isVisible = true return this } fun description(description: String): AboutItemLayout { if (description.isNotBlank()) { description_textview.text = description - description_textview.visibility = View.VISIBLE + description_textview.isVisible = true } else { - description_textview.visibility = View.GONE + description_textview.isVisible = false } return this } fun switch(on: Boolean): AboutItemLayout { setting_switch.isChecked = on - setting_switch.visibility = View.VISIBLE + setting_switch.isVisible = true return this } diff --git a/app/src/main/res/layout/about_item.xml b/app/src/main/res/layout/about_item.xml index 2f182075..c3e2063e 100644 --- a/app/src/main/res/layout/about_item.xml +++ b/app/src/main/res/layout/about_item.xml @@ -1,8 +1,7 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/about_item_header.xml b/app/src/main/res/layout/about_item_header.xml index b3062b3e..58fd2c13 100644 --- a/app/src/main/res/layout/about_item_header.xml +++ b/app/src/main/res/layout/about_item_header.xml @@ -1,5 +1,5 @@ - - \ No newline at end of file + \ No newline at end of file From 1f61a9bcf9431dd7fc9d6e1054563d4be424d695 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 31 Aug 2019 02:54:24 +0200 Subject: [PATCH 011/122] Use ktx to set text watcher --- .../activities/appmanager/AppsActivity.kt | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt index 8b45a17b..acd5d36b 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt @@ -7,9 +7,7 @@ import android.graphics.drawable.Drawable import android.os.Build.VERSION import android.os.Build.VERSION_CODES import android.os.Bundle -import android.text.Editable import android.text.InputFilter -import android.text.TextWatcher import android.view.LayoutInflater import android.view.MotionEvent import android.view.View @@ -21,6 +19,7 @@ import androidx.core.content.res.ResourcesCompat import androidx.core.view.ViewCompat import androidx.core.view.doOnPreDraw import androidx.core.view.isVisible +import androidx.core.widget.doAfterTextChanged import androidx.interpolator.view.animation.FastOutLinearInInterpolator import androidx.interpolator.view.animation.LinearOutSlowInInterpolator import androidx.recyclerview.widget.LinearLayoutManager @@ -102,18 +101,10 @@ class AppsActivity : BaseActivity(R.layout.activity_apps, true), AppsContract.Ap } true } - addTextChangedListener(object : TextWatcher { - override fun afterTextChanged(s: Editable?) { - presenter.updateFilter(s) - setCompoundDrawables(null, null, if (!s.isNullOrEmpty()) clearDrawable else null, null) - } - - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { - } - - override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { - } - }) + doAfterTextChanged { + presenter.updateFilter(it) + setCompoundDrawables(null, null, if (!it.isNullOrEmpty()) clearDrawable else null, null) + } setOnTouchListener { v, event -> var consumed = false if (v is EditText) { From 7d4a9c4e0cbcd6ddc2a2e7b5fee7c3d8fabbce2c Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 31 Aug 2019 20:59:13 +0200 Subject: [PATCH 012/122] Move initView into base activity --- .../activities/about/AboutActivity.kt | 8 +-- .../activities/apkinstall/ApkActivity.kt | 23 +++----- .../activities/appmanager/AppsActivity.kt | 5 +- .../activities/appmanager/AppsAdapter.kt | 1 - .../shortcut/CreateShortcutActivity.kt | 4 +- .../widgetconfig/WidgetConfigActivity.kt | 59 +++++++++---------- .../developerwidget/base/BaseActivity.kt | 3 + 7 files changed, 43 insertions(+), 60 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt index 2dbef055..85f9b81a 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt @@ -5,7 +5,6 @@ import android.content.ComponentName import android.content.pm.PackageManager import android.os.Build.VERSION import android.os.Build.VERSION_CODES -import android.os.Bundle import android.view.MenuItem import androidx.appcompat.app.AppCompatDelegate import com.g00fy2.developerwidget.BuildConfig @@ -23,11 +22,6 @@ class AboutActivity : BaseActivity(R.layout.activity_about), AboutContract.About override fun providePresenter(): BasePresenter = presenter - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - initView() - } - override fun onResume() { super.onResume() updateThemeToggleView() @@ -44,7 +38,7 @@ class AboutActivity : BaseActivity(R.layout.activity_about), AboutContract.About } } - private fun initView() { + override fun initView() { supportActionBar?.setDisplayHomeAsUpEnabled(true) setActionbarElevationListener(about_root_scrollview) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt index f8e9a5ca..229fe330 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt @@ -1,6 +1,5 @@ package com.g00fy2.developerwidget.activities.apkinstall -import android.os.Bundle import android.view.View import androidx.appcompat.widget.TooltipCompat import androidx.core.view.ViewCompat @@ -20,9 +19,15 @@ class ApkActivity : BaseActivity(R.layout.activity_apk, true), ApkContract.ApkVi override fun providePresenter(): BasePresenter = presenter - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + override fun onResume() { + super.onResume() + progressbar.visibility = View.VISIBLE + no_items_imageview.visibility = View.INVISIBLE + no_items_textview.text = getString(R.string.scanning_apks) + no_items_textview.visibility = View.VISIBLE + } + override fun initView() { adapter = ApkAdapter() adapter.setOnApkClicked { apkFile -> presenter.installApk(apkFile) } adapter.setOnApkSelect { selectedCount -> showOptions(selectedCount > 0) } @@ -47,11 +52,6 @@ class ApkActivity : BaseActivity(R.layout.activity_apk, true), ApkContract.ApkVi } } - override fun onResume() { - super.onResume() - initView() - } - override fun toggleResultView(apkFiles: List, missingPermissions: Boolean) { if (missingPermissions) { progressbar.visibility = View.GONE @@ -68,13 +68,6 @@ class ApkActivity : BaseActivity(R.layout.activity_apk, true), ApkContract.ApkVi adapter.submitList(apkFiles) } - private fun initView() { - progressbar.visibility = View.VISIBLE - no_items_imageview.visibility = View.INVISIBLE - no_items_textview.text = getString(R.string.scanning_apks) - no_items_textview.visibility = View.VISIBLE - } - private fun showOptions(show: Boolean) { delete_header_group.visibility = if (show) View.VISIBLE else View.GONE } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt index acd5d36b..c79f1c8c 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt @@ -6,7 +6,6 @@ import android.graphics.PorterDuff import android.graphics.drawable.Drawable import android.os.Build.VERSION import android.os.Build.VERSION_CODES -import android.os.Bundle import android.text.InputFilter import android.view.LayoutInflater import android.view.MotionEvent @@ -44,9 +43,7 @@ class AppsActivity : BaseActivity(R.layout.activity_apps, true), AppsContract.Ap override fun providePresenter(): BasePresenter = presenter - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - + override fun initView() { adapter = AppsAdapter() adapter.setOnAppClicked { appInfo -> presenter.openAppSettingsActivity(appInfo) } adapter.setCommitCallback(Runnable { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt index b5893a14..861fabf7 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt @@ -79,5 +79,4 @@ class AppsAdapter : BaseAdapter(AppsDiffUtilsCallback() submitList(itemsCopy) } } - } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt index d940154f..395fed85 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt @@ -9,7 +9,6 @@ import android.graphics.Canvas import android.graphics.drawable.Icon import android.os.Build.VERSION import android.os.Build.VERSION_CODES -import android.os.Bundle import android.widget.LinearLayout import androidx.annotation.DrawableRes import androidx.annotation.RequiresApi @@ -38,8 +37,7 @@ class CreateShortcutActivity : BaseActivity(R.layout.activity_create_shortcut), override fun providePresenter(): BasePresenter = presenter - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + override fun initView() { setResult(Activity.RESULT_CANCELED) adapter = ShortcutAdapter() diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index cc7506c3..8c847299 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -15,7 +15,6 @@ import android.graphics.Rect import android.graphics.drawable.Drawable import android.os.Build.VERSION import android.os.Build.VERSION_CODES -import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.MotionEvent @@ -61,8 +60,17 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg override fun providePresenter(): BasePresenter = presenter - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + override fun onResume() { + super.onResume() + resetView() + } + + override fun onDestroy() { + super.onDestroy() + if (VERSION.SDK_INT >= VERSION_CODES.O) unregisterReceiver(closeConfigureActivityReceiver) + } + + override fun initView() { setResult(Activity.RESULT_CANCELED) intent.extras?.let { @@ -102,17 +110,23 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg if (VERSION.SDK_INT in VERSION_CODES.LOLLIPOP until VERSION_CODES.O) { WebView(this) } - initViews() - } - - override fun onResume() { - super.onResume() - initViews() - } - override fun onDestroy() { - super.onDestroy() - if (VERSION.SDK_INT >= VERSION_CODES.O) unregisterReceiver(closeConfigureActivityReceiver) + device_title_edittextview.apply { + onFocusChangeListener = OnFocusChangeListener { _, hasFocus -> + if (!hasFocus) { + presenter.setCustomDeviceName(device_title_edittextview.text.toString()) + toggleDeviceNameEdit(false) + } + } + setOnEditorActionListener { v, actionId, _ -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + v.clearFocus() + } + true + } + } + share_fab.setOnClickListener { presenter.shareDeviceData() } + resetView() } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -162,7 +176,7 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg return super.dispatchTouchEvent(event) } - private fun initViews() { + private fun resetView() { val showAddWidget = (!launchedFromAppLauncher || (widgetCount() < 1 && isPinAppWidgetSupported())) if (showAddWidget) { apply_button.apply { @@ -202,21 +216,6 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg setPadding(paddingLeft, paddingTop, (16 * resources.displayMetrics.density).toInt(), paddingBottom) } } - device_title_edittextview.apply { - onFocusChangeListener = OnFocusChangeListener { _, hasFocus -> - if (!hasFocus) { - presenter.setCustomDeviceName(device_title_edittextview.text.toString()) - toggleDeviceNameEdit(false) - } - } - setOnEditorActionListener { v, actionId, _ -> - if (actionId == EditorInfo.IME_ACTION_DONE) { - v.clearFocus() - } - true - } - } - share_fab.setOnClickListener { presenter.shareDeviceData() } } private fun toggleDeviceNameEdit(editable: Boolean) { @@ -302,4 +301,4 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg const val EXTRA_APPWIDGET_FROM_PIN_APP = "EXTRA_APPWIDGET_FROM_PIN_APP" const val EXTRA_APPWIDGET_CUSTOM_DEVICE_NAME = "EXTRA_APPWIDGET_CUSTOM_DEVICE_NAME" } -} +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt index 5fa4d5af..9f6d38a1 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt @@ -38,6 +38,7 @@ abstract class BaseActivity(@LayoutRes contentLayoutId: Int, private val isDialo dayNightController.loadCustomDefaultMode() lifecycle.addObserver(providePresenter()) initCompatNavigationBar() + initView() } override fun onDestroy() { @@ -77,4 +78,6 @@ abstract class BaseActivity(@LayoutRes contentLayoutId: Int, private val isDialo resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_NO abstract fun providePresenter(): BaseContract.BasePresenter + + abstract fun initView() } \ No newline at end of file From 0a18602425b545a79bb59c5853c55211d5a13321 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 31 Aug 2019 21:00:05 +0200 Subject: [PATCH 013/122] Cleanup line breaks --- .../activities/widgetconfig/WidgetConfigPresenterImpl.kt | 1 - .../kotlin/com/g00fy2/developerwidget/base/BasePresenterImpl.kt | 1 - .../developerwidget/controllers/PermissionControllerImpl.kt | 1 - .../g00fy2/developerwidget/controllers/StringControllerImpl.kt | 1 - app/src/main/kotlin/com/g00fy2/developerwidget/di/AppModule.kt | 1 - .../com/g00fy2/developerwidget/di/BroadcastBindingModule.kt | 1 - .../kotlin/com/g00fy2/developerwidget/di/ControllerModule.kt | 1 - .../kotlin/com/g00fy2/developerwidget/ktx/AppInfoExtensions.kt | 2 +- .../developerwidget/receiver/widget/WidgetProviderImpl.kt | 2 +- 9 files changed, 2 insertions(+), 9 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt index e0a1a97e..cde28d76 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt @@ -113,6 +113,5 @@ class WidgetConfigPresenterImpl @Inject constructor() : BasePresenterImpl(), }.removeSurrounding("\n") } - override fun showManuallyAddWidgetNotice() = toastController.showToast(R.string.manually_add_widget) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BasePresenterImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BasePresenterImpl.kt index a3740e9d..3578afc0 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BasePresenterImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BasePresenterImpl.kt @@ -14,5 +14,4 @@ abstract class BasePresenterImpl : BaseContract.BasePresenter { @OnLifecycleEvent(Event.ON_DESTROY) fun cancelJob() = job.cancel() - } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/PermissionControllerImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/PermissionControllerImpl.kt index f27c946f..cbc0d80c 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/PermissionControllerImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/PermissionControllerImpl.kt @@ -45,5 +45,4 @@ class PermissionControllerImpl @Inject constructor() : PermissionController { override fun requestPermissions(permissions: Array) { if (!hasPermissions(permissions)) (context as Activity).requestPermissions(permissions, 1) } - } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StringControllerImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StringControllerImpl.kt index aa2df2f8..14067b4b 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StringControllerImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StringControllerImpl.kt @@ -12,5 +12,4 @@ class StringControllerImpl @Inject constructor() : StringController { lateinit var context: Context override fun getString(resId: Int): String = context.getString(resId) - } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/di/AppModule.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/di/AppModule.kt index 5e4c9683..d5684723 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/di/AppModule.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/di/AppModule.kt @@ -15,5 +15,4 @@ abstract class AppModule { @Singleton @Named(APPLICATION) abstract fun provideApplicationContext(application: DevWidgetApp): Context - } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt index 091eecf0..157bc1f7 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt @@ -10,5 +10,4 @@ abstract class BroadcastBindingModule { @ContributesAndroidInjector(modules = [WidgetProviderModule::class]) abstract fun bindWidgetProvider(): WidgetProviderImpl - } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/di/ControllerModule.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/di/ControllerModule.kt index 20525d8f..ec318ff2 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/di/ControllerModule.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/di/ControllerModule.kt @@ -53,5 +53,4 @@ abstract class ActivityControllerModule { @Binds @ActivityScope abstract fun provideStorageDirsController(storageDirsControllerImpl: StorageDirsControllerImpl): StorageDirsController - } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/AppInfoExtensions.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/AppInfoExtensions.kt index 05538688..64861d5a 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/AppInfoExtensions.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/AppInfoExtensions.kt @@ -22,4 +22,4 @@ fun AppInfo.filterPackageName(filterEntries: Collection): Boolean { if (filterPackageName(i)) return true } return false -} +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderImpl.kt index ccdd4507..e476dd33 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderImpl.kt @@ -144,4 +144,4 @@ class WidgetProviderImpl : AppWidgetProvider(), WidgetProvider { companion object { const val UPDATE_WIDGET_MANUALLY_ACTION = BuildConfig.APPLICATION_ID + ".APPWIDGET_MANUAL_UPDATE" } -} +} \ No newline at end of file From 4ea94c531e1208b86ea9656ca38751c4ad38558b Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 31 Aug 2019 21:08:02 +0200 Subject: [PATCH 014/122] Move tavis conditions directly into jobs --- .travis.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index c02ebbb6..b08a1da3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,12 +19,6 @@ cache: - $HOME/.gradle/wrapper/ - $HOME/.android/build-cache/ -stages: -- name: Build debug - if: branch IN (develop, master) -- name: Build and deploy release on tags - if: tag IS present - android_phases: - phase: &before_install # download and unzip Android SDK command line tools @@ -87,13 +81,15 @@ android_phases: jobs: include: - - stage: Build debug + - # Build debug + if: branch IN (develop, master) before_install: *before_install install: *install before_script: *before_script script: "./gradlew assembleDebug --scan" before_cache: *before_cache - - stage: Build and deploy release on tags + - # Build and deploy release on tags + if: tag IS present before_install: *before_install install: *install before_script: *before_script From 8c5705f534c5a8b5e461cb601eca9e066ee41070 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Mon, 2 Sep 2019 00:27:13 +0200 Subject: [PATCH 015/122] Update gradle scan plugin --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3a3d5a6f..ba7ddaae 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { minSdkVersion = 14 targetSdkVersion = 29 androidGradleVersion = '3.6.0-alpha09' - gradleScanVersion = '2.3' + gradleScanVersion = '2.4.1' versioningPluginVersion = '1.0.0' // Library versions From a75615a2b019fee28b19930e204271afc0782d92 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Mon, 2 Sep 2019 11:27:33 +0200 Subject: [PATCH 016/122] Fix custom view ripple background --- .../activities/about/views/AboutItemLayout.kt | 2 ++ .../g00fy2/developerwidget/base/BaseViewHolder.kt | 13 ++----------- .../g00fy2/developerwidget/ktx/ViewExtension.kt | 14 ++++++++++++++ app/src/main/res/layout/about_item.xml | 3 +-- 4 files changed, 19 insertions(+), 13 deletions(-) create mode 100644 app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt index 85ff699e..670b7c8c 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt @@ -8,6 +8,7 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.children import androidx.core.view.isVisible import com.g00fy2.developerwidget.R +import com.g00fy2.developerwidget.ktx.addRipple import kotlinx.android.synthetic.main.about_item.view.* class AboutItemLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : @@ -57,6 +58,7 @@ class AboutItemLayout @JvmOverloads constructor(context: Context, attrs: Attribu } fun action(action: () -> Unit): AboutItemLayout { + addRipple() setOnClickListener { action() if (setting_switch.isVisible) setting_switch.isChecked = !setting_switch.isChecked diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt index 9363b274..51c2638c 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt @@ -1,20 +1,11 @@ package com.g00fy2.developerwidget.base -import android.os.Build.VERSION -import android.os.Build.VERSION_CODES -import android.util.TypedValue import android.view.View import androidx.recyclerview.widget.RecyclerView +import com.g00fy2.developerwidget.ktx.addRipple import kotlinx.android.extensions.LayoutContainer open class BaseViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer { - fun addRipple() { - TypedValue().apply { - containerView.context.theme.resolveAttribute(android.R.attr.selectableItemBackground, this, true) - }.resourceId.let { - if (VERSION.SDK_INT < VERSION_CODES.M) itemView.setBackgroundResource(it) else itemView.foreground = - containerView.context.getDrawable(it) - } - } + fun addRipple() = containerView.addRipple(true) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt new file mode 100644 index 00000000..539771b6 --- /dev/null +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt @@ -0,0 +1,14 @@ +package com.g00fy2.developerwidget.ktx + +import android.os.Build.VERSION +import android.os.Build.VERSION_CODES +import android.util.TypedValue +import android.view.View + +fun View.addRipple(asForeground: Boolean = false) { + TypedValue().apply { context.theme.resolveAttribute(android.R.attr.selectableItemBackground, this, true) } + .resourceId.let { + if (VERSION.SDK_INT < VERSION_CODES.M || !asForeground) setBackgroundResource(it) else foreground = + context.getDrawable(it) + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/about_item.xml b/app/src/main/res/layout/about_item.xml index c3e2063e..28002a45 100644 --- a/app/src/main/res/layout/about_item.xml +++ b/app/src/main/res/layout/about_item.xml @@ -4,8 +4,6 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="72dp" - android:background="?android:attr/selectableItemBackground" - tools:ignore="ContentDescription" > From 18752112f0f812513c7b1536a6add73477b9cdad Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 4 Sep 2019 20:16:51 +0200 Subject: [PATCH 017/122] Android Q AOSP memory leak workaround --- .../com/g00fy2/developerwidget/base/BaseActivity.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt index 9f6d38a1..8fec5d11 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt @@ -47,6 +47,15 @@ abstract class BaseActivity(@LayoutRes contentLayoutId: Int, private val isDialo lifecycle.removeObserver(providePresenter()) } + // TODO check if there will be a fix for https://issuetracker.google.com/issues/139738913 in AppCompatActivity or next Android release + override fun onBackPressed() { + if (VERSION.SDK_INT == VERSION_CODES.Q && isTaskRoot && supportFragmentManager.backStackEntryCount == 0) { + finishAfterTransition() + } else { + super.onBackPressed() + } + } + protected fun setActionbarElevationListener(viewGroup: ViewGroup) { supportActionBar?.elevation = 0f viewGroup.viewTreeObserver.addOnScrollChangedListener { From 6fcd554f6186bb461541c74c270bdd1aa16af615 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 21:25:18 +0200 Subject: [PATCH 018/122] Do not show loading animations in onresume when apks already found --- .../activities/apkinstall/ApkActivity.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt index 229fe330..4148509b 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt @@ -21,10 +21,12 @@ class ApkActivity : BaseActivity(R.layout.activity_apk, true), ApkContract.ApkVi override fun onResume() { super.onResume() - progressbar.visibility = View.VISIBLE - no_items_imageview.visibility = View.INVISIBLE - no_items_textview.text = getString(R.string.scanning_apks) - no_items_textview.visibility = View.VISIBLE + if (adapter.itemCount == 0) { + progressbar.visibility = View.VISIBLE + no_items_imageview.visibility = View.INVISIBLE + no_items_textview.text = getString(R.string.scanning_apks) + no_items_textview.visibility = View.VISIBLE + } } override fun initView() { From 02814ba0e13595d67fbbe485b2a881aa5dc70120 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 21:26:03 +0200 Subject: [PATCH 019/122] Optimize dialog activity layouts and fix jumping progress view when filter is active --- app/src/main/res/layout/activity_apk.xml | 16 ++- app/src/main/res/layout/activity_apps.xml | 147 +++++++++++----------- 2 files changed, 82 insertions(+), 81 deletions(-) diff --git a/app/src/main/res/layout/activity_apk.xml b/app/src/main/res/layout/activity_apk.xml index 52c723b0..fe4803f4 100644 --- a/app/src/main/res/layout/activity_apk.xml +++ b/app/src/main/res/layout/activity_apk.xml @@ -93,10 +93,12 @@ android:layout_height="96dp" android:contentDescription="@string/no_apps_found" android:visibility="invisible" - app:layout_constraintBottom_toTopOf="@+id/cancel_textview" + app:layout_constraintBottom_toTopOf="@+id/no_items_textview" app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/textView" + app:layout_constraintTop_toTopOf="@+id/recyclerview" + app:layout_constraintVertical_chainStyle="packed" app:srcCompat="@drawable/ic_sad" /> @@ -106,10 +108,10 @@ android:layout_height="64dp" android:layout_gravity="center" android:indeterminate="true" - app:layout_constraintBottom_toTopOf="@+id/cancel_textview" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/textView" + app:layout_constraintBottom_toBottomOf="@+id/no_items_imageview" + app:layout_constraintEnd_toEndOf="@+id/no_items_imageview" + app:layout_constraintStart_toStartOf="@+id/no_items_imageview" + app:layout_constraintTop_toTopOf="@+id/no_items_imageview" /> diff --git a/app/src/main/res/layout/activity_apps.xml b/app/src/main/res/layout/activity_apps.xml index 2d19e604..6e376fb6 100644 --- a/app/src/main/res/layout/activity_apps.xml +++ b/app/src/main/res/layout/activity_apps.xml @@ -47,7 +47,11 @@ app:srcCompat="@drawable/ic_filter" /> - + - - + - + + - - - - - - - - - - - - - - + + + + + + + + From 7cfc6adc7cd5a983935efcd79a61cf253ae2f871 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 21:26:21 +0200 Subject: [PATCH 020/122] Update gradle --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 584a7b51..ebad942f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip From c0e640d79abcd6c31ea1ab5c55b35cf141d60f48 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 21:26:55 +0200 Subject: [PATCH 021/122] Reformat file --- .../developerwidget/activities/appmanager/AppsActivity.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt index c79f1c8c..50348c7e 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt @@ -130,9 +130,9 @@ class AppsActivity : BaseActivity(R.layout.activity_apps, true), AppsContract.Ap } ViewCompat.animate(progressbar).alpha(0f) - .setDuration(resources.getInteger(android.R.integer.config_shortAnimTime).toLong()).withEndAction { - progressbar.visibility = View.INVISIBLE - }.start() + .setDuration(resources.getInteger(android.R.integer.config_shortAnimTime).toLong()) + .withEndAction { progressbar.visibility = View.INVISIBLE } + .start() } override fun updateAppFilter(filters: List) = adapter.updateAppFilters(filters) From 904a77b05908de90ae048f25a25f7fce11e9aa9f Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 21:28:00 +0200 Subject: [PATCH 022/122] Update dependencies and make use of ktx lifecycle aware coroutine scopes --- app/build.gradle | 1 + .../activities/apkinstall/ApkPresenterImpl.kt | 5 +++-- .../g00fy2/developerwidget/base/BaseContract.kt | 6 +++--- .../developerwidget/base/BasePresenterImpl.kt | 16 +--------------- .../data/WidgetsPreferencesDataSourceImpl.kt | 10 +--------- build.gradle | 15 ++++++++------- 6 files changed, 17 insertions(+), 36 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 1bab2780..99a6c714 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -78,6 +78,7 @@ dependencies { implementation "androidx.appcompat:appcompat:$appcompatVersion" implementation "androidx.core:core-ktx:$coreKtxVersion" implementation "androidx.activity:activity:$activityVersion" + implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion" implementation "androidx.recyclerview:recyclerview:$recyclerviewVersion" implementation "androidx.constraintlayout:constraintlayout:$constraintlayoutVersion" implementation "androidx.vectordrawable:vectordrawable:$vectorDrawableVersion" diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkPresenterImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkPresenterImpl.kt index bd659ab2..dc0be36e 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkPresenterImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkPresenterImpl.kt @@ -3,6 +3,7 @@ package com.g00fy2.developerwidget.activities.apkinstall import android.Manifest import androidx.lifecycle.Lifecycle.Event import androidx.lifecycle.OnLifecycleEvent +import androidx.lifecycle.lifecycleScope import com.g00fy2.developerwidget.base.BasePresenterImpl import com.g00fy2.developerwidget.controllers.IntentController import com.g00fy2.developerwidget.controllers.PermissionController @@ -34,7 +35,7 @@ class ApkPresenterImpl @Inject constructor() : BasePresenterImpl(), ApkContract. @OnLifecycleEvent(Event.ON_RESUME) fun scanStorageForApks() { if (permissionController.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - launch { + view.lifecycleScope.launch { withContext(Dispatchers.IO) { mutableSetOf().apply { for (dir in storageDirsController.getStorageDirectories()) { @@ -66,7 +67,7 @@ class ApkPresenterImpl @Inject constructor() : BasePresenterImpl(), ApkContract. override fun deleteApkFiles(apkFiles: List?) { if (permissionController.hasPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)) ) { - launch { + view.lifecycleScope.launch { withContext(Dispatchers.IO) { apkFiles?.let { files -> for (apkFile in files) { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseContract.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseContract.kt index 4185ee44..bca0099e 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseContract.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseContract.kt @@ -1,11 +1,11 @@ package com.g00fy2.developerwidget.base import androidx.lifecycle.LifecycleObserver -import kotlinx.coroutines.CoroutineScope +import androidx.lifecycle.LifecycleOwner interface BaseContract { - interface BaseView + interface BaseView : LifecycleOwner - interface BasePresenter : LifecycleObserver, CoroutineScope + interface BasePresenter : LifecycleObserver } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BasePresenterImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BasePresenterImpl.kt index 3578afc0..93a53133 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BasePresenterImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BasePresenterImpl.kt @@ -1,17 +1,3 @@ package com.g00fy2.developerwidget.base -import androidx.lifecycle.Lifecycle.Event -import androidx.lifecycle.OnLifecycleEvent -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlin.coroutines.CoroutineContext - -abstract class BasePresenterImpl : BaseContract.BasePresenter { - - private val job: Job by lazy { Job() } - - override val coroutineContext: CoroutineContext = Dispatchers.Main + job - - @OnLifecycleEvent(Event.ON_DESTROY) - fun cancelJob() = job.cancel() -} \ No newline at end of file +abstract class BasePresenterImpl : BaseContract.BasePresenter \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/data/WidgetsPreferencesDataSourceImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/data/WidgetsPreferencesDataSourceImpl.kt index 2641f032..a0868116 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/data/WidgetsPreferencesDataSourceImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/data/WidgetsPreferencesDataSourceImpl.kt @@ -4,23 +4,15 @@ import android.content.Context import android.util.SparseArray import com.g00fy2.developerwidget.controllers.WidgetPreferenceControllerImpl import com.g00fy2.developerwidget.di.annotations.APPLICATION -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job import javax.inject.Inject import javax.inject.Named -import kotlin.coroutines.CoroutineContext -class WidgetsPreferencesDataSourceImpl @Inject constructor() : WidgetsPreferencesDataSource, CoroutineScope { +class WidgetsPreferencesDataSourceImpl @Inject constructor() : WidgetsPreferencesDataSource { @Inject @field:Named(APPLICATION) lateinit var context: Context - private val job: Job by lazy { Job() } - - override val coroutineContext: CoroutineContext = Dispatchers.Main + job - override suspend fun getCustomDeviceNames(widgetIds: IntArray): SparseArray { val customDeviceNames = SparseArray() for (widgetId in widgetIds) { diff --git a/build.gradle b/build.gradle index ba7ddaae..f6c2a0b7 100644 --- a/build.gradle +++ b/build.gradle @@ -5,19 +5,20 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '3.6.0-alpha09' + androidGradleVersion = '3.6.0-alpha10' gradleScanVersion = '2.4.1' versioningPluginVersion = '1.0.0' // Library versions kotlinVersion = '1.3.50' - coroutinesVersion = '1.3.0' - appcompatVersion = '1.1.0-rc01' - coreKtxVersion = '1.2.0-alpha03' - activityVersion = '1.1.0-alpha02' - materialVersion = '1.1.0-alpha09' + coroutinesVersion = '1.3.1' + appcompatVersion = '1.1.0' + coreKtxVersion = '1.2.0-alpha04' + activityVersion = '1.1.0-alpha03' + lifecycleVersion = '2.2.0-alpha04' + materialVersion = '1.1.0-alpha10' recyclerviewVersion = '1.1.0-beta03' - vectorDrawableVersion = '1.1.0-rc01' + vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta2' timberVersion = '4.7.1' daggerVersion = '2.24' From 51010eaf056b1268da95bd6ddc0b4d0fe80dd8c3 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 21:52:00 +0200 Subject: [PATCH 023/122] Remove obsolete proguard rule --- app/proguard-rules.pro | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index c00b0a2e..ce2b2616 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,5 +1 @@ -# Ensure the custom, fast service loader implementation is removed. --assumevalues class kotlinx.coroutines.internal.MainDispatcherLoader { - boolean FAST_SERVICE_LOADER_ENABLED return false; -} --checkdiscard class kotlinx.coroutines.internal.FastServiceLoader \ No newline at end of file +# Add project specific ProGuard rules here. \ No newline at end of file From 6184242e1aa9e326ed0b7c162e71c256c7b53482 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 21:52:16 +0200 Subject: [PATCH 024/122] Fix missing lifecycleScopes --- .../activities/appmanager/AppsPresenterImpl.kt | 3 ++- .../activities/widgetconfig/WidgetConfigPresenterImpl.kt | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsPresenterImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsPresenterImpl.kt index 05e8cc95..ceff7583 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsPresenterImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsPresenterImpl.kt @@ -4,6 +4,7 @@ import android.content.pm.ApplicationInfo import android.text.Editable import androidx.lifecycle.Lifecycle.Event import androidx.lifecycle.OnLifecycleEvent +import androidx.lifecycle.lifecycleScope import com.g00fy2.developerwidget.base.BasePresenterImpl import com.g00fy2.developerwidget.controllers.IntentController import com.g00fy2.developerwidget.controllers.WidgetPreferenceController @@ -32,7 +33,7 @@ class AppsPresenterImpl @Inject constructor() : BasePresenterImpl(), AppsContrac @OnLifecycleEvent(Event.ON_RESUME) fun scanApps() { - launch { + view.lifecycleScope.launch { withContext(Dispatchers.IO) { getInstalledUserApps() }.let { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt index cde28d76..7e63e820 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt @@ -2,6 +2,7 @@ package com.g00fy2.developerwidget.activities.widgetconfig import androidx.lifecycle.Lifecycle.Event import androidx.lifecycle.OnLifecycleEvent +import androidx.lifecycle.lifecycleScope import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.base.BasePresenterImpl import com.g00fy2.developerwidget.controllers.IntentController @@ -35,7 +36,7 @@ class WidgetConfigPresenterImpl @Inject constructor() : BasePresenterImpl(), @OnLifecycleEvent(Event.ON_CREATE) override fun loadDeviceData() { - launch { + view.lifecycleScope.launch { withContext(Dispatchers.IO) { getDeviceData() }.let { @@ -46,7 +47,7 @@ class WidgetConfigPresenterImpl @Inject constructor() : BasePresenterImpl(), @OnLifecycleEvent(Event.ON_CREATE) override fun loadCustomDeviceName() { - launch { + view.lifecycleScope.launch { withContext(Dispatchers.IO) { widgetPreferenceController.getCustomDeviceName() }.let { @@ -96,7 +97,7 @@ class WidgetConfigPresenterImpl @Inject constructor() : BasePresenterImpl(), } override fun shareDeviceData() { - launch { + view.lifecycleScope.launch { withContext(Dispatchers.IO) { getDeviceData() }.let { intentController.shareDeviceData(formatDeviceDataString(it)) } From 513134c8076f953186417cb370249282f80b886f Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 22:11:02 +0200 Subject: [PATCH 025/122] Cleanup and reformat xml layout files --- app/src/main/res/layout/activity_apk.xml | 2 -- app/src/main/res/layout/activity_apps.xml | 7 ++++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout/activity_apk.xml b/app/src/main/res/layout/activity_apk.xml index fe4803f4..140003d7 100644 --- a/app/src/main/res/layout/activity_apk.xml +++ b/app/src/main/res/layout/activity_apk.xml @@ -95,7 +95,6 @@ android:visibility="invisible" app:layout_constraintBottom_toTopOf="@+id/no_items_textview" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/recyclerview" app:layout_constraintVertical_chainStyle="packed" @@ -128,7 +127,6 @@ android:textSize="14sp" app:layout_constraintBottom_toBottomOf="@+id/recyclerview" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/no_items_imageview" /> diff --git a/app/src/main/res/layout/activity_apps.xml b/app/src/main/res/layout/activity_apps.xml index 6e376fb6..796b6c3e 100644 --- a/app/src/main/res/layout/activity_apps.xml +++ b/app/src/main/res/layout/activity_apps.xml @@ -47,12 +47,14 @@ app:srcCompat="@drawable/ic_filter" /> + - + + + Date: Thu, 5 Sep 2019 23:00:30 +0200 Subject: [PATCH 026/122] Fix outer background shape radius to get consistent margins to inner background --- app/src/main/res/drawable/bg_widget_outer_shape.xml | 2 +- app/src/main/res/drawable/bg_widget_outer_shape_day.xml | 2 +- app/src/main/res/drawable/bg_widget_outer_shape_night.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/drawable/bg_widget_outer_shape.xml b/app/src/main/res/drawable/bg_widget_outer_shape.xml index 8eeca606..6aba3753 100644 --- a/app/src/main/res/drawable/bg_widget_outer_shape.xml +++ b/app/src/main/res/drawable/bg_widget_outer_shape.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_widget_outer_shape_day.xml b/app/src/main/res/drawable/bg_widget_outer_shape_day.xml index 4823e38a..35c212d1 100644 --- a/app/src/main/res/drawable/bg_widget_outer_shape_day.xml +++ b/app/src/main/res/drawable/bg_widget_outer_shape_day.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_widget_outer_shape_night.xml b/app/src/main/res/drawable/bg_widget_outer_shape_night.xml index 99817e62..fd00d280 100644 --- a/app/src/main/res/drawable/bg_widget_outer_shape_night.xml +++ b/app/src/main/res/drawable/bg_widget_outer_shape_night.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file From d76c9fc93d2e84ca4cc8c21f05703e2824b44881 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 23:03:40 +0200 Subject: [PATCH 027/122] Rename WidgetProvider, remove presenter logic and use coroutine GlobalScope --- app/src/main/AndroidManifest.xml | 2 +- .../widgetconfig/WidgetConfigActivity.kt | 14 +++---- .../controllers/DayNightControllerImpl.kt | 6 +-- .../di/BroadcastBindingModule.kt | 7 ++-- ...idgetProviderImpl.kt => WidgetProvider.kt} | 33 ++++++++++----- .../receiver/widget/WidgetProviderContract.kt | 25 ----------- .../receiver/widget/WidgetProviderModule.kt | 16 ------- .../widget/WidgetProviderPresenterImpl.kt | 42 ------------------- 8 files changed, 37 insertions(+), 108 deletions(-) rename app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/{WidgetProviderImpl.kt => WidgetProvider.kt} (85%) delete mode 100644 app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderContract.kt delete mode 100644 app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderModule.kt delete mode 100644 app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderPresenterImpl.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 39129172..0d38354d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -83,7 +83,7 @@ android:taskAffinity="" android:theme="@android:style/Theme.Translucent.NoTitleBar"/> - + diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index 8c847299..744207ee 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -34,7 +34,7 @@ import com.g00fy2.developerwidget.base.BaseContract.BasePresenter import com.g00fy2.developerwidget.data.DeviceDataItem import com.g00fy2.developerwidget.ktx.hideKeyboard import com.g00fy2.developerwidget.ktx.showKeyboard -import com.g00fy2.developerwidget.receiver.widget.WidgetProviderImpl +import com.g00fy2.developerwidget.receiver.widget.WidgetProvider import kotlinx.android.synthetic.main.activity_widget_config.* import javax.inject.Inject @@ -234,8 +234,8 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg if (!existing) { setResult(Activity.RESULT_OK, Intent().apply { putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId) }) } - sendBroadcast(Intent(applicationContext, WidgetProviderImpl::class.java).apply { - action = WidgetProviderImpl.UPDATE_WIDGET_MANUALLY_ACTION + sendBroadcast(Intent(applicationContext, WidgetProvider::class.java).apply { + action = WidgetProvider.UPDATE_WIDGET_MANUALLY_ACTION putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId) }) finish() @@ -248,15 +248,15 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg if (appWidgetManager.isRequestPinAppWidgetSupported) { supported = true val successCallback = PendingIntent.getBroadcast( - this, 0, Intent(applicationContext, WidgetProviderImpl::class.java).apply { - action = WidgetProviderImpl.UPDATE_WIDGET_MANUALLY_ACTION + this, 0, Intent(applicationContext, WidgetProvider::class.java).apply { + action = WidgetProvider.UPDATE_WIDGET_MANUALLY_ACTION putExtra(EXTRA_APPWIDGET_FROM_PIN_APP, true) putExtra(EXTRA_APPWIDGET_CUSTOM_DEVICE_NAME, device_title_edittextview.text.toString()) }, PendingIntent.FLAG_UPDATE_CURRENT ) appWidgetManager.requestPinAppWidget( - ComponentName(applicationContext, WidgetProviderImpl::class.java), + ComponentName(applicationContext, WidgetProvider::class.java), null, successCallback ) @@ -277,7 +277,7 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg private fun widgetCount() = AppWidgetManager.getInstance(this).getAppWidgetIds( ComponentName( applicationContext, - WidgetProviderImpl::class.java + WidgetProvider::class.java ) ).size diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt index 5691a5dd..58c86d0c 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt @@ -8,7 +8,7 @@ import androidx.appcompat.app.AppCompatDelegate import androidx.core.content.edit import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.di.annotations.APPLICATION -import com.g00fy2.developerwidget.receiver.widget.WidgetProviderImpl +import com.g00fy2.developerwidget.receiver.widget.WidgetProvider import javax.inject.Inject import javax.inject.Named @@ -49,8 +49,8 @@ class DayNightControllerImpl @Inject constructor() : DayNightController { private fun applyMode(mode: Int) = AppCompatDelegate.setDefaultNightMode(mode) private fun updateWidgetTheme() { - context.sendBroadcast(Intent(context, WidgetProviderImpl::class.java).apply { - action = WidgetProviderImpl.UPDATE_WIDGET_MANUALLY_ACTION + context.sendBroadcast(Intent(context, WidgetProvider::class.java).apply { + action = WidgetProvider.UPDATE_WIDGET_MANUALLY_ACTION putExtra(UPDATE_WIDGET_THEME, true) }) } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt index 157bc1f7..83cc2533 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt @@ -1,13 +1,12 @@ package com.g00fy2.developerwidget.di -import com.g00fy2.developerwidget.receiver.widget.WidgetProviderImpl -import com.g00fy2.developerwidget.receiver.widget.WidgetProviderModule +import com.g00fy2.developerwidget.receiver.widget.WidgetProvider import dagger.Module import dagger.android.ContributesAndroidInjector @Module abstract class BroadcastBindingModule { - @ContributesAndroidInjector(modules = [WidgetProviderModule::class]) - abstract fun bindWidgetProvider(): WidgetProviderImpl + @ContributesAndroidInjector + abstract fun bindWidgetProvider(): WidgetProvider } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProvider.kt similarity index 85% rename from app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderImpl.kt rename to app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProvider.kt index e476dd33..5a8d573d 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProvider.kt @@ -19,17 +19,23 @@ import com.g00fy2.developerwidget.activities.widgetconfig.WidgetConfigActivity import com.g00fy2.developerwidget.controllers.DayNightController import com.g00fy2.developerwidget.controllers.DayNightControllerImpl import com.g00fy2.developerwidget.data.DeviceDataItem +import com.g00fy2.developerwidget.data.DeviceDataSource import com.g00fy2.developerwidget.data.DeviceDataSourceImpl -import com.g00fy2.developerwidget.receiver.widget.WidgetProviderContract.WidgetProvider -import com.g00fy2.developerwidget.receiver.widget.WidgetProviderContract.WidgetProviderPresenter +import com.g00fy2.developerwidget.data.WidgetsPreferencesDataSource import dagger.android.AndroidInjection +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import timber.log.Timber import javax.inject.Inject -class WidgetProviderImpl : AppWidgetProvider(), WidgetProvider { +class WidgetProvider : AppWidgetProvider() { @Inject - lateinit var presenter: WidgetProviderPresenter + lateinit var deviceDataSource: DeviceDataSource + @Inject + lateinit var widgetsPreferencesDataSource: WidgetsPreferencesDataSource @Inject lateinit var dayNightController: DayNightController @@ -46,7 +52,7 @@ class WidgetProviderImpl : AppWidgetProvider(), WidgetProvider { val widgetId = intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID) ?: AppWidgetManager.INVALID_APPWIDGET_ID val customDeviceName = intent.extras?.getString(WidgetConfigActivity.EXTRA_APPWIDGET_CUSTOM_DEVICE_NAME) ?: "" if (widgetId != AppWidgetManager.INVALID_APPWIDGET_ID && customDeviceName.isNotBlank()) { - presenter.saveCustomDeviceName(widgetId, customDeviceName) + widgetsPreferencesDataSource.saveCustomDeviceName(widgetId, customDeviceName) } context.sendBroadcast(Intent(WidgetConfigActivity.EXTRA_APPWIDGET_CLOSE_CONFIGURE)) } @@ -55,7 +61,7 @@ class WidgetProviderImpl : AppWidgetProvider(), WidgetProvider { onUpdate( context, appWidgetManager, - appWidgetManager.getAppWidgetIds(ComponentName(context, WidgetProviderImpl::class.java)) + appWidgetManager.getAppWidgetIds(ComponentName(context, WidgetProvider::class.java)) ) } else { intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID)?.let { @@ -65,15 +71,22 @@ class WidgetProviderImpl : AppWidgetProvider(), WidgetProvider { } } - override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) = - presenter.getDeviceData(appWidgetIds) + override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { + GlobalScope.launch { + withContext(Dispatchers.IO) { + val data = deviceDataSource.getStaticDeviceData() + val customDeviceNames = widgetsPreferencesDataSource.getCustomDeviceNames(appWidgetIds) + updateWidgetData(appWidgetIds, data, customDeviceNames) + } + } + } override fun onDeleted(context: Context?, appWidgetIds: IntArray) { Timber.d("onDeleted widget %s", appWidgetIds.first()) - presenter.clearWidgetPreferences(appWidgetIds.first()) + widgetsPreferencesDataSource.clearWidgetPreferences(appWidgetIds.first()) } - override fun updateWidgetData( + private fun updateWidgetData( appWidgetIds: IntArray, data: Map, customDeviceNames: SparseArray diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderContract.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderContract.kt deleted file mode 100644 index e0a57542..00000000 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderContract.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.g00fy2.developerwidget.receiver.widget - -import android.util.SparseArray -import com.g00fy2.developerwidget.data.DeviceDataItem - -interface WidgetProviderContract { - - interface WidgetProvider { - - fun updateWidgetData( - appWidgetIds: IntArray, - data: Map, - customDeviceNames: SparseArray - ) - } - - interface WidgetProviderPresenter { - - fun getDeviceData(widgetIDs: IntArray) - - fun saveCustomDeviceName(widgetId: Int, customDeviceName: String): Boolean - - fun clearWidgetPreferences(widgetId: Int) - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderModule.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderModule.kt deleted file mode 100644 index 64adfc44..00000000 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderModule.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.g00fy2.developerwidget.receiver.widget - -import com.g00fy2.developerwidget.receiver.widget.WidgetProviderContract.WidgetProvider -import com.g00fy2.developerwidget.receiver.widget.WidgetProviderContract.WidgetProviderPresenter -import dagger.Binds -import dagger.Module - -@Module -abstract class WidgetProviderModule { - - @Binds - abstract fun provideWidgetProvider(widgetProviderImpl: WidgetProviderImpl): WidgetProvider - - @Binds - abstract fun provideWidgetProviderPresenter(presenter: WidgetProviderPresenterImpl): WidgetProviderPresenter -} \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderPresenterImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderPresenterImpl.kt deleted file mode 100644 index fb867c28..00000000 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderPresenterImpl.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.g00fy2.developerwidget.receiver.widget - -import com.g00fy2.developerwidget.data.DeviceDataSource -import com.g00fy2.developerwidget.data.WidgetsPreferencesDataSource -import com.g00fy2.developerwidget.receiver.widget.WidgetProviderContract.WidgetProvider -import com.g00fy2.developerwidget.receiver.widget.WidgetProviderContract.WidgetProviderPresenter -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import javax.inject.Inject -import kotlin.coroutines.CoroutineContext - -class WidgetProviderPresenterImpl @Inject constructor() : WidgetProviderPresenter, CoroutineScope { - - @Inject - lateinit var widgetProvider: WidgetProvider - @Inject - lateinit var deviceDataSource: DeviceDataSource - @Inject - lateinit var widgetsPreferencesDataSource: WidgetsPreferencesDataSource - - private val job: Job by lazy { Job() } - - override val coroutineContext: CoroutineContext = Dispatchers.Main + job - - override fun getDeviceData(widgetIDs: IntArray) { - launch { - withContext(Dispatchers.IO) { - val data = deviceDataSource.getStaticDeviceData() - val customDeviceNames = widgetsPreferencesDataSource.getCustomDeviceNames(widgetIDs) - widgetProvider.updateWidgetData(widgetIDs, data, customDeviceNames) - } - } - } - - override fun saveCustomDeviceName(widgetId: Int, customDeviceName: String) = - widgetsPreferencesDataSource.saveCustomDeviceName(widgetId, customDeviceName) - - override fun clearWidgetPreferences(widgetId: Int) = widgetsPreferencesDataSource.clearWidgetPreferences(widgetId) -} \ No newline at end of file From 13d2ff25af531698d114937b600b0eccfddb20ad Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 23:33:59 +0200 Subject: [PATCH 028/122] Replace restricted api call --- .../activities/widgetconfig/WidgetConfigActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index 744207ee..e013f007 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -87,7 +87,7 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg setActionbarElevationListener(widget_config_root_scrollview) widget_config_root_scrollview.viewTreeObserver.addOnScrollChangedListener { val scrollableRange = - widget_config_root_scrollview.computeVerticalScrollRange() - widget_config_root_scrollview.height + widget_config_root_scrollview.getChildAt(0).bottom - widget_config_root_scrollview.height val fabOffset = (share_fab.height / 2) + share_fab.marginBottom if (widget_config_root_scrollview.scrollY < scrollableRange - fabOffset) { share_fab.hide() From 0dbb8347ec57d88d6dfee1107bf4904db2552dda Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 23:38:39 +0200 Subject: [PATCH 029/122] Suppress irrelevant lint warnings --- app/src/main/AndroidManifest.xml | 3 ++- .../data/device/systemapps/SystemAppsDataProvider.kt | 2 +- app/src/main/res/drawable-night/ic_sad.xml | 4 +++- app/src/main/res/drawable/ic_changes_logo.xml | 4 +++- app/src/main/res/drawable/ic_github_logo_shape.xml | 4 +++- app/src/main/res/drawable/ic_sad.xml | 4 +++- app/src/main/res/drawable/ic_twitter_logo.xml | 4 +++- 7 files changed, 18 insertions(+), 7 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0d38354d..bdad6238 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,8 @@ + package="com.g00fy2.developerwidget" + tools:ignore="LockedOrientationActivity"> diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/data/device/systemapps/SystemAppsDataProvider.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/data/device/systemapps/SystemAppsDataProvider.kt index eef35b63..7991c0fa 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/data/device/systemapps/SystemAppsDataProvider.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/data/device/systemapps/SystemAppsDataProvider.kt @@ -21,7 +21,7 @@ class SystemAppsDataProvider { } } - @SuppressLint("PrivateApi") + @SuppressLint("PrivateApi", "WebViewApiAvailability") fun getWebViewImplementation(context: Context): String { return when { VERSION.SDK_INT >= VERSION_CODES.O -> WebView.getCurrentWebViewPackage()?.let { diff --git a/app/src/main/res/drawable-night/ic_sad.xml b/app/src/main/res/drawable-night/ic_sad.xml index f5ae6da9..bd4c41aa 100644 --- a/app/src/main/res/drawable-night/ic_sad.xml +++ b/app/src/main/res/drawable-night/ic_sad.xml @@ -1,4 +1,5 @@ + android:pathData="M227.496 327.992c-13.254 0-24-10.742-24-24v-32c0-4.418 3.582-8 8-8s8 3.582 8 8v32c0 4.422 3.582 8 8 8s8-3.578 8-8v-32c0-4.418 3.582-8 8-8s8 3.582 8 8v32c0 13.258-10.746 24-24 24zm-42.742-152c-3.234 0-6.152-1.949-7.391-4.938-1.238-2.988-0.555-6.43 1.734-8.715l58.742-58.746c3.141-3.031 8.129-2.988 11.215 0.098 3.086 3.086 3.129 8.074 0.098 11.215l-58.742 58.742c-1.5 1.504-3.535 2.344-5.656 2.344zm-32.008 32c-3.234 0-6.152-1.949-7.391-4.938-1.238-2.988-0.555-6.43 1.734-8.715l16-16c3.137-3.035 8.129-2.988 11.215 0.094 3.086 3.086 3.129 8.078 0.098 11.215l-16 16c-1.5 1.504-3.535 2.344-5.656 2.344zM99.664 362.906c-2.125 0-4.16-0.844-5.664-2.344-31.184-31.266-31.184-81.871 0-113.137l29.09-29.086c3.137-3.035 8.129-2.988 11.215 0.094 3.086 3.086 3.129 8.078 0.098 11.215l-29.082 29.09c-24.949 25.012-24.949 65.5 0 90.512 2.289 2.289 2.973 5.727 1.734 8.719-1.238 2.988-4.156 4.938-7.391 4.938zm0 0" + tools:ignore="VectorPath"/> diff --git a/app/src/main/res/drawable/ic_changes_logo.xml b/app/src/main/res/drawable/ic_changes_logo.xml index 528e5728..e874dc78 100644 --- a/app/src/main/res/drawable/ic_changes_logo.xml +++ b/app/src/main/res/drawable/ic_changes_logo.xml @@ -1,9 +1,11 @@ + android:pathData="M256 0C114.615 0 0 114.615 0 256s114.615 256 256 256 256-114.615 256-256S397.385 0 256 0zM74.325 162.731c4.851-5.773 12.001-9.114 19.541-9.131h102.4c7.908-0.001 15.374 3.652 20.224 9.899l28.757 36.864-32.512 41.728-26.453-34.133c-1.719-2.126-4.352-3.3-7.083-3.157H94.805c-12.879 0.355-24.117-8.679-26.539-21.333-1.138-7.469 1.079-15.058 6.059-20.737zm142.166 185.77c-4.85 6.246-12.316 9.9-20.224 9.899h-102.4c-14.137 0.206-25.764-11.087-25.97-25.224-0.023-1.584 0.101-3.167 0.37-4.728 2.458-12.621 13.686-21.61 26.539-21.248H179.2c2.626 0.014 5.113-1.182 6.741-3.243l109.227-140.459c4.924-6.342 12.537-10.007 20.565-9.899h54.101v-13.568c-0.008-9.426 7.627-17.073 17.053-17.08 4.555-0.004 8.923 1.814 12.131 5.048l39.765 39.68c6.669 6.661 6.675 17.467 0.013 24.136l-0.013 0.013-39.765 39.765c-6.637 6.692-17.443 6.737-24.136 0.1-3.256-3.229-5.075-7.632-5.048-12.217V204.8H332.8c-2.626-0.014-5.113 1.182-6.741 3.243L216.491 348.501zm222.293-4.181l-0.427-0.085L399.019 384c-6.638 6.692-17.443 6.737-24.136 0.099-3.234-3.208-5.052-7.576-5.048-12.131V358.4h-54.101c-7.908 0.001-15.373-3.652-20.224-9.899l-28.757-36.864 32.512-41.728 26.453 34.133c1.719 2.126 4.352 3.3 7.083 3.157h37.376v-14.763c-0.007-9.426 7.628-17.073 17.053-17.08 4.513-0.004 8.845 1.781 12.046 4.963l39.851 39.851c6.575 6.754 6.429 17.559-0.325 24.134l-0.018 0.016z" + tools:ignore="VectorPath"/> \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_github_logo_shape.xml b/app/src/main/res/drawable/ic_github_logo_shape.xml index 463dae98..bdad04a5 100644 --- a/app/src/main/res/drawable/ic_github_logo_shape.xml +++ b/app/src/main/res/drawable/ic_github_logo_shape.xml @@ -1,9 +1,11 @@ + android:pathData="M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14 0.954 8.945 0.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-0.571-0.049-5.708-0.144-15.417-0.098-9.709-0.144-18.179-0.144-25.406l-6.567 1.136c-4.187 0.767-9.469 1.092-15.846 1-6.374-0.089-12.991-0.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-0.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-0.572-1.335-0.098-2.43 1.427-3.289 1.525-0.859 4.281-1.276 8.28-1.276l5.708 0.853c3.807 0.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-0.476 16.274-1.423 4.565-0.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-0.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-0.01-39.771-9.818-76.454-29.414-110.049z" + tools:ignore="VectorPath"/> \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_sad.xml b/app/src/main/res/drawable/ic_sad.xml index 5d07ddfb..c8e21c2e 100644 --- a/app/src/main/res/drawable/ic_sad.xml +++ b/app/src/main/res/drawable/ic_sad.xml @@ -1,4 +1,5 @@ + android:pathData="M227.496 327.992c-13.254 0-24-10.742-24-24v-32c0-4.418 3.582-8 8-8s8 3.582 8 8v32c0 4.422 3.582 8 8 8s8-3.578 8-8v-32c0-4.418 3.582-8 8-8s8 3.582 8 8v32c0 13.258-10.746 24-24 24zm-42.742-152c-3.234 0-6.152-1.949-7.391-4.938-1.238-2.988-0.555-6.43 1.734-8.715l58.742-58.746c3.141-3.031 8.129-2.988 11.215 0.098 3.086 3.086 3.129 8.074 0.098 11.215l-58.742 58.742c-1.5 1.504-3.535 2.344-5.656 2.344zm-32.008 32c-3.234 0-6.152-1.949-7.391-4.938-1.238-2.988-0.555-6.43 1.734-8.715l16-16c3.137-3.035 8.129-2.988 11.215 0.094 3.086 3.086 3.129 8.078 0.098 11.215l-16 16c-1.5 1.504-3.535 2.344-5.656 2.344zM99.664 362.906c-2.125 0-4.16-0.844-5.664-2.344-31.184-31.266-31.184-81.871 0-113.137l29.09-29.086c3.137-3.035 8.129-2.988 11.215 0.094 3.086 3.086 3.129 8.078 0.098 11.215l-29.082 29.09c-24.949 25.012-24.949 65.5 0 90.512 2.289 2.289 2.973 5.727 1.734 8.719-1.238 2.988-4.156 4.938-7.391 4.938zm0 0" + tools:ignore="VectorPath"/> diff --git a/app/src/main/res/drawable/ic_twitter_logo.xml b/app/src/main/res/drawable/ic_twitter_logo.xml index 16e58b79..0a531ea3 100644 --- a/app/src/main/res/drawable/ic_twitter_logo.xml +++ b/app/src/main/res/drawable/ic_twitter_logo.xml @@ -1,9 +1,11 @@ + android:pathData="M24.826 0C11.137 0 0 11.137 0 24.826c0 13.688 11.137 24.826 24.826 24.826 13.688 0 24.826-11.138 24.826-24.826C49.652 11.137 38.516 0 24.826 0zm11.075 19.144c0.011 0.246 0.017 0.494 0.017 0.742 0 7.551-5.746 16.255-16.259 16.255-3.227 0-6.231-0.943-8.759-2.565 0.447 0.053 0.902 0.08 1.363 0.08 2.678 0 5.141-0.914 7.097-2.446-2.5-0.046-4.611-1.698-5.338-3.969 0.348 0.066 0.707 0.103 1.074 0.103 0.521 0 1.027-0.068 1.506-0.199-2.614-0.524-4.583-2.833-4.583-5.603l0.001-0.072c0.77 0.427 1.651 0.685 2.587 0.714-1.532-1.023-2.541-2.773-2.541-4.755 0-1.048 0.281-2.03 0.773-2.874 2.817 3.458 7.029 5.732 11.777 5.972-0.098-0.419-0.147-0.854-0.147-1.303 0-3.155 2.558-5.714 5.713-5.714 1.644 0 3.127 0.694 4.171 1.804 1.303-0.256 2.523-0.73 3.63-1.387-0.43 1.335-1.333 2.454-2.516 3.162 1.157-0.138 2.261-0.444 3.282-0.899-0.762 1.144-1.731 2.151-2.848 2.954z" + tools:ignore="VectorPath"/> \ No newline at end of file From 452dff08bbe3ab8b491d74990d4ac71104bfe944 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 23:49:03 +0200 Subject: [PATCH 030/122] Reformat xml file --- app/src/main/res/layout/activity_apps.xml | 142 +++++++++++----------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/app/src/main/res/layout/activity_apps.xml b/app/src/main/res/layout/activity_apps.xml index 796b6c3e..9c5c8513 100644 --- a/app/src/main/res/layout/activity_apps.xml +++ b/app/src/main/res/layout/activity_apps.xml @@ -1,10 +1,10 @@ @@ -55,85 +55,85 @@ > - - - + android:background="@color/backgroundColor" + android:orientation="vertical" + > - + - + - + - + - - + + + + - + Date: Thu, 5 Sep 2019 23:56:44 +0200 Subject: [PATCH 031/122] Update deps --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f6c2a0b7..5b45c498 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ buildscript { activityVersion = '1.1.0-alpha03' lifecycleVersion = '2.2.0-alpha04' materialVersion = '1.1.0-alpha10' - recyclerviewVersion = '1.1.0-beta03' + recyclerviewVersion = '1.1.0-beta04' vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta2' timberVersion = '4.7.1' From 8174840984ac24bae6dd9875bc05784ded09b33a Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Sep 2019 23:57:37 +0200 Subject: [PATCH 032/122] Mark releases from travis as prerelease by default --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b08a1da3..457a9a2a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -78,6 +78,7 @@ android_phases: name: $TRAVIS_TAG tag_name: $TRAVIS_TAG body: "Generated release from Travis CI for build $TRAVIS_BUILD_NUMBER" + prerelease: true jobs: include: From f9aa8ee0fa55d9024108110e25b2f083158c244c Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Fri, 6 Sep 2019 00:14:42 +0200 Subject: [PATCH 033/122] Revert WidgetProvider renaming to avoid update issues --- app/src/main/AndroidManifest.xml | 2 +- .../widgetconfig/WidgetConfigActivity.kt | 14 +++++++------- .../controllers/DayNightControllerImpl.kt | 6 +++--- .../developerwidget/di/BroadcastBindingModule.kt | 4 ++-- .../{WidgetProvider.kt => WidgetProviderImpl.kt} | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) rename app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/{WidgetProvider.kt => WidgetProviderImpl.kt} (98%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bdad6238..1ef531ce 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -84,7 +84,7 @@ android:taskAffinity="" android:theme="@android:style/Theme.Translucent.NoTitleBar"/> - + diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index e013f007..25a0dfa0 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -34,7 +34,7 @@ import com.g00fy2.developerwidget.base.BaseContract.BasePresenter import com.g00fy2.developerwidget.data.DeviceDataItem import com.g00fy2.developerwidget.ktx.hideKeyboard import com.g00fy2.developerwidget.ktx.showKeyboard -import com.g00fy2.developerwidget.receiver.widget.WidgetProvider +import com.g00fy2.developerwidget.receiver.widget.WidgetProviderImpl import kotlinx.android.synthetic.main.activity_widget_config.* import javax.inject.Inject @@ -234,8 +234,8 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg if (!existing) { setResult(Activity.RESULT_OK, Intent().apply { putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId) }) } - sendBroadcast(Intent(applicationContext, WidgetProvider::class.java).apply { - action = WidgetProvider.UPDATE_WIDGET_MANUALLY_ACTION + sendBroadcast(Intent(applicationContext, WidgetProviderImpl::class.java).apply { + action = WidgetProviderImpl.UPDATE_WIDGET_MANUALLY_ACTION putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId) }) finish() @@ -248,15 +248,15 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg if (appWidgetManager.isRequestPinAppWidgetSupported) { supported = true val successCallback = PendingIntent.getBroadcast( - this, 0, Intent(applicationContext, WidgetProvider::class.java).apply { - action = WidgetProvider.UPDATE_WIDGET_MANUALLY_ACTION + this, 0, Intent(applicationContext, WidgetProviderImpl::class.java).apply { + action = WidgetProviderImpl.UPDATE_WIDGET_MANUALLY_ACTION putExtra(EXTRA_APPWIDGET_FROM_PIN_APP, true) putExtra(EXTRA_APPWIDGET_CUSTOM_DEVICE_NAME, device_title_edittextview.text.toString()) }, PendingIntent.FLAG_UPDATE_CURRENT ) appWidgetManager.requestPinAppWidget( - ComponentName(applicationContext, WidgetProvider::class.java), + ComponentName(applicationContext, WidgetProviderImpl::class.java), null, successCallback ) @@ -277,7 +277,7 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg private fun widgetCount() = AppWidgetManager.getInstance(this).getAppWidgetIds( ComponentName( applicationContext, - WidgetProvider::class.java + WidgetProviderImpl::class.java ) ).size diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt index 58c86d0c..5691a5dd 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt @@ -8,7 +8,7 @@ import androidx.appcompat.app.AppCompatDelegate import androidx.core.content.edit import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.di.annotations.APPLICATION -import com.g00fy2.developerwidget.receiver.widget.WidgetProvider +import com.g00fy2.developerwidget.receiver.widget.WidgetProviderImpl import javax.inject.Inject import javax.inject.Named @@ -49,8 +49,8 @@ class DayNightControllerImpl @Inject constructor() : DayNightController { private fun applyMode(mode: Int) = AppCompatDelegate.setDefaultNightMode(mode) private fun updateWidgetTheme() { - context.sendBroadcast(Intent(context, WidgetProvider::class.java).apply { - action = WidgetProvider.UPDATE_WIDGET_MANUALLY_ACTION + context.sendBroadcast(Intent(context, WidgetProviderImpl::class.java).apply { + action = WidgetProviderImpl.UPDATE_WIDGET_MANUALLY_ACTION putExtra(UPDATE_WIDGET_THEME, true) }) } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt index 83cc2533..fecee317 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/di/BroadcastBindingModule.kt @@ -1,6 +1,6 @@ package com.g00fy2.developerwidget.di -import com.g00fy2.developerwidget.receiver.widget.WidgetProvider +import com.g00fy2.developerwidget.receiver.widget.WidgetProviderImpl import dagger.Module import dagger.android.ContributesAndroidInjector @@ -8,5 +8,5 @@ import dagger.android.ContributesAndroidInjector abstract class BroadcastBindingModule { @ContributesAndroidInjector - abstract fun bindWidgetProvider(): WidgetProvider + abstract fun bindWidgetProvider(): WidgetProviderImpl } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProvider.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderImpl.kt similarity index 98% rename from app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProvider.kt rename to app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderImpl.kt index 5a8d573d..68963522 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProvider.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/receiver/widget/WidgetProviderImpl.kt @@ -30,7 +30,7 @@ import kotlinx.coroutines.withContext import timber.log.Timber import javax.inject.Inject -class WidgetProvider : AppWidgetProvider() { +class WidgetProviderImpl : AppWidgetProvider() { @Inject lateinit var deviceDataSource: DeviceDataSource @@ -61,7 +61,7 @@ class WidgetProvider : AppWidgetProvider() { onUpdate( context, appWidgetManager, - appWidgetManager.getAppWidgetIds(ComponentName(context, WidgetProvider::class.java)) + appWidgetManager.getAppWidgetIds(ComponentName(context, WidgetProviderImpl::class.java)) ) } else { intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID)?.let { From 63ea870bb1c844bfa087c5a15fb513ccb2ba3fa8 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Fri, 6 Sep 2019 09:43:45 +0200 Subject: [PATCH 034/122] Remove shortcut bottom padding --- app/src/main/res/layout/activity_create_shortcut.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/res/layout/activity_create_shortcut.xml b/app/src/main/res/layout/activity_create_shortcut.xml index 97cf4cfb..34d41c3b 100644 --- a/app/src/main/res/layout/activity_create_shortcut.xml +++ b/app/src/main/res/layout/activity_create_shortcut.xml @@ -8,7 +8,6 @@ android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingBottom="8dp" > From 1c71d5a29d7b4dff82c6a3dfd74e69505cff5f62 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 10 Sep 2019 01:15:37 +0200 Subject: [PATCH 035/122] Update dependency --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5b45c498..f2e86e4f 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { constraintlayoutVersion = '2.0.0-beta2' timberVersion = '4.7.1' daggerVersion = '2.24' - versCompVersion = '1.3.2' + versCompVersion = '1.3.3' } repositories { google() From 731746ff45f850e732b6516c09e3ee8cd976ba6d Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 11 Sep 2019 02:02:41 +0200 Subject: [PATCH 036/122] Adjust widget background shape --- app/src/main/res/drawable/bg_widget_inner_shape.xml | 2 +- app/src/main/res/drawable/bg_widget_inner_shape_day.xml | 2 +- app/src/main/res/drawable/bg_widget_inner_shape_night.xml | 2 +- app/src/main/res/drawable/bg_widget_outer_shape.xml | 2 +- app/src/main/res/drawable/bg_widget_outer_shape_day.xml | 2 +- app/src/main/res/drawable/bg_widget_outer_shape_night.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/drawable/bg_widget_inner_shape.xml b/app/src/main/res/drawable/bg_widget_inner_shape.xml index 669b3370..8df00f71 100644 --- a/app/src/main/res/drawable/bg_widget_inner_shape.xml +++ b/app/src/main/res/drawable/bg_widget_inner_shape.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_widget_inner_shape_day.xml b/app/src/main/res/drawable/bg_widget_inner_shape_day.xml index 1db58967..44ab65b9 100644 --- a/app/src/main/res/drawable/bg_widget_inner_shape_day.xml +++ b/app/src/main/res/drawable/bg_widget_inner_shape_day.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_widget_inner_shape_night.xml b/app/src/main/res/drawable/bg_widget_inner_shape_night.xml index d29e2e71..e9061b42 100644 --- a/app/src/main/res/drawable/bg_widget_inner_shape_night.xml +++ b/app/src/main/res/drawable/bg_widget_inner_shape_night.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_widget_outer_shape.xml b/app/src/main/res/drawable/bg_widget_outer_shape.xml index 6aba3753..8eeca606 100644 --- a/app/src/main/res/drawable/bg_widget_outer_shape.xml +++ b/app/src/main/res/drawable/bg_widget_outer_shape.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_widget_outer_shape_day.xml b/app/src/main/res/drawable/bg_widget_outer_shape_day.xml index 35c212d1..4823e38a 100644 --- a/app/src/main/res/drawable/bg_widget_outer_shape_day.xml +++ b/app/src/main/res/drawable/bg_widget_outer_shape_day.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_widget_outer_shape_night.xml b/app/src/main/res/drawable/bg_widget_outer_shape_night.xml index fd00d280..99817e62 100644 --- a/app/src/main/res/drawable/bg_widget_outer_shape_night.xml +++ b/app/src/main/res/drawable/bg_widget_outer_shape_night.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file From 8454576036413a4d883ad1833a0c4c1c9fe70388 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 11 Sep 2019 02:03:13 +0200 Subject: [PATCH 037/122] Cleanup --- .../developerwidget/activities/apkinstall/ApkPresenterImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkPresenterImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkPresenterImpl.kt index dc0be36e..e06a7bc6 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkPresenterImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkPresenterImpl.kt @@ -47,7 +47,7 @@ class ApkPresenterImpl @Inject constructor() : BasePresenterImpl(), ApkContract. } } } else { - view.toggleResultView(emptyList(), missingPermissions = true) + view.toggleResultView(emptyList(), true) } } From 4e1933c2ca109af2c490d32bc814769c75befec7 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 11 Sep 2019 02:07:28 +0200 Subject: [PATCH 038/122] Add edge-to-edge look and make navigation bar transparent --- .../activities/about/AboutActivity.kt | 7 ++++++ .../shortcut/CreateShortcutActivity.kt | 7 ++++++ .../widgetconfig/WidgetConfigActivity.kt | 24 ++++++++++++------ .../developerwidget/base/BaseActivity.kt | 25 ++++++++++++++++--- .../developerwidget/ktx/ViewExtension.kt | 23 ++++++++++++++++- app/src/main/res/layout/activity_about.xml | 1 + .../res/layout/activity_create_shortcut.xml | 5 ++-- .../res/layout/activity_widget_config.xml | 1 + app/src/main/res/values-night-v29/colors.xml | 2 ++ app/src/main/res/values-night/colors.xml | 3 +-- app/src/main/res/values-v26/colors.xml | 4 --- app/src/main/res/values-v29/colors.xml | 2 ++ app/src/main/res/values/colors.xml | 4 +-- 13 files changed, 85 insertions(+), 23 deletions(-) delete mode 100644 app/src/main/res/values-v26/colors.xml diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt index 85f9b81a..a6bdd9ac 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt @@ -7,11 +7,13 @@ import android.os.Build.VERSION import android.os.Build.VERSION_CODES import android.view.MenuItem import androidx.appcompat.app.AppCompatDelegate +import androidx.core.view.updatePadding import com.g00fy2.developerwidget.BuildConfig import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.activities.widgetconfig.ConfigLauncherActivity import com.g00fy2.developerwidget.base.BaseActivity import com.g00fy2.developerwidget.base.BaseContract.BasePresenter +import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets import kotlinx.android.synthetic.main.activity_about.* import javax.inject.Inject @@ -113,6 +115,11 @@ class AboutActivity : BaseActivity(R.layout.activity_about), AboutContract.About description(BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ") " + BuildConfig.BUILD_TYPE) action { presenter.honorClicking() } } + if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) { + about_root_scrollview.doOnApplyWindowInsets { view, insets, padding -> + view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) + } + } } override fun updateThemeToggleView() { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt index 395fed85..ef982bdb 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt @@ -16,6 +16,7 @@ import androidx.annotation.StringRes import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.getSystemService import androidx.core.graphics.drawable.toBitmap +import androidx.core.view.updatePadding import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import com.g00fy2.developerwidget.R @@ -23,6 +24,7 @@ import com.g00fy2.developerwidget.activities.apkinstall.ApkActivity import com.g00fy2.developerwidget.activities.appmanager.AppsActivity import com.g00fy2.developerwidget.base.BaseActivity import com.g00fy2.developerwidget.base.BaseContract.BasePresenter +import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets import kotlinx.android.synthetic.main.activity_create_shortcut.* import javax.inject.Inject @@ -51,6 +53,11 @@ class CreateShortcutActivity : BaseActivity(R.layout.activity_create_shortcut), shortcutInfoList = generateShortcutInfoList() adapter.submitList(shortcutInfoList) adapter.setOnShortcutSelected { shortcutPosition -> onItemClick(shortcutPosition) } + if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) { + recyclerview.doOnApplyWindowInsets { view, insets, padding -> + view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) + } + } } private fun onItemClick(position: Int) { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index 25a0dfa0..09b9974f 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -26,12 +26,14 @@ import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.getSystemService import androidx.core.content.res.ResourcesCompat import androidx.core.view.marginBottom +import androidx.core.view.updatePadding import androidx.recyclerview.widget.LinearLayoutManager import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.activities.about.AboutActivity import com.g00fy2.developerwidget.base.BaseActivity import com.g00fy2.developerwidget.base.BaseContract.BasePresenter import com.g00fy2.developerwidget.data.DeviceDataItem +import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets import com.g00fy2.developerwidget.ktx.hideKeyboard import com.g00fy2.developerwidget.ktx.showKeyboard import com.g00fy2.developerwidget.receiver.widget.WidgetProviderImpl @@ -85,14 +87,15 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg } setActionbarElevationListener(widget_config_root_scrollview) - widget_config_root_scrollview.viewTreeObserver.addOnScrollChangedListener { - val scrollableRange = - widget_config_root_scrollview.getChildAt(0).bottom - widget_config_root_scrollview.height - val fabOffset = (share_fab.height / 2) + share_fab.marginBottom - if (widget_config_root_scrollview.scrollY < scrollableRange - fabOffset) { - share_fab.hide() - } else { - share_fab.show() + widget_config_root_scrollview.apply { + viewTreeObserver.addOnScrollChangedListener { + val scrollableRange = getChildAt(0).bottom - height + paddingBottom + val fabOffset = (share_fab.height / 2) + share_fab.marginBottom + if (scrollY < scrollableRange - fabOffset) { + share_fab.hide() + } else { + share_fab.show() + } } } @@ -126,6 +129,11 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg } } share_fab.setOnClickListener { presenter.shareDeviceData() } + if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) { + widget_config_root_scrollview.doOnApplyWindowInsets { view, insets, padding -> + view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) + } + } resetView() } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt index 8fec5d11..48032458 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt @@ -9,7 +9,9 @@ import android.view.ViewGroup import android.view.Window import androidx.annotation.LayoutRes import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.updatePadding import com.g00fy2.developerwidget.controllers.DayNightController +import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets import dagger.android.AndroidInjection import timber.log.Timber import javax.inject.Inject @@ -39,6 +41,7 @@ abstract class BaseActivity(@LayoutRes contentLayoutId: Int, private val isDialo lifecycle.addObserver(providePresenter()) initCompatNavigationBar() initView() + if (!isDialogActivity) initGestureNavigation() } override fun onDestroy() { @@ -71,12 +74,28 @@ abstract class BaseActivity(@LayoutRes contentLayoutId: Int, private val isDialo } } + private fun initGestureNavigation() { + if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) { + window.decorView.let { + it.systemUiVisibility.let { flags -> + it.systemUiVisibility = + flags or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE + } + } + findViewById(android.R.id.content)?.let { + it.doOnApplyWindowInsets { view, insets, padding -> + view.updatePadding(top = padding.top + insets.systemWindowInsetTop) + } + } + } + } + private fun initCompatNavigationBar() { // api 27+ allow applying flag via xml (windowLightNavigationBar) if (VERSION.SDK_INT == VERSION_CODES.O && isInNightMode()) { - window.decorView.let { view -> - view.systemUiVisibility.let { flags -> - view.systemUiVisibility = flags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR + window.decorView.let { + it.systemUiVisibility.let { flags -> + it.systemUiVisibility = flags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR } } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt index 539771b6..52f74ec1 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt @@ -4,6 +4,8 @@ import android.os.Build.VERSION import android.os.Build.VERSION_CODES import android.util.TypedValue import android.view.View +import android.view.WindowInsets +import androidx.annotation.RequiresApi fun View.addRipple(asForeground: Boolean = false) { TypedValue().apply { context.theme.resolveAttribute(android.R.attr.selectableItemBackground, this, true) } @@ -11,4 +13,23 @@ fun View.addRipple(asForeground: Boolean = false) { if (VERSION.SDK_INT < VERSION_CODES.M || !asForeground) setBackgroundResource(it) else foreground = context.getDrawable(it) } -} \ No newline at end of file +} + +@RequiresApi(VERSION_CODES.KITKAT_WATCH) +fun View.doOnApplyWindowInsets(f: (View, WindowInsets, InitialPadding) -> Unit) { + val initialPadding = recordInitialPaddingForView(this) + setOnApplyWindowInsetsListener { v, insets -> + f(v, insets, initialPadding) + insets + } +} + + +data class InitialPadding( + val left: Int, val top: Int, + val right: Int, val bottom: Int +) + +private fun recordInitialPaddingForView(view: View) = InitialPadding( + view.paddingLeft, view.paddingTop, view.paddingRight, view.paddingBottom +) \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index 83c34ec1..e2c05c85 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -6,6 +6,7 @@ android:id="@+id/about_root_scrollview" android:layout_width="match_parent" android:layout_height="match_parent" + android:clipToPadding="false" android:scrollbars="vertical" > - - + android:clipToPadding="false" + /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_widget_config.xml b/app/src/main/res/layout/activity_widget_config.xml index 01fe79a1..1d8b715d 100644 --- a/app/src/main/res/layout/activity_widget_config.xml +++ b/app/src/main/res/layout/activity_widget_config.xml @@ -6,6 +6,7 @@ android:id="@+id/widget_config_root_scrollview" android:layout_width="match_parent" android:layout_height="match_parent" + android:clipToPadding="false" android:scrollbars="vertical" > @color/black @color/black + @color/transparent + #1f1f1f @color/black diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 33170474..ce3e1389 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -8,8 +8,7 @@ #80212121 #3c3c3c - @color/black - @color/black + #A6000000 #a0a0a0 #1ffafafa diff --git a/app/src/main/res/values-v26/colors.xml b/app/src/main/res/values-v26/colors.xml deleted file mode 100644 index 7ee24850..00000000 --- a/app/src/main/res/values-v26/colors.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - @color/white - diff --git a/app/src/main/res/values-v29/colors.xml b/app/src/main/res/values-v29/colors.xml index 5a75378c..189c302e 100644 --- a/app/src/main/res/values-v29/colors.xml +++ b/app/src/main/res/values-v29/colors.xml @@ -4,4 +4,6 @@ #8ab4f8 @color/colorAccent + @color/transparent + @color/transparent diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index c66038b4..599c3684 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -13,8 +13,8 @@ #80212121 @color/lighterGrey - @color/black - @color/dividerGrey + #A6FFFFFF + @color/navigationBarColor @color/black #33303030 From e5b954b5821fb7b8a24bd965ea6d28c0ce744bba Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 12 Sep 2019 02:23:40 +0200 Subject: [PATCH 039/122] Update android studio and switch to new AndroidX ViewBinding --- app/build.gradle | 8 +- .../activities/about/AboutActivity.kt | 51 ++++++----- .../about/views/AboutHeaderLayout.kt | 10 +-- .../activities/about/views/AboutItemLayout.kt | 32 ++++--- .../activities/apkinstall/ApkActivity.kt | 59 ++++++------ .../activities/apkinstall/ApkAdapter.kt | 29 +++--- .../activities/appmanager/AppsActivity.kt | 90 ++++++++++--------- .../activities/appmanager/AppsAdapter.kt | 23 ++--- .../shortcut/CreateShortcutActivity.kt | 26 ++++-- .../activities/shortcut/ShortcutAdapter.kt | 16 ++-- .../widgetconfig/DeviceDataAdapter.kt | 45 +++++----- .../widgetconfig/WidgetConfigActivity.kt | 73 ++++++++------- .../developerwidget/base/BaseActivity.kt | 9 +- .../developerwidget/base/BaseViewHolder.kt | 7 +- build.gradle | 2 +- 15 files changed, 261 insertions(+), 219 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 99a6c714..fb4f0939 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,8 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' apply plugin: 'eu.appcom.gradle.android-versioning' -androidExtensions { - experimental = true -} - android { compileSdkVersion rootProject.compileSdkVersion buildToolsVersion rootProject.buildToolsVersion @@ -41,6 +36,9 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + viewBinding { + enabled = true + } versioning { baseName = 'developerwidget' } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt index a6bdd9ac..8012381e 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt @@ -8,22 +8,29 @@ import android.os.Build.VERSION_CODES import android.view.MenuItem import androidx.appcompat.app.AppCompatDelegate import androidx.core.view.updatePadding +import androidx.viewbinding.ViewBinding import com.g00fy2.developerwidget.BuildConfig import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.activities.widgetconfig.ConfigLauncherActivity import com.g00fy2.developerwidget.base.BaseActivity import com.g00fy2.developerwidget.base.BaseContract.BasePresenter +import com.g00fy2.developerwidget.databinding.ActivityAboutBinding import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets -import kotlinx.android.synthetic.main.activity_about.* import javax.inject.Inject -class AboutActivity : BaseActivity(R.layout.activity_about), AboutContract.AboutView { +class AboutActivity : BaseActivity(), AboutContract.AboutView { @Inject lateinit var presenter: AboutContract.AboutPresenter + private lateinit var binding: ActivityAboutBinding override fun providePresenter(): BasePresenter = presenter + override fun setViewBinding(): ViewBinding { + binding = ActivityAboutBinding.inflate(layoutInflater) + return binding + } + override fun onResume() { super.onResume() updateThemeToggleView() @@ -42,88 +49,88 @@ class AboutActivity : BaseActivity(R.layout.activity_about), AboutContract.About override fun initView() { supportActionBar?.setDisplayHomeAsUpEnabled(true) - setActionbarElevationListener(about_root_scrollview) + setActionbarElevationListener(binding.aboutRootScrollview) - app_version_textview.text = String.format(getString(R.string.app_version), BuildConfig.VERSION_NAME) + binding.appVersionTextview.text = String.format(getString(R.string.app_version), BuildConfig.VERSION_NAME) - theme_item.init { + binding.themeItem.init { title(R.string.app_theme) action { presenter.toggleDayNightMode() } } - privacy_item.init { + binding.privacyItem.init { icon(R.drawable.ic_privacy_logo) title(R.string.privacy_policy) action { presenter.openUrl(PRIVACY_POLICY) } } - license_item.init { + binding.privacyItem.init { icon(R.drawable.ic_open_source_logo) title(R.string.license) description(R.string.mit_license) action { presenter.openUrl(MIT_LICENSE) } } - feedback_item.init { + binding.feedbackItem.init { icon(R.drawable.ic_feedback) title(R.string.feedback) description(R.string.feedback_description) action { showFeedbackOptions() } } - source_code_item.init { + binding.sourceCodeItem.init { icon(R.drawable.ic_github_logo_shape) title(R.string.source_code) action { presenter.openUrl(GITHUB_PROJECT) } } - changelog_item.init { + binding.changelogItem.init { icon(R.drawable.ic_changes_logo) title(R.string.changelog) action { presenter.openUrl(CHANGES) } } - author_header.init { + binding.authorHeader.init { title(R.string.author) } - twitter_item.init { + binding.twitterItem.init { icon(R.drawable.ic_twitter_logo) title(R.string.twitter) description(R.string.twitter_username) action { presenter.openUrl(TWITTER_USER) } } - github_item.init { + binding.githubItem.init { icon(R.drawable.ic_github_logo_shape) title(R.string.github) description(R.string.github_username) action { presenter.openUrl(GITHUB_USER) } } - licenses_header.init { + binding.licenseItem.init { title(R.string.licenses) } - open_source_licenses_item.init { + binding.openSourceLicensesItem.init { title(R.string.open_source_licenses) description(R.string.open_source_licenses_description) action { presenter.openUrl(OSS_LICENSES) } } - image_licenses_item.init { + binding.imageLicensesItem.init { title(R.string.icon_credits) description(R.string.icon_credits_description) action { presenter.openUrl(ICON_CREDITS) } } - hide_launcher_icon_item.init { + binding.hideLauncherIconItem.init { title(R.string.show_app_icon) description(R.string.show_app_icon_description) action { toggleLauncherIcon() } } - build_number_item.init { + binding.buildNumberItem.init { title(R.string.build_number) description(BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ") " + BuildConfig.BUILD_TYPE) action { presenter.honorClicking() } } if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) { - about_root_scrollview.doOnApplyWindowInsets { view, insets, padding -> + binding.aboutRootScrollview.doOnApplyWindowInsets { view, insets, padding -> view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) } } } override fun updateThemeToggleView() { - theme_item.let { + binding.themeItem.let { when (dayNightController.getCurrentDefaultMode()) { AppCompatDelegate.MODE_NIGHT_YES -> it.icon(R.drawable.ic_mode_night).description(R.string.night_mode) AppCompatDelegate.MODE_NIGHT_NO -> it.icon(R.drawable.ic_mode_day).description(R.string.day_mode) @@ -132,10 +139,10 @@ class AboutActivity : BaseActivity(R.layout.activity_about), AboutContract.About } } - private fun updateLauncherIconSwitch() = hide_launcher_icon_item.switch(!isLauncherIconDisabled()) + private fun updateLauncherIconSwitch() = binding.hideLauncherIconItem.switch(!isLauncherIconDisabled()) private fun updateLauncherIconItem() { - if (VERSION.SDK_INT >= VERSION_CODES.Q) hide_launcher_icon_item.isEnabled = isLauncherIconDisabled() + if (VERSION.SDK_INT >= VERSION_CODES.Q) binding.hideLauncherIconItem.isEnabled = isLauncherIconDisabled() } private fun showFeedbackOptions() { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutHeaderLayout.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutHeaderLayout.kt index 0f506918..a9a3cb79 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutHeaderLayout.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutHeaderLayout.kt @@ -2,10 +2,10 @@ package com.g00fy2.developerwidget.activities.about.views import android.content.Context import android.util.AttributeSet +import android.view.LayoutInflater import android.widget.FrameLayout import androidx.annotation.StringRes -import com.g00fy2.developerwidget.R -import kotlinx.android.synthetic.main.about_item_header.view.* +import com.g00fy2.developerwidget.databinding.AboutItemHeaderBinding class AboutHeaderLayout @JvmOverloads constructor( context: Context, @@ -13,12 +13,10 @@ class AboutHeaderLayout @JvmOverloads constructor( defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr) { - init { - inflate(context, R.layout.about_item_header, this) - } + private val binding = AboutItemHeaderBinding.inflate(LayoutInflater.from(context), this) fun title(@StringRes titleRes: Int): AboutHeaderLayout { - header_textview.setText(titleRes) + binding.headerTextview.setText(titleRes) return this } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt index 670b7c8c..458c376e 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt @@ -2,21 +2,19 @@ package com.g00fy2.developerwidget.activities.about.views import android.content.Context import android.util.AttributeSet +import android.view.LayoutInflater import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.children import androidx.core.view.isVisible -import com.g00fy2.developerwidget.R +import com.g00fy2.developerwidget.databinding.AboutItemBinding import com.g00fy2.developerwidget.ktx.addRipple -import kotlinx.android.synthetic.main.about_item.view.* class AboutItemLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ConstraintLayout(context, attrs, defStyleAttr) { - init { - inflate(context, R.layout.about_item, this) - } + private val binding = AboutItemBinding.inflate(LayoutInflater.from(context), this) override fun setEnabled(enabled: Boolean) { super.setEnabled(enabled) @@ -24,36 +22,36 @@ class AboutItemLayout @JvmOverloads constructor(context: Context, attrs: Attribu } fun icon(@DrawableRes iconRes: Int): AboutItemLayout { - icon_imageview.setImageResource(iconRes) - icon_imageview.isVisible = true + binding.iconImageview.setImageResource(iconRes) + binding.iconImageview.isVisible = true return this } fun title(@StringRes titleRes: Int): AboutItemLayout { - title_textview.setText(titleRes) - title_textview.isVisible = true + binding.titleTextview.setText(titleRes) + binding.titleTextview.isVisible = true return this } fun description(@StringRes descriptionRes: Int): AboutItemLayout { - description_textview.setText(descriptionRes) - description_textview.isVisible = true + binding.descriptionTextview.setText(descriptionRes) + binding.descriptionTextview.isVisible = true return this } fun description(description: String): AboutItemLayout { if (description.isNotBlank()) { - description_textview.text = description - description_textview.isVisible = true + binding.descriptionTextview.text = description + binding.descriptionTextview.isVisible = true } else { - description_textview.isVisible = false + binding.descriptionTextview.isVisible = false } return this } fun switch(on: Boolean): AboutItemLayout { - setting_switch.isChecked = on - setting_switch.isVisible = true + binding.settingSwitch.isChecked = on + binding.settingSwitch.isVisible = true return this } @@ -61,7 +59,7 @@ class AboutItemLayout @JvmOverloads constructor(context: Context, attrs: Attribu addRipple() setOnClickListener { action() - if (setting_switch.isVisible) setting_switch.isChecked = !setting_switch.isChecked + if (binding.settingSwitch.isVisible) binding.settingSwitch.isChecked = !binding.settingSwitch.isChecked } return this } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt index 4148509b..5fc1284c 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt @@ -4,28 +4,35 @@ import android.view.View import androidx.appcompat.widget.TooltipCompat import androidx.core.view.ViewCompat import androidx.recyclerview.widget.LinearLayoutManager +import androidx.viewbinding.ViewBinding import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.base.BaseActivity import com.g00fy2.developerwidget.base.BaseContract.BasePresenter -import kotlinx.android.synthetic.main.activity_apk.* +import com.g00fy2.developerwidget.databinding.ActivityApkBinding import javax.inject.Inject -class ApkActivity : BaseActivity(R.layout.activity_apk, true), ApkContract.ApkView { +class ApkActivity : BaseActivity(true), ApkContract.ApkView { @Inject lateinit var presenter: ApkContract.ApkPresenter private lateinit var adapter: ApkAdapter + private lateinit var binding: ActivityApkBinding override fun providePresenter(): BasePresenter = presenter + override fun setViewBinding(): ViewBinding { + binding = ActivityApkBinding.inflate(layoutInflater) + return binding + } + override fun onResume() { super.onResume() if (adapter.itemCount == 0) { - progressbar.visibility = View.VISIBLE - no_items_imageview.visibility = View.INVISIBLE - no_items_textview.text = getString(R.string.scanning_apks) - no_items_textview.visibility = View.VISIBLE + binding.progressbar.visibility = View.VISIBLE + binding.noItemsImageview.visibility = View.INVISIBLE + binding.noItemsTextview.text = getString(R.string.scanning_apks) + binding.noItemsTextview.visibility = View.VISIBLE } } @@ -35,20 +42,20 @@ class ApkActivity : BaseActivity(R.layout.activity_apk, true), ApkContract.ApkVi adapter.setOnApkSelect { selectedCount -> showOptions(selectedCount > 0) } adapter.setCommitCallback(Runnable { adapter.itemCount.let { - recyclerview.overScrollMode = if (it == 0) View.OVER_SCROLL_NEVER else View.OVER_SCROLL_ALWAYS - no_items_textview.visibility = if (it == 0) View.VISIBLE else View.INVISIBLE - no_items_imageview.visibility = if (it == 0) View.VISIBLE else View.INVISIBLE + binding.recyclerview.overScrollMode = if (it == 0) View.OVER_SCROLL_NEVER else View.OVER_SCROLL_ALWAYS + binding.noItemsTextview.visibility = if (it == 0) View.VISIBLE else View.INVISIBLE + binding.noItemsImageview.visibility = if (it == 0) View.VISIBLE else View.INVISIBLE } }) - recyclerview.setHasFixedSize(true) - recyclerview.layoutManager = LinearLayoutManager(this) - recyclerview.adapter = adapter + binding.recyclerview.setHasFixedSize(true) + binding.recyclerview.layoutManager = LinearLayoutManager(this) + binding.recyclerview.adapter = adapter - cancel_textview.setOnClickListener { finish() } - TooltipCompat.setTooltipText(delete_imageview, delete_imageview.contentDescription) - delete_imageview.setOnClickListener { showConfirmationDialog() } - TooltipCompat.setTooltipText(clear_imageview, clear_imageview.contentDescription) - clear_imageview.setOnClickListener { + binding.cancelTextview.setOnClickListener { finish() } + TooltipCompat.setTooltipText(binding.clearImageview, binding.clearImageview.contentDescription) + binding.deleteImageview.setOnClickListener { showConfirmationDialog() } + TooltipCompat.setTooltipText(binding.clearImageview, binding.clearImageview.contentDescription) + binding.clearImageview.setOnClickListener { adapter.clearSelectedList() showOptions(false) } @@ -56,22 +63,22 @@ class ApkActivity : BaseActivity(R.layout.activity_apk, true), ApkContract.ApkVi override fun toggleResultView(apkFiles: List, missingPermissions: Boolean) { if (missingPermissions) { - progressbar.visibility = View.GONE - no_items_textview.text = getString(R.string.missing_permissions) + binding.progressbar.visibility = View.GONE + binding.noItemsTextview.text = getString(R.string.missing_permissions) } else { - no_items_textview.visibility = View.INVISIBLE - no_items_textview.text = getString(R.string.no_apk_found) - ViewCompat.animate(progressbar).alpha(0f) + binding.noItemsTextview.visibility = View.INVISIBLE + binding.noItemsTextview.text = getString(R.string.no_apk_found) + ViewCompat.animate(binding.progressbar).alpha(0f) .setDuration(resources.getInteger(android.R.integer.config_shortAnimTime).toLong()).withEndAction { - progressbar.visibility = View.INVISIBLE - progressbar.alpha = 1f + binding.progressbar.visibility = View.INVISIBLE + binding.progressbar.alpha = 1f }.start() } adapter.submitList(apkFiles) } private fun showOptions(show: Boolean) { - delete_header_group.visibility = if (show) View.VISIBLE else View.GONE + binding.deleteHeaderGroup.visibility = if (show) View.VISIBLE else View.GONE } private fun showConfirmationDialog() { @@ -79,7 +86,7 @@ class ApkActivity : BaseActivity(R.layout.activity_apk, true), ApkContract.ApkVi deleteMessage(adapter.getSelectedCount()) deleteAction { showOptions(false) - progressbar.visibility = View.VISIBLE + binding.progressbar.visibility = View.VISIBLE presenter.deleteApkFiles(adapter.getSelectedApkFilesAndClear()) } }.show() diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkAdapter.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkAdapter.kt index 5f219120..5dab8d5e 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkAdapter.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkAdapter.kt @@ -11,8 +11,7 @@ import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.activities.apkinstall.ApkAdapter.ApkViewHolder import com.g00fy2.developerwidget.base.BaseAdapter import com.g00fy2.developerwidget.base.BaseViewHolder -import kotlinx.android.synthetic.main.apk_item.* -import kotlinx.android.synthetic.main.apk_item.view.* +import com.g00fy2.developerwidget.databinding.ApkItemBinding class ApkAdapter : BaseAdapter(ApksDiffUtilsCallback()) { @@ -20,19 +19,17 @@ class ApkAdapter : BaseAdapter(ApksDiffUtilsCallback()) private var onApkClicked: ((ApkFile?) -> Unit) = {} private var onApkSelected: ((Int) -> Unit) = {} - inner class ApkViewHolder(containerView: View) : BaseViewHolder(containerView) { + inner class ApkViewHolder(val binding: ApkItemBinding) : BaseViewHolder(binding) { fun setSelected(position: Int) { selectedPositions.contains(position).let { selected -> - itemView.app_icon_imageview.visibility = - if (selected) View.INVISIBLE else View.VISIBLE - itemView.selected_icon_imageview.visibility = - if (selected) View.VISIBLE else View.INVISIBLE + binding.appIconImageview.visibility = if (selected) View.INVISIBLE else View.VISIBLE + binding.selectedIconImageview.visibility = if (selected) View.VISIBLE else View.INVISIBLE } } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ApkViewHolder { - return ApkViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.apk_item, parent, false)).apply { + return ApkViewHolder(ApkItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)).apply { addRipple() itemView.setOnClickListener { adapterPosition.let { @@ -67,16 +64,16 @@ class ApkAdapter : BaseAdapter(ApksDiffUtilsCallback()) override fun onBindViewHolder(holderApk: ApkViewHolder, position: Int) { holderApk.apply { val apkFile = getItem(position) - filename_textview.text = apkFile.fileName - app_name_textview.text = apkFile.appName - app_version_textview.text = + binding.filenameTextview.text = apkFile.fileName + binding.appNameTextview.text = apkFile.appName + binding.appVersionTextview.text = String.format(itemView.context.getString(R.string.apk_version), apkFile.versionName, apkFile.versionCode) - file_size_textview.text = apkFile.size - app_debug_imageview.visibility = if (apkFile.debuggable) View.VISIBLE else View.INVISIBLE - file_date_textview.text = apkFile.lastModified - app_icon_imageview.setImageDrawable(apkFile.appIcon) + binding.fileSizeTextview.text = apkFile.size + binding.appDebugImageview.visibility = if (apkFile.debuggable) View.VISIBLE else View.INVISIBLE + binding.fileDateTextview.text = apkFile.lastModified + binding.appIconImageview.setImageDrawable(apkFile.appIcon) if (VERSION.SDK_INT >= VERSION_CODES.O) { - app_icon_imageview.setBackgroundResource(if (apkFile.appIcon is InsetDrawable) R.drawable.bg_adaptive_launcher_icon else 0) + binding.appIconImageview.setBackgroundResource(if (apkFile.appIcon is InsetDrawable) R.drawable.bg_adaptive_launcher_icon else 0) } setSelected(position) } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt index 50348c7e..f75d2efc 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt @@ -22,20 +22,22 @@ import androidx.core.widget.doAfterTextChanged import androidx.interpolator.view.animation.FastOutLinearInInterpolator import androidx.interpolator.view.animation.LinearOutSlowInInterpolator import androidx.recyclerview.widget.LinearLayoutManager +import androidx.viewbinding.ViewBinding import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.base.BaseActivity import com.g00fy2.developerwidget.base.BaseContract.BasePresenter +import com.g00fy2.developerwidget.databinding.ActivityAppsBinding import com.g00fy2.developerwidget.ktx.collapse import com.g00fy2.developerwidget.ktx.expand import com.g00fy2.developerwidget.ktx.hideKeyboard import com.google.android.material.chip.Chip -import kotlinx.android.synthetic.main.activity_apps.* import javax.inject.Inject -class AppsActivity : BaseActivity(R.layout.activity_apps, true), AppsContract.AppsView { +class AppsActivity : BaseActivity(true), AppsContract.AppsView { @Inject lateinit var presenter: AppsContract.AppsPresenter + private lateinit var binding: ActivityAppsBinding private lateinit var adapter: AppsAdapter private var scrollToTopAfterCommit = false @@ -43,42 +45,47 @@ class AppsActivity : BaseActivity(R.layout.activity_apps, true), AppsContract.Ap override fun providePresenter(): BasePresenter = presenter + override fun setViewBinding(): ViewBinding { + binding = ActivityAppsBinding.inflate(layoutInflater) + return binding + } + override fun initView() { adapter = AppsAdapter() adapter.setOnAppClicked { appInfo -> presenter.openAppSettingsActivity(appInfo) } adapter.setCommitCallback(Runnable { adapter.itemCount.let { - no_items_textview.visibility = if (it == 0) View.VISIBLE else View.INVISIBLE - no_items_imageview.visibility = if (it == 0) View.VISIBLE else View.INVISIBLE - recyclerview.overScrollMode = if (it == 0) View.OVER_SCROLL_NEVER else View.OVER_SCROLL_ALWAYS + binding.noItemsTextview.visibility = if (it == 0) View.VISIBLE else View.INVISIBLE + binding.noItemsImageview.visibility = if (it == 0) View.VISIBLE else View.INVISIBLE + binding.recyclerview.overScrollMode = if (it == 0) View.OVER_SCROLL_NEVER else View.OVER_SCROLL_ALWAYS } if (scrollToTopAfterCommit) { scrollToTopAfterCommit = false - recyclerview.scrollToPosition(0) + binding.recyclerview.scrollToPosition(0) } }) - recyclerview.setHasFixedSize(true) - recyclerview.itemAnimator = null - recyclerview.layoutManager = LinearLayoutManager(this) - recyclerview.adapter = adapter + binding.recyclerview.setHasFixedSize(true) + binding.recyclerview.itemAnimator = null + binding.recyclerview.layoutManager = LinearLayoutManager(this) + binding.recyclerview.adapter = adapter - cancel_textview.setOnClickListener { finish() } + binding.cancelTextview.setOnClickListener { finish() } initFilterViews() } private fun initFilterViews() { - app_filter_info.setOnClickListener { + binding.appFilterInfo.setOnClickListener { scrollToTopAfterCommit = true presenter.disableFilter() - app_filter_info.collapse(true, LinearOutSlowInInterpolator()) + binding.appFilterInfo.collapse(true, LinearOutSlowInInterpolator()) } - TooltipCompat.setTooltipText(filter_imageview, filter_imageview.contentDescription) - filter_imageview.setOnClickListener { + TooltipCompat.setTooltipText(binding.filterImageview, binding.filterImageview.contentDescription) + binding.filterImageview.setOnClickListener { presenter.updateFilter(null) toggleFilterView() } - filter_edittext.apply { + binding.filterEdittext.apply { filters = arrayOf(InputFilter { source, _, _, _, _, _ -> if (source.isEmpty() || source.matches("^[a-zA-Z0-9._*]*$".toRegex())) { null @@ -87,14 +94,14 @@ class AppsActivity : BaseActivity(R.layout.activity_apps, true), AppsContract.Ap } }) setOnEditorActionListener { _, actionId, _ -> - val filterString = filter_edittext.text.toString().trim() + val filterString = binding.filterEdittext.text.toString().trim() if (actionId == EditorInfo.IME_ACTION_DONE && filterString.isNotEmpty() && !presenter.duplicateFilter( filterString ) ) { presenter.addAppFilter(filterString) addFilterChip(filterString) - filter_edittext.text.clear() + binding.filterEdittext.text.clear() } true } @@ -107,7 +114,7 @@ class AppsActivity : BaseActivity(R.layout.activity_apps, true), AppsContract.Ap if (v is EditText) { if (event.x >= v.width - v.totalPaddingRight) { if (event.action == MotionEvent.ACTION_UP) { - filter_edittext.text.clear() + binding.filterEdittext.text.clear() } consumed = true } @@ -117,21 +124,22 @@ class AppsActivity : BaseActivity(R.layout.activity_apps, true), AppsContract.Ap } // necessary to measure the view heights for animations setFilterChips(presenter.getCurrentFilter()) - filter_linearlayout.doOnPreDraw { it.visibility = View.GONE } - app_filter_info.doOnPreDraw { it.visibility = View.GONE } + binding.filterLinearlayout.doOnPreDraw { it.visibility = View.GONE } + binding.appFilterInfo.doOnPreDraw { it.visibility = View.GONE } } override fun toggleResultView(installedAppPackages: List, filters: List) { adapter.initialList(installedAppPackages, filters) - show_all_textview.text = getString(R.string.show_all_apps).format(installedAppPackages.size) - app_filter_info.visibility = if (filters.isEmpty() || installedAppPackages.isEmpty()) View.GONE else View.VISIBLE - if (filter_edittext.text.toString().isNotEmpty()) { - adapter.updateAppFilter(filter_edittext.text.toString()) + binding.showAllTextview.text = getString(R.string.show_all_apps).format(installedAppPackages.size) + binding.appFilterInfo.visibility = + if (filters.isEmpty() || installedAppPackages.isEmpty()) View.GONE else View.VISIBLE + if (binding.filterEdittext.text.toString().isNotEmpty()) { + adapter.updateAppFilter(binding.filterEdittext.text.toString()) } - ViewCompat.animate(progressbar).alpha(0f) + ViewCompat.animate(binding.progressbar).alpha(0f) .setDuration(resources.getInteger(android.R.integer.config_shortAnimTime).toLong()) - .withEndAction { progressbar.visibility = View.INVISIBLE } + .withEndAction { binding.progressbar.visibility = View.INVISIBLE } .start() } @@ -141,43 +149,43 @@ class AppsActivity : BaseActivity(R.layout.activity_apps, true), AppsContract.Ap override fun updateFilterIcon(filterActive: Boolean) { if (filterActive) { - filter_imageview.setColorFilter(ResourcesCompat.getColor(resources, R.color.colorAccent, null)) + binding.filterImageview.setColorFilter(ResourcesCompat.getColor(resources, R.color.colorAccent, null)) } else { - filter_imageview.clearColorFilter() + binding.filterImageview.clearColorFilter() } } private fun toggleFilterView() { - if (filter_linearlayout.isVisible) { - if (presenter.getCurrentFilter().isNotEmpty()) app_filter_info.expand(true, FastOutLinearInInterpolator()) - filter_linearlayout.collapse(easing = FastOutLinearInInterpolator()) - filter_edittext.hideKeyboard() + if (binding.filterLinearlayout.isVisible) { + if (presenter.getCurrentFilter().isNotEmpty()) binding.appFilterInfo.expand(true, FastOutLinearInInterpolator()) + binding.filterLinearlayout.collapse(easing = FastOutLinearInInterpolator()) + binding.filterEdittext.hideKeyboard() } else { - if (app_filter_info.isVisible) app_filter_info.collapse(true, LinearOutSlowInInterpolator()) - filter_edittext.text.clear() + if (binding.appFilterInfo.isVisible) binding.appFilterInfo.collapse(true, LinearOutSlowInInterpolator()) + binding.filterEdittext.text.clear() setFilterChips(presenter.getCurrentFilter()) - filter_linearlayout.expand(easing = LinearOutSlowInInterpolator()) + binding.filterLinearlayout.expand(easing = LinearOutSlowInInterpolator()) } } private fun removeAppFilter(chip: Chip) { - chip_group.removeView(chip) + binding.chipGroup.removeView(chip) scrollToTopAfterCommit = true - presenter.removeAppFilter(chip.text.toString(), filter_edittext.text.toString()) + presenter.removeAppFilter(chip.text.toString(), binding.filterEdittext.text.toString()) } private fun setFilterChips(filters: Collection) { - chip_group.removeAllViews() + binding.chipGroup.removeAllViews() for (i in filters) { addFilterChip(i) } } private fun addFilterChip(filterString: String) { - (LayoutInflater.from(this).inflate(R.layout.filter_chip, chip_group, false) as Chip).let { + (LayoutInflater.from(this).inflate(R.layout.filter_chip, binding.chipGroup, false) as Chip).let { it.text = filterString it.isClickable = false - chip_group.addView(it) + binding.chipGroup.addView(it) it.setOnCloseIconClickListener { view -> removeAppFilter(view as Chip) } } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt index 861fabf7..06e86142 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt @@ -7,18 +7,21 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.g00fy2.developerwidget.R +import com.g00fy2.developerwidget.activities.appmanager.AppsAdapter.AppViewHolder import com.g00fy2.developerwidget.base.BaseAdapter import com.g00fy2.developerwidget.base.BaseViewHolder +import com.g00fy2.developerwidget.databinding.AppItemBinding import com.g00fy2.developerwidget.ktx.filterPackageName -import kotlinx.android.synthetic.main.app_item.* -class AppsAdapter : BaseAdapter(AppsDiffUtilsCallback()) { +class AppsAdapter : BaseAdapter(AppsDiffUtilsCallback()) { private var onAppClicked: ((AppInfo?) -> Unit) = {} private var itemsCopy = ArrayList() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder { - return BaseViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.app_item, parent, false)).apply { + inner class AppViewHolder(val binding: AppItemBinding) : BaseViewHolder(binding) + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder { + return AppViewHolder(AppItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)).apply { addRipple() itemView.setOnClickListener { onAppClicked(getSelectedPackageName(adapterPosition)) @@ -26,16 +29,16 @@ class AppsAdapter : BaseAdapter(AppsDiffUtilsCallback() } } - override fun onBindViewHolder(holderApk: BaseViewHolder, position: Int) { + override fun onBindViewHolder(holderApk: AppViewHolder, position: Int) { holderApk.apply { val appInfo = getItem(position) - appename_textview.text = appInfo.appName - apppackage_textview.text = appInfo.packageName - app_version_textview.text = + binding.appenameTextview.text = appInfo.appName + binding.apppackageTextview.text = appInfo.packageName + binding.appVersionTextview.text = String.format(itemView.context.getString(R.string.apk_version), appInfo.versionName, appInfo.versionCode) - app_icon_imageview.setImageDrawable(appInfo.appIcon) + binding.appIconImageview.setImageDrawable(appInfo.appIcon) if (VERSION.SDK_INT >= VERSION_CODES.O) { - app_icon_imageview.setBackgroundResource(if (appInfo.appIcon is InsetDrawable) R.drawable.bg_adaptive_launcher_icon else 0) + binding.appIconImageview.setBackgroundResource(if (appInfo.appIcon is InsetDrawable) R.drawable.bg_adaptive_launcher_icon else 0) } } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt index ef982bdb..458b7d30 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt @@ -19,42 +19,52 @@ import androidx.core.graphics.drawable.toBitmap import androidx.core.view.updatePadding import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager +import androidx.viewbinding.ViewBinding import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.activities.apkinstall.ApkActivity import com.g00fy2.developerwidget.activities.appmanager.AppsActivity import com.g00fy2.developerwidget.base.BaseActivity import com.g00fy2.developerwidget.base.BaseContract.BasePresenter +import com.g00fy2.developerwidget.databinding.ActivityCreateShortcutBinding import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets -import kotlinx.android.synthetic.main.activity_create_shortcut.* import javax.inject.Inject @RequiresApi(VERSION_CODES.N_MR1) -class CreateShortcutActivity : BaseActivity(R.layout.activity_create_shortcut), - CreateShortcutContract.CreateShortcutView { +class CreateShortcutActivity : BaseActivity(), CreateShortcutContract.CreateShortcutView { @Inject lateinit var presenter: CreateShortcutContract.CreateShortcutPresenter + private lateinit var binding: ActivityCreateShortcutBinding private lateinit var adapter: ShortcutAdapter private lateinit var shortcutInfoList: List override fun providePresenter(): BasePresenter = presenter + override fun setViewBinding(): ViewBinding { + binding = ActivityCreateShortcutBinding.inflate(layoutInflater) + return binding + } + override fun initView() { setResult(Activity.RESULT_CANCELED) adapter = ShortcutAdapter() - recyclerview.setHasFixedSize(true) - recyclerview.layoutManager = LinearLayoutManager(this) - recyclerview.adapter = adapter + binding.recyclerview.setHasFixedSize(true) + binding.recyclerview.layoutManager = LinearLayoutManager(this) + binding.recyclerview.adapter = adapter getDrawable(R.drawable.divider_line)?.let { - recyclerview.addItemDecoration(DividerItemDecoration(this, LinearLayout.VERTICAL).apply { setDrawable(it) }) + binding.recyclerview.addItemDecoration( + DividerItemDecoration( + this, + LinearLayout.VERTICAL + ).apply { setDrawable(it) }) } shortcutInfoList = generateShortcutInfoList() adapter.submitList(shortcutInfoList) adapter.setOnShortcutSelected { shortcutPosition -> onItemClick(shortcutPosition) } if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) { - recyclerview.doOnApplyWindowInsets { view, insets, padding -> + binding.recyclerview.doOnApplyWindowInsets { view, insets, padding -> view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/ShortcutAdapter.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/ShortcutAdapter.kt index 71a735fc..73da61df 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/ShortcutAdapter.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/ShortcutAdapter.kt @@ -5,26 +5,28 @@ import android.os.Build.VERSION_CODES import android.view.LayoutInflater import android.view.ViewGroup import androidx.annotation.RequiresApi -import com.g00fy2.developerwidget.R +import com.g00fy2.developerwidget.activities.shortcut.ShortcutAdapter.ShortcutViewHolder import com.g00fy2.developerwidget.base.BaseAdapter import com.g00fy2.developerwidget.base.BaseViewHolder -import kotlinx.android.synthetic.main.shortcut_item.* +import com.g00fy2.developerwidget.databinding.ShortcutItemBinding -class ShortcutAdapter : BaseAdapter(ShortcutDiffUtilsCallback()) { +class ShortcutAdapter : BaseAdapter(ShortcutDiffUtilsCallback()) { private var onShortcutSelected: ((Int) -> Unit) = {} - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder { - return BaseViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.shortcut_item, parent, false)).apply { + inner class ShortcutViewHolder(val binding: ShortcutItemBinding) : BaseViewHolder(binding) + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShortcutViewHolder { + return ShortcutViewHolder(ShortcutItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)).apply { addRipple() itemView.setOnClickListener { onShortcutSelected(adapterPosition) } } } @RequiresApi(VERSION_CODES.N_MR1) - override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { + override fun onBindViewHolder(holder: ShortcutViewHolder, position: Int) { holder.apply { - shortcut_title_textview.text = + binding.shortcutTitleTextview.text = getItem(position)?.longLabel?.toString() ?: getItem(position)?.shortLabel.toString() } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/DeviceDataAdapter.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/DeviceDataAdapter.kt index ac6f4db3..c927d816 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/DeviceDataAdapter.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/DeviceDataAdapter.kt @@ -3,27 +3,30 @@ package com.g00fy2.developerwidget.activities.widgetconfig import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.base.BaseAdapter import com.g00fy2.developerwidget.base.BaseViewHolder import com.g00fy2.developerwidget.data.DeviceDataItem -import kotlinx.android.synthetic.main.device_data_header_item.* -import kotlinx.android.synthetic.main.device_data_value_item.* +import com.g00fy2.developerwidget.databinding.DeviceDataHeaderItemBinding +import com.g00fy2.developerwidget.databinding.DeviceDataValueItemBinding class DeviceDataAdapter : BaseAdapter, BaseViewHolder>(DeviceDataDiffUtilsCallback()) { + inner class DeviceDataHeaderViewHolder(val binding: DeviceDataHeaderItemBinding) : BaseViewHolder(binding) + inner class DeviceDataValueViewHolder(val binding: DeviceDataValueItemBinding) : BaseViewHolder(binding) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder { return when (viewType) { - HEADER_TYPE -> BaseViewHolder( - LayoutInflater.from(parent.context).inflate( - R.layout.device_data_header_item, + HEADER_TYPE -> DeviceDataHeaderViewHolder( + DeviceDataHeaderItemBinding.inflate( + LayoutInflater.from(parent.context), parent, false ) ) - VALUE_TYPE -> BaseViewHolder( - LayoutInflater.from(parent.context).inflate( - R.layout.device_data_value_item, + VALUE_TYPE + -> DeviceDataValueViewHolder( + DeviceDataValueItemBinding.inflate( + LayoutInflater.from(parent.context), parent, false ) @@ -35,17 +38,19 @@ class DeviceDataAdapter : BaseAdapter, BaseViewHold } override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { - holder.apply { - getItem(position).let { - when (holder.itemViewType) { - HEADER_TYPE -> { - header_divider_view.visibility = if (position == 0) View.INVISIBLE else View.VISIBLE - header_title_textview.text = itemView.context.getString(it.second.title) - } - VALUE_TYPE -> { - device_data_title.text = itemView.context.getString(it.second.title) - device_data.text = it.second.value - } + if (holder is DeviceDataHeaderViewHolder) { + holder.apply { + getItem(position).let { + binding.headerDividerView.visibility = if (position == 0) View.INVISIBLE else View.VISIBLE + binding.headerTitleTextview.text = itemView.context.getString(it.second.title) + } + } + } else if (holder is DeviceDataValueViewHolder) { + holder.apply { + getItem(position).let { + binding.deviceDataTitle.text = itemView.context.getString(it.second.title) + binding.deviceData.text = it.second.value + } } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index 09b9974f..80e17aa3 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -28,27 +28,29 @@ import androidx.core.content.res.ResourcesCompat import androidx.core.view.marginBottom import androidx.core.view.updatePadding import androidx.recyclerview.widget.LinearLayoutManager +import androidx.viewbinding.ViewBinding import com.g00fy2.developerwidget.R import com.g00fy2.developerwidget.activities.about.AboutActivity import com.g00fy2.developerwidget.base.BaseActivity import com.g00fy2.developerwidget.base.BaseContract.BasePresenter import com.g00fy2.developerwidget.data.DeviceDataItem +import com.g00fy2.developerwidget.databinding.ActivityWidgetConfigBinding import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets import com.g00fy2.developerwidget.ktx.hideKeyboard import com.g00fy2.developerwidget.ktx.showKeyboard import com.g00fy2.developerwidget.receiver.widget.WidgetProviderImpl -import kotlinx.android.synthetic.main.activity_widget_config.* import javax.inject.Inject -class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), WidgetConfigContract.WidgetConfigView { +class WidgetConfigActivity : BaseActivity(), WidgetConfigContract.WidgetConfigView { @Inject lateinit var presenter: WidgetConfigContract.WidgetConfigPresenter + private lateinit var binding: ActivityWidgetConfigBinding + private lateinit var adapter: DeviceDataAdapter private var updateExistingWidget = false private var launchedFromAppLauncher = true private var widgetId: Int = AppWidgetManager.INVALID_APPWIDGET_ID - private lateinit var adapter: DeviceDataAdapter private val editDrawable by lazy { initEditDrawable() } private val closeConfigureActivityReceiver by lazy { @@ -62,6 +64,11 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg override fun providePresenter(): BasePresenter = presenter + override fun setViewBinding(): ViewBinding { + binding = ActivityWidgetConfigBinding.inflate(layoutInflater) + return binding + } + override fun onResume() { super.onResume() resetView() @@ -86,24 +93,24 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg return } - setActionbarElevationListener(widget_config_root_scrollview) - widget_config_root_scrollview.apply { + setActionbarElevationListener(binding.widgetConfigRootScrollview) + binding.widgetConfigRootScrollview.apply { viewTreeObserver.addOnScrollChangedListener { val scrollableRange = getChildAt(0).bottom - height + paddingBottom - val fabOffset = (share_fab.height / 2) + share_fab.marginBottom + val fabOffset = (binding.shareFab.height / 2) + binding.shareFab.marginBottom if (scrollY < scrollableRange - fabOffset) { - share_fab.hide() + binding.shareFab.hide() } else { - share_fab.show() + binding.shareFab.show() } } } adapter = DeviceDataAdapter() - recyclerview.setHasFixedSize(false) - recyclerview.layoutManager = LinearLayoutManager(this) - recyclerview.isNestedScrollingEnabled = false - recyclerview.adapter = adapter + binding.recyclerview.setHasFixedSize(false) + binding.recyclerview.layoutManager = LinearLayoutManager(this) + binding.recyclerview.isNestedScrollingEnabled = false + binding.recyclerview.adapter = adapter // register broadcast receiver to finish activity after pin widget if (VERSION.SDK_INT >= VERSION_CODES.O) { @@ -114,10 +121,10 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg WebView(this) } - device_title_edittextview.apply { + binding.deviceTitleEdittextview.apply { onFocusChangeListener = OnFocusChangeListener { _, hasFocus -> if (!hasFocus) { - presenter.setCustomDeviceName(device_title_edittextview.text.toString()) + presenter.setCustomDeviceName(binding.deviceTitleEdittextview.text.toString()) toggleDeviceNameEdit(false) } } @@ -128,9 +135,9 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg true } } - share_fab.setOnClickListener { presenter.shareDeviceData() } + binding.shareFab.setOnClickListener { presenter.shareDeviceData() } if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) { - widget_config_root_scrollview.doOnApplyWindowInsets { view, insets, padding -> + binding.widgetConfigRootScrollview.doOnApplyWindowInsets { view, insets, padding -> view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) } } @@ -154,24 +161,24 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg override fun showDeviceData(data: List>) = adapter.submitList(data) override fun setDeviceTitle(title: String) { - device_title_textview.text = title - device_title_textview.visibility = View.VISIBLE - device_title_edittextview.setText(title) - device_title_edittextview.setSelection(device_title_edittextview.text.length) + binding.deviceTitleTextview.text = title + binding.deviceTitleTextview.visibility = View.VISIBLE + binding.deviceTitleEdittextview.setText(title) + binding.deviceTitleEdittextview.setSelection(binding.deviceTitleEdittextview.text.length) } override fun setDeviceTitleHint(hint: String) { - device_title_edittextview.hint = hint + binding.deviceTitleEdittextview.hint = hint } override fun setSubtitle(data: Pair) { - device_subtitle_textview.text = getString(R.string.subtitle).format(data.first, data.second) + binding.deviceSubtitleTextview.text = getString(R.string.subtitle).format(data.first, data.second) } override fun dispatchTouchEvent(event: MotionEvent): Boolean { if (event.action == MotionEvent.ACTION_DOWN) { currentFocus.let { - if (it != null && it == device_title_edittextview) { + if (it != null && it == binding.deviceTitleEdittextview) { Rect().let { rect -> it.getGlobalVisibleRect(rect) if (!rect.contains(event.rawX.toInt(), event.rawY.toInt())) { @@ -187,7 +194,7 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg private fun resetView() { val showAddWidget = (!launchedFromAppLauncher || (widgetCount() < 1 && isPinAppWidgetSupported())) if (showAddWidget) { - apply_button.apply { + binding.applyButton.apply { visibility = View.VISIBLE when { launchedFromAppLauncher -> { @@ -205,9 +212,9 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg } } } else { - apply_button.visibility = View.GONE + binding.applyButton.visibility = View.GONE } - device_title_textview.apply { + binding.deviceTitleTextview.apply { setOnClickListener { toggleDeviceNameEdit(true) } if (showAddWidget) { isClickable = true @@ -227,18 +234,18 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg } private fun toggleDeviceNameEdit(editable: Boolean) { - device_title_textview.visibility = if (editable) View.INVISIBLE else View.VISIBLE - device_title_edittextview.visibility = if (editable) View.VISIBLE else View.INVISIBLE + binding.deviceTitleTextview.visibility = if (editable) View.INVISIBLE else View.VISIBLE + binding.deviceTitleEdittextview.visibility = if (editable) View.VISIBLE else View.INVISIBLE if (editable) { - device_title_edittextview.requestFocus() - device_title_edittextview.showKeyboard() + binding.deviceTitleEdittextview.requestFocus() + binding.deviceTitleEdittextview.showKeyboard() } else { - device_title_edittextview.hideKeyboard() + binding.deviceTitleEdittextview.hideKeyboard() } } private fun updateWidgetAndFinish(existing: Boolean) { - presenter.setCustomDeviceName(device_title_edittextview.text.toString(), true) + presenter.setCustomDeviceName(binding.deviceTitleEdittextview.text.toString(), true) if (!existing) { setResult(Activity.RESULT_OK, Intent().apply { putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId) }) } @@ -259,7 +266,7 @@ class WidgetConfigActivity : BaseActivity(R.layout.activity_widget_config), Widg this, 0, Intent(applicationContext, WidgetProviderImpl::class.java).apply { action = WidgetProviderImpl.UPDATE_WIDGET_MANUALLY_ACTION putExtra(EXTRA_APPWIDGET_FROM_PIN_APP, true) - putExtra(EXTRA_APPWIDGET_CUSTOM_DEVICE_NAME, device_title_edittextview.text.toString()) + putExtra(EXTRA_APPWIDGET_CUSTOM_DEVICE_NAME, binding.deviceTitleEdittextview.text.toString()) }, PendingIntent.FLAG_UPDATE_CURRENT ) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt index 48032458..c75e969b 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt @@ -7,17 +7,16 @@ import android.os.Bundle import android.view.View import android.view.ViewGroup import android.view.Window -import androidx.annotation.LayoutRes import androidx.appcompat.app.AppCompatActivity import androidx.core.view.updatePadding +import androidx.viewbinding.ViewBinding import com.g00fy2.developerwidget.controllers.DayNightController import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets import dagger.android.AndroidInjection import timber.log.Timber import javax.inject.Inject -abstract class BaseActivity(@LayoutRes contentLayoutId: Int, private val isDialogActivity: Boolean = false) : - AppCompatActivity(contentLayoutId) { +abstract class BaseActivity(private val isDialogActivity: Boolean = false) : AppCompatActivity() { @Inject lateinit var dayNightController: DayNightController @@ -29,12 +28,14 @@ abstract class BaseActivity(@LayoutRes contentLayoutId: Int, private val isDialo if (isDialogActivity) { requestWindowFeature(Window.FEATURE_NO_TITLE) super.onCreate(savedInstanceState) + setContentView(setViewBinding().root) val width = (resources.displayMetrics.widthPixels * 0.95).toInt() val height = (resources.displayMetrics.heightPixels * 0.80).toInt() window.setLayout(width, height) } else { super.onCreate(savedInstanceState) + setContentView(setViewBinding().root) } dayNightController.loadCustomDefaultMode() @@ -107,5 +108,7 @@ abstract class BaseActivity(@LayoutRes contentLayoutId: Int, private val isDialo abstract fun providePresenter(): BaseContract.BasePresenter + abstract fun setViewBinding(): ViewBinding + abstract fun initView() } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt index 51c2638c..b7455958 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt @@ -1,11 +1,10 @@ package com.g00fy2.developerwidget.base -import android.view.View import androidx.recyclerview.widget.RecyclerView +import androidx.viewbinding.ViewBinding import com.g00fy2.developerwidget.ktx.addRipple -import kotlinx.android.extensions.LayoutContainer -open class BaseViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer { +open class BaseViewHolder(private val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) { - fun addRipple() = containerView.addRipple(true) + fun addRipple() = binding.root.addRipple(true) } \ No newline at end of file diff --git a/build.gradle b/build.gradle index f2e86e4f..c44eaadd 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '3.6.0-alpha10' + androidGradleVersion = '3.6.0-alpha11' gradleScanVersion = '2.4.1' versioningPluginVersion = '1.0.0' From 0756b96c32b41b668d90d39859772cc316a1dc7d Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 12 Sep 2019 21:25:44 +0200 Subject: [PATCH 040/122] Refactor adapter and viewholder logic --- .../activities/apkinstall/ApkAdapter.kt | 43 +++++++------- .../activities/appmanager/AppsAdapter.kt | 29 +++++----- .../activities/shortcut/ShortcutAdapter.kt | 17 +++--- .../widgetconfig/DeviceDataAdapter.kt | 57 ++++++++----------- .../developerwidget/base/BaseAdapter.kt | 7 ++- .../developerwidget/base/BaseViewHolder.kt | 4 +- 6 files changed, 75 insertions(+), 82 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkAdapter.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkAdapter.kt index 5dab8d5e..8059ba29 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkAdapter.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkAdapter.kt @@ -19,7 +19,24 @@ class ApkAdapter : BaseAdapter(ApksDiffUtilsCallback()) private var onApkClicked: ((ApkFile?) -> Unit) = {} private var onApkSelected: ((Int) -> Unit) = {} - inner class ApkViewHolder(val binding: ApkItemBinding) : BaseViewHolder(binding) { + inner class ApkViewHolder(val binding: ApkItemBinding) : BaseViewHolder(binding) { + override fun onBind(item: ApkFile) { + item.run { + binding.filenameTextview.text = fileName + binding.appNameTextview.text = appName + binding.appVersionTextview.text = + String.format(itemView.context.getString(R.string.apk_version), item.versionName, item.versionCode) + binding.fileSizeTextview.text = item.size + binding.appDebugImageview.visibility = if (item.debuggable) View.VISIBLE else View.INVISIBLE + binding.fileDateTextview.text = item.lastModified + binding.appIconImageview.setImageDrawable(item.appIcon) + if (VERSION.SDK_INT >= VERSION_CODES.O) { + binding.appIconImageview.setBackgroundResource(if (item.appIcon is InsetDrawable) R.drawable.bg_adaptive_launcher_icon else 0) + } + } + setSelected(adapterPosition) + } + fun setSelected(position: Int) { selectedPositions.contains(position).let { selected -> binding.appIconImageview.visibility = if (selected) View.INVISIBLE else View.VISIBLE @@ -61,29 +78,11 @@ class ApkAdapter : BaseAdapter(ApksDiffUtilsCallback()) } } - override fun onBindViewHolder(holderApk: ApkViewHolder, position: Int) { - holderApk.apply { - val apkFile = getItem(position) - binding.filenameTextview.text = apkFile.fileName - binding.appNameTextview.text = apkFile.appName - binding.appVersionTextview.text = - String.format(itemView.context.getString(R.string.apk_version), apkFile.versionName, apkFile.versionCode) - binding.fileSizeTextview.text = apkFile.size - binding.appDebugImageview.visibility = if (apkFile.debuggable) View.VISIBLE else View.INVISIBLE - binding.fileDateTextview.text = apkFile.lastModified - binding.appIconImageview.setImageDrawable(apkFile.appIcon) - if (VERSION.SDK_INT >= VERSION_CODES.O) { - binding.appIconImageview.setBackgroundResource(if (apkFile.appIcon is InsetDrawable) R.drawable.bg_adaptive_launcher_icon else 0) - } - setSelected(position) - } - } - - override fun onBindViewHolder(holderApk: ApkViewHolder, position: Int, payloads: List) { + override fun onBindViewHolder(holder: ApkViewHolder, position: Int, payloads: List) { if (payloads.isEmpty()) { - onBindViewHolder(holderApk, position) + super.onBindViewHolder(holder, position) } else { - holderApk.setSelected(position) + holder.setSelected(position) } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt index 06e86142..12ca4a3f 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsAdapter.kt @@ -18,7 +18,20 @@ class AppsAdapter : BaseAdapter(AppsDiffUtilsCallback()) private var onAppClicked: ((AppInfo?) -> Unit) = {} private var itemsCopy = ArrayList() - inner class AppViewHolder(val binding: AppItemBinding) : BaseViewHolder(binding) + inner class AppViewHolder(val binding: AppItemBinding) : BaseViewHolder(binding) { + override fun onBind(item: AppInfo) { + item.run { + binding.appenameTextview.text = appName + binding.apppackageTextview.text = packageName + binding.appVersionTextview.text = + String.format(itemView.context.getString(R.string.apk_version), versionName, versionCode) + binding.appIconImageview.setImageDrawable(appIcon) + if (VERSION.SDK_INT >= VERSION_CODES.O) { + binding.appIconImageview.setBackgroundResource(if (appIcon is InsetDrawable) R.drawable.bg_adaptive_launcher_icon else 0) + } + } + } + } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder { return AppViewHolder(AppItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)).apply { @@ -29,20 +42,6 @@ class AppsAdapter : BaseAdapter(AppsDiffUtilsCallback()) } } - override fun onBindViewHolder(holderApk: AppViewHolder, position: Int) { - holderApk.apply { - val appInfo = getItem(position) - binding.appenameTextview.text = appInfo.appName - binding.apppackageTextview.text = appInfo.packageName - binding.appVersionTextview.text = - String.format(itemView.context.getString(R.string.apk_version), appInfo.versionName, appInfo.versionCode) - binding.appIconImageview.setImageDrawable(appInfo.appIcon) - if (VERSION.SDK_INT >= VERSION_CODES.O) { - binding.appIconImageview.setBackgroundResource(if (appInfo.appIcon is InsetDrawable) R.drawable.bg_adaptive_launcher_icon else 0) - } - } - } - fun initialList(list: List?, filters: Collection) { itemsCopy.clear() list?.let { itemsCopy.addAll(it) } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/ShortcutAdapter.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/ShortcutAdapter.kt index 73da61df..c020832e 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/ShortcutAdapter.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/ShortcutAdapter.kt @@ -10,11 +10,18 @@ import com.g00fy2.developerwidget.base.BaseAdapter import com.g00fy2.developerwidget.base.BaseViewHolder import com.g00fy2.developerwidget.databinding.ShortcutItemBinding +@RequiresApi(VERSION_CODES.N_MR1) class ShortcutAdapter : BaseAdapter(ShortcutDiffUtilsCallback()) { private var onShortcutSelected: ((Int) -> Unit) = {} - inner class ShortcutViewHolder(val binding: ShortcutItemBinding) : BaseViewHolder(binding) + inner class ShortcutViewHolder(val binding: ShortcutItemBinding) : BaseViewHolder(binding) { + override fun onBind(item: ShortcutInfo) { + item.run { + binding.shortcutTitleTextview.text = item.longLabel ?: item.shortLabel ?: "" + } + } + } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShortcutViewHolder { return ShortcutViewHolder(ShortcutItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)).apply { @@ -23,14 +30,6 @@ class ShortcutAdapter : BaseAdapter(ShortcutDi } } - @RequiresApi(VERSION_CODES.N_MR1) - override fun onBindViewHolder(holder: ShortcutViewHolder, position: Int) { - holder.apply { - binding.shortcutTitleTextview.text = - getItem(position)?.longLabel?.toString() ?: getItem(position)?.shortLabel.toString() - } - } - fun setOnShortcutSelected(onShortcutSelected: (Int) -> Unit) { this.onShortcutSelected = onShortcutSelected } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/DeviceDataAdapter.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/DeviceDataAdapter.kt index c927d816..e58e73e4 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/DeviceDataAdapter.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/DeviceDataAdapter.kt @@ -9,27 +9,37 @@ import com.g00fy2.developerwidget.data.DeviceDataItem import com.g00fy2.developerwidget.databinding.DeviceDataHeaderItemBinding import com.g00fy2.developerwidget.databinding.DeviceDataValueItemBinding -class DeviceDataAdapter : BaseAdapter, BaseViewHolder>(DeviceDataDiffUtilsCallback()) { +class DeviceDataAdapter : + BaseAdapter, BaseViewHolder>>(DeviceDataDiffUtilsCallback()) { + + inner class DeviceDataHeaderViewHolder(val binding: DeviceDataHeaderItemBinding) : + BaseViewHolder>(binding) { + override fun onBind(item: Pair) { + item.run { + binding.headerDividerView.visibility = if (adapterPosition == 0) View.INVISIBLE else View.VISIBLE + binding.headerTitleTextview.text = itemView.context.getString(second.title) + } + } + } - inner class DeviceDataHeaderViewHolder(val binding: DeviceDataHeaderItemBinding) : BaseViewHolder(binding) - inner class DeviceDataValueViewHolder(val binding: DeviceDataValueItemBinding) : BaseViewHolder(binding) + inner class DeviceDataValueViewHolder(val binding: DeviceDataValueItemBinding) : + BaseViewHolder>(binding) { + override fun onBind(item: Pair) { + item.run { + binding.deviceDataTitle.text = itemView.context.getString(second.title) + binding.deviceData.text = second.value + } + } + } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder> { return when (viewType) { HEADER_TYPE -> DeviceDataHeaderViewHolder( - DeviceDataHeaderItemBinding.inflate( - LayoutInflater.from(parent.context), - parent, - false - ) + DeviceDataHeaderItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) ) VALUE_TYPE -> DeviceDataValueViewHolder( - DeviceDataValueItemBinding.inflate( - LayoutInflater.from(parent.context), - parent, - false - ) + DeviceDataValueItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) ) else -> { throw IllegalStateException("Unknown ViewType") @@ -37,25 +47,6 @@ class DeviceDataAdapter : BaseAdapter, BaseViewHold } } - override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { - if (holder is DeviceDataHeaderViewHolder) { - holder.apply { - getItem(position).let { - binding.headerDividerView.visibility = if (position == 0) View.INVISIBLE else View.VISIBLE - binding.headerTitleTextview.text = itemView.context.getString(it.second.title) - } - } - } else if (holder is DeviceDataValueViewHolder) { - holder.apply { - getItem(position).let { - binding.deviceDataTitle.text = itemView.context.getString(it.second.title) - binding.deviceData.text = it.second.value - - } - } - } - } - override fun getItemViewType(position: Int) = if (getItem(position).second.isHeader) HEADER_TYPE else VALUE_TYPE companion object { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseAdapter.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseAdapter.kt index 6b7b9599..a92a2dc7 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseAdapter.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseAdapter.kt @@ -2,9 +2,8 @@ package com.g00fy2.developerwidget.base import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter -import androidx.recyclerview.widget.RecyclerView -abstract class BaseAdapter constructor(diffCallback: DiffUtil.ItemCallback) : +abstract class BaseAdapter> constructor(diffCallback: DiffUtil.ItemCallback) : ListAdapter(diffCallback) { private var commitCallback: Runnable? = null @@ -13,6 +12,10 @@ abstract class BaseAdapter constructor(diffCall submitList(list, commitCallback) } + override fun onBindViewHolder(holder: VH, position: Int) { + holder.onBind(getItem(position)) + } + open fun clearList() { submitList(null) } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt index b7455958..60dba33d 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt @@ -4,7 +4,9 @@ import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding import com.g00fy2.developerwidget.ktx.addRipple -open class BaseViewHolder(private val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) { +abstract class BaseViewHolder(private val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) { + + abstract fun onBind(item: T) fun addRipple() = binding.root.addRipple(true) } \ No newline at end of file From 440be24c8c1b4851a0e2f3f59ee7d5540836c045 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 12 Sep 2019 23:49:41 +0200 Subject: [PATCH 041/122] Fix scroll bottom edgeEffect by dynamically switching clipToPadding on scroll end --- .../activities/about/AboutActivity.kt | 9 +++++++++ .../activities/widgetconfig/WidgetConfigActivity.kt | 4 ++++ .../g00fy2/developerwidget/ktx/ActivityExtension.kt | 13 +++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ActivityExtension.kt diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt index 8012381e..cf307963 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt @@ -16,6 +16,7 @@ import com.g00fy2.developerwidget.base.BaseActivity import com.g00fy2.developerwidget.base.BaseContract.BasePresenter import com.g00fy2.developerwidget.databinding.ActivityAboutBinding import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets +import com.g00fy2.developerwidget.ktx.gesturalNavigationMode import javax.inject.Inject class AboutActivity : BaseActivity(), AboutContract.AboutView { @@ -126,6 +127,14 @@ class AboutActivity : BaseActivity(), AboutContract.AboutView { binding.aboutRootScrollview.doOnApplyWindowInsets { view, insets, padding -> view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) } + binding.aboutRootScrollview.apply { + viewTreeObserver.addOnScrollChangedListener { + val scrollableRange = getChildAt(0).bottom - height + paddingBottom + if (!gesturalNavigationMode()) { + clipToPadding = (scrollY >= scrollableRange) + } + } + } } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index 80e17aa3..2c90440d 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -36,6 +36,7 @@ import com.g00fy2.developerwidget.base.BaseContract.BasePresenter import com.g00fy2.developerwidget.data.DeviceDataItem import com.g00fy2.developerwidget.databinding.ActivityWidgetConfigBinding import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets +import com.g00fy2.developerwidget.ktx.gesturalNavigationMode import com.g00fy2.developerwidget.ktx.hideKeyboard import com.g00fy2.developerwidget.ktx.showKeyboard import com.g00fy2.developerwidget.receiver.widget.WidgetProviderImpl @@ -103,6 +104,9 @@ class WidgetConfigActivity : BaseActivity(), WidgetConfigContract.WidgetConfigVi } else { binding.shareFab.show() } + if (VERSION.SDK_INT >= VERSION_CODES.O_MR1 && !gesturalNavigationMode()) { + clipToPadding = (scrollY >= scrollableRange) + } } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ActivityExtension.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ActivityExtension.kt new file mode 100644 index 00000000..de3ba401 --- /dev/null +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ActivityExtension.kt @@ -0,0 +1,13 @@ +package com.g00fy2.developerwidget.ktx + +import android.app.Activity +import android.os.Build.VERSION +import android.os.Build.VERSION_CODES + +fun Activity.gesturalNavigationMode(): Boolean { + return if (VERSION.SDK_INT >= VERSION_CODES.Q) { + window.decorView.rootWindowInsets.systemGestureInsets.left > 0 + } else { + false + } +} \ No newline at end of file From bc628a6f9e556041e593b2f0f0b68c9975a9edf0 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Mon, 16 Sep 2019 22:54:06 +0200 Subject: [PATCH 042/122] Cleanup code --- .../developerwidget/activities/appmanager/AppsActivity.kt | 2 +- .../activities/widgetconfig/WidgetConfigActivity.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt index f75d2efc..bec9ee80 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt @@ -199,7 +199,7 @@ class AppsActivity : BaseActivity(true), AppsContract.AppsView { @Suppress("DEPRECATION") setColorFilter(ResourcesCompat.getColor(resources, R.color.iconTintColor, null), PorterDuff.Mode.SRC_IN) } - setBounds(0, 0, this.intrinsicWidth, this.intrinsicHeight) + setBounds(0, 0, intrinsicWidth, intrinsicHeight) } } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index 2c90440d..00c6c876 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -309,7 +309,7 @@ class WidgetConfigActivity : BaseActivity(), WidgetConfigContract.WidgetConfigVi @Suppress("DEPRECATION") setColorFilter(ResourcesCompat.getColor(resources, R.color.iconTintColor, null), PorterDuff.Mode.SRC_IN) } - setBounds(0, 0, this.intrinsicWidth, this.intrinsicHeight) + setBounds(0, 0, intrinsicWidth, intrinsicHeight) alpha = 128 } } From cdc801d2504bc32ef113c36b008d8a2b007ef44e Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 17 Sep 2019 01:55:24 +0200 Subject: [PATCH 043/122] Simplify isPinAppWidgetSupported method --- .../activities/widgetconfig/WidgetConfigActivity.kt | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index 00c6c876..892c640d 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -285,13 +285,8 @@ class WidgetConfigActivity : BaseActivity(), WidgetConfigContract.WidgetConfigVi if (!supported) presenter.showManuallyAddWidgetNotice() } - private fun isPinAppWidgetSupported(): Boolean { - return if (VERSION.SDK_INT >= VERSION_CODES.O) { - getSystemService()?.isRequestPinAppWidgetSupported ?: false - } else { - false - } - } + private fun isPinAppWidgetSupported() = + VERSION.SDK_INT >= VERSION_CODES.O && getSystemService()?.isRequestPinAppWidgetSupported ?: false private fun widgetCount() = AppWidgetManager.getInstance(this).getAppWidgetIds( ComponentName( From 7ca0b767397f7844481222d9f6b2252dff5aa84d Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 17 Sep 2019 15:16:04 +0200 Subject: [PATCH 044/122] Fix about items view binding --- .../activities/about/AboutActivity.kt | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt index cf307963..661318f6 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt @@ -63,7 +63,17 @@ class AboutActivity : BaseActivity(), AboutContract.AboutView { title(R.string.privacy_policy) action { presenter.openUrl(PRIVACY_POLICY) } } - binding.privacyItem.init { + binding.sourceCodeItem.init { + icon(R.drawable.ic_github_logo_shape) + title(R.string.source_code) + action { presenter.openUrl(GITHUB_PROJECT) } + } + binding.changelogItem.init { + icon(R.drawable.ic_changes_logo) + title(R.string.changelog) + action { presenter.openUrl(CHANGES) } + } + binding.licenseItem.init { icon(R.drawable.ic_open_source_logo) title(R.string.license) description(R.string.mit_license) @@ -75,16 +85,6 @@ class AboutActivity : BaseActivity(), AboutContract.AboutView { description(R.string.feedback_description) action { showFeedbackOptions() } } - binding.sourceCodeItem.init { - icon(R.drawable.ic_github_logo_shape) - title(R.string.source_code) - action { presenter.openUrl(GITHUB_PROJECT) } - } - binding.changelogItem.init { - icon(R.drawable.ic_changes_logo) - title(R.string.changelog) - action { presenter.openUrl(CHANGES) } - } binding.authorHeader.init { title(R.string.author) } @@ -100,7 +100,7 @@ class AboutActivity : BaseActivity(), AboutContract.AboutView { description(R.string.github_username) action { presenter.openUrl(GITHUB_USER) } } - binding.licenseItem.init { + binding.licensesHeader.init { title(R.string.licenses) } binding.openSourceLicensesItem.init { From 123febdf9824a9979a92cddb93585a42bbcdd590 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 19 Sep 2019 02:30:45 +0200 Subject: [PATCH 045/122] Update android studio and add task to print used r8 version --- build.gradle | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c44eaadd..fecc6b9d 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '3.6.0-alpha11' + androidGradleVersion = '3.6.0-alpha12' gradleScanVersion = '2.4.1' versioningPluginVersion = '1.0.0' @@ -61,3 +61,12 @@ allprojects { task clean(type: Delete) { delete rootProject.buildDir } + +task printR8Version() { + def version = 'unkown' + try { + version = com.android.tools.r8.Version.getVersionString() + } finally { + println "R8 version: $version" + } +} From a21e9e3df45fad7355a8f607be26f0a4046eafdd Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 19 Sep 2019 10:03:14 +0200 Subject: [PATCH 046/122] Update lifecycle library and optimize gradle task --- build.gradle | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index fecc6b9d..e2266386 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ buildscript { appcompatVersion = '1.1.0' coreKtxVersion = '1.2.0-alpha04' activityVersion = '1.1.0-alpha03' - lifecycleVersion = '2.2.0-alpha04' + lifecycleVersion = '2.2.0-alpha05' materialVersion = '1.1.0-alpha10' recyclerviewVersion = '1.1.0-beta04' vectorDrawableVersion = '1.1.0' @@ -63,10 +63,9 @@ task clean(type: Delete) { } task printR8Version() { - def version = 'unkown' try { - version = com.android.tools.r8.Version.getVersionString() - } finally { - println "R8 version: $version" + println "R8 version: " + com.android.tools.r8.Version.getVersionString() + } catch (ignored) { + println 'R8 version: unkown' } } From ac12485edba80f297a8dad90f9895f1515ef5008 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 21 Sep 2019 02:39:41 +0200 Subject: [PATCH 047/122] Fix webview crash on some lollipop devices --- .../activities/widgetconfig/WidgetConfigActivity.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index 892c640d..74f83b64 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -8,6 +8,7 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.content.res.Resources import android.graphics.BlendMode import android.graphics.BlendModeColorFilter import android.graphics.PorterDuff @@ -122,7 +123,11 @@ class WidgetConfigActivity : BaseActivity(), WidgetConfigContract.WidgetConfigVi } // set up webview pre oreo to get implementation information if (VERSION.SDK_INT in VERSION_CODES.LOLLIPOP until VERSION_CODES.O) { - WebView(this) + try { + WebView(this) + } catch (e: Resources.NotFoundException) { + WebView(applicationContext) + } } binding.deviceTitleEdittextview.apply { From 4f008e83671ebd1ee22b8576499dbf8e53d4f9c2 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 21 Sep 2019 02:40:49 +0200 Subject: [PATCH 048/122] Revert changing navigation bar color to white on pre oreo devices --- app/src/main/res/values-v26/colors.xml | 4 ++++ app/src/main/res/values/colors.xml | 2 +- app/src/main/res/values/styles.xml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/values-v26/colors.xml diff --git a/app/src/main/res/values-v26/colors.xml b/app/src/main/res/values-v26/colors.xml new file mode 100644 index 00000000..77a1d6f5 --- /dev/null +++ b/app/src/main/res/values-v26/colors.xml @@ -0,0 +1,4 @@ + + + #A6FFFFFF + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 599c3684..39743700 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -13,7 +13,7 @@ #80212121 @color/lighterGrey - #A6FFFFFF + @color/black @color/navigationBarColor @color/black #33303030 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 6472bc42..7ce3e2e1 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -12,8 +12,8 @@ @null @color/colorEdgeEffect + @color/navigationBarColor - @color/navigationBarColor @color/navigationBarDividerColor From 9ef1495d177ede58b9a58ada1cea585aef9ff657 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 21 Sep 2019 15:13:19 +0200 Subject: [PATCH 049/122] Filter empty categories in device data list --- .../activities/widgetconfig/WidgetConfigPresenterImpl.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt index 7e63e820..4f5e4050 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigPresenterImpl.kt @@ -81,7 +81,7 @@ class WidgetConfigPresenterImpl @Inject constructor() : BasePresenterImpl(), override fun showHomescreen() = intentController.showHomescreen() private suspend fun getDeviceData(): List> { - return deviceDataSource + val itemList = deviceDataSource .getStaticDeviceData() .plus(deviceDataSource.getHardwareData()) .plus(deviceDataSource.getSoftwareInfo()) @@ -94,6 +94,9 @@ class WidgetConfigPresenterImpl @Inject constructor() : BasePresenterImpl(), { !it.second.isHeader }, { stringController.getString(it.second.title) }) ) + + val emptyCategories = itemList.groupingBy { it.second.category }.eachCount().filter { it.value > 1 } + return itemList.filter { emptyCategories.containsKey(it.second.category) } } override fun shareDeviceData() { From 399bccb25721879e586b859a6aa2ed5829b91704 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 21 Sep 2019 15:55:00 +0200 Subject: [PATCH 050/122] Remove unnecessary title attribute from category enum --- .../developerwidget/data/DeviceDataItem.kt | 16 ++++++++-------- .../developerwidget/data/DeviceDataSourceImpl.kt | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataItem.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataItem.kt index 7c960467..ab2cbcd7 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataItem.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataItem.kt @@ -12,13 +12,13 @@ class DeviceDataItem(value: String, @StringRes title: Int, category: Category, i var category = category; private set var isHeader = isHeader; private set - enum class Category(val title: String, @StringRes val titleRes: Int) { - DEVICE("Device", R.string.device_title), - SYSTEM("System", R.string.system_title), - CPU("CPU", R.string.cpu_title), - MEMORY("Memory", R.string.memory_title), - DISPLAY("Display", R.string.display_title), - FEATURES("Features", R.string.features_title), - SOFTWARE("Software", R.string.software_title) + enum class Category(@StringRes val titleRes: Int) { + DEVICE(R.string.device_title), + SYSTEM(R.string.system_title), + CPU(R.string.cpu_title), + MEMORY(R.string.memory_title), + DISPLAY(R.string.display_title), + FEATURES(R.string.features_title), + SOFTWARE(R.string.software_title) } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataSourceImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataSourceImpl.kt index a11b1462..52eb877f 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataSourceImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataSourceImpl.kt @@ -98,7 +98,7 @@ class DeviceDataSourceImpl @Inject constructor() : DeviceDataSource { override suspend fun getHeaderItems(): Map { val data = HashMap() Category.values().forEach { - data[it.title] = DeviceDataItem(it, true) + data[it.name] = DeviceDataItem(it, true) } return data } From 932f397d27aa912d4ff5898e877c54174ca45831 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 21 Sep 2019 16:09:59 +0200 Subject: [PATCH 051/122] Fix typo and suppress lint check in build script --- build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e2266386..e3512b33 100644 --- a/build.gradle +++ b/build.gradle @@ -64,8 +64,9 @@ task clean(type: Delete) { task printR8Version() { try { + //noinspection UnnecessaryQualifiedReference println "R8 version: " + com.android.tools.r8.Version.getVersionString() } catch (ignored) { - println 'R8 version: unkown' + println 'R8 version: unknown' } } From 1c79915491452dafc238464fa746823f4670a8b9 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 24 Sep 2019 21:01:54 +0200 Subject: [PATCH 052/122] Use window constant for accessing the main layout container --- .../main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt index c75e969b..7a7669f9 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt @@ -83,7 +83,7 @@ abstract class BaseActivity(private val isDialogActivity: Boolean = false) : App flags or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE } } - findViewById(android.R.id.content)?.let { + findViewById(Window.ID_ANDROID_CONTENT)?.let { it.doOnApplyWindowInsets { view, insets, padding -> view.updatePadding(top = padding.top + insets.systemWindowInsetTop) } From 15aa971560358aaa960c53b2a1eb62d499ab4dc5 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 24 Sep 2019 21:02:06 +0200 Subject: [PATCH 053/122] Update gradle scan plugin --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e3512b33..9f4a92f4 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { minSdkVersion = 14 targetSdkVersion = 29 androidGradleVersion = '3.6.0-alpha12' - gradleScanVersion = '2.4.1' + gradleScanVersion = '2.4.2' versioningPluginVersion = '1.0.0' // Library versions From 711491bfba68bee45608c335471e5160778cfc89 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 26 Sep 2019 00:20:12 +0200 Subject: [PATCH 054/122] Refactor gradle scripts --- app/build.gradle | 10 ++++++++++ build.gradle | 32 ++++++++++++++------------------ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index fb4f0939..6811da08 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -67,6 +67,16 @@ android { } } +repositories { + google() + mavenCentral() + jcenter { + content { + includeModule 'com.g00fy2', 'versioncompare' + includeModule 'org.jetbrains.trove4j', 'trove4j' // required by com.android.tools.lint:lint-gradle + } + } +} dependencies { // Kotlin implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" diff --git a/build.gradle b/build.gradle index 9f4a92f4..5d8c3439 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,5 @@ +apply plugin: 'com.gradle.build-scan' + buildscript { ext { // SDK and plugins @@ -7,7 +9,7 @@ buildscript { targetSdkVersion = 29 androidGradleVersion = '3.6.0-alpha12' gradleScanVersion = '2.4.2' - versioningPluginVersion = '1.0.0' + versioningPluginVersion = '1.0.2' // Library versions kotlinVersion = '1.3.50' @@ -27,8 +29,17 @@ buildscript { repositories { google() mavenCentral() - jcenter() - maven { url 'https://plugins.gradle.org/m2/' } + jcenter() { + content { + includeModule 'eu.appcom.gradle', 'android-versioning' + includeModule 'org.jetbrains.trove4j', 'trove4j' + } + } + gradlePluginPortal() { + content { + includeModule 'com.gradle', 'build-scan-plugin' + } + } } dependencies { classpath "com.android.tools.build:gradle:$androidGradleVersion" @@ -38,26 +49,11 @@ buildscript { } } -apply plugin: 'com.gradle.build-scan' - buildScan { termsOfServiceUrl = 'https://gradle.com/terms-of-service' termsOfServiceAgree = 'yes' } -allprojects { - repositories { - google() - mavenCentral() - jcenter { - content { - includeModule 'com.g00fy2', 'versioncompare' - includeModule 'org.jetbrains.trove4j', 'trove4j' // required by com.android.tools.lint:lint-gradle - } - } - } -} - task clean(type: Delete) { delete rootProject.buildDir } From 1601f5de75655f7ace032c2a632106a28cc0b509 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 26 Sep 2019 00:50:44 +0200 Subject: [PATCH 055/122] Increase gradle jvm memory heap size --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 19e41955..b52439ea 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,4 +16,4 @@ android.namespacedRClass=true android.useMinimalKeepRules=true # Set the build VMs heap size. -org.gradle.jvmargs=-Xmx1536m +org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 From 8995f8d32a2bc8cc9c8bfd80da5a95e52ee99dd3 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 28 Sep 2019 01:54:57 +0200 Subject: [PATCH 056/122] Update coroutines --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5d8c3439..cbb83422 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ buildscript { // Library versions kotlinVersion = '1.3.50' - coroutinesVersion = '1.3.1' + coroutinesVersion = '1.3.2' appcompatVersion = '1.1.0' coreKtxVersion = '1.2.0-alpha04' activityVersion = '1.1.0-alpha03' From bf1d3844a41742b721a480c2ae62d5f3e3177f9a Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 28 Sep 2019 15:00:37 +0200 Subject: [PATCH 057/122] Update Readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8b622408..90e983f4 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ [](https://raw.githubusercontent.com/G00fY2/DeveloperWidget/gh-pages/media/store_screenshot_4.png) [](https://raw.githubusercontent.com/G00fY2/DeveloperWidget/gh-pages/media/store_screenshot_5.png) +created with [App Mockup](https://app-mockup.com) + ## Description The app was built from a developer for developers. You may know the hassle of having multiple physical devices running different software. This app will help you keep track of important device information and allows you to organize your apps and local APK files. You will never again struggle to find APK files using a file browser or search for the app settings menu on a custom manufacturer UI. From 02383f11f10965da5f3dc05d287331eb072ff978 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 28 Sep 2019 17:16:17 +0200 Subject: [PATCH 058/122] Make use of view binding in dialogs --- .../activities/about/AboutFeedbackDialog.kt | 8 +++++--- .../activities/apkinstall/ApkDeleteDialog.kt | 12 +++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutFeedbackDialog.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutFeedbackDialog.kt index 19344bb8..3bd995ea 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutFeedbackDialog.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutFeedbackDialog.kt @@ -1,20 +1,22 @@ package com.g00fy2.developerwidget.activities.about import android.content.Context -import android.widget.TextView import androidx.appcompat.app.AppCompatDialog import com.g00fy2.developerwidget.R +import com.g00fy2.developerwidget.databinding.AboutFeedbackDialogBinding class AboutFeedbackDialog(context: Context) { + private var binding: AboutFeedbackDialogBinding private val dialog = AppCompatDialog(context, R.style.DialogTheme).apply { setCancelable(true) setCanceledOnTouchOutside(true) + binding = AboutFeedbackDialogBinding.inflate(layoutInflater) setContentView(R.layout.about_feedback_dialog) } fun mailAction(mailIssueAction: () -> Unit): AboutFeedbackDialog { - dialog.findViewById(R.id.mailTextView)?.setOnClickListener { + binding.mailTextView.setOnClickListener { dialog.dismiss() mailIssueAction() } @@ -22,7 +24,7 @@ class AboutFeedbackDialog(context: Context) { } fun githubAction(githubIssueAction: () -> Unit): AboutFeedbackDialog { - dialog.findViewById(R.id.githubTextView)?.setOnClickListener { + binding.githubTextView.setOnClickListener { dialog.dismiss() githubIssueAction() } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkDeleteDialog.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkDeleteDialog.kt index 74a011ba..641ec618 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkDeleteDialog.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkDeleteDialog.kt @@ -1,20 +1,22 @@ package com.g00fy2.developerwidget.activities.apkinstall import android.content.Context -import android.widget.TextView import androidx.appcompat.app.AppCompatDialog import com.g00fy2.developerwidget.R +import com.g00fy2.developerwidget.databinding.ApkDeleteDialogBinding class ApkDeleteDialog(context: Context) { + private var binding: ApkDeleteDialogBinding private val dialog = AppCompatDialog(context, R.style.DialogTheme).apply { setCancelable(true) - setContentView(R.layout.apk_delete_dialog) - findViewById(R.id.dialog_cancel_textview)?.setOnClickListener { dismiss() } + binding = ApkDeleteDialogBinding.inflate(layoutInflater) + setContentView(binding.root) + binding.dialogCancelTextview.setOnClickListener { dismiss() } } fun deleteMessage(count: Int): ApkDeleteDialog { - dialog.findViewById(R.id.dialog_message_textview)?.text = if (count > 1) String.format( + binding.dialogMessageTextview.text = if (count > 1) String.format( dialog.context.resources.getString(R.string.message_delete_multi), count ) else dialog.context.resources.getString(R.string.message_delete_single) @@ -23,7 +25,7 @@ class ApkDeleteDialog(context: Context) { } fun deleteAction(deleteAction: () -> Unit): ApkDeleteDialog { - dialog.findViewById(R.id.dialog_delete_textview)?.setOnClickListener { + binding.dialogDeleteTextview.setOnClickListener { dialog.dismiss() deleteAction() } From ec2b8803318e0d183a3b5dafb81fbddfb138e322 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Mon, 30 Sep 2019 15:36:13 +0200 Subject: [PATCH 059/122] Extend BaseActivity from DaggerAppCompatActivity --- .../kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt index 7a7669f9..e43fbfbc 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt @@ -7,22 +7,20 @@ import android.os.Bundle import android.view.View import android.view.ViewGroup import android.view.Window -import androidx.appcompat.app.AppCompatActivity import androidx.core.view.updatePadding import androidx.viewbinding.ViewBinding import com.g00fy2.developerwidget.controllers.DayNightController import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets -import dagger.android.AndroidInjection +import dagger.android.support.DaggerAppCompatActivity import timber.log.Timber import javax.inject.Inject -abstract class BaseActivity(private val isDialogActivity: Boolean = false) : AppCompatActivity() { +abstract class BaseActivity(private val isDialogActivity: Boolean = false) : DaggerAppCompatActivity() { @Inject lateinit var dayNightController: DayNightController override fun onCreate(savedInstanceState: Bundle?) { - AndroidInjection.inject(this) Timber.d("Lifecycle: %s1 onCreate %s2", localClassName, hashCode()) if (isDialogActivity) { From 335f03ee551db381d343a8ee73d63009c1881ee1 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sun, 6 Oct 2019 20:24:10 +0200 Subject: [PATCH 060/122] Update material design components --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index cbb83422..899a4534 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ buildscript { coreKtxVersion = '1.2.0-alpha04' activityVersion = '1.1.0-alpha03' lifecycleVersion = '2.2.0-alpha05' - materialVersion = '1.1.0-alpha10' + materialVersion = '1.1.0-beta01' recyclerviewVersion = '1.1.0-beta04' vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta2' From 52914c83c18135b0e442b2995e103a930291b5d5 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 10 Oct 2019 15:11:12 +0200 Subject: [PATCH 061/122] Update dependencies --- build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 899a4534..c9a04f60 100644 --- a/build.gradle +++ b/build.gradle @@ -15,11 +15,11 @@ buildscript { kotlinVersion = '1.3.50' coroutinesVersion = '1.3.2' appcompatVersion = '1.1.0' - coreKtxVersion = '1.2.0-alpha04' - activityVersion = '1.1.0-alpha03' - lifecycleVersion = '2.2.0-alpha05' + coreKtxVersion = '1.2.0-beta01' + activityVersion = '1.1.0-beta01' + lifecycleVersion = '2.2.0-beta01' materialVersion = '1.1.0-beta01' - recyclerviewVersion = '1.1.0-beta04' + recyclerviewVersion = '1.1.0-beta05' vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta2' timberVersion = '4.7.1' From c112a465884b930996e91e6208ad45e98499b3dc Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 10 Oct 2019 22:58:04 +0200 Subject: [PATCH 062/122] Update android studio --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c9a04f60..ceb95ac8 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '3.6.0-alpha12' + androidGradleVersion = '3.6.0-beta01' gradleScanVersion = '2.4.2' versioningPluginVersion = '1.0.2' From 1df64359ce93c7ffd88b0cab8553c55815c0a3d0 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 16 Oct 2019 11:57:59 +0200 Subject: [PATCH 063/122] Update gradle wrapper files --- gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 92 +++++++++++++++-------- gradlew.bat | 30 +++++--- 4 files changed, 81 insertions(+), 44 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 13372aef5e24af05341d49695ee84e5f9b594659..5c2d1cf016b3885f6930543d57b744ea8c220a1a 100644 GIT binary patch literal 55616 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�J+L&6O)2CL%pxI@Gv&XXKx zY*yF%8{4kP(#nhT+`ZvX00#e(n`>Ot@(~Lo!Af#%Wa4rLayvtbPFQ^oOq_(I3XDMw zyO$Z~9@fSK>~*C{->PREgtn>sf(b1SbIo;~7XMD;0~Ew)t_gTumSpk7;n44nQUMFb z@QRcbnredr2F&!ax;`M4u$dPolnZaSYOTAE0#e&W?MOW0l-E)>Ap1m-uK8x>!uzce zNFa`R@{>A5pOez0UW0k(C!eB)y1#CK@w&!5ad=PDm}7=^TcjGeo3h6&ZGJzf)fAbhf3E`oy>TG6Yc4& zN%tFR<8G%ZA60W6W3ZA6`k9rStem{`?KV?SCHuG96?Dn9T!^X)6Du3Dm$>p7l({}! zOxe=qsBOCw6-ND1F-O$=5&-&H3J;vCwD({!Lt?BY>~UH?K#&xnfpgQ!YvZ;3lFxmVX`Yf#Rqoxk=U3Kh@OJF+gKtN-Y6XG*0 z#yi!q1k>F2uFDDr!Iym14S^1e6gPGXJB)(y@kN2_!l7(z$c}cnLxT;YP+C8PdtX$7 z4DJh(+$Yq*qPoO?fLPvTi&~mDA0S83qZtfVr6M&0c*zPk2rV+ezT+%Hx1cE$6^X;p zgkUHXCQ(H%X(dUhCs3}?|10RXLJ{uN-c)H}&|-^>)>$stWC}GC9W0`zJHydpj!Z>` zmN!~animXQLGAE_Wj}7Eh;3y}yORjG!r}3zx2r83zElo{q?06N80EPZVSQe*(=_4l zZAOL!6qYx@v>UV9OTrlh)p7;X-ec+5-No_}knAe+`o=$SbIZhI91x4Wk&8YM5vCPu zNpZg%L5@VU5{@&6arOH1_u41P5_9XxT7trwwK`GZhvqMG+%Ke&w6iW>fh(|(l-qKH z?tGk9&my>n^k4wn)B18mZj?j|>_Pt|7X()W^ps36EXRmT)!;29A$ZP{@Y|GS@iaOT zWd{E7nB$iI#%!VmvT!y>P1Y^Ed2mqn^E5wHuRp_09G=2QYhc#@*5HbD`>=s!gBr5Z zV+s7zdEM2#u5Pw||L3-;JH0O1`>t*vjE$qr$qFaEw9#tLkLn_8=(KPQM$ajZMF&(D zu(tFf&l`Dz>bc6TnYjw1=eC-ruCS+fYuyyY5@0X{34J3<{+`Jb zELT+R1wb_K(VR@!i8@Q@%aMN6b%Uamrjs{cy|D>kXINne04Rjb50vOJfmI z=A~pE%5R!vS`Q&Si4SOD{E(BikeV|HJR9+g$!;BQb}h;oKG%_`WK8yUDqNGaQ?oy< z@Dc>_#qQ*ebFW*dh(k-|zB1vpjDF!x?hNHJyv#7XEK)xuTEURZ6$o<1+fN^=TskB7 zSfgB({@-fW#w@aD!FM}<%Xcroi!ZoC_ZVtA3v1C!I_9?*Ja>g z$P`3Sc>{!*i4_jVsI`) zCH)})1!jb?rc+Ia6n}ICUUpf}@|y3s{|Y?Kefc^Q3`l(VVRt!cjd+OpYL2{!@eu)r zA_}2QkWEb@NH7DjMd3|YJe9oPsK!cL#aM|CBcOFhOyP?iiyY0A5(Zz2fg@d5!SP9! zWt)y@<0JbW@PyXGh`?cv4`@M*dq=eRi1!67|DbVWPrbvK!$_*Um_zD|Jf!=UX#j;p z%bWyI51f+J)1c7rcLT2-r_Fk?#sNTKiUVE4lp=_1drJIvo(IxlYo=z^ zsQiF^FF0ZfvO|leU|;+0?w*a+YnQN~Q}b!6ZtP%`cdICnzRq4#)fRDH(lpkT)c7{EZoEO{PzCS zA?YeN)qz-l;fe2X?x{MWTjYa#M-}1&8+LZ}T3P`J{l%(NYwX&k!1qZJ{Mkiw-{{u8&fgFP+b zs4-5-g*o`k^#lDZvlDDqRHKlnjckBtuk@h&Rc`$3Rb+f`RBSw5CsO{>`y z8OGWFH=Y$*U7sUf(2RH4K{nWN-cVW@l=u>TpQS@+Qqy?)nLGecPuu`{D8@y=LNOz; zIZJ4MxOL!vsldU_j!{|Fvp-UC2T2opl{}+RJ9bn)L-TW4Ml)~;-;Jjs;z- zw|}T?$m-2ws{%~Al-7gZLY;c?IKzR-SMZ}(-cG)B&Xf6cBz}8Vo zOBUUDc#(1fg=zGI{ieRcc9^{G3;T=D z2Yb{F-G9N#)!mmxZ}?I<*xJ~N#t>WI&Cn49OYQQ4q_4ci4pD)zgVdox&J*TJwagW^xr8SnTxf#erPAdl zjPZpkH2_@fMK}}@K5!k%i_m&I+#{EfFYBHm@u$3F(VNlnhOZa0TEaEdItFkv`fGK_TR5W8TzdS;3UlikM5=hAR#JMUl0)LGtv*Iq8iV9wO@g`ubl1&v`^JskZMqSh&E2?UHHM)pf43i6BWtp#Rh{3-no3J zW!Fdb1*q3M(q&;>F8sH~j4_Opncd9L@*OHC$|~{)1pew=HSPxn##Tl>03*aOq@pwR zj`&~f-aoOhe7p1gUzCfLS-1O={a>K;jtxYV(euJo&9;5LVMxNOK~A@o2rAYIN2E$W zF@CD|#U5_SfxNmT^5UfS*Z-f^Vr!yr637n_5RGI)d1=7Tifgq~Yul!7i&uor)#jnD ztS|~VaZ4x$p)ZwO60t(p212rY^q0(_60lHkfKZ)}HEgj0$#*@|E~0V2)^jbz9_fM@<)^Ze5&?CAlB zzaG<(7Tb&z41XxmUDK^i`U`H zD5*=T^n|PM5Hwh?$Exsp`4VbFXehKj6f&Y^?oG3<_7)i%}6fh2TB*{|MuLH zOk{Aep+P`o5kWwR|GS|L3i|(TXbaVh1fW@9`m3 z%ig(0)|h5|i+lOId*qXU=5scc3djdQ47h)&nwf+)fN?KuGvWYr&5o!X)sLOz#)@De z#?^BMz-Rb;k* z@F?az`2rtK(akuTulA@Wup_3P<~1v7=G7ZycTTK3$f3d$bWiP`K1Z!VRj!XdCI=-+ z6*f-|h!3%+4g~N+>}dkQAQUHG3!|1^6JyHF_(+e&QHX@2Gs}$P&E3YC@nG=pQR8gr zuG?#KjJmOh56)jB4|;eVGVCcTyVK|koxYZj@m2pG-jf!4C@5~z3r9(7@mpucRcGIR zgBfuVNMvBDCCbLfp5^f)$A8`wTk1B47_Q2cBj{{!*#kB%0$Xa!o5lu;YR}G{47YXh zlIBOeG`OaW_|e zT-Ic|%*kFQYteQ%V=d%NNcx#<)}fv@YA_R0mz!C;a*-dC=I>@LGREcq;N7)i%+!>Y zW4$0qPXThKN*>!9Sq67uaEgYSlW3@=)=}soEpToJp44j4tjBP$rc4nS<+K$`ZHEi* z#x`rkh|Rd{$LKcfYgSSVZh7jcx|~J?S#;N#E%ok zTm&#uWAiY{iOlub(E}(biGnj8mE-t_S&(0M{;akC_vNA4;j1u)jWBlvfz4>m6&(~t zp0mUh3xmyQ#T5^CeCDhm$tM)6#?CQPk|nYtJ2WW1&_j2Gj*t#?L7)bnS8++^hX=*{ zvV0}?FFjcER39@#=pS@2`%oB0|1cOP6az334iIMkjoFXNo$Hj48Ovwu30ottp&sVf zrl<>KG?tMGEksus~oRHiEhu!nxy4?M>)_qV$_kIUlbOOukRLviI9xKn&aQ|r&9RxgIIVVzSKI5BztkdK73RG7D!LK#9$ zH2h%$DK4@0^EWb}gPjC(9^)Rf!JcWpsrIdir6R<=GEqp3+R)F~V&a92Vvbm4AdGVU zosT2Tfy!_R!d4-qoeog=sgk{kYqVoD(4%y~lcP`(ZF*qu_(8blj>!k>e7b4ZNVdpYcrJq|JcNS$(|>w5 zCLtuk9RbJ*u&@Sr7@@lxle#CO-ciVOcd|?@Aay$8ChiS~>;mGzy$X|2UlI|1cD@pA zyh5wKQ5kVboAZg=^NF(MlY=lS9r2mftGI_Ytx@>|H?_lrfzV6FR|B!k9TPrclIC6( z4fvQZ*-5hxd zoB;r-^FWWmznFu4+p@q}er-HY#X}4z3CgGse;W?{+DE_aX;|qQeQ;8xbeO4A@Ie+JV*cNX`4lyK9s}j?A$qq zt%P0OCmYp&rwy$=V5B*Hw=VN^hSdMUR7}p@1{5v>Lrr*wE?qmVJoKAa38aiRnr>gb z)7F$t-S&9TM4SQ2=Ib5Pe_Frt@6IX2QZ=ge$T@ZhNa4pj$1>gQGxeujrrXhqw5C|s zyPvV!&A17}q@v037Mt24g6gCfZ5USg=_X=d=$ZF}jBE@BrU&<+n9+LAQ&O>Os6(%~ z1KX&qOqmS)8ohpX^>NNOjyqOg@Z^z)2i090T5%NphH?cE($pR`L|J2XiO5yJNh}e< zX7{_R6EN(k$< zlcGYl2tpz9$1#tvsJqMBT)_LH@!&L5j~-Xcn^zK1Gpne$$3F@+8obu!CmZc|S~4M# z^F3r@*_lEByL2~>wgiVp2gqMx1vC%KSSUjr+7^oOA6nv3*E_OOS#-s-waR%#eP!F|0fITKZ}Rumsxz-_Z~X` z{!t|__>m=>czus6fO9|Tim(x#Q$hn5A4DB-ub{UAmHy+%z!wmXqN>;BDDWsqXuf;( z=?OZ46b>ya7IJQD-?nd8o6#^Kza^u8YcoS>g}>!SdYANlN)y4>yt*9NSxF%_4=HU- zt*D_xj}}=uJo8FL7K-rDX`V@Sjl(CtNEDIQk31?pC?aJm`I3^p=-=ZO|}C6R{?feMfZ>V~?@tehl}M$Uv%y^nM6&Kb$46oZbaj zb}WtJhFkF)D7n`1Uo^FX5Oj3rWAzc`h-5bMm1-K4j5G^z>KQR++);MO(M>l5Suy5u zrlQN-{s7{elMghKYo#7*YvRQbYI9etWxt2gDoTP4W{O|8Q-^7gnYh(Aeh;er?O zy-c~{h^qu1+Vl~sbguKnB^7DN)sGz7-4<=v002qlrjzs!bjB<_wP@TrdHbnO`Y@*U zYLVM~xTB#0do7>mIRCkXXcq4gbDd|=VIq|Wj(Xuy7z8-1rG^Mx z9Kh^BPZ)WOq;SpKzvl>}s&ow2>E~UcFu50ZCOHBVF8^YaFqaO|Do&ujYPykm6F+0j zWvg+08C*K?&J4EId%!5Mrj?dLFc}0fH!%-3$&G*&u{XuTHAtcF0p-x&lCTLpQv!-P z4=lsG!X`v6X^Y}MZiPf}#Uw3>HLDnic|a*h)iIo#SRcD5?6C^K_K*r8E{K)u%E?j| zbXGJ<5t}IUE6@=iEVPm*<<71{k$~X_m&0)qgpxe91ZfhJi6FoM5@w7%!#So+RFLxo z%R%TU7H_EotpJ0MUr0G_?q9oN>g_e0@pX0hlCLOXI;gx6Nx(MoRKs2aSi@(Vsgwby z`ucXml)+J{D@3w^xb_^YBs&m`e`mGBdI(d?+?-4bmx8GNmT^PB4^2!ZaeI!bk3w-IT#=yHDPx zz19y*W<&YhgGN$}H3L%aXWVN=Y^=Flce7vmyzaIfcAv)Q823QX?xzQkP7$!I7a9vp z76QV^TQhjl)U#}r$D`uZ!vg6qCJeKQ)A9uk=YQMp7-LmRje7%D`08|aag|%CS#+Fi zh6IrE)c#UcK!h(^NZsXvFS#}+=@*KQ6cT;8Hz3I1=mpXkpI*20y%ML72_Q<^?v+^NK+YgkBWSAX9|le$8-zd*3V zp3R1lg;gV){xDX}2yLDclDBt-u9vBd^=&;_ufkQ@v+u0fOXJHB1)72?HrAO0A9($W zGds}jj&tDdgFmiZ;U`$~L#jF|2B%0cm(o9*X>c00>QVvJ&|?gHGPYt7Jom$7VQo3% z3>v+LS>l+#=MJ*)iv&v?V(@Dt=)uT#8*OHqTInGD>Hz3q~`cDwUXT3Fe4< zq~s$0AQmo2Ea7BW?)V))|Izh~tYhnQf49?>#vjaFm`ggVyWw(@M_kw1C*m{3fXs;G zU9e*1oBt0WIv~kBJ)UrKlyQPO@hFYcCKs$!Le<%55U|PR?`@?EySgxH!r4T-ol#;E%#LljKAm7B7 zl>8@+bqCTFcC6Ac?tz)_=Y4YqoE?FQDJvSG$d6*eV}7FOWuhI!ABqWY5dXhT^q&QL zPKxl5{O+IzSW69x2x97JDE;e-Q&pAEdo~oVWdV2le6K z{X677{0s{0I*ZYk_>Oq+0QXr?Ie*Z5AwZF^5>px3`%}#c**!iCJXDt399%sg&OLjS zv<%V}&8qZtDnLTCs$=rZm^c?0vOkhe^CTiZj{Fz|i10~giL1oIod|_(&WL=vwRjy@<)nt zh>1vO!DGB8^0og=|CHEoleP{qIImAQ^An+IaD4sTKdyO8-AlJ}!Uor$QE}we9BwB+ zHU3mG%U3VHXO(hMndq~^SF>2`oMU_ScHhk2qjlyt@b9!Z7(q2RK}_ckPgh1E*f=e@ zuL=AQNoHR1zkHD;LwUY2+aX$;rBvxdDDXDx-U|V=&L5;nN7c=^ZG8BGR*L&`|VewMg;n z+3TIp?|m=7mfynMy*YcQAyV+~S@vV@-FBbL-`U&IuROpHA>Q58MhK6(0&?PFR1*|{ z95%65jP%2Umw~MTo`GJOqBItwiO3K#_S$|0JcI}HQz%oPRv_cSl$>k3++qLFmJgY) z`k1#be~gcr?XVxqH^by%vfcDMW@a>W7k1A-w*4#c?g*;qLun}f^_7cIkmv}DAO&cG z?ba~#3Im|@@}i2#e|Ry%j^DSC`}+uh{Q!NDeI>84(1Bh6TmrPEIAn(2;F9e${gSj6)x+pBcm9Bz8DC9i-`N1-> zi=yR`Y$c!3r~d7A8f*s))f@wKH(0uFzT-9aU7+2UkHaes+iEa2*j|agPN3E6FIhLw zSCV=v^z$11w)oW&t{(BH)4B#adydr}*oSfyuFo===}n;I60rlDH9gmEZn`e?vo)|& z_$xPl!q_y@j4c;-22Cg80ux9u@o+->dtZnb+Bsc2vIj||c0DbRi-UkE3d*UE;zArPOly;b+{~Hp9?ex5jqkJDZy8#!<)9+T8p{WS^-3cQvgkRgi$7f)8G(REfA}-4%cColl{B^rV z8`ieSEA%J|v|Pb^G#wC}w4NBEu(QTeLn#AoMGSj3TtCfH^SND53IJ;8Bh52QWUYJe zL}4@;gWNF9u(Ku#gD##DLyxcq1JSVle+B#T z*TI4ZB5`-056VE6?$0?-@j>w(ng)O3(Ylnxh%1gi>tMxQRr~B8q3LT793?B*aX4$q zZ3LwGBP-@4-eC1oo~nbobRTvf>O*_r%f_iy`zX7}9nWCT)`4;4ZE<*ID-ez|Q5nsPi2^leu03l!(J9kw&hJL`f^*WrHUm7MxX@#wXT-ilP$WZcNJ`}107#sHtB6e zd3Cx$`ZjjhybfPq0B>!WK`u1E#7<-gd!kqTd1D&91t;d48R~F<`M@AK7wOl%K@}Kn zi6PS*1*hxG=(>}o1D2&|{`LFt15J`UWZ)kXPJ8z>--@n6eHEJQT_fLdRi6XwNs z4;v&)oG}MhOiSW>*hite2}Q+)Kq~rn19A+~ljRAMMJz_5FP+(F#VK%G6f%3)!p=|B zU&U$S@c!+fEXuZ1z*5-sGr>IDK>w7*!Z0hG205n{!ixhTGI}v~KqPD`0k4 zH#3+BLzl35jJ2`8H%D@@k`p@BKgoSjao1VQvxJChNHz4Oba3eJqV0j7)osDsop+FI zLw8eBIC^|@hy^Ck8`%wk7`0JAndK3hOp!5U=>mW|B+NpIBlN*?39ZEP5p8JUavn`X ztQv+k|DJ4D>?$?Ea)j@PHeVFYJr+k)a)(TgNUbMc>>_DL$T?~(qv=xsytfgf=anzG5%>A0RD48NtU9<$JXLlTVH2=`_^%+(@Dvi42@r+`k zRea+fAZ2*?N((GsW%8ycs4aRtsiOsR4*CJ)b|szxc+v_OX4eza%Vyf=KDAv1YZ}0R zcpUFKoPXYI35yooa0s6R=0X)p9Q@6AKsC|h2IzKBeX`B(ku`M12Udd2>uug~v&)rT zEwMunGUM-3!)!%#b~v$#6olp?L1n@{^#A(YFzmEpIZDu5ULFDR z5p_q)f4|6-@(_pI&>$n=v`7ugYI>y_0qE_~YfQuj<4*UG6r>A*Zs zs4wI@6}o@7+&$6TfE;J{jHV*A7eiG0QQ@Rd0*C`vgRrk)n$hvZ$KV0i1*})?ZAfL9 zDoJ|iM)@YPpT;eXm7P3l`W#?R=E61^g!e7C_ZKYMmHS95?Z5&pB_r5F;ZW-NU|3bh za7`olSi|KjsIc+_CV@+GZSJ-Mth&&c_@x(A;(xf;SZ01O_T`K;!&-`a^?_ejykX-a z5C0P!`JeATo()Fh%(vp-N@h$I1gP67E-9h;+pjGs^I$os0wKiUaUIM8h~SZPj4?2o zGKud^uxIElbQax5@(&OXqJIrY8NXh~ljLo2xHQNdi2BU&pK;H1zVx&J>ij<;l?LKs z*iKEK9yAfZQ&1B~jZ`KuQz!;9T8W8=f6)x2wT^&pFyb({CD@+)b&W}TJe#=Fji13P zZFD=-nORqtAzD@I3i`FYn}wCt>`O{8Tk|!d1gFWT9bK$m$;A^yD^Ixdt!jRZ9s)+~=c{X@HZ7Xh3dJ3$>3JQFo9ts2UvcUee(MEx*?T=a?!ERVnRTZ% zXKq%X39xO#JtY5Z8J6W-69}n`(uS>Zw~iv5wv|nbYq$TQin2=spgO>JJDCw-wjB+l zv#K*_)7x=InB!XDHHjZ3LW|kwANJH+<+4vHbiC{AaBnPdh8I;XEyjpjUO>>CmW&;3U4T8SQ%zu}@!j-)C`Phr`1^aGBtww`mGE>dxf)B=b;W33PcRoSK zeIxMS7$Z=k$tfEzsmc>I@el)Q4Xxym zxF1WUlS1HMu|h{|T40T4wOnVLeiVpjkPYE&picaKwVHmtq9d5+5%!W(rEW^uz-%E& zCW)01Y*Ky~uGAVm|MkC53&+MQln397-TqtX3jWveHhYx-(5pVBf+~#0&p%0K#3BTZ zbRQZ)HHid$P)HI%Qd+8xrW4v^xJIUWbZ#1!C71FG_)AX;J)Q>BKj3SBY;7nOm$R#( zhd&b*S%lo_;B@zP>m{ep?{?<+^RE34@n5VO#upj3AVMmV-}r0<(+9{Jn9sibMR19dIp=8sp~F7ZjY%c zr(1t0ak>8pPkf65KbdOr0Wqh&&Eag5XR`^3KMEJF6?RZOEuh#Kmrs-kvBc3U4$1GA z)5tCCGitGlJv60|7=XK}Ht2F(nmi!r>sXbgn^}N(RlTS9aZoxzcYF9@>5t+E0|D5yG9 zsg6FJDs+Y=0hVhb^_M4Fee5nKggKu+TH#?BEz$(TTI<7P_K;28E0Pbz*w);Mzvkor z9QR1PCv}p(O`c2ykYwZzw4?=0K(2$Xrgh1TvWo1wT8*wjbNs%YrSi!iXB-LK*AW{{%(<&OGtc3KK4~l8^@p+nd z+C00zWN-B;O`QF48JmTc$asnYn|isi4a)OsKYpb>!V2AK8J;d@^f0BDi1LlGnKWze z1r#~KCQ<_q`?7N;MK+EbfE3$_MS1?Wm#)X4lvLP`s`k80TbgF*WQ}$9vP{I4d0&%I z?z$8wbeE-W>SE0;oebAD^k!3ZXHhK%JbgOn({@E`OG#F!)6O!*&V)V60`kssZZe9> z1xO6DWb+DyC@w)pA`*5hY!(%^qJml)2Ahvg59&Z|kM(p#8^d!RfW_L&s`cX2|A(GZ zo$7cKHv1vn<@Hb=rb$hGVZ5w}qMu{i0N6ZTJO=)B-G;_8vB7fAq&ldb6k-TfOTF?M ziLJ3Reg1O?sSy=E$?Sm6r8A$aLV}IF zkU3{NaD;mKSH;Y_Qpd1OR+DL0AYG862YFuxg*kcCiKH zph(BS6b*v6QC31bFt``?IYLsxk_PtnFfZmWEP~ST)YO^&;w-Pd23G z<2?9?bk9{F1D5nJ!%JZ!!`If71F%+t3QTxxX`%7eWyxns1`U_2toZGfMOmYR25Sa0 zLT)Y=zMA5=HPp#TFktbBf4U^p7N;2@B^Q*yO|7QYbmO=`K6VH1y;CIxnHd&$*cA84 zBhBo+Jm%*(o`CKCu5*!xWq5bj_8%ih@k)3gw)U6g1(4`5n&pZ7<`do8R&5a!CVOOE z!`Ii!Z-N;}vOt*IIQqnxN{)&INaocBR zn>9nh8SODdbpbm`Fvsx+sW-N*w{DW9Z5bqwhON_HZUpSsuh}7SB1hH(`#v?*G#+1Gv~+Sq{8FV%|Z&Y2cgN#3DgpiS^K3-oB`6mo@0Il5ao;;Tz)#q7hrX4`1+mq4ZF^+l-oY0 zi!Mc8=+ZEhJsoWi)+om25L;BMbrlMA18gXagvl$7pz1Pj>ngjWy0{jFlkZ2qsf+BI zUH=&Ww~ooN)tf8-E@0- zzE=+Eu$u{U4RcEJuj2j^#ZZA)u=nC94~`$ma8~XFv$@@8c~krz|2{rH;rEe#`I^&-oWsaI}pD1SoY^?5%N^JTj zLyQidCnvOaoN}ReShnZuw_8<2I7#xzf~dx4w8Dieycki0Ig^A*Z(lkuHw22ie)A^s z4ExqlEuTuj&vgFePr*LjeX3M{p^)uI|6?Mq6Wpg1c2KnGd%Wj`h~3hh;}9c{`v~t(ZWGj(h;FZ&0xemS~P=6=VC@D>@RX2GrG|~8cjMR z#TTp5n3h&s{()eP_}lE<)@b%mA|)M?KZTgl^Z&7~bv^AfQoe=gIC3&l2LoUOfUAlA zPhx9gQLIsYJZ^_VeTgg0j5~~M-m^0Lh(aE3i`q%rQ3n>)hD0&JB4uGBQddT{a6YuO z6e26lk2N~5gbjv5Fpcx|eiqlE2dIhE$IFT%yV}9b$ogGyf8jmzwdh>@o}N1{2=>af zt5|><2G1IZ6oYZBoaRIwSOMs67%3(hRwx+VsibHOnUdBUZ1VgL7iweY%NC$ZfNtIE zq2zxT^5-b;LHm%#qgnbg_8S?==i|~%eYpeev7CIxdw#_oq2K$fTlP>W__IgWA2ezC z>x1};j$JwRBnlz+WsYQf%AWhm^7YXZI846Ah1{5LtjZTVn|iIbxdMtOax0@RlX$dR z|19pe=ny2%vs7autkmgbg(S!RlH4(qW{(PH7??=0LWhb@)1k5oekAt;I;~V$hQhcw zDYL_>b`|D2)5XOgbE~(tM47MOYLqU#)|jiF436c31piDZrO%Sp8HAFt(zKPuZ;x6L zKXfT>{b?an4}IQ?+XmnmjElVtvyYcPpI)WTX<(P-|FtObJ}VU=mjNN~IR`Yaiauk% zg1MI$@&28oDQlr7i)rJ~JbIEt5h9W-4@2x%AM(s|hiB4eb)T)`{^|;rny^E&6EplY zd%fXFA;oLVc%BNfL*aY*+dTI9nJA3Rm2I&>uTI&CO9=3Edkctci2*k=k+l#XJ8aXY zeSNn5rG%0qtG={47CTf@30D-HOz6s@ai3tOSpj`p?cQlEdv49+SW=Y^n6RX!C~{Xki81AQr)>^U!F)rfXkU?L)qQr2El8T zCbQWy+|Je8YYM<9Zy~QeezA~jXbREW50?iegl@yed+$UL`~C`hL$#u_|2+@uOsZ2? z{50KIYw45**;*DE6y_^VtJ&vZH!3&nw zMryQMPg_m8EP-(pub)F!5aIV6F#41i9Xi_kp+$xue*xJ7jzHQT2Sh5a5HOTm?JpjC z?aL-2twBkkGPWjqPq2rXujb(Qv?K_@0Yq}s+fz=~Hg*lP?;fADdsL1QiCeP|wZS={ z3k+1R6Iaef^Oh#$k-eHW zS|l^te4C;_)5QBsQQB0NvKFClY_RQPHMxKTPFq#w!+d{kt;MRQ`>A(( z?OnTG`SXFC>P{FCMLyK+$LYsva@v~E0!{BmnA@Zaw z{f_GG-dv?(mwHBiT*6OHo9w1&jl)`G85lc?wh%8WB$<}HECXrT7~=ZZX{xT}it7Gb_l&z+*P?)@5VS zrMlpU5Y|q|@|8E`&6L-)&SSw&Q3~zBnKe%6XOQt&}nJ+H@57z&uk9-<9jT)5{Ij(wqBcY=P`+%SR+?16PCJ*m*(0F%}a1Ej*HY zIz<-`n5tc0|gy)r~EY>8f_LGLoO2kLRpbKj0lsGIzbX~iRk zqoMO6*^8hT&L;GZ!OzD0z=lt}T~8*ADd6LP!WtN64A z&iPXi5>lC6_JG=7s4Wp$&AHJk$8NpY-zUUGfscXLIP5bcEz)_tKq3;M{?33KU`p>)kWZbBpX;Fn*zV%1qn3w88mq@j0Kw_n%j)V zkM778NbsF%=javXK4?QQ#h@0~0CEYU@wE039v+^GiJ(Sz!p!!vQQlz6nBV6cbsCGx zHq_rqtNzHlWDyNm=ixgfc`qUPAQ)5hBm@Kx|-)n3ijI()qD(k*chOAs!vDrw+?#`b?5d-Fc&BEQ+ z5wQ8NX$Cp?5l8!S7=gk(LwTsIDCI7BnQ{V=Ovt3+hnhcGw(U(U6%WajH~H^&iTsea zbF<;)@Tgmt5DYz%lMP z00ouYSRD`>(1+Xd(%kaWKAE9^A&o1W^(9j&dWKG@`Hagl<{ycnz1-VYDTyPneNH4B zZY=pbfGIZ7u;eq{2smOF6uNN!1)i(KZ^}gR2RxoGVctOliI`L0Y$nIzwb$J+xS$r- z90Lrjj{&rZ#0H8cpaYi+-~fp3YBO~Pj2FB>AS6{hSfC&U>fpx&Fmb=1?2>AUP^@qv zq3*Iu3I2m`Q&PcHzUECcT&a}g8Tx1zmuX1Jg{hR5of+Gf_^b%qoSj^)>MnVG@>=q= z);;LBPE8$oi$Zg~wRJ4yRna!PcyxYN=eGL$wh2>`Gg5hX66GFn_ZuK3Oggw%LGZ|& z{G>#Bw4JNUe_}XU9Im}Zl<91#&yRmRyU=ZrI?H)&nUUVlzjvV48KQJ2D83cXkA41C zaBMF?@Xa>IHiym@MJCEmJkr=1OTpNw`HCqjlCv$2og1jTw^$K!{QBKMA3Y{Y^Fi~7 zsJB<=oEC#qKHl|x9L@j)*2ry)Xa$#V#@7z1wL8Dy2O<#e)DQw0HUw0KYb2HH>|9B* zyPdXGbI$cLah&SduU|SyjYlSTbKA4B@U}TN|opa zHpOy|kFyc>BMAL~fb(@F#`G}yHG|A{JAtW2h3=*9czq);$2$CI?TNld{02@GvCZD1 z)FVR%dpr~l>>1dPY+?20)?aL`5WI?QqjgohI13$uENcn)MDU_}30vyLD^NI=Az+3} zXJw~{2<93&O#K%1&8COqA_WJA@j88@ovqn2tE{dTu}cU5^_a<%*G}0X`unh({8H^cQN(BZ#su8%fEx@NO_ZjNWN4ZH=b?>Cs zL>_08b1Z9^a%eTOW7w8hMW!*6mwe;HDwRLBHD$F~7aVb#iJQxvEFmXw7Xm8vU&!*r^T zg#^2$kfKLjaFnv_5|5+6jaWy}%wMlFQ6~K%38I(a6K;mnaN`KSn%O2{P*TR&9br6jkn`Hbq+N)69hq^RuB6`*+j(0?|iA0ks+ZUJc|s+3fO9pl`f0C3hQey(e2E! zG1kIN$S(I~YkMPTfCD7hbzq;$hOh_Ye{(SPLZ%xPuzPvB zXl!4N;n2*f20KzQUBHQE>M|i$EC&l(bnG-0l5uZ%$SI`8@!dp%NtLM9Hns1_`)^Em z!rfxM!Jp9gPsGJPMLA2Qt8~N1#Nzkly$9goIpeO_j*B%<<*2Ad&^?WCM1BM36?VgKo-B07NDX>q6=w{ivv~JfvnG<@z zR=AlP6DW2Z-$(Gl^e4$GBa#SZc1h~DP{C`WBOPs@=)MP}_N0m__m1z`J4eV*L~8)B zjNusOz)#zdVSy0{fg(S6*wm5eIol3#w0XAhzJ8r|zuO$$fm!Qs^S4E6|HkBRbp@I!S&SGe{Ix@?eNO2Q{;%rVBA(;SfWYQm^IV)Ep$dG=;{*hYt@Y+g zXZutU3drV8QS9IAoaOnK&VYh1&z!*}`<%0PeX*%0-E=`A?eZu-xLF1H*eJ6QS8A*d zrm(eUHY_I$A9&rd8kg<*2ufERu5tpKCx|sfq>~f*vDfa1&2BWB+GMr{mrPW`CA3?_ zR%uB3=e%_mJi<8` zU8|PU+6tR5A@qqnvI}*90U{)FD=P{_>ZA*1y((8oUn`cdRR=IQFG5P~bzAj=>5<}a z;dvyxXS|OS(GV@dGY0AS7PzHDJaOlw#glM zKJJewOIqMmQ~i+V+6%5+e7BFe4ttRIQKC3BFd&Mkfz(jij3UQ&{GwFLi8ICfJEh)zwmSGQkk7;Ry-u|s!*$+5*)tccG@~3?_BIR|3h?dWI2FX_?mIB6H&|)4hj6| zfQ242gWZd4Ua%~;9Iuw(#6*!OzdLHB=b z40|!=EcvH3Thm0hg|>)CT1-Mia;?EHp)$PX$cmUG3;O7Mrvu?jr1Xr_BG@pj5?IVq zZlKJB64OzEUgcD}C;b^-(>Pb!&`KNUCf+&Nmbfg9P6*%(qO#-*ymJ-?YoA#H8d+P* zK6%)@4C+)eo4Ix7m#>b)L$Ol>Bm`G#5oMYO4Ghuhb`k1tgv4WwpWyDRPb$`*yD#yY zf{KsGE`LB0x{2)YT&aqwF4Sxvei1J;;Qx{=J$Iw3qN?rZW%*XZgEYE#rvJq4W`eg+ z!u!3aZ{a7v_$`5Q@Yj@bAu2?+$LZSx$3nO4_(h(do?K%68{|-|n=Fmob0OL#+I&#>}rU z(JTc2zVgbemA-jUrudi@+rOD;I+VU58{(&0Z=@CkAdjHJX6fwY%Mg*|2;RnyqO98D zL<{^XS6bdQM&bj*eKA6m8P3>Y?t-{rOXygLQXCRgAwAd`7=caA+UGCwWHfEQf&fOtzwovF_XN^ZeUHe@VWL}J$ZEl5R_=gv!N0oiMXgtw5*@c?C>3(^CPC&raN(y0@^ zgeQy#A=yehlWxre>)Ta1;DLiDM4L>U4SS&&M|W268}3XPOV$0OOR57Ri7}C2?51(6 zlC&!^JG(qh`HHEjoT;3^w%O3kNAOusj1KENK2I1S)Xx_Jl|5{7S43{?s1sgL_ZzdF zfDS1;VwohRoewIcLa^yKv~1EULfP?U+&yi6Pw<{>{`^jC6!;aNo5%}oz~F4wn+fHK zO(&Pom?vJ^f$`$;Jmg zOGB25TAvElG9syq%u?!4I@|q&aGhtu4f8h_yn~^alnfOBWRBeV3*#QgVp&aeY9pJr zvYRW%J=Ng*ys>Ec?MMMHRh1KF+qcT8&;bDQ>JK@OArcP>{Byp^#b>B*L6w=gE(&BOm8*g?)1hvh5s;M4?Dm19+H% z6{-X3+NlV^0Ogr}OWQiw4RVDy#I5-pbtaiwxv{e)JMy=w{$0b%Ebml-5Ej$T(L%N8 zggR)lr{i zGjNEQmW0x2r{ZbyNh_#jN@SN$(BRijK@$&f$!p|6!s6rJZ)vrQ8ok`tY-{fK|K@)TQVvkSSVhS*=A}23ngdIrHgO_IvK>snFZGLcAxtwx6SB~X5E>3}po57YQ8+!k5I zwf?n_>MPLFe-#wH3GPnMH`P~CL>lAvPWv97(|*FH9d>b5+V1!m`o376LoSWa!d3{7 zGe4OzLaFS<~91l{_ zi)=dRXT;A-pDg%%a$2jP7NOqRJu*HLUhm3?fZy{n0HR&;JAmxF&~ z9^_Q)0|IA5?oq+2Weyqu@Nu@GrY3W=Lr0LbNsZrDq)x+8C(1?RyxwIx7q|kNWa}J@onNEK?Pjv$)K{ zV%_F%-Q-88F|>R(I2FYJUqwVBVwvHDSQDABxaS~ylt@zs_}dBt@`m?6(NR1pd9k`N zM>!&L2#xWw%}f2*`YI>>V3CL?GsBi1h=gYGLkv(6;EH?fT@c{PgA#W=1xsb9D3B87?2V49R_(W67Lmp^HJbp?1=~U!j){-Ak zg(ts&Hc07#qdvj_kg93_a|7YgJ`5pU*bl@2QN+aDyf8KuZ@588Oy}@cHaBbHnQ|^S zsdLI(eQ)w``Mhw_PE=FDhLSJU@d0d#oBtuc!%YTZpRZQPt|(%tEb_cVD6tE&`A4%jm_jO_me z(SMWQyz5b~<>FCd3bZ1LB8tSPA*b0qqCYYQc2q17g5!!U4Y0E7d-Se3PVE?UFT(|G zacP)w3U zpDT~)6Yg^cgeix?EK%iDEk+J(P$TTT#jKLmpaU;SBqKCt$NLY*Q-UEDq?b-SRHA_wILA;0Z(lUx<(^4%StnR|OG&R4SviKln`kp8eVZk>wslm&5hgi5 zjgO7Wo`@EzT!F-I4>L_UuxD??vP(~-VZ}Fd7Ua|8lcI&*cUEFRLW-ZWB>0iPgF4;` zO`yP;mr?-8@#nMX_?Oz8%!Ju-0;vCHKm*5oXn}^ANI?5ESb*w@(jNuVDb)JJI{l$! zy0ifGMP^g_P1>+N0!&J9OeC0R|)7Q%g)7hBrMo&$J9-bdjmJO&ktS8Q3k4}gWt z;ZAx8XManRI-UyPRJX*zN5K8ghIHzZb)Z zLRgFu9={`A{BC><6Oyq(v4uM*cnKpC=1M{K*^-jPEq|7wdOz}8w#tZ@qm;>?iMfvS zhe&-O#X^99R~`xbNQMZ9=dcu?-IsLY0~GPo(C-2Q%cgioPE7?jmqQ*c%*!wnCvG{k z*p`LGyFa!<1Roob9%u0s6Z_;0l$26u^M|6x(+LYK((`!Bv@h@+YP`dO_}t)Jb8c>!6HRATe4;Ec6v$ z5|)+^2~0GvB_e;s20n9#jM;b#Y;clUR~hw6oJ~i&v)*ClW#N=LvRIOcox#LrL(mEs zN<@sxtRpALbmgY*G=1zrX+INXxa)ek-u%go*^O!7JKtbE7o!x5sbo`Pof zBk>c8OSV6mNo9d{*QVa}g8A7ez(a=5?N-GH0IWTPX1_GbYUYCTM)P>_RnFRehU2iYe1+OurW9EBs& zQ+}cKHAWy0(Sk8rQgq%BYr=%HOPj`E$*vFe2O2rDk64Mnl8mjqS1}N-v&`7^e&CtW z8?b*i){e#<(h>aJV53SupI)etb3i zM^q?fs?UyScrtby){n))!em*Ot^!Y)I_$Di9Q;DhQf+8eYi%MXy!&#EZ>dmxSii4I5ne15Ee+6r zFTX|}SZIo0(?oQo*u+s8I!yL(DiHW`va<=$?=sM2@%Uy>1h}q|9%cIK#+B7&0l@X~ zUrGQ4PQa5^Ui^IirqFc6P^af3{+R@Ne6otDN*~h)l`6)(9?fe>3-;@CNl9&K=w>(x zY3#Kj*6$Ua%=p|^NO2B+XC~7Q1L# zaI+L&{kmL7LV)l7m{NW=$n0&ae@1gvwe+KwPn^Y-<0YGFs+;6!r=?){qnny`jk;Z|Id$LYKDU)46VGt1C%qq}ewv*DDR*_F z?i;~@ymqHMaQ;Edhj&Vi zYqtN~%l9)DuJ4mj-Pt&klF*9c?QVA9qc|igP4SgL7g=HFS=krAi$*Xw2o_`|k*Py- z4`u!{qjJ+)`9*_67HOZ3?=@SQpE}c5(7$3|K zE5!pjkXSaF=-A!4zJ&W|U?b8?HQFln0n#6yd>@m9=ck7C!5MCq z`S$mtoOaQ~fO$A{OvIk9&>o41pC@S5GC`3tm6Blq9JGQ@QRBh(*vS@e43Tc=pp!Fi z9Zzl@FF##ChF%eAx5%ICTkrWR;K(^<_Cd(mty6|}q<^9R^*IN9&+s#oWBQ~w=QYL_ zGF0}}h%HdN_(WU0dPlp9S$yT7f9lsIo3O+Ew8-l_5HPb9yA?Efl7Zfi14%pC0lLbd zS@WsBf%$}@Ko3id4mX#1C<3?jT?rH$xn)m2OyDO80qu}KvnDe-0O1Es`)y9Re4L~Y z=+*d-<2MCZa^9(#d=Hst-fMgu9nap+;D+do^d|4#sk|i*5J$ad&Cc5iiAa}Y%8&EQ z>SJc2anSWW``XCZakE{Wzu6uEfJMOY8nJQE6f3MAzD`;F6;!Mlbi~ZKUyRUgY%sim zVAkxL98fdJBvIiRQyI0xUO*+^g<+sA#`$4h4NbT1C~;X69S1OBW#hDmy~ItQP&UtH zX2&iw;Di_DArO$b%~=0&KcxGRX3n~B`~!Rc&Xs!0grSE1ds|K+BVDyO089H%ss!&? zQ&=*RB}tUfBr}BkozpUea9cZd(q@hrV{g|>xPI>Q2r>QWl|1(~G0g zKA=Awf2kN}SR<#Sl;)$X1;r#SH=f=j?XHU}!FOcF?jZN|Tm48?UwufPAQJfjO+XwK z--k3rm3CtveG>h5z;&^{LkeerRk7Na?A!igaS}}8ndHTpetMGgk|XDY=gowxM5Ybc zB7uZ0BggSLqFx#{Y#kkUX>?0XAk~G;e)PJF8{=*q4IgFuJ5s`5gDae7-uTYu5`FLK z7zr=e69OQ=R-u~w{+Qf%hZ4O||DBKY^Yg#v*ZR&%rxZ}{{swZU{a@D^FhG%M96*^m zXnClDCe#2@Jaw(Y&h=e~HAZj7Lf{%GLcn07LQb3J{0?Y1(ZOwK**%?&l{tt1y@jeM z8BHbZhiaOko1`~sPewgPfk ziQZZmY|vWsHC9_;J-Qa#bcQc<0RI|_I zyCMy($9kmBxaInERGy=bOwVt+yNm7J8@Blp9sXq9JP26RQ2Z4H z2s6SS>C&gf<9aTk&PayX`*R8v07)9`1Zg9V$LubEla zf<#486NK-J+{~f69ee$qb>0X`<-N0r4Y8=+8(>7Ikmt62dlra)%t!%{_9dNA7GwUJ z^ot2KdX%i!j7_`>Y3FOmu~g0@6&FR12mBZC3xqoiY>vVX(Yx`DNU?JDsz}<|jqnZj z@^@Jq41Ew;LP)hLQd=B(l3b!mJ`%^o?6B|L3TQc|J$?(lhm}2sDZj4zQY;5kAI7VD zILYkl9O-WdHMhjI)hIg4LbgNY^I?n;oqw39oc&Sf++5@U^r?YXv7c4f_ z91-Vpx0h%3gC^bFjCL-jj{Ghg+Cf~1tVz1R> zO|lKw-|O`Y_I2$@OyKMuLV|&L13Ues0Jf@_njllzYI}zo3t8mP_4BfUq6TncC8B7E z=y4d~wu#*H4T@S*GbVEjHs1ibBDv39W3_=v#n-y#_XW>iMDnJb+&;q5RDO3T{BSzl z1hSlM`jO>z{d9Hqi3Kd*;X|MHNM@dyfi#{I5k5W!jw#c+4wypY*m-yglT#_&JOCM= zU4w5HrgF?dwGT%4Gh3KqOhy!1J?}4~2K@Vzvnx;M5F;jYozH5$@7+ptzUj@VYS(C} zMz3VpSv07ZlxyRQvw-xSS=dUIJ-a{1@b0c~>zP@liw&i<5Om`k&09^&r@6>5s}Euf zrJB|?m+3U8@I)u%45JxLoTew$7Xox$TE^+PeAwv-LvpnjzUfq0L#1C(;h!9aDG|_- zinfGJdEkVIP0`JNGuoV!IzZ1kH!_tUS`(73ELT0X;QBK)1z>Xy@--3C7I zXVbEu#HUR2Q*j0vHYn`Iq-a19hcTy+z6bsuNhYx{P2UoLW{{^aPTlyn7tbBbJ8pji zy^(y_{h6l(whhe@qynkIe8QUh1;JZ z^3i+L8;_yrnaV4x!=!sztRE6E3?|s4W{vYoQ=^HRUQ3FwNW0L1=LUFyWBa%)e~H7V zdBx8S?>rZ+oh#B{KA4MRXS}Z|OklducV87SDAuS$aa&;Ae7t}$o!^>Ue?-0Q=uyn* zVWhasL6{PVf)31Uof<&R{(60R;~8tlV|iL+5Z((2X2DTD{{GA{>f@fhIAt8IFF~p+ z?x)`mYeHDa)%7vayBl8xP)AMJEz>xEdCvngF4I+64pe~QPl(RP+4oHi4^=e4$UK$y$-^A@FZ8Y}wNC0P(2c$7CT;#6F4J za>fMj(WtbWJsJheWT%~Em|b%;I_$e~GFjPhClR{Y6b?Deod+irqTXzM-1E|N@Yd@M zovw&;H9z3<&SFwI?5950GZ4)%=%qhIC-QTDV@^)ejo2vF$al3D5$1%w~U4|5VN)0dy{_abofiv2q`JbKogb zrKQB#!keLbwTN~%C+a#aG2e^aZAQ`v-@@L4mbJDECV^0vlUbxU8E4*m8B1#b-zNxr zuzqQRC2sclu{^6Sd{?GvW=^xCYj7P z;TZih#A_-Q=xFYdSBsn?M(A4_Gx2S9;}Exv$SMZf0hx0@CY=zr)dmFkYR9Sk-j%R~ z@LL?&5@u&(etX7Ltn~UGOwf2H)OH)4nv!Hkhl;2jpbo&~zSdPl^zu0VVv#E~uUjZ| zdb;KpbH8^=M$xL}`zxrdcXWj=$tKVXFVe!kkj35cy~^hHJxol8Y7{z zXOZC4AJ3i`)p$LWPU1t1%-nHW)##b6nSkmDoj;Ssz^L4&LQ-FTS?cyLtn5p!Y|gA4 zj3S}vtp@vKQ+#^iVx!(#zAqsUOr$lE>xQq0uYd>DAx7r_+*}_>kK}KnD+mImh+}TZ1%r zewXU-doL<>Q-b$Y4gpIcy^D1#yT;4)#@pPjriHKL$@>9?EJO-@G>mf+1A8JMOtxB# zCB$B#v(j%#kAp$HGsRB;qEE`*K{+Vw0fGch7Qi~4{%KmAY-l`lGFp$ye4xaGI$^XV zKEJ(++`5EbT@}aVOAekxHHjwIOlv>u%#qDgMKHAib5$hB8>V~0{kN|1F6awgLdJ-5 zHG@H5PxfSuqpuvdT00AZ(6W9=eUG&&8;$xGL$i8~h&ZIls6u*ab{1R&1np?vdpus0 zP{8J;87gzEoT3L6l45fbn`!skPif!E;bqxt7h8R>=@q*?7t(crYeVs^r8^Y(Q}62Z zTJ?X@79x|iIny5NqqQLs%eYl#T9T(XWH9rF>!y!fg>H6|Jumxj@0hm@WkCw zh++vu^4A$-3&Zyr9$)}6RHVePr-Nsazyo|Ufa?+^eli#|Y}AH2T}UJx&U~hUMk5pP z=8MgRpRD^6Ma`){2Prg;5T}1xbZIrLhwzr6mI6d`na&}(s2(J>aQ#T;?EYE2_$?{r zm=JTRI+rNAIKlYmwvYJEsh*U2WG8nXKd?r-;2m6)bg_J>l|__r3rE9SF49yW&mCZz zmm&vcjGjh9`5;cVqLg0S>Di`Owi6=y8)a^rh+S)jm_X84s!qCFeW8jb>$6a%r$Rpq#vMn!h{098@qW_`q2-@J&YzGd;K0l`Ihle@7DkR z?kW4{nV1$zd?ERO>qKJ>tV8P3$@dl_1fcBUnkM%NQRC*G-!Y%g0%C2ADbzgUaAuCr zguej1o(xaZ_a?%gCc1q(h(`E^*e{nj`fpV&e&-wZj-Y%j-wRz3hi|k8dy}IXyPnbu zUG|j^SA2fRsw0@q4^fhq4s!Hz^N?y#J#S8s!ZWOEPL$Rd4;*0Ci$>d)ys!ULMh6L# z1lKIQP;m3Z>wB~1st=en$epMpaIcT%|I^Pe`@8?~^NZ4tg8~kL1^L&wWdJGm1Ks*L zkpFy``<(J#1SDG>*wD`fh4bg9pZ$1Tk78+{FF!e&gA6tQx$@7?ps&F|Q^L!E_@6Tv z7#i54SUXT?fPnPh49NZ3e~v%Q!AsuQQ-O%Ku`ZbFDuSI53_P z8wh}f2eJ)fzQDb!!LwMPlo2F4C22qnyQDBv#IU7zdaTM0|u$!{v@?`tmOo> zAI5^J^>>AO!83;mU*tj+d#>n#d!5lbVU?p$@V8r}i z`IVh*pqc^|j1uHkn(mckKi(Jk=O`@j{TRWE zD*Y$FsKDROk2aRC#_6An|2VN01YNBP>MCsiy%uz?^-nbdI{XkJ`vbjl zR{RR0G67D6QUc8;FkirbyaI!P3BCf+OkcnsQ?xJOD~GGEKnx3@SQ-m(d4}l4$@Yt* zOY-qQ1MSK(Q%>7wB(SPoOcz^9rhW2KrA+y+E&A z;K(GXL<$umV&D3&EK8k)sEyVFsS0C;zgz@Ui#L{u8-eK z-*T&dX}eb2Tr;-uEN?KP3W!38emMqTiq)#rG<0!bYI-yv$2I zy?S1H1)Vm%NLJ242l`F@)y4l=I{&+lq*`BKB~OC?la0TZ0wC$HCxE36;Bg;0&N~HY V&}jHG \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +64,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +75,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +105,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -105,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` @@ -150,11 +170,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 8a0b282a..9618d8d9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -8,14 +24,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +62,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +75,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line From e53060c118c312447a1131580bbd53f9329f07ae Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 16 Oct 2019 12:31:24 +0200 Subject: [PATCH 064/122] Switch back to distribution all to allow IDE code completion and gradle source code navigation --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7c4388a9..ca9d6281 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 3d883aab008b7d3476ce88d4427fa90fe379a7a0 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Mon, 21 Oct 2019 15:14:49 +0200 Subject: [PATCH 065/122] Update to gradle 6 and migrate to new scan plugin --- build.gradle | 14 ----------- gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 58702 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 29 ++++++++++------------- settings.gradle | 11 +++++++++ 5 files changed, 24 insertions(+), 32 deletions(-) diff --git a/build.gradle b/build.gradle index ceb95ac8..e5f79841 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,3 @@ -apply plugin: 'com.gradle.build-scan' - buildscript { ext { // SDK and plugins @@ -8,7 +6,6 @@ buildscript { minSdkVersion = 14 targetSdkVersion = 29 androidGradleVersion = '3.6.0-beta01' - gradleScanVersion = '2.4.2' versioningPluginVersion = '1.0.2' // Library versions @@ -35,25 +32,14 @@ buildscript { includeModule 'org.jetbrains.trove4j', 'trove4j' } } - gradlePluginPortal() { - content { - includeModule 'com.gradle', 'build-scan-plugin' - } - } } dependencies { classpath "com.android.tools.build:gradle:$androidGradleVersion" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" - classpath "com.gradle:build-scan-plugin:$gradleScanVersion" classpath "eu.appcom.gradle:android-versioning:$versioningPluginVersion" } } -buildScan { - termsOfServiceUrl = 'https://gradle.com/terms-of-service' - termsOfServiceAgree = 'yes' -} - task clean(type: Delete) { delete rootProject.buildDir } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..cc4fdc293d0e50b0ad9b65c16e7ddd1db2f6025b 100644 GIT binary patch delta 16535 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 Date: Tue, 22 Oct 2019 01:27:21 +0200 Subject: [PATCH 066/122] Update material design components --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e5f79841..cd4bf333 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ buildscript { coreKtxVersion = '1.2.0-beta01' activityVersion = '1.1.0-beta01' lifecycleVersion = '2.2.0-beta01' - materialVersion = '1.1.0-beta01' + materialVersion = '1.2.0-alpha01' recyclerviewVersion = '1.1.0-beta05' vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta2' From 36182859870c4db4b048b716eacd944ae6912492 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 23 Oct 2019 11:48:55 +0200 Subject: [PATCH 067/122] Update dagger and remove field qualifier annotations --- .../developerwidget/controllers/DayNightControllerImpl.kt | 2 +- .../developerwidget/controllers/IntentControllerImpl.kt | 2 +- .../developerwidget/controllers/PermissionControllerImpl.kt | 2 +- .../developerwidget/controllers/StorageDirsControllerImpl.kt | 2 +- .../developerwidget/controllers/StringControllerImpl.kt | 2 +- .../g00fy2/developerwidget/controllers/ToastControllerImpl.kt | 2 +- .../controllers/WidgetPreferenceControllerImpl.kt | 4 ++-- .../com/g00fy2/developerwidget/data/DeviceDataSourceImpl.kt | 2 +- .../developerwidget/data/WidgetsPreferencesDataSourceImpl.kt | 2 +- build.gradle | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt index 5691a5dd..4310446b 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/DayNightControllerImpl.kt @@ -15,7 +15,7 @@ import javax.inject.Named class DayNightControllerImpl @Inject constructor() : DayNightController { @Inject - @field:Named(APPLICATION) + @Named(APPLICATION) lateinit var context: Context @Inject lateinit var toastController: ToastController diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/IntentControllerImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/IntentControllerImpl.kt index 69181dab..6d00d830 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/IntentControllerImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/IntentControllerImpl.kt @@ -20,7 +20,7 @@ import javax.inject.Named class IntentControllerImpl @Inject constructor() : IntentController { @Inject - @field:Named(ACTIVITY) + @Named(ACTIVITY) lateinit var context: Context @Inject lateinit var toastController: ToastController diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/PermissionControllerImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/PermissionControllerImpl.kt index cbc0d80c..a9340d52 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/PermissionControllerImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/PermissionControllerImpl.kt @@ -14,7 +14,7 @@ import javax.inject.Named class PermissionControllerImpl @Inject constructor() : PermissionController { @Inject - @field:Named(ACTIVITY) + @Named(ACTIVITY) lateinit var context: Context override fun hasPermission(permission: String): Boolean { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StorageDirsControllerImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StorageDirsControllerImpl.kt index 4dc20d65..ad0571dd 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StorageDirsControllerImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StorageDirsControllerImpl.kt @@ -18,7 +18,7 @@ import javax.inject.Named class StorageDirsControllerImpl @Inject constructor() : StorageDirsController { @Inject - @field:Named(ACTIVITY) + @Named(ACTIVITY) lateinit var context: Context /** diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StringControllerImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StringControllerImpl.kt index 14067b4b..52ca07ad 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StringControllerImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/StringControllerImpl.kt @@ -8,7 +8,7 @@ import javax.inject.Named class StringControllerImpl @Inject constructor() : StringController { @Inject - @field:Named(ACTIVITY) + @Named(ACTIVITY) lateinit var context: Context override fun getString(resId: Int): String = context.getString(resId) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/ToastControllerImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/ToastControllerImpl.kt index e345a95e..3d423498 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/ToastControllerImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/ToastControllerImpl.kt @@ -9,7 +9,7 @@ import javax.inject.Named class ToastControllerImpl @Inject constructor() : ToastController { @Inject - @field:Named(APPLICATION) + @Named(APPLICATION) lateinit var context: Context private var toast: Toast? = null diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/WidgetPreferenceControllerImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/WidgetPreferenceControllerImpl.kt index dc566074..b7b247a5 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/WidgetPreferenceControllerImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/controllers/WidgetPreferenceControllerImpl.kt @@ -10,10 +10,10 @@ import javax.inject.Named class WidgetPreferenceControllerImpl @Inject constructor() : WidgetPreferenceController { @Inject - @field:Named(ACTIVITY) + @Named(ACTIVITY) lateinit var context: Context @Inject - @field:Named(WIDGET_ID) + @Named(WIDGET_ID) lateinit var widgetId: String private val sharedPreference by lazy { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataSourceImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataSourceImpl.kt index 52eb877f..70c280b4 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataSourceImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/data/DeviceDataSourceImpl.kt @@ -17,7 +17,7 @@ import javax.inject.Named class DeviceDataSourceImpl @Inject constructor() : DeviceDataSource { @Inject - @field:Named(APPLICATION) + @Named(APPLICATION) lateinit var context: Context override suspend fun getStaticDeviceData(): Map { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/data/WidgetsPreferencesDataSourceImpl.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/data/WidgetsPreferencesDataSourceImpl.kt index a0868116..99ed443d 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/data/WidgetsPreferencesDataSourceImpl.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/data/WidgetsPreferencesDataSourceImpl.kt @@ -10,7 +10,7 @@ import javax.inject.Named class WidgetsPreferencesDataSourceImpl @Inject constructor() : WidgetsPreferencesDataSource { @Inject - @field:Named(APPLICATION) + @Named(APPLICATION) lateinit var context: Context override suspend fun getCustomDeviceNames(widgetIds: IntArray): SparseArray { diff --git a/build.gradle b/build.gradle index cd4bf333..a9a43eee 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ buildscript { vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta2' timberVersion = '4.7.1' - daggerVersion = '2.24' + daggerVersion = '2.25' versCompVersion = '1.3.3' } repositories { From 80a163ff135c94a287ddc91d20f8e2af8755a378 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 24 Oct 2019 00:49:33 +0200 Subject: [PATCH 068/122] Change companion modules with provide methods to objects --- .../appmanager/AppsActivityModule.kt | 23 +++++++++---------- .../WidgetConfigActivityModule.kt | 21 ++++++++--------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivityModule.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivityModule.kt index d0a46fd8..56d702d2 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivityModule.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivityModule.kt @@ -10,7 +10,7 @@ import dagger.Module import dagger.Provides import javax.inject.Named -@Module(includes = [ActivityModule::class]) +@Module(includes = [ActivityModule::class, WidgetIDModule::class]) abstract class AppsActivityModule { @Binds @@ -28,17 +28,16 @@ abstract class AppsActivityModule { @Binds @ActivityScope abstract fun provideAppInfoBuilder(appInfoBuilder: AppInfo.AppInfoBuilderImpl): AppInfo.AppInfoBuilder +} - @Module - companion object { - - @JvmStatic - @Provides - @ActivityScope - @Named(WIDGET_ID) - fun provideWidgetId(activity: AppsActivity): String { - return (activity.intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID) - ?: AppWidgetManager.INVALID_APPWIDGET_ID).toString() - } +@Module +object WidgetIDModule { + + @Provides + @ActivityScope + @Named(WIDGET_ID) + fun provideWidgetId(activity: AppsActivity): String { + return (activity.intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID) + ?: AppWidgetManager.INVALID_APPWIDGET_ID).toString() } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivityModule.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivityModule.kt index 082a7339..facaea1f 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivityModule.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivityModule.kt @@ -10,7 +10,7 @@ import dagger.Module import dagger.Provides import javax.inject.Named -@Module(includes = [ActivityModule::class]) +@Module(includes = [ActivityModule::class, WidgetIDModule::class]) abstract class WidgetConfigActivityModule { @Binds @@ -24,17 +24,16 @@ abstract class WidgetConfigActivityModule { @Binds @ActivityScope abstract fun provideWidgetConfigPresenter(presenter: WidgetConfigPresenterImpl): WidgetConfigContract.WidgetConfigPresenter +} - @Module - companion object { +@Module +object WidgetIDModule { - @JvmStatic - @Provides - @ActivityScope - @Named(WIDGET_ID) - fun provideWidgetId(activity: WidgetConfigActivity): String { - return (activity.intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID) - ?: AppWidgetManager.INVALID_APPWIDGET_ID).toString() - } + @Provides + @ActivityScope + @Named(WIDGET_ID) + fun provideWidgetId(activity: WidgetConfigActivity): String { + return (activity.intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID) + ?: AppWidgetManager.INVALID_APPWIDGET_ID).toString() } } \ No newline at end of file From a1c256513c9ba20b5365d56fc5924dec59b9a94a Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 24 Oct 2019 00:59:18 +0200 Subject: [PATCH 069/122] Update Android Studio and dependencies --- app/build.gradle | 1 + build.gradle | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 6811da08..5766e365 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -76,6 +76,7 @@ repositories { includeModule 'org.jetbrains.trove4j', 'trove4j' // required by com.android.tools.lint:lint-gradle } } + maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' } } dependencies { // Kotlin diff --git a/build.gradle b/build.gradle index a9a43eee..b8a9622c 100644 --- a/build.gradle +++ b/build.gradle @@ -5,18 +5,18 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '3.6.0-beta01' + androidGradleVersion = '4.0.0-alpha01' versioningPluginVersion = '1.0.2' // Library versions - kotlinVersion = '1.3.50' + kotlinVersion = '1.3.60-eap-25' coroutinesVersion = '1.3.2' appcompatVersion = '1.1.0' coreKtxVersion = '1.2.0-beta01' - activityVersion = '1.1.0-beta01' - lifecycleVersion = '2.2.0-beta01' + activityVersion = '1.1.0-rc01' + lifecycleVersion = '2.2.0-rc01' materialVersion = '1.2.0-alpha01' - recyclerviewVersion = '1.1.0-beta05' + recyclerviewVersion = '1.1.0-rc01' vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta2' timberVersion = '4.7.1' @@ -32,6 +32,7 @@ buildscript { includeModule 'org.jetbrains.trove4j', 'trove4j' } } + maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' } } dependencies { classpath "com.android.tools.build:gradle:$androidGradleVersion" From a64f3858a87af6aaeb88f1ef12d493f3796efcf3 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 24 Oct 2019 01:04:55 +0200 Subject: [PATCH 070/122] Update deps --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b8a9622c..12dcec17 100644 --- a/build.gradle +++ b/build.gradle @@ -18,9 +18,9 @@ buildscript { materialVersion = '1.2.0-alpha01' recyclerviewVersion = '1.1.0-rc01' vectorDrawableVersion = '1.1.0' - constraintlayoutVersion = '2.0.0-beta2' + constraintlayoutVersion = '2.0.0-beta3' timberVersion = '4.7.1' - daggerVersion = '2.25' + daggerVersion = '2.25.2' versCompVersion = '1.3.3' } repositories { From 3c6f7a3944bf51610708b1e7192771a8c155f18a Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 24 Oct 2019 15:08:53 +0200 Subject: [PATCH 071/122] Downgrade kotlin to fix kapt issues --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 12dcec17..0928abc8 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { versioningPluginVersion = '1.0.2' // Library versions - kotlinVersion = '1.3.60-eap-25' + kotlinVersion = '1.3.50' coroutinesVersion = '1.3.2' appcompatVersion = '1.1.0' coreKtxVersion = '1.2.0-beta01' From 63f57890ea9b2cc24f5ac52a22f7077e9fa80085 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 31 Oct 2019 19:34:03 +0100 Subject: [PATCH 072/122] Update gradle --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3c1bf7ea..aaaa7e54 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-rc-1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-rc-2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 2538024df665a485633a4f58a753eaa58c6d20f9 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 31 Oct 2019 19:34:39 +0100 Subject: [PATCH 073/122] Update kotlin and add javax annotation to fix kapt on java9+ jvm --- app/build.gradle | 7 +------ build.gradle | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 5766e365..fe1fd581 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -59,12 +59,6 @@ android { kotlinOptions { jvmTarget = '1.8' } - kapt { - javacOptions { - option('-source', '8') - option('-target', '8') - } - } } repositories { @@ -105,4 +99,5 @@ dependencies { implementation "com.google.dagger:dagger-android:$daggerVersion" implementation "com.google.dagger:dagger-android-support:$daggerVersion" kapt "com.google.dagger:dagger-android-processor:$daggerVersion" + compileOnly "javax.annotation:javax.annotation-api:1.3.2" } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 0928abc8..12dcec17 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { versioningPluginVersion = '1.0.2' // Library versions - kotlinVersion = '1.3.50' + kotlinVersion = '1.3.60-eap-25' coroutinesVersion = '1.3.2' appcompatVersion = '1.1.0' coreKtxVersion = '1.2.0-beta01' From 4ba5eebcffc00365fb650a6fab214393f7da8dd8 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 31 Oct 2019 19:51:32 +0100 Subject: [PATCH 074/122] Update kotlin eap and cleanup build files --- app/build.gradle | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index fe1fd581..16a43f01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -99,5 +99,5 @@ dependencies { implementation "com.google.dagger:dagger-android:$daggerVersion" implementation "com.google.dagger:dagger-android-support:$daggerVersion" kapt "com.google.dagger:dagger-android-processor:$daggerVersion" - compileOnly "javax.annotation:javax.annotation-api:1.3.2" + compileOnly 'javax.annotation:javax.annotation-api:1.3.2' } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 12dcec17..a83ad577 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { versioningPluginVersion = '1.0.2' // Library versions - kotlinVersion = '1.3.60-eap-25' + kotlinVersion = '1.3.60-eap-76' coroutinesVersion = '1.3.2' appcompatVersion = '1.1.0' coreKtxVersion = '1.2.0-beta01' From 62949e0a2b607abbc399a0a3fb54010d10d36b76 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 31 Oct 2019 22:10:15 +0100 Subject: [PATCH 075/122] Try using canary cmdline-tools --- .travis.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 457a9a2a..be27a3ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,8 @@ git: depth: false env: global: - # for updates check developer.android.com/studio#downloads (current 26.1.1) - - ANDROID_SDK_TOOLS=sdk-tools-linux-4333796.zip + # for updates check (dl.google.com/android/repository/repository2-1.xml) + - ANDROID_SDK_CMD_TOOLS=commandlinetools-linux-5842447_latest.zip # storepass, keypass, keyalias - secure: K4PVOrcYr6ZV16GgZWcw5RGDqxRTrilMK6pjz1r+RkQX6EPywmTsUH0y8EGP44bZc+TFMM0UfGPulHfrKzC3LDVSe+CpvNdQqq8c2Ysc9lQLubvFmVlWZ2rjHhA3jtg33FDIAWipb41WZEdmCJE1EI+OMbh8p8/7cGZ4K4tpd3B8ViXrf16ht50C56glL1lS3Jog/g9OEIPdhzYF23nYPOAeV3xJg3WBGxUUMOwp3vrpMJ/bYvnh/XLHUpPWnCcSWhKZolE3C6Itlv3CUdCyd2u8dnbTFX7KK0g4nrJdXJAyith0aE2RB6APdDDIdZkF3p2qU3aWBWVvNzjGc6tYpP9OB8sjobcx9oG8lIaO09qZnM+fLTs5b3ulvl8d3UZI0KxgSocvjxpltrqeuNODGarzwIWAmjxKr3Qnfo5LFUna1UMxKJ1ARyT7zS9yUbfE6ek42aEe7rEaqryjNFE5X6b9D2WexN+68YynvdRfDXlFx2JIW3hWTi7AG4zBI0LKhhtruwLY1hKty3JR5/Dz/dIMW6JZUmLdE7drPmLNBcKRh1H778EOcaD+1q1bzVnwbA+HLfHkO9Rzmk7UOY1ttWzFBH23W/pI6D6mn4WTFng0/iOEsw7fwHaXPGv6ZXxserC/nzmeYb0AfK3wq2p2ztEDtbSblw9lkMBYlvNi5I8= - secure: SEcF7dl6ImTdeUYtw6dGeHRXbS4h8Ec9+Dnt2rFeobupo4e64818Fo10Uqqf+eM/5VVF2FAJLnEiq1SgfWZKjvUz9batJZNknc2JSKEGQPFaUD55USFCt2rxoLPFJKIee07kPTiXGPM2WWA+42cD+HpXAErMTd3BESsGwjni+xj2PhJuETDGrw+0D5T4TOXgd0uXNPl4p1PE+l3SejPqGQ961Wo+hbxd/y9JyZy/jZ9WW8XA6eEXXtecRY33NspwT58mBXDgZLIM/C3W0qfrGCiOPxwk0RpMo7YMbmYVPLG75AzihDtQ2F7P5edHz7v0yCAejrN23hi1LHb4Uku8tC2jzrH5eUpKfZuqap8DRcbdXq5je3oeuLSUu39FrzsDEmennS0eaD4jTsB5Sy2wld/UCmzV0QenUtPdBaFLU2Rxos3xJW4a2KyENRm5TGVNR/NAWpoacLed3zqDmb3K13WwskTGE1/mXRl+o0T0BVOBXuHXQ+nqATnGuAbw97LhhOeBZ/jA2yWBsaTxdjhB3E3uKWYZYdGIIgOwrZdM0RrVSgepg7NP+vh9iO70ckEzP+w4yws2ElKE3ZiOexEmrkFmqlxQW08b1FMaKJwpfsNiHkwW6u1jq1oeEBIzUrAMmo92uAjDAHKfn7FOsx5RVg20EKP9Rk9l2YKRA5dGJFI= @@ -22,18 +22,17 @@ cache: android_phases: - phase: &before_install # download and unzip Android SDK command line tools - - wget -nv https://dl.google.com/android/repository/$ANDROID_SDK_TOOLS - - unzip -q $ANDROID_SDK_TOOLS -d $HOME/sdk - # add deprecated java ee module to jdk10 to run the sdkmanager - - export JAVA_OPTS="-XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee" + - wget -nv https://dl.google.com/android/repository/$ANDROID_SDK_CMD_TOOLS + - unzip -q $ANDROID_SDK_CMD_TOOLS -d $HOME/sdk/cmdline-tools # set SDK tools path variable and ANDROID_HOME - - export PATH=$PATH:$HOME/sdk/tools/bin + - export PATH=$PATH:$HOME/sdk/cmdline-tools/tools/bin - export ANDROID_HOME=$HOME/sdk # create empty cfg file to prevent sdkmanager warning message - mkdir -p $HOME/.android && touch $HOME/.android/repositories.cfg # decrypt private keystore - openssl aes-256-cbc -K $encrypted_a8fbd6bbc21d_key -iv $encrypted_a8fbd6bbc21d_iv -in keystore.jks.enc -out keystore.jks -d - phase: &install + - sdkmanager --version # accept licenses for all available packages that have not already been accepted - yes | sdkmanager --licenses >/dev/null - phase: &before_script From d27ec19b956a40b00ab2c375c0bbbc7f46f6db6b Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 31 Oct 2019 22:23:20 +0100 Subject: [PATCH 076/122] Fix unpacking --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index be27a3ad..af24e26a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ android_phases: - phase: &before_install # download and unzip Android SDK command line tools - wget -nv https://dl.google.com/android/repository/$ANDROID_SDK_CMD_TOOLS + - mkdir -p $HOME/sdk/cmdline-tools - unzip -q $ANDROID_SDK_CMD_TOOLS -d $HOME/sdk/cmdline-tools # set SDK tools path variable and ANDROID_HOME - export PATH=$PATH:$HOME/sdk/cmdline-tools/tools/bin From 85126cfb1a27f8b799213aefd4b254a1687b2469 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 31 Oct 2019 23:28:55 +0100 Subject: [PATCH 077/122] Cleanup travis file and use default jdk11 --- .travis.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index af24e26a..9d7b75f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: java os: linux dist: bionic group: edge -jdk: openjdk10 git: depth: false env: @@ -23,17 +22,13 @@ android_phases: - phase: &before_install # download and unzip Android SDK command line tools - wget -nv https://dl.google.com/android/repository/$ANDROID_SDK_CMD_TOOLS - - mkdir -p $HOME/sdk/cmdline-tools - - unzip -q $ANDROID_SDK_CMD_TOOLS -d $HOME/sdk/cmdline-tools + - mkdir -p $HOME/sdk/cmdline-tools && unzip -q $ANDROID_SDK_CMD_TOOLS -d $HOME/sdk/cmdline-tools # set SDK tools path variable and ANDROID_HOME - export PATH=$PATH:$HOME/sdk/cmdline-tools/tools/bin - export ANDROID_HOME=$HOME/sdk - # create empty cfg file to prevent sdkmanager warning message - - mkdir -p $HOME/.android && touch $HOME/.android/repositories.cfg # decrypt private keystore - openssl aes-256-cbc -K $encrypted_a8fbd6bbc21d_key -iv $encrypted_a8fbd6bbc21d_iv -in keystore.jks.enc -out keystore.jks -d - phase: &install - - sdkmanager --version # accept licenses for all available packages that have not already been accepted - yes | sdkmanager --licenses >/dev/null - phase: &before_script From 3af1a5856656f284d348576b24b05521ada85a38 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 31 Oct 2019 23:50:49 +0100 Subject: [PATCH 078/122] Add empty sdkmanager cfg file to travis config again --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9d7b75f6..a3d6adc6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,8 @@ android_phases: # set SDK tools path variable and ANDROID_HOME - export PATH=$PATH:$HOME/sdk/cmdline-tools/tools/bin - export ANDROID_HOME=$HOME/sdk + # create empty cfg file to prevent sdkmanager warning message + - mkdir -p $HOME/.android && touch $HOME/.android/repositories.cfg # decrypt private keystore - openssl aes-256-cbc -K $encrypted_a8fbd6bbc21d_key -iv $encrypted_a8fbd6bbc21d_iv -in keystore.jks.enc -out keystore.jks -d - phase: &install From afa8f64416ddb56aec1b34e9725c44a4b435d509 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 5 Nov 2019 16:35:31 +0100 Subject: [PATCH 079/122] Set CI specific kotlin compiler flags --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index a3d6adc6..4c077d33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,6 +38,10 @@ android_phases: - chmod +x gradlew # create dir for gradle settings - mkdir -p $HOME/.gradle + # disable kotlin incremental compilation + - echo "kotlin.incremental=false" >> $HOME/.gradle/gradle.properties + # disable kotlin compiler daemon + - echo "kotlin.compiler.execution.strategy=in-process" >> $HOME/.gradle/gradle.properties # disable gradle daemon for current user - echo "org.gradle.daemon=false" >> $HOME/.gradle/gradle.properties # set gradle log format to plain From 8e8d16144c983c35008569f8295021573dde72dc Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 6 Nov 2019 09:31:52 +0100 Subject: [PATCH 080/122] Update gradle --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aaaa7e54..9b977254 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-rc-2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-rc-3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 89e9a292c57e0573964797a87a4b5dd0f1ca03c8 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Fri, 8 Nov 2019 09:04:04 +0100 Subject: [PATCH 081/122] Update android studio and dependencies --- build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index a83ad577..7ca55fa7 100644 --- a/build.gradle +++ b/build.gradle @@ -5,16 +5,16 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '4.0.0-alpha01' + androidGradleVersion = '4.0.0-alpha02' versioningPluginVersion = '1.0.2' // Library versions kotlinVersion = '1.3.60-eap-76' coroutinesVersion = '1.3.2' appcompatVersion = '1.1.0' - coreKtxVersion = '1.2.0-beta01' - activityVersion = '1.1.0-rc01' - lifecycleVersion = '2.2.0-rc01' + coreKtxVersion = '1.2.0-beta02' + activityVersion = '1.1.0-rc02' + lifecycleVersion = '2.2.0-rc02' materialVersion = '1.2.0-alpha01' recyclerviewVersion = '1.1.0-rc01' vectorDrawableVersion = '1.1.0' From b7332a5a69be261003fb0463b9212648fd82ea8b Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Fri, 8 Nov 2019 21:34:37 +0100 Subject: [PATCH 082/122] Update gradle --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9b977254..562e2c88 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-rc-3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 8ea517e464cc3ef6c9b7eded86e6dfda460cdfff Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 14 Nov 2019 21:44:07 +0100 Subject: [PATCH 083/122] Update android studio --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7ca55fa7..e9b37b10 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '4.0.0-alpha02' + androidGradleVersion = '4.0.0-alpha03' versioningPluginVersion = '1.0.2' // Library versions From bbc1595da61c3efd68ce99d3f3a1b38e77489bdb Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Mon, 18 Nov 2019 15:38:48 +0100 Subject: [PATCH 084/122] Cleanup travis yaml based on travis config validation --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4c077d33..7e0a8943 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,19 +66,18 @@ android_phases: - ls -d $HOME/.gradle/wrapper/dists/* -1t | tail -n +2 | xargs rm -rf - phase: &deploy provider: releases - api_key: + token: secure: J5U/QxYAcGZn/pZeU8+YK7ani5dn64McDEVj5BxTBbywfhfpabzug+6H8k6Mnvs8m8CEvi2NsgptyvsxMt6952dNFI9F0URRsDkDdBvKQKdBmhCmCWVckRushfrn5k8RTjpJFYExiuDw6mSPZVtVzdXgHTgiZzPW20skROgoOq6Jb2CMa9awyI1Pbni7Emirkdl3N+h8krCyi/T06va1QebbWYsdLem8EvPgREBV+fDZ8RR+ABnT68aV7Jyq5YWortThT0TRAQ5f17C/T/aDWU7TqL4+HbfGEMvlO4vFYKUHNhxB6ZssaOpLSRVZKq4kecr2PQWIzQX+VFo4Fyxe3kTqfgidR2ptihkAERFz5FCHsEDDSRliatUUFpXxNLaa4ZIooo5p5uThRniu9COjdwuJZtFUIqstL1IrLntv4+3P2SY2BfdsTkgSuq7NT37u6MbT/cdr+dO7jgCoRIyxRzQGoeViALjzwIdXS2iBCwEpex9IDdvjsHmFJIo+8IsJGeGUCRsJL0tFBtZ8lIks1bh+t7pxKywhS3vXGny2ZCaIdA55g0b5N0D64P12ibWI80B7EAEv43Xmb5oVkVYdq9PdPJFoG/b4nDy8NfbQCWv9P/xgP6KwogAPsCJJ7tS4qn2HV6eUKrsj7ioBwpHsn/3ZEL0gU3sBnGJk20hyZyc= file_glob: true file: - $TRAVIS_BUILD_DIR/app/build/outputs/apk/release/*.apk - $TRAVIS_BUILD_DIR/app/build/outputs/mapping/release/mapping.txt - skip_cleanup: true draft: false on: tags: true name: $TRAVIS_TAG tag_name: $TRAVIS_TAG - body: "Generated release from Travis CI for build $TRAVIS_BUILD_NUMBER" + release_notes: "Generated release from Travis CI for build $TRAVIS_BUILD_NUMBER" prerelease: true jobs: From cb05d8898c81d6ba220640a37032b8b5df381452 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Mon, 18 Nov 2019 16:28:43 +0100 Subject: [PATCH 085/122] Switch to dpl v2 preview and remove default option --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7e0a8943..33ac0cf2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,9 +66,9 @@ android_phases: - ls -d $HOME/.gradle/wrapper/dists/* -1t | tail -n +2 | xargs rm -rf - phase: &deploy provider: releases + edge: true token: secure: J5U/QxYAcGZn/pZeU8+YK7ani5dn64McDEVj5BxTBbywfhfpabzug+6H8k6Mnvs8m8CEvi2NsgptyvsxMt6952dNFI9F0URRsDkDdBvKQKdBmhCmCWVckRushfrn5k8RTjpJFYExiuDw6mSPZVtVzdXgHTgiZzPW20skROgoOq6Jb2CMa9awyI1Pbni7Emirkdl3N+h8krCyi/T06va1QebbWYsdLem8EvPgREBV+fDZ8RR+ABnT68aV7Jyq5YWortThT0TRAQ5f17C/T/aDWU7TqL4+HbfGEMvlO4vFYKUHNhxB6ZssaOpLSRVZKq4kecr2PQWIzQX+VFo4Fyxe3kTqfgidR2ptihkAERFz5FCHsEDDSRliatUUFpXxNLaa4ZIooo5p5uThRniu9COjdwuJZtFUIqstL1IrLntv4+3P2SY2BfdsTkgSuq7NT37u6MbT/cdr+dO7jgCoRIyxRzQGoeViALjzwIdXS2iBCwEpex9IDdvjsHmFJIo+8IsJGeGUCRsJL0tFBtZ8lIks1bh+t7pxKywhS3vXGny2ZCaIdA55g0b5N0D64P12ibWI80B7EAEv43Xmb5oVkVYdq9PdPJFoG/b4nDy8NfbQCWv9P/xgP6KwogAPsCJJ7tS4qn2HV6eUKrsj7ioBwpHsn/3ZEL0gU3sBnGJk20hyZyc= - file_glob: true file: - $TRAVIS_BUILD_DIR/app/build/outputs/apk/release/*.apk - $TRAVIS_BUILD_DIR/app/build/outputs/mapping/release/mapping.txt From f5ce8f57adccbf0cad3586d614f71aedffae6493 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 19 Nov 2019 00:32:43 +0100 Subject: [PATCH 086/122] Update gradle --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 562e2c88..1ba7206f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 9852f86d0ec0cf68c8b0900cfd03526944e67315 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 19 Nov 2019 00:33:29 +0100 Subject: [PATCH 087/122] Update kotlin to 1.3.60 and force transitive android plugin dependency version --- app/build.gradle | 1 - build.gradle | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 16a43f01..66e8630d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -70,7 +70,6 @@ repositories { includeModule 'org.jetbrains.trove4j', 'trove4j' // required by com.android.tools.lint:lint-gradle } } - maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' } } dependencies { // Kotlin diff --git a/build.gradle b/build.gradle index e9b37b10..be41a7fa 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { versioningPluginVersion = '1.0.2' // Library versions - kotlinVersion = '1.3.60-eap-76' + kotlinVersion = '1.3.60' coroutinesVersion = '1.3.2' appcompatVersion = '1.1.0' coreKtxVersion = '1.2.0-beta02' @@ -32,13 +32,17 @@ buildscript { includeModule 'org.jetbrains.trove4j', 'trove4j' } } - maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' } } dependencies { classpath "com.android.tools.build:gradle:$androidGradleVersion" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" classpath "eu.appcom.gradle:android-versioning:$versioningPluginVersion" } + configurations.all { + resolutionStrategy { + force "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion" + } + } } task clean(type: Delete) { From 00a384eb634bddab5c7a8ecb63a8ecd54ef542b9 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 21 Nov 2019 01:36:57 +0100 Subject: [PATCH 088/122] Update android studio --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index be41a7fa..cd4080e5 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '4.0.0-alpha03' + androidGradleVersion = '4.0.0-alpha04' versioningPluginVersion = '1.0.2' // Library versions From 94bfe1e4374bc47b0da7c0062fb185b298c8de76 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 21 Nov 2019 02:02:40 +0100 Subject: [PATCH 089/122] Update dependencies --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index cd4080e5..8a70f486 100644 --- a/build.gradle +++ b/build.gradle @@ -12,11 +12,11 @@ buildscript { kotlinVersion = '1.3.60' coroutinesVersion = '1.3.2' appcompatVersion = '1.1.0' - coreKtxVersion = '1.2.0-beta02' + coreKtxVersion = '1.2.0-rc01' activityVersion = '1.1.0-rc02' lifecycleVersion = '2.2.0-rc02' materialVersion = '1.2.0-alpha01' - recyclerviewVersion = '1.1.0-rc01' + recyclerviewVersion = '1.1.0' vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta3' timberVersion = '4.7.1' From 17176aa9e079ac3d9efdbe1003bf13d8df1674f3 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Mon, 25 Nov 2019 18:05:14 +0100 Subject: [PATCH 090/122] Update gradle --- gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 58798 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index cc4fdc293d0e50b0ad9b65c16e7ddd1db2f6025b..6d183c6b6f1b37f3fb960b68d8b1386b3e010383 100644 GIT binary patch delta 7979 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 delta 7862 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1ba7206f..780eeaa3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-milestone-1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 4faa3b7ba0267dba5f4b9f3bc0e071f2c04bcf7f Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Mon, 25 Nov 2019 18:14:26 +0100 Subject: [PATCH 091/122] Update material design components --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8a70f486..ffc2cf33 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ buildscript { coreKtxVersion = '1.2.0-rc01' activityVersion = '1.1.0-rc02' lifecycleVersion = '2.2.0-rc02' - materialVersion = '1.2.0-alpha01' + materialVersion = '1.2.0-alpha02' recyclerviewVersion = '1.1.0' vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta3' From 9b36d20876db13ddc2bb3b580e51ae33eaded434 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 26 Nov 2019 02:07:33 +0100 Subject: [PATCH 092/122] Rearrange initView methods and optimize config activity init --- .../activities/about/AboutActivity.kt | 32 +++++++++---------- .../activities/apkinstall/ApkActivity.kt | 20 ++++++------ .../widgetconfig/WidgetConfigActivity.kt | 23 +++++++------ .../res/layout/activity_widget_config.xml | 3 +- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt index 661318f6..1c802785 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt @@ -32,22 +32,6 @@ class AboutActivity : BaseActivity(), AboutContract.AboutView { return binding } - override fun onResume() { - super.onResume() - updateThemeToggleView() - updateLauncherIconSwitch() - updateLauncherIconItem() - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return if (item.itemId == id.home) { - finish() - true - } else { - super.onOptionsItemSelected(item) - } - } - override fun initView() { supportActionBar?.setDisplayHomeAsUpEnabled(true) setActionbarElevationListener(binding.aboutRootScrollview) @@ -138,6 +122,22 @@ class AboutActivity : BaseActivity(), AboutContract.AboutView { } } + override fun onResume() { + super.onResume() + updateThemeToggleView() + updateLauncherIconSwitch() + updateLauncherIconItem() + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return if (item.itemId == id.home) { + finish() + true + } else { + super.onOptionsItemSelected(item) + } + } + override fun updateThemeToggleView() { binding.themeItem.let { when (dayNightController.getCurrentDefaultMode()) { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt index 5fc1284c..446eba38 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/apkinstall/ApkActivity.kt @@ -26,16 +26,6 @@ class ApkActivity : BaseActivity(true), ApkContract.ApkView { return binding } - override fun onResume() { - super.onResume() - if (adapter.itemCount == 0) { - binding.progressbar.visibility = View.VISIBLE - binding.noItemsImageview.visibility = View.INVISIBLE - binding.noItemsTextview.text = getString(R.string.scanning_apks) - binding.noItemsTextview.visibility = View.VISIBLE - } - } - override fun initView() { adapter = ApkAdapter() adapter.setOnApkClicked { apkFile -> presenter.installApk(apkFile) } @@ -61,6 +51,16 @@ class ApkActivity : BaseActivity(true), ApkContract.ApkView { } } + override fun onResume() { + super.onResume() + if (adapter.itemCount == 0) { + binding.progressbar.visibility = View.VISIBLE + binding.noItemsImageview.visibility = View.INVISIBLE + binding.noItemsTextview.text = getString(R.string.scanning_apks) + binding.noItemsTextview.visibility = View.VISIBLE + } + } + override fun toggleResultView(apkFiles: List, missingPermissions: Boolean) { if (missingPermissions) { binding.progressbar.visibility = View.GONE diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index 74f83b64..219a9481 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -71,16 +71,6 @@ class WidgetConfigActivity : BaseActivity(), WidgetConfigContract.WidgetConfigVi return binding } - override fun onResume() { - super.onResume() - resetView() - } - - override fun onDestroy() { - super.onDestroy() - if (VERSION.SDK_INT >= VERSION_CODES.O) unregisterReceiver(closeConfigureActivityReceiver) - } - override fun initView() { setResult(Activity.RESULT_CANCELED) @@ -150,7 +140,16 @@ class WidgetConfigActivity : BaseActivity(), WidgetConfigContract.WidgetConfigVi view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) } } - resetView() + } + + override fun onResume() { + super.onResume() + updateWidgetButton() + } + + override fun onDestroy() { + super.onDestroy() + if (VERSION.SDK_INT >= VERSION_CODES.O) unregisterReceiver(closeConfigureActivityReceiver) } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -200,7 +199,7 @@ class WidgetConfigActivity : BaseActivity(), WidgetConfigContract.WidgetConfigVi return super.dispatchTouchEvent(event) } - private fun resetView() { + private fun updateWidgetButton() { val showAddWidget = (!launchedFromAppLauncher || (widgetCount() < 1 && isPinAppWidgetSupported())) if (showAddWidget) { binding.applyButton.apply { diff --git a/app/src/main/res/layout/activity_widget_config.xml b/app/src/main/res/layout/activity_widget_config.xml index 1d8b715d..94af6f91 100644 --- a/app/src/main/res/layout/activity_widget_config.xml +++ b/app/src/main/res/layout/activity_widget_config.xml @@ -108,7 +108,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" - android:visibility="invisible" + android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:tint="@color/backgroundColor" @@ -116,6 +116,7 @@ app:backgroundTint="@color/colorAccent" app:fabCustomSize="40dp" app:srcCompat="@drawable/ic_share" + tools:visibility="visible" /> Date: Tue, 26 Nov 2019 02:23:52 +0100 Subject: [PATCH 093/122] Force latest kotlin version for transitive build tools dependencies --- app/build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 66e8630d..ae8c5391 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -59,6 +59,12 @@ android { kotlinOptions { jvmTarget = '1.8' } + configurations.all { + resolutionStrategy { + force "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion" + force "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion" + } + } } repositories { From 001549723230f4bf73cb90a6cea435da1bca2658 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 26 Nov 2019 09:11:52 +0100 Subject: [PATCH 094/122] Revert fab visibility to fix missing show animation --- app/src/main/res/layout/activity_widget_config.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/res/layout/activity_widget_config.xml b/app/src/main/res/layout/activity_widget_config.xml index 94af6f91..1d8b715d 100644 --- a/app/src/main/res/layout/activity_widget_config.xml +++ b/app/src/main/res/layout/activity_widget_config.xml @@ -108,7 +108,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" - android:visibility="gone" + android:visibility="invisible" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:tint="@color/backgroundColor" @@ -116,7 +116,6 @@ app:backgroundTint="@color/colorAccent" app:fabCustomSize="40dp" app:srcCompat="@drawable/ic_share" - tools:visibility="visible" /> Date: Wed, 27 Nov 2019 09:50:24 +0100 Subject: [PATCH 095/122] Update kotlin --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ffc2cf33..7d8409e6 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { versioningPluginVersion = '1.0.2' // Library versions - kotlinVersion = '1.3.60' + kotlinVersion = '1.3.61' coroutinesVersion = '1.3.2' appcompatVersion = '1.1.0' coreKtxVersion = '1.2.0-rc01' From c4fabd02480c76fa853f9765283f20cbf7047e43 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 28 Nov 2019 01:17:04 +0100 Subject: [PATCH 096/122] Add licence report gradle plugin --- build.gradle | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 7d8409e6..04c1645b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,9 @@ +import com.android.tools.r8.Version +import com.github.jk1.license.filter.* +import com.github.jk1.license.render.* + +apply plugin: 'com.github.jk1.dependency-license-report' + buildscript { ext { // SDK and plugins @@ -7,6 +13,7 @@ buildscript { targetSdkVersion = 29 androidGradleVersion = '4.0.0-alpha04' versioningPluginVersion = '1.0.2' + licenseReportVersion = '1.11' // Library versions kotlinVersion = '1.3.61' @@ -32,11 +39,13 @@ buildscript { includeModule 'org.jetbrains.trove4j', 'trove4j' } } + gradlePluginPortal() } dependencies { classpath "com.android.tools.build:gradle:$androidGradleVersion" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" classpath "eu.appcom.gradle:android-versioning:$versioningPluginVersion" + classpath "com.github.jk1:gradle-license-report:$licenseReportVersion" } configurations.all { resolutionStrategy { @@ -45,14 +54,19 @@ buildscript { } } +licenseReport { + configurations = ['releaseRuntimeClasspath'] + renderers = [new SimpleHtmlReportRenderer(), new JsonReportRenderer()] + filters = [new LicenseBundleNormalizer()] +} + task clean(type: Delete) { delete rootProject.buildDir } task printR8Version() { try { - //noinspection UnnecessaryQualifiedReference - println "R8 version: " + com.android.tools.r8.Version.getVersionString() + println "R8 version: " + Version.getVersionString() } catch (ignored) { println 'R8 version: unknown' } From c68cf1951d4242bc9317b1ddb1edc30137386628 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Fri, 29 Nov 2019 09:20:16 +0100 Subject: [PATCH 097/122] Update gradle --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 780eeaa3..c5d9e945 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-milestone-1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-milestone-2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 8c61f418dd539d7a2d96ea89193b6fb05438551a Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 5 Dec 2019 17:07:49 +0100 Subject: [PATCH 098/122] Update Android Studio and gradle --- app/build.gradle | 6 ------ build.gradle | 7 +------ gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index ae8c5391..66e8630d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -59,12 +59,6 @@ android { kotlinOptions { jvmTarget = '1.8' } - configurations.all { - resolutionStrategy { - force "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion" - force "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion" - } - } } repositories { diff --git a/build.gradle b/build.gradle index 04c1645b..a9749918 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '4.0.0-alpha04' + androidGradleVersion = '4.0.0-alpha05' versioningPluginVersion = '1.0.2' licenseReportVersion = '1.11' @@ -47,11 +47,6 @@ buildscript { classpath "eu.appcom.gradle:android-versioning:$versioningPluginVersion" classpath "com.github.jk1:gradle-license-report:$licenseReportVersion" } - configurations.all { - resolutionStrategy { - force "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion" - } - } } licenseReport { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c5d9e945..5434f1fe 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-milestone-2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-milestone-3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From ea6e0278e6d41d0c9425975bfc3ed54aaf9d7cbc Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 7 Dec 2019 13:53:58 +0100 Subject: [PATCH 099/122] Migrate to new buildfeature config --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 66e8630d..cab961bd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -36,8 +36,8 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } - viewBinding { - enabled = true + buildFeatures { + viewBinding = true } versioning { baseName = 'developerwidget' From 457659180ff41e061d13001beb214bf489c14491 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Sat, 7 Dec 2019 13:54:12 +0100 Subject: [PATCH 100/122] Update dependencies --- build.gradle | 6 +++--- settings.gradle | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index a9749918..56e2199d 100644 --- a/build.gradle +++ b/build.gradle @@ -18,10 +18,10 @@ buildscript { // Library versions kotlinVersion = '1.3.61' coroutinesVersion = '1.3.2' - appcompatVersion = '1.1.0' + appcompatVersion = '1.2.0-alpha01' coreKtxVersion = '1.2.0-rc01' - activityVersion = '1.1.0-rc02' - lifecycleVersion = '2.2.0-rc02' + activityVersion = '1.1.0-rc03' + lifecycleVersion = '2.2.0-rc03' materialVersion = '1.2.0-alpha02' recyclerviewVersion = '1.1.0' vectorDrawableVersion = '1.1.0' diff --git a/settings.gradle b/settings.gradle index 537d7e9a..2c8b87ff 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ plugins { - id 'com.gradle.enterprise' version '3.0' + id 'com.gradle.enterprise' version '3.1' } gradleEnterprise { From 5183ba0c19a467d665b0615f4de91c8b3a84d5df Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 10 Dec 2019 12:37:32 +0100 Subject: [PATCH 101/122] Move gradle settings to command line options --- .travis.yml | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index 33ac0cf2..52c4502d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,31 +36,18 @@ android_phases: - phase: &before_script # set executable flag for gradle wrapper - chmod +x gradlew - # create dir for gradle settings - - mkdir -p $HOME/.gradle - # disable kotlin incremental compilation - - echo "kotlin.incremental=false" >> $HOME/.gradle/gradle.properties - # disable kotlin compiler daemon - - echo "kotlin.compiler.execution.strategy=in-process" >> $HOME/.gradle/gradle.properties - # disable gradle daemon for current user - - echo "org.gradle.daemon=false" >> $HOME/.gradle/gradle.properties - # set gradle log format to plain - - echo "org.gradle.console=plain" >> $HOME/.gradle/gradle.properties - # enable gradle build cache - - echo "org.gradle.caching=true" >> $HOME/.gradle/gradle.properties - # log all gradle warnings - - echo "org.gradle.warning.mode=all" >> $HOME/.gradle/gradle.properties - phase: &before_cache - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ - - rm -f $HOME/.gradle/caches/*/fileHashes/fileHashes.bin - - rm -f $HOME/.gradle/caches/*/fileHashes/fileHashes.lock - - rm -f $HOME/.gradle/caches/*/javaCompile/javaCompile.lock - - rm -f $HOME/.gradle/caches/*/executionHistory/executionHistory.lock - - rm -f $HOME/.gradle/caches/journal-1/file-access.bin - - rm -f $HOME/.gradle/caches/journal-1/journal-1.lock - - rm -f $HOME/.gradle/caches/transforms-1/transforms-1.lock - - rm -f $HOME/.gradle/caches/user-id.txt.lock + - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock + - rm -rf $HOME/.gradle/caches/*/plugin-resolution/ + - rm -f $HOME/.gradle/caches/*/fileHashes/fileHashes.bin + - rm -f $HOME/.gradle/caches/*/fileHashes/fileHashes.lock + - rm -f $HOME/.gradle/caches/*/javaCompile/javaCompile.lock + - rm -f $HOME/.gradle/caches/*/executionHistory/executionHistory.bin + - rm -f $HOME/.gradle/caches/*/executionHistory/executionHistory.lock + - rm -f $HOME/.gradle/caches/journal-1/file-access.bin + - rm -f $HOME/.gradle/caches/journal-1/journal-1.lock + - rm -f $HOME/.gradle/caches/transforms-1/transforms-1.lock + - rm -f $HOME/.gradle/caches/user-id.txt.lock # only cache latest gradle version used by the wrapper # list content in wrapper/dist sorted by modification time and remove entries starting by the second entry - ls -d $HOME/.gradle/wrapper/dists/* -1t | tail -n +2 | xargs rm -rf @@ -87,13 +74,13 @@ jobs: before_install: *before_install install: *install before_script: *before_script - script: "./gradlew assembleDebug --scan" + script: "./gradlew assembleDebug --no-daemon --build-cache --console=plain --warning-mode=all --scan" before_cache: *before_cache - # Build and deploy release on tags if: tag IS present before_install: *before_install install: *install before_script: *before_script - script: "./gradlew assembleRelease -Pmy_storepass=$storepass -Pmy_keyalias=$keyalias -Pmy_keypass=$keypass --scan" + script: "./gradlew assembleRelease -Pmy_storepass=$storepass -Pmy_keyalias=$keyalias -Pmy_keypass=$keypass --no-daemon --no-build-cache --console=plain --warning-mode=all --scan" before_cache: *before_cache deploy: *deploy \ No newline at end of file From 39572b7210f62f39e1083d38e035d6ecc269d66c Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 10 Dec 2019 21:28:14 +0100 Subject: [PATCH 102/122] Update android studio --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 56e2199d..6b9cd24f 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '4.0.0-alpha05' + androidGradleVersion = '4.0.0-alpha06' versioningPluginVersion = '1.0.2' licenseReportVersion = '1.11' From e78784592b1ad775ec85b35265924042ceacc295 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Tue, 17 Dec 2019 00:42:39 +0100 Subject: [PATCH 103/122] Update dependencies --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6b9cd24f..26c5c1be 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ buildscript { materialVersion = '1.2.0-alpha02' recyclerviewVersion = '1.1.0' vectorDrawableVersion = '1.1.0' - constraintlayoutVersion = '2.0.0-beta3' + constraintlayoutVersion = '2.0.0-beta4' timberVersion = '4.7.1' daggerVersion = '2.25.2' versCompVersion = '1.3.3' From 811e4e568a92c3811505c00f613a5203d459d5ac Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Fri, 20 Dec 2019 12:23:07 +0100 Subject: [PATCH 104/122] Update gradle and recyclerview version --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 26c5c1be..47defb9f 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ buildscript { activityVersion = '1.1.0-rc03' lifecycleVersion = '2.2.0-rc03' materialVersion = '1.2.0-alpha02' - recyclerviewVersion = '1.1.0' + recyclerviewVersion = '1.2.0-alpha01' vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta4' timberVersion = '4.7.1' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5434f1fe..9bd8801f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-milestone-3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-rc-1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 2918d68a109f28dcb277f7fd4bc90c7d4b794ab2 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 25 Dec 2019 13:37:22 +0100 Subject: [PATCH 105/122] Update android studio --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 47defb9f..287ee5ba 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '4.0.0-alpha06' + androidGradleVersion = '4.0.0-alpha07' versioningPluginVersion = '1.0.2' licenseReportVersion = '1.11' From 9e89af93f080d450871962cde76a375d376816f4 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 25 Dec 2019 13:39:09 +0100 Subject: [PATCH 106/122] Remove constraint layout namespace workaround --- app/src/main/res/values/attrs.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 78bed956..5afcdcaf 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -3,12 +3,4 @@ false false 300 - - - - - - - - \ No newline at end of file From 7525d691b624bb2c0949b83ea6f4b6a2bd0b2f98 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 25 Dec 2019 13:43:01 +0100 Subject: [PATCH 107/122] Remove fab from scrollview and add fab inset logic --- .../activities/about/AboutActivity.kt | 2 +- .../shortcut/CreateShortcutActivity.kt | 2 +- .../widgetconfig/WidgetConfigActivity.kt | 9 +- .../developerwidget/base/BaseActivity.kt | 2 +- .../developerwidget/ktx/ViewExtension.kt | 35 ++- .../res/layout/activity_widget_config.xml | 236 +++++++++--------- 6 files changed, 160 insertions(+), 126 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt index 1c802785..fee33b96 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt @@ -108,7 +108,7 @@ class AboutActivity : BaseActivity(), AboutContract.AboutView { action { presenter.honorClicking() } } if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) { - binding.aboutRootScrollview.doOnApplyWindowInsets { view, insets, padding -> + binding.aboutRootScrollview.doOnApplyWindowInsets { view, insets, padding, _ -> view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) } binding.aboutRootScrollview.apply { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt index 458b7d30..7aa08ea5 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/shortcut/CreateShortcutActivity.kt @@ -64,7 +64,7 @@ class CreateShortcutActivity : BaseActivity(), CreateShortcutContract.CreateShor adapter.submitList(shortcutInfoList) adapter.setOnShortcutSelected { shortcutPosition -> onItemClick(shortcutPosition) } if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) { - binding.recyclerview.doOnApplyWindowInsets { view, insets, padding -> + binding.recyclerview.doOnApplyWindowInsets { view, insets, padding, _ -> view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index 219a9481..670d11bb 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -26,7 +26,6 @@ import android.webkit.WebView import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.getSystemService import androidx.core.content.res.ResourcesCompat -import androidx.core.view.marginBottom import androidx.core.view.updatePadding import androidx.recyclerview.widget.LinearLayoutManager import androidx.viewbinding.ViewBinding @@ -40,6 +39,7 @@ import com.g00fy2.developerwidget.ktx.doOnApplyWindowInsets import com.g00fy2.developerwidget.ktx.gesturalNavigationMode import com.g00fy2.developerwidget.ktx.hideKeyboard import com.g00fy2.developerwidget.ktx.showKeyboard +import com.g00fy2.developerwidget.ktx.updateMargin import com.g00fy2.developerwidget.receiver.widget.WidgetProviderImpl import javax.inject.Inject @@ -89,7 +89,7 @@ class WidgetConfigActivity : BaseActivity(), WidgetConfigContract.WidgetConfigVi binding.widgetConfigRootScrollview.apply { viewTreeObserver.addOnScrollChangedListener { val scrollableRange = getChildAt(0).bottom - height + paddingBottom - val fabOffset = (binding.shareFab.height / 2) + binding.shareFab.marginBottom + val fabOffset = binding.shareFab.height + (12 * resources.displayMetrics.density).toInt() if (scrollY < scrollableRange - fabOffset) { binding.shareFab.hide() } else { @@ -136,9 +136,12 @@ class WidgetConfigActivity : BaseActivity(), WidgetConfigContract.WidgetConfigVi } binding.shareFab.setOnClickListener { presenter.shareDeviceData() } if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) { - binding.widgetConfigRootScrollview.doOnApplyWindowInsets { view, insets, padding -> + binding.widgetConfigRootScrollview.doOnApplyWindowInsets { view, insets, padding, _ -> view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) } + binding.shareFab.doOnApplyWindowInsets { view, insets, _, margin -> + view.updateMargin(bottom = margin.bottom + insets.systemWindowInsetBottom) + } } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt index e43fbfbc..d3543620 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseActivity.kt @@ -82,7 +82,7 @@ abstract class BaseActivity(private val isDialogActivity: Boolean = false) : Dag } } findViewById(Window.ID_ANDROID_CONTENT)?.let { - it.doOnApplyWindowInsets { view, insets, padding -> + it.doOnApplyWindowInsets { view, insets, padding, _ -> view.updatePadding(top = padding.top + insets.systemWindowInsetTop) } } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt index 52f74ec1..b49dcb11 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewExtension.kt @@ -4,8 +4,14 @@ import android.os.Build.VERSION import android.os.Build.VERSION_CODES import android.util.TypedValue import android.view.View +import android.view.ViewGroup import android.view.WindowInsets +import androidx.annotation.Px import androidx.annotation.RequiresApi +import androidx.core.view.marginBottom +import androidx.core.view.marginLeft +import androidx.core.view.marginRight +import androidx.core.view.marginTop fun View.addRipple(asForeground: Boolean = false) { TypedValue().apply { context.theme.resolveAttribute(android.R.attr.selectableItemBackground, this, true) } @@ -15,21 +21,44 @@ fun View.addRipple(asForeground: Boolean = false) { } } +fun View.updateMargin( + @Px left: Int = marginLeft, + @Px top: Int = marginTop, + @Px right: Int = marginRight, + @Px bottom: Int = marginBottom +) { + val params = layoutParams as ViewGroup.MarginLayoutParams + params.leftMargin = left + params.topMargin = top + params.rightMargin = right + params.bottomMargin = bottom + layoutParams = params +} + @RequiresApi(VERSION_CODES.KITKAT_WATCH) -fun View.doOnApplyWindowInsets(f: (View, WindowInsets, InitialPadding) -> Unit) { +fun View.doOnApplyWindowInsets(f: (View, WindowInsets, InitialPadding, InitialMargin) -> Unit) { val initialPadding = recordInitialPaddingForView(this) + val initialMargin = recordInitialMarginForView(this) setOnApplyWindowInsetsListener { v, insets -> - f(v, insets, initialPadding) + f(v, insets, initialPadding, initialMargin) insets } } - data class InitialPadding( val left: Int, val top: Int, val right: Int, val bottom: Int ) +data class InitialMargin( + val left: Int, val top: Int, + val right: Int, val bottom: Int +) + private fun recordInitialPaddingForView(view: View) = InitialPadding( view.paddingLeft, view.paddingTop, view.paddingRight, view.paddingBottom +) + +private fun recordInitialMarginForView(view: View) = InitialMargin( + view.marginLeft, view.marginTop, view.marginRight, view.marginBottom ) \ No newline at end of file diff --git a/app/src/main/res/layout/activity_widget_config.xml b/app/src/main/res/layout/activity_widget_config.xml index 1d8b715d..fcfc1f88 100644 --- a/app/src/main/res/layout/activity_widget_config.xml +++ b/app/src/main/res/layout/activity_widget_config.xml @@ -1,128 +1,130 @@ - - - - - - - - - - - - - - + > + + + + + + + + + + + \ No newline at end of file From 6880c18b2111052a57ae470b1fa9cee8a4c04c06 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 25 Dec 2019 19:17:18 +0100 Subject: [PATCH 108/122] Adjust dark mode background color to current google apps --- app/src/main/res/values-night-v29/colors.xml | 9 +-------- app/src/main/res/values-night/colors.xml | 2 +- app/src/main/res/values-v23/colors.xml | 2 +- app/src/main/res/values-v29/colors.xml | 1 - app/src/main/res/values/colors.xml | 4 ++-- 5 files changed, 5 insertions(+), 13 deletions(-) diff --git a/app/src/main/res/values-night-v29/colors.xml b/app/src/main/res/values-night-v29/colors.xml index 12d6bbd9..380e35d8 100644 --- a/app/src/main/res/values-night-v29/colors.xml +++ b/app/src/main/res/values-night-v29/colors.xml @@ -1,12 +1,5 @@ - @color/black - @color/black - - @color/transparent - - #1f1f1f - @color/black - @color/white + @color/transparent diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index ce3e1389..049f3aed 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -6,7 +6,7 @@ @color/nightBackground #80212121 - #3c3c3c + #5f6368 #A6000000 #a0a0a0 diff --git a/app/src/main/res/values-v23/colors.xml b/app/src/main/res/values-v23/colors.xml index c13100a8..0b50ed03 100644 --- a/app/src/main/res/values-v23/colors.xml +++ b/app/src/main/res/values-v23/colors.xml @@ -1,4 +1,4 @@ - #e8eaed + @color/colorPrimary diff --git a/app/src/main/res/values-v29/colors.xml b/app/src/main/res/values-v29/colors.xml index 189c302e..e0023ee1 100644 --- a/app/src/main/res/values-v29/colors.xml +++ b/app/src/main/res/values-v29/colors.xml @@ -1,6 +1,5 @@ - @color/black #8ab4f8 @color/colorAccent diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 39743700..2efaa95e 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -35,8 +35,8 @@ @color/lighterGrey #33808080 - #212121 - #262728 + #202124 + @color/nightBackground #2581df #313235 From 60a7c953bc5829d7da5441c7a358a09dc2a8683e Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 25 Dec 2019 19:38:14 +0100 Subject: [PATCH 109/122] Add app bundle task and deployment, move gradle settings and cache control to before_script --- .travis.yml | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 52c4502d..2ce33f6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,6 +36,24 @@ android_phases: - phase: &before_script # set executable flag for gradle wrapper - chmod +x gradlew + # create dir for gradle settings + - mkdir -p $HOME/.gradle + # disable gradle daemon for current user + - echo "org.gradle.daemon=false" >> $HOME/.gradle/gradle.properties + # set gradle log format to plain + - echo "org.gradle.console=plain" >> $HOME/.gradle/gradle.properties + # log all gradle warnings + - echo "org.gradle.warning.mode=all" >> $HOME/.gradle/gradle.properties + # control gradle build cache + - if [[ $TRAVIS_TAG == "" ]]; then + echo "org.gradle.caching=true" >> $HOME/.gradle/gradle.properties; + echo "android.enableBuildCache=true" >> $HOME/.gradle/gradle.properties; + echo "Build cache enabled"; + else + echo "org.gradle.caching=false" >> $HOME/.gradle/gradle.properties; + echo "android.enableBuildCache=false" >> $HOME/.gradle/gradle.properties; + echo "Build cache disabled"; + fi - phase: &before_cache - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - rm -rf $HOME/.gradle/caches/*/plugin-resolution/ @@ -57,6 +75,7 @@ android_phases: token: secure: J5U/QxYAcGZn/pZeU8+YK7ani5dn64McDEVj5BxTBbywfhfpabzug+6H8k6Mnvs8m8CEvi2NsgptyvsxMt6952dNFI9F0URRsDkDdBvKQKdBmhCmCWVckRushfrn5k8RTjpJFYExiuDw6mSPZVtVzdXgHTgiZzPW20skROgoOq6Jb2CMa9awyI1Pbni7Emirkdl3N+h8krCyi/T06va1QebbWYsdLem8EvPgREBV+fDZ8RR+ABnT68aV7Jyq5YWortThT0TRAQ5f17C/T/aDWU7TqL4+HbfGEMvlO4vFYKUHNhxB6ZssaOpLSRVZKq4kecr2PQWIzQX+VFo4Fyxe3kTqfgidR2ptihkAERFz5FCHsEDDSRliatUUFpXxNLaa4ZIooo5p5uThRniu9COjdwuJZtFUIqstL1IrLntv4+3P2SY2BfdsTkgSuq7NT37u6MbT/cdr+dO7jgCoRIyxRzQGoeViALjzwIdXS2iBCwEpex9IDdvjsHmFJIo+8IsJGeGUCRsJL0tFBtZ8lIks1bh+t7pxKywhS3vXGny2ZCaIdA55g0b5N0D64P12ibWI80B7EAEv43Xmb5oVkVYdq9PdPJFoG/b4nDy8NfbQCWv9P/xgP6KwogAPsCJJ7tS4qn2HV6eUKrsj7ioBwpHsn/3ZEL0gU3sBnGJk20hyZyc= file: + - $TRAVIS_BUILD_DIR/app/build/outputs/bundle/release/*.aab - $TRAVIS_BUILD_DIR/app/build/outputs/apk/release/*.apk - $TRAVIS_BUILD_DIR/app/build/outputs/mapping/release/mapping.txt draft: false @@ -74,13 +93,15 @@ jobs: before_install: *before_install install: *install before_script: *before_script - script: "./gradlew assembleDebug --no-daemon --build-cache --console=plain --warning-mode=all --scan" + script: "./gradlew assembleDebug --scan" before_cache: *before_cache - # Build and deploy release on tags if: tag IS present before_install: *before_install install: *install before_script: *before_script - script: "./gradlew assembleRelease -Pmy_storepass=$storepass -Pmy_keyalias=$keyalias -Pmy_keypass=$keypass --no-daemon --no-build-cache --console=plain --warning-mode=all --scan" + script: + - "./gradlew assembleRelease -Pmy_storepass=$storepass -Pmy_keyalias=$keyalias -Pmy_keypass=$keypass --scan" + - "./gradlew :app:bundleRelease -Pmy_storepass=$storepass -Pmy_keyalias=$keyalias -Pmy_keypass=$keypass" before_cache: *before_cache deploy: *deploy \ No newline at end of file From 0e63c29ccf66db797b0fd531c258d07c17a818a4 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 26 Dec 2019 16:14:58 +0100 Subject: [PATCH 110/122] Update dependencies --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 287ee5ba..02d5baba 100644 --- a/build.gradle +++ b/build.gradle @@ -22,12 +22,12 @@ buildscript { coreKtxVersion = '1.2.0-rc01' activityVersion = '1.1.0-rc03' lifecycleVersion = '2.2.0-rc03' - materialVersion = '1.2.0-alpha02' + materialVersion = '1.2.0-alpha03' recyclerviewVersion = '1.2.0-alpha01' vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta4' timberVersion = '4.7.1' - daggerVersion = '2.25.2' + daggerVersion = '2.25.3' versCompVersion = '1.3.3' } repositories { From e0012fd6f0a83cee93294694aa5f1c7784cb2946 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 26 Dec 2019 16:22:58 +0100 Subject: [PATCH 111/122] Adjust dayNight theme to fit current google look and remove api 29 specific night style --- app/src/main/res/drawable-night/ic_about.xml | 4 +- app/src/main/res/layout/activity_apps.xml | 2 +- app/src/main/res/layout/filter_chip.xml | 2 +- .../main/res/menu-v29/configuration_menu.xml | 10 ----- app/src/main/res/values-night-v29/colors.xml | 5 --- app/src/main/res/values-night-v29/styles.xml | 21 --------- app/src/main/res/values-night/colors.xml | 12 +++--- app/src/main/res/values-night/styles.xml | 12 ++++++ app/src/main/res/values-v29/colors.xml | 3 -- app/src/main/res/values/colors.xml | 43 +++++++++++-------- app/src/main/res/values/styles.xml | 6 +++ 11 files changed, 52 insertions(+), 68 deletions(-) delete mode 100644 app/src/main/res/menu-v29/configuration_menu.xml delete mode 100644 app/src/main/res/values-night-v29/colors.xml delete mode 100644 app/src/main/res/values-night-v29/styles.xml diff --git a/app/src/main/res/drawable-night/ic_about.xml b/app/src/main/res/drawable-night/ic_about.xml index 85057128..9771b2e1 100644 --- a/app/src/main/res/drawable-night/ic_about.xml +++ b/app/src/main/res/drawable-night/ic_about.xml @@ -4,9 +4,9 @@ android:viewportWidth="24" android:width="24dp"> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_apps.xml b/app/src/main/res/layout/activity_apps.xml index 9c5c8513..1973a67a 100644 --- a/app/src/main/res/layout/activity_apps.xml +++ b/app/src/main/res/layout/activity_apps.xml @@ -90,7 +90,7 @@ android:paddingRight="24dp" android:paddingTop="12dp" android:singleLine="true" - android:textColor="@color/filterTextColor" + android:textColorHint="@color/textTertiary" /> \ No newline at end of file diff --git a/app/src/main/res/menu-v29/configuration_menu.xml b/app/src/main/res/menu-v29/configuration_menu.xml deleted file mode 100644 index 5d67a5d3..00000000 --- a/app/src/main/res/menu-v29/configuration_menu.xml +++ /dev/null @@ -1,10 +0,0 @@ - -

- - \ No newline at end of file diff --git a/app/src/main/res/values-night-v29/colors.xml b/app/src/main/res/values-night-v29/colors.xml deleted file mode 100644 index 380e35d8..00000000 --- a/app/src/main/res/values-night-v29/colors.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - @color/white - @color/transparent - diff --git a/app/src/main/res/values-night-v29/styles.xml b/app/src/main/res/values-night-v29/styles.xml deleted file mode 100644 index 5abf5817..00000000 --- a/app/src/main/res/values-night-v29/styles.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 049f3aed..2d8a0912 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -4,19 +4,17 @@ @color/nightPrimary @color/nightAccent + @color/nightTextPrimary + @color/nightTextTertiary + @color/nightBackground - #80212121 + @color/transparentBackground50_night #5f6368 - #A6000000 + #A6202124 #a0a0a0 #1ffafafa - @color/white - @color/white - #b3b3b3 - @color/nightGrey - #e4e4e5 #33000000 diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml index 56beb7f1..f689c799 100644 --- a/app/src/main/res/values-night/styles.xml +++ b/app/src/main/res/values-night/styles.xml @@ -7,4 +7,16 @@ false + + + + diff --git a/app/src/main/res/values-v29/colors.xml b/app/src/main/res/values-v29/colors.xml index e0023ee1..5400cbc3 100644 --- a/app/src/main/res/values-v29/colors.xml +++ b/app/src/main/res/values-v29/colors.xml @@ -1,8 +1,5 @@ - #8ab4f8 - - @color/colorAccent @color/transparent @color/transparent diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 2efaa95e..cbd330a9 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,16 +1,18 @@ - #F8F9FA + #F8F8F8 #999999 @color/originalAccent - #1a73e8 + + @color/dayTextPrimary + @color/dayTextTertiary @color/white @color/white @color/nightBackground - #80ffffff + @color/transparentBackground50_day #80ffffff - #80212121 + #80202124 @color/lighterGrey @color/black @@ -18,27 +20,32 @@ @color/black #33303030 - @color/lightGrey - @color/lightGrey - @color/white - @color/lightGrey - @color/lightGrey - @color/white - @color/lightGrey + @color/textTertiary + @color/dayTextTertiary + @color/nightTextPrimary + @color/textTertiary + @color/dayTextTertiary + @color/nightTextPrimary + @color/textTertiary + + @color/lighterGrey + #33808080 + + #00000000 #ffffff #000000 - #808080 #e0e0e0 + #1a73e8 - @color/black - @color/lighterGrey - #33808080 - + #202124 + #5f6368 + #e8eaed + #9aa0a6 #202124 @color/nightBackground - #2581df - #313235 + #8ab4f8 + #3c4043 #1a73e8 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 7ce3e2e1..6e2d40d9 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -6,6 +6,9 @@ @color/colorPrimaryDark @color/colorAccent + @color/textPrimary + @color/textTertiary + @color/backgroundColor @style/ActionBarAccent @style/ActionBarBackground @@ -37,6 +40,9 @@ @color/colorPrimaryDark @color/colorAccent + @color/textPrimary + @color/textTertiary + true @drawable/bg_dialog_shape false From c968cc3bee9984787ec17e535a29194cc48fef8f Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 26 Dec 2019 17:10:17 +0100 Subject: [PATCH 112/122] Fix feedback dialog --- .../developerwidget/activities/about/AboutFeedbackDialog.kt | 2 +- app/src/main/res/layout/about_feedback_dialog.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutFeedbackDialog.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutFeedbackDialog.kt index 3bd995ea..5fc55e7b 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutFeedbackDialog.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutFeedbackDialog.kt @@ -12,7 +12,7 @@ class AboutFeedbackDialog(context: Context) { setCancelable(true) setCanceledOnTouchOutside(true) binding = AboutFeedbackDialogBinding.inflate(layoutInflater) - setContentView(R.layout.about_feedback_dialog) + setContentView(binding.root) } fun mailAction(mailIssueAction: () -> Unit): AboutFeedbackDialog { diff --git a/app/src/main/res/layout/about_feedback_dialog.xml b/app/src/main/res/layout/about_feedback_dialog.xml index 2e469b28..2670aa83 100644 --- a/app/src/main/res/layout/about_feedback_dialog.xml +++ b/app/src/main/res/layout/about_feedback_dialog.xml @@ -2,14 +2,14 @@ Date: Thu, 26 Dec 2019 17:40:22 +0100 Subject: [PATCH 113/122] Fix widget night text color --- app/src/main/res/values-night/colors.xml | 3 +++ app/src/main/res/values/colors.xml | 10 ++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 2d8a0912..953bd2f7 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -15,6 +15,9 @@ #a0a0a0 #1ffafafa + @color/nightTextPrimary + @color/nightTextPrimary + @color/nightGrey #33000000 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index cbd330a9..423f71d9 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -21,11 +21,8 @@ #33303030 @color/textTertiary - @color/dayTextTertiary - @color/nightTextPrimary @color/textTertiary - @color/dayTextTertiary - @color/nightTextPrimary + @color/textTertiary @color/lighterGrey @@ -47,5 +44,10 @@ #8ab4f8 #3c4043 + @color/dayTextTertiary + @color/dayTextTertiary + @color/nightTextPrimary + @color/nightTextPrimary + #1a73e8 From c2e22a00edb6af4d7513faff0fe8cd366bbc1f62 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 26 Dec 2019 19:21:01 +0100 Subject: [PATCH 114/122] Update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0db2eb33..cb0d9ed2 100644 --- a/.gitignore +++ b/.gitignore @@ -88,6 +88,7 @@ captures/ .idea/usage.statistics.xml .idea/contentModel.xml .idea/kotlinc.xml +.idea/jarRepositories.xml # optional .idea/dictionaries .idea/inspectionProfiles From e84151ef03a46399d49535dd35980790c4a7de8b Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 26 Dec 2019 19:23:46 +0100 Subject: [PATCH 115/122] Add drawables to fit night accent color --- app/src/main/res/drawable-night/ic_check.xml | 9 +++++++++ app/src/main/res/drawable-night/ic_clear.xml | 9 +++++++++ app/src/main/res/drawable-night/ic_delete.xml | 12 ++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 app/src/main/res/drawable-night/ic_check.xml create mode 100644 app/src/main/res/drawable-night/ic_clear.xml create mode 100644 app/src/main/res/drawable-night/ic_delete.xml diff --git a/app/src/main/res/drawable-night/ic_check.xml b/app/src/main/res/drawable-night/ic_check.xml new file mode 100644 index 00000000..b3b91ba2 --- /dev/null +++ b/app/src/main/res/drawable-night/ic_check.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-night/ic_clear.xml b/app/src/main/res/drawable-night/ic_clear.xml new file mode 100644 index 00000000..f775ee90 --- /dev/null +++ b/app/src/main/res/drawable-night/ic_clear.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-night/ic_delete.xml b/app/src/main/res/drawable-night/ic_delete.xml new file mode 100644 index 00000000..86f608cc --- /dev/null +++ b/app/src/main/res/drawable-night/ic_delete.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file From 600b57a61472e210993f5ba7c7f95d566f50a3c3 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Thu, 26 Dec 2019 19:24:53 +0100 Subject: [PATCH 116/122] Add workaround to disabled textviews after overwriting textcolor in app style --- .../activities/about/views/AboutItemLayout.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt index 458c376e..06f4378c 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/views/AboutItemLayout.kt @@ -10,6 +10,7 @@ import androidx.core.view.children import androidx.core.view.isVisible import com.g00fy2.developerwidget.databinding.AboutItemBinding import com.g00fy2.developerwidget.ktx.addRipple +import com.google.android.material.textview.MaterialTextView class AboutItemLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ConstraintLayout(context, attrs, defStyleAttr) { @@ -18,7 +19,13 @@ class AboutItemLayout @JvmOverloads constructor(context: Context, attrs: Attribu override fun setEnabled(enabled: Boolean) { super.setEnabled(enabled) - for (child in children) child.isEnabled = enabled + for (child in children) { + if (child::class == MaterialTextView::class) { + child.alpha = if (enabled) 1f else 0.38f + } else { + child.isEnabled = enabled + } + } } fun icon(@DrawableRes iconRes: Int): AboutItemLayout { From f1fc12b4c2b9740aea022ca50c915885673c9f71 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Mon, 30 Dec 2019 15:41:11 +0100 Subject: [PATCH 117/122] Simplify travis yml --- .travis.yml | 58 ++++++++++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2ce33f6f..794108a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,8 +18,7 @@ cache: - $HOME/.gradle/wrapper/ - $HOME/.android/build-cache/ -android_phases: -- phase: &before_install +before_install: # download and unzip Android SDK command line tools - wget -nv https://dl.google.com/android/repository/$ANDROID_SDK_CMD_TOOLS - mkdir -p $HOME/sdk/cmdline-tools && unzip -q $ANDROID_SDK_CMD_TOOLS -d $HOME/sdk/cmdline-tools @@ -30,31 +29,29 @@ android_phases: - mkdir -p $HOME/.android && touch $HOME/.android/repositories.cfg # decrypt private keystore - openssl aes-256-cbc -K $encrypted_a8fbd6bbc21d_key -iv $encrypted_a8fbd6bbc21d_iv -in keystore.jks.enc -out keystore.jks -d -- phase: &install +install: # accept licenses for all available packages that have not already been accepted - yes | sdkmanager --licenses >/dev/null -- phase: &before_script +before_script: # set executable flag for gradle wrapper - chmod +x gradlew # create dir for gradle settings - mkdir -p $HOME/.gradle - # disable gradle daemon for current user + # disable gradle daemon - echo "org.gradle.daemon=false" >> $HOME/.gradle/gradle.properties # set gradle log format to plain - echo "org.gradle.console=plain" >> $HOME/.gradle/gradle.properties # log all gradle warnings - echo "org.gradle.warning.mode=all" >> $HOME/.gradle/gradle.properties # control gradle build cache - - if [[ $TRAVIS_TAG == "" ]]; then + - if [[ $CACHING == "true" ]]; then echo "org.gradle.caching=true" >> $HOME/.gradle/gradle.properties; echo "android.enableBuildCache=true" >> $HOME/.gradle/gradle.properties; - echo "Build cache enabled"; else echo "org.gradle.caching=false" >> $HOME/.gradle/gradle.properties; echo "android.enableBuildCache=false" >> $HOME/.gradle/gradle.properties; - echo "Build cache disabled"; fi -- phase: &before_cache +before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - rm -rf $HOME/.gradle/caches/*/plugin-resolution/ - rm -f $HOME/.gradle/caches/*/fileHashes/fileHashes.bin @@ -69,39 +66,32 @@ android_phases: # only cache latest gradle version used by the wrapper # list content in wrapper/dist sorted by modification time and remove entries starting by the second entry - ls -d $HOME/.gradle/wrapper/dists/* -1t | tail -n +2 | xargs rm -rf -- phase: &deploy - provider: releases - edge: true - token: - secure: J5U/QxYAcGZn/pZeU8+YK7ani5dn64McDEVj5BxTBbywfhfpabzug+6H8k6Mnvs8m8CEvi2NsgptyvsxMt6952dNFI9F0URRsDkDdBvKQKdBmhCmCWVckRushfrn5k8RTjpJFYExiuDw6mSPZVtVzdXgHTgiZzPW20skROgoOq6Jb2CMa9awyI1Pbni7Emirkdl3N+h8krCyi/T06va1QebbWYsdLem8EvPgREBV+fDZ8RR+ABnT68aV7Jyq5YWortThT0TRAQ5f17C/T/aDWU7TqL4+HbfGEMvlO4vFYKUHNhxB6ZssaOpLSRVZKq4kecr2PQWIzQX+VFo4Fyxe3kTqfgidR2ptihkAERFz5FCHsEDDSRliatUUFpXxNLaa4ZIooo5p5uThRniu9COjdwuJZtFUIqstL1IrLntv4+3P2SY2BfdsTkgSuq7NT37u6MbT/cdr+dO7jgCoRIyxRzQGoeViALjzwIdXS2iBCwEpex9IDdvjsHmFJIo+8IsJGeGUCRsJL0tFBtZ8lIks1bh+t7pxKywhS3vXGny2ZCaIdA55g0b5N0D64P12ibWI80B7EAEv43Xmb5oVkVYdq9PdPJFoG/b4nDy8NfbQCWv9P/xgP6KwogAPsCJJ7tS4qn2HV6eUKrsj7ioBwpHsn/3ZEL0gU3sBnGJk20hyZyc= - file: - - $TRAVIS_BUILD_DIR/app/build/outputs/bundle/release/*.aab - - $TRAVIS_BUILD_DIR/app/build/outputs/apk/release/*.apk - - $TRAVIS_BUILD_DIR/app/build/outputs/mapping/release/mapping.txt - draft: false - on: - tags: true - name: $TRAVIS_TAG - tag_name: $TRAVIS_TAG - release_notes: "Generated release from Travis CI for build $TRAVIS_BUILD_NUMBER" - prerelease: true jobs: include: - # Build debug if: branch IN (develop, master) - before_install: *before_install - install: *install - before_script: *before_script + env: CACHING=true script: "./gradlew assembleDebug --scan" - before_cache: *before_cache - # Build and deploy release on tags if: tag IS present - before_install: *before_install - install: *install - before_script: *before_script + env: CACHING=false script: - "./gradlew assembleRelease -Pmy_storepass=$storepass -Pmy_keyalias=$keyalias -Pmy_keypass=$keypass --scan" - "./gradlew :app:bundleRelease -Pmy_storepass=$storepass -Pmy_keyalias=$keyalias -Pmy_keypass=$keypass" - before_cache: *before_cache - deploy: *deploy \ No newline at end of file + deploy: + provider: releases + edge: true + token: + secure: J5U/QxYAcGZn/pZeU8+YK7ani5dn64McDEVj5BxTBbywfhfpabzug+6H8k6Mnvs8m8CEvi2NsgptyvsxMt6952dNFI9F0URRsDkDdBvKQKdBmhCmCWVckRushfrn5k8RTjpJFYExiuDw6mSPZVtVzdXgHTgiZzPW20skROgoOq6Jb2CMa9awyI1Pbni7Emirkdl3N+h8krCyi/T06va1QebbWYsdLem8EvPgREBV+fDZ8RR+ABnT68aV7Jyq5YWortThT0TRAQ5f17C/T/aDWU7TqL4+HbfGEMvlO4vFYKUHNhxB6ZssaOpLSRVZKq4kecr2PQWIzQX+VFo4Fyxe3kTqfgidR2ptihkAERFz5FCHsEDDSRliatUUFpXxNLaa4ZIooo5p5uThRniu9COjdwuJZtFUIqstL1IrLntv4+3P2SY2BfdsTkgSuq7NT37u6MbT/cdr+dO7jgCoRIyxRzQGoeViALjzwIdXS2iBCwEpex9IDdvjsHmFJIo+8IsJGeGUCRsJL0tFBtZ8lIks1bh+t7pxKywhS3vXGny2ZCaIdA55g0b5N0D64P12ibWI80B7EAEv43Xmb5oVkVYdq9PdPJFoG/b4nDy8NfbQCWv9P/xgP6KwogAPsCJJ7tS4qn2HV6eUKrsj7ioBwpHsn/3ZEL0gU3sBnGJk20hyZyc= + file: + - $TRAVIS_BUILD_DIR/app/build/outputs/bundle/release/*.aab + - $TRAVIS_BUILD_DIR/app/build/outputs/apk/release/*.apk + - $TRAVIS_BUILD_DIR/app/build/outputs/mapping/release/mapping.txt + draft: false + on: + tags: true + name: $TRAVIS_TAG + tag_name: $TRAVIS_TAG + release_notes: "Generated release from Travis CI for build $TRAVIS_BUILD_NUMBER" + prerelease: true \ No newline at end of file From cda6c34786d35f83ee12bdb5897d69a043e24d13 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Mon, 30 Dec 2019 15:41:33 +0100 Subject: [PATCH 118/122] Optimize viewgroup animation extensions --- .../ktx/ViewGroupExtensions.kt | 75 ++++++++++--------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewGroupExtensions.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewGroupExtensions.kt index 6323312e..d730f1ac 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewGroupExtensions.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/ktx/ViewGroupExtensions.kt @@ -4,48 +4,53 @@ import android.animation.TimeInterpolator import android.animation.ValueAnimator import android.view.View import android.view.ViewGroup +import android.view.animation.AccelerateDecelerateInterpolator import androidx.core.animation.doOnEnd import com.g00fy2.developerwidget.R -fun ViewGroup.expand(fade: Boolean = false, easing: TimeInterpolator? = null) = this.apply { - val params = layoutParams as ViewGroup.MarginLayoutParams - params.topMargin = -height - layoutParams = params - if (fade) alpha = 0f - visibility = View.VISIBLE +fun ViewGroup.expand(fade: Boolean = false, easing: TimeInterpolator = AccelerateDecelerateInterpolator()) { + this.apply { + val params = layoutParams as ViewGroup.MarginLayoutParams + params.topMargin = -height + layoutParams = params + if (fade) alpha = 0f + visibility = View.VISIBLE - val viewHeight = height - ValueAnimator.ofInt(-viewHeight, 0).apply { - addUpdateListener { - (it.animatedValue as Int).let { value -> - params.topMargin = value - layoutParams = params - if (fade) alpha = (viewHeight + value) / viewHeight.toFloat() + val viewHeight = height + ValueAnimator.ofInt(-viewHeight, 0).apply { + addUpdateListener { + (it.animatedValue as Int).let { value -> + params.topMargin = value + layoutParams = params + if (fade) alpha = (viewHeight + value) / viewHeight.toFloat() + } } - } - easing?.let { easing -> interpolator = easing } - duration = resources.getInteger(R.integer.animation_duration).toLong() - }.start() + interpolator = easing + duration = resources.getInteger(R.integer.animation_duration).toLong() + }.start() + } } -fun ViewGroup.collapse(fade: Boolean = false, easing: TimeInterpolator? = null) = this.apply { - val params = layoutParams as ViewGroup.MarginLayoutParams - params.topMargin = 0 - layoutParams = params - if (fade) alpha = 1f - visibility = View.VISIBLE +fun ViewGroup.collapse(fade: Boolean = false, easing: TimeInterpolator = AccelerateDecelerateInterpolator()) { + this.apply { + val params = layoutParams as ViewGroup.MarginLayoutParams + params.topMargin = 0 + layoutParams = params + if (fade) alpha = 1f + visibility = View.VISIBLE - val viewHeight = height - ValueAnimator.ofInt(0, -viewHeight).apply { - addUpdateListener { - (it.animatedValue as Int).let { value -> - params.topMargin = value - layoutParams = params - if (fade) alpha = (viewHeight + value) / viewHeight.toFloat() + val viewHeight = height + ValueAnimator.ofInt(0, -viewHeight).apply { + addUpdateListener { + (it.animatedValue as Int).let { value -> + params.topMargin = value + layoutParams = params + if (fade) alpha = (viewHeight + value) / viewHeight.toFloat() + } } - } - easing?.let { easing -> interpolator = easing } - duration = resources.getInteger(R.integer.animation_duration).toLong() - doOnEnd { visibility = View.GONE } - }.start() + interpolator = easing + duration = resources.getInteger(R.integer.animation_duration).toLong() + doOnEnd { visibility = View.GONE } + }.start() + } } \ No newline at end of file From 6290886143246e48dd87603a210a0d0d4bf5b64b Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 8 Jan 2020 14:50:48 +0100 Subject: [PATCH 119/122] Use itemView to add ripple --- .../kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt index 60dba33d..929b71a9 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/base/BaseViewHolder.kt @@ -4,9 +4,9 @@ import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding import com.g00fy2.developerwidget.ktx.addRipple -abstract class BaseViewHolder(private val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) { +abstract class BaseViewHolder(binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) { abstract fun onBind(item: T) - fun addRipple() = binding.root.addRipple(true) + fun addRipple() = itemView.addRipple(true) } \ No newline at end of file From 8afa33c9adf830da174b331e02f5dc7caad0a840 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 8 Jan 2020 14:51:32 +0100 Subject: [PATCH 120/122] Update dependencies and gradle --- build.gradle | 10 +++++----- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index 02d5baba..e185f339 100644 --- a/build.gradle +++ b/build.gradle @@ -11,13 +11,13 @@ buildscript { buildToolsVersion = '29.0.2' minSdkVersion = 14 targetSdkVersion = 29 - androidGradleVersion = '4.0.0-alpha07' + androidGradleVersion = '4.0.0-alpha08' versioningPluginVersion = '1.0.2' - licenseReportVersion = '1.11' + licenseReportVersion = '1.12' // Library versions kotlinVersion = '1.3.61' - coroutinesVersion = '1.3.2' + coroutinesVersion = '1.3.3' appcompatVersion = '1.2.0-alpha01' coreKtxVersion = '1.2.0-rc01' activityVersion = '1.1.0-rc03' @@ -27,8 +27,8 @@ buildscript { vectorDrawableVersion = '1.1.0' constraintlayoutVersion = '2.0.0-beta4' timberVersion = '4.7.1' - daggerVersion = '2.25.3' - versCompVersion = '1.3.3' + daggerVersion = '2.25.4' + versCompVersion = '1.3.4' } repositories { google() diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9bd8801f..e3185a77 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-rc-1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-rc-2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index 2c8b87ff..0c0a85aa 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ plugins { - id 'com.gradle.enterprise' version '3.1' + id 'com.gradle.enterprise' version '3.1.1' } gradleEnterprise { From 6109237a006eb586e57f182ad606c4d409af74ed Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 8 Jan 2020 16:14:43 +0100 Subject: [PATCH 121/122] Update gradle wrapper --- gradle/wrapper/gradle-wrapper.jar | Bin 58798 -> 58695 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 6d183c6b6f1b37f3fb960b68d8b1386b3e010383..f3d88b1c2faf2fc91d853cd5d4242b5547257070 100644 GIT binary patch delta 6646 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 delta 6879 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 Date: Thu, 9 Jan 2020 23:56:43 +0100 Subject: [PATCH 122/122] Refactor code and optimize onTouchListener --- .../activities/about/AboutActivity.kt | 6 +++--- .../activities/appmanager/AppsActivity.kt | 21 ++++++++----------- .../widgetconfig/WidgetConfigActivity.kt | 4 ++-- .../systemapps/SystemAppsDataProvider.kt | 16 +++++++------- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt index fee33b96..45156673 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/about/AboutActivity.kt @@ -108,10 +108,10 @@ class AboutActivity : BaseActivity(), AboutContract.AboutView { action { presenter.honorClicking() } } if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) { - binding.aboutRootScrollview.doOnApplyWindowInsets { view, insets, padding, _ -> - view.updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) - } binding.aboutRootScrollview.apply { + doOnApplyWindowInsets { _, insets, padding, _ -> + updatePadding(bottom = padding.bottom + insets.systemWindowInsetBottom) + } viewTreeObserver.addOnScrollChangedListener { val scrollableRange = getChildAt(0).bottom - height + paddingBottom if (!gesturalNavigationMode()) { diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt index bec9ee80..4bceadf7 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/appmanager/AppsActivity.kt @@ -11,7 +11,6 @@ import android.view.LayoutInflater import android.view.MotionEvent import android.view.View import android.view.inputmethod.EditorInfo -import android.widget.EditText import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.widget.TooltipCompat import androidx.core.content.res.ResourcesCompat @@ -94,14 +93,14 @@ class AppsActivity : BaseActivity(true), AppsContract.AppsView { } }) setOnEditorActionListener { _, actionId, _ -> - val filterString = binding.filterEdittext.text.toString().trim() + val filterString = text.toString().trim() if (actionId == EditorInfo.IME_ACTION_DONE && filterString.isNotEmpty() && !presenter.duplicateFilter( filterString ) ) { presenter.addAppFilter(filterString) addFilterChip(filterString) - binding.filterEdittext.text.clear() + text.clear() } true } @@ -109,17 +108,15 @@ class AppsActivity : BaseActivity(true), AppsContract.AppsView { presenter.updateFilter(it) setCompoundDrawables(null, null, if (!it.isNullOrEmpty()) clearDrawable else null, null) } - setOnTouchListener { v, event -> - var consumed = false - if (v is EditText) { - if (event.x >= v.width - v.totalPaddingRight) { - if (event.action == MotionEvent.ACTION_UP) { - binding.filterEdittext.text.clear() - } - consumed = true + setOnTouchListener { _, event -> + if (event.x >= width - totalPaddingRight) { + if (event.action == MotionEvent.ACTION_UP) { + performClick() + text.clear() } + return@setOnTouchListener true } - consumed + false } } // necessary to measure the view heights for animations diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt index 670d11bb..f957436e 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/activities/widgetconfig/WidgetConfigActivity.kt @@ -127,9 +127,9 @@ class WidgetConfigActivity : BaseActivity(), WidgetConfigContract.WidgetConfigVi toggleDeviceNameEdit(false) } } - setOnEditorActionListener { v, actionId, _ -> + setOnEditorActionListener { _, actionId, _ -> if (actionId == EditorInfo.IME_ACTION_DONE) { - v.clearFocus() + clearFocus() } true } diff --git a/app/src/main/kotlin/com/g00fy2/developerwidget/data/device/systemapps/SystemAppsDataProvider.kt b/app/src/main/kotlin/com/g00fy2/developerwidget/data/device/systemapps/SystemAppsDataProvider.kt index 7991c0fa..0a3c398e 100644 --- a/app/src/main/kotlin/com/g00fy2/developerwidget/data/device/systemapps/SystemAppsDataProvider.kt +++ b/app/src/main/kotlin/com/g00fy2/developerwidget/data/device/systemapps/SystemAppsDataProvider.kt @@ -24,22 +24,24 @@ class SystemAppsDataProvider { @SuppressLint("PrivateApi", "WebViewApiAvailability") fun getWebViewImplementation(context: Context): String { return when { - VERSION.SDK_INT >= VERSION_CODES.O -> WebView.getCurrentWebViewPackage()?.let { - context.packageManager.getApplicationLabel( - it.applicationInfo - ).toString() + " " + it.versionName - } ?: "" + VERSION.SDK_INT >= VERSION_CODES.O -> { + WebView.getCurrentWebViewPackage()?.let { + context.packageManager.getApplicationLabel(it.applicationInfo).toString() + " " + it.versionName + } ?: "" + } VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP -> { try { (Class.forName("android.webkit.WebViewFactory") .getMethod("getLoadedPackageInfo") - .invoke(null) as PackageInfo?)?.let { context.packageManager.getApplicationLabel(it.applicationInfo).toString() + " " + it.versionName } + .invoke(null) as PackageInfo?)?.let { + context.packageManager.getApplicationLabel(it.applicationInfo).toString() + " " + it.versionName + } ?: "" } catch (t: Throwable) { "" } } - Version(VERSION.RELEASE.toString()).isAtLeast("4.4.3") -> "WebView v33.0.0.0" + Version(VERSION.RELEASE).isAtLeast("4.4.3") -> "WebView v33.0.0.0" VERSION.SDK_INT >= VERSION_CODES.KITKAT -> "WebView v30.0.0.0" else -> try { context.packageManager.getPackageInfo("com.google.android.webview", 0)