From a380adea1052d39f23c9c4d432a9380ce347d6c4 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Mon, 24 Dec 2018 00:27:25 -0500 Subject: Migrate to androidx (#178) * Initial refactor * Remove alpha version usages * Update test code * Add tests for checkbox * Fix invalid card import * Remove more old support content * Update kotlin version * Add back kotterknife with new imports * Update docs * Use bold notice * Add changelog * Remove deprecation for kotterknife * Remove unused dependencies * Update changelog --- buildSrc/README.md | 2 +- .../groovy/ca/allanwang/kau/Dependencies.groovy | 5 ++- .../main/groovy/ca/allanwang/kau/Versions.groovy | 46 +++++++++++++++------- 3 files changed, 36 insertions(+), 17 deletions(-) (limited to 'buildSrc') diff --git a/buildSrc/README.md b/buildSrc/README.md index 60d2dfc..91a60ac 100644 --- a/buildSrc/README.md +++ b/buildSrc/README.md @@ -48,7 +48,7 @@ You are free to use the values through `kau.[tagName]`. As an example, AppCompat is imported in KAU using ```gradle -api "com.android.support:appcompat-v7:${kau.supportLibs}" +api "androidx.appcompat:appcompat:${kau.appcompat}" ``` # Plugins diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy index ec3d208..a27e503 100644 --- a/buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy +++ b/buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy @@ -7,6 +7,7 @@ class Dependencies { static def kotlin = "org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}" static def kotlinTest = "org.jetbrains.kotlin:kotlin-test-junit:${Versions.kotlin}" static def junit = "junit:junit:${Versions.junit}" - static def espresso = "com.android.support.test.espresso:espresso-core:${Versions.espresso}" - static def testRunner = "com.android.support.test:runner:${Versions.testRunner}" + static def espresso = "androidx.test.espresso:espresso-core:${Versions.espresso}" + static def testRunner = "androidx.test.ext:junit:${Versions.testRunner}" + static def testRules = "androidx.test:rules:${Versions.testRules}" } \ No newline at end of file diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy index 55fc646..637ae68 100644 --- a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy +++ b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy @@ -8,14 +8,26 @@ class Versions { // https://developer.android.com/studio/releases/build-tools static def buildTools = '28.0.3' - // https://developer.android.com/topic/libraries/support-library/revisions - static def supportLibs = '28.0.0' + // https://mvnrepository.com/artifact/androidx.appcompat/appcompat?repo=google + static def appcompat = '1.0.2' + + // https://mvnrepository.com/artifact/com.google.android.material/material + static def googleMaterial = '1.0.0' + + // https://mvnrepository.com/artifact/androidx.recyclerview/recyclerview + static def recyclerView = '1.0.0' + + // https://mvnrepository.com/artifact/androidx.cardview/cardview + static def cardView = '1.0.0' + + // https://mvnrepository.com/artifact/androidx.constraintlayout/constraintlayout + static def constraintLayout = '1.1.3' // https://kotlinlang.org/docs/reference/using-gradle.html - static def kotlin = '1.2.71' + static def kotlin = '1.3.11' // https://github.com/mikepenz/AboutLibraries/releases - static def aboutLibraries = '6.1.1' + static def aboutLibraries = '6.2.0' // https://github.com/Kotlin/anko/releases static def anko = '0.10.5' @@ -23,29 +35,35 @@ class Versions { // https://github.com/wasabeef/Blurry/releases static def blurry = '2.1.1' - // https://dl.google.com/dl/android/maven2/com/android/support/constraint/group-index.xml - static def constraintLayout = '1.1.3' - // https://github.com/mikepenz/FastAdapter#using-maven - static def fastAdapter = '3.2.9' + static def fastAdapter = '3.3.1' static def fastAdapterCommons = fastAdapter // https://github.com/bumptech/glide/releases static def glide = '4.8.0' // https://github.com/mikepenz/Android-Iconics#1-provide-the-gradle-dependency - static def iconics = '3.0.4' - static def iconicsGoogle = '3.0.1.2' - static def iconicsMaterial = '2.2.0.4' - static def iconicsCommunity = '2.0.46.1' + static def iconics = '3.1.0' + static def iconicsGoogle = '3.0.1.3' + static def iconicsMaterial = '2.2.0.5' + static def iconicsCommunity = '2.7.94.1' // https://github.com/afollestad/material-dialogs/releases static def materialDialog = '0.9.6.0' - static def espresso = '3.0.1' + // https://mvnrepository.com/artifact/androidx.test.espresso/espresso-core?repo=google + static def espresso = '3.1.1' + + // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api static def junit = '4.12' - static def testRunner = '1.0.1' + + static def testRunner = '1.1.0' + + // https://mvnrepository.com/artifact/androidx.test/rules?repo=google + static def testRules = '1.1.1' + + // https://mvnrepository.com/artifact/com.android.tools.build/gradle?repo=google static def gradlePlugin = '3.2.1' static def mavenPlugin = '2.1' static def playPublishPlugin = '1.2.2' -- cgit v1.2.3 From fb90c4a4ab23f2fd246c29c1dde4d6e155a2e38b Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Mon, 24 Dec 2018 01:17:31 -0500 Subject: Enhancement/ktlint (#179) * Add spotless dependency * Apply ktlint * Add license headers --- .../ca/allanwang/kau/about/AboutActivityBase.kt | 27 ++- .../kotlin/ca/allanwang/kau/about/AboutBinder.kt | 21 +- .../ca/allanwang/kau/about/AboutPanelDelegate.kt | 41 +++- .../ca/allanwang/kau/about/CollapsibleTextView.kt | 23 +- .../kotlin/ca/allanwang/kau/about/CutoutIItem.kt | 22 +- .../main/kotlin/ca/allanwang/kau/about/FaqIItem.kt | 41 ++-- .../kotlin/ca/allanwang/kau/about/LibraryIItem.kt | 45 ++-- .../ca/allanwang/kau/adapters/AdapterUtils.kt | 19 +- .../kau/adapters/FastItemThemedAdapter.kt | 25 ++- .../kau/adapters/RepeatedClickListener.kt | 36 +++- .../allanwang/kau/animators/AnimatorInterfaces.kt | 21 +- .../ca/allanwang/kau/animators/DefaultAnimator.kt | 18 +- .../allanwang/kau/animators/FadeScaleAnimator.kt | 32 ++- .../ca/allanwang/kau/animators/KauAnimator.kt | 32 ++- .../ca/allanwang/kau/animators/NoAnimator.kt | 26 ++- .../ca/allanwang/kau/animators/SlideAnimator.kt | 29 ++- .../kotlin/ca/allanwang/kau/iitems/CardIItem.kt | 33 ++- .../kotlin/ca/allanwang/kau/iitems/HeaderIItem.kt | 25 ++- .../kotlin/ca/allanwang/kau/iitems/KauIItem.kt | 25 ++- build.gradle | 3 + .../main/groovy/ca/allanwang/kau/Plugins.groovy | 1 + .../main/groovy/ca/allanwang/kau/Versions.groovy | 3 + .../ca/allanwang/kau/colorpicker/CircleView.kt | 60 ++++-- .../ca/allanwang/kau/colorpicker/ColorPalette.kt | 169 ++++++++------- .../allanwang/kau/colorpicker/ColorPickerDialog.kt | 17 +- .../allanwang/kau/colorpicker/ColorPickerView.kt | 74 +++++-- .../kau/ui/activities/ElasticRecyclerActivity.kt | 19 +- .../ca/allanwang/kau/ui/views/BoundedCardView.kt | 23 +- .../kotlin/ca/allanwang/kau/ui/views/CutoutView.kt | 48 +++-- .../ca/allanwang/kau/ui/views/MeasuredImageView.kt | 24 ++- .../ui/widgets/ElasticDragDismissFrameLayout.kt | 115 ++++++---- .../ca/allanwang/kau/ui/widgets/TextSlider.kt | 50 +++-- .../kotlin/ca/allanwang/kau/kpref/KPrefTest.kt | 19 +- .../ca/allanwang/kau/utils/KotterknifeTest.kt | 17 +- .../kotlin/ca/allanwang/kau/xml/FaqTest.kt | 24 ++- .../kotlin/ca/allanwang/kau/email/EmailBuilder.kt | 56 +++-- .../ca/allanwang/kau/internal/KauBaseActivity.kt | 17 +- .../kotlin/ca/allanwang/kau/kotlin/Debouncer.kt | 16 +- .../kotlin/ca/allanwang/kau/kotlin/FlyWeight.kt | 18 +- .../kotlin/ca/allanwang/kau/kotlin/LazyContext.kt | 22 +- .../ca/allanwang/kau/kotlin/LazyResettable.kt | 17 +- .../main/kotlin/ca/allanwang/kau/kotlin/Streams.kt | 17 +- .../main/kotlin/ca/allanwang/kau/kotlin/Utils.kt | 17 +- .../src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt | 18 +- .../main/kotlin/ca/allanwang/kau/kpref/KPref.kt | 18 +- .../kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt | 50 +++-- .../ca/allanwang/kau/kpref/KPrefSingleDelegate.kt | 21 +- .../ca/allanwang/kau/kpref/KPrefTransaction.kt | 29 ++- .../src/main/kotlin/ca/allanwang/kau/logging/KL.kt | 17 +- .../kotlin/ca/allanwang/kau/logging/KauLogger.kt | 43 ++-- .../allanwang/kau/permissions/PermissionManager.kt | 29 ++- .../allanwang/kau/permissions/PermissionResult.kt | 17 +- .../ca/allanwang/kau/permissions/Permissions.kt | 26 ++- .../ca/allanwang/kau/swipe/RelativeSlider.kt | 27 ++- .../ca/allanwang/kau/swipe/SwipeBackHelper.kt | 22 +- .../ca/allanwang/kau/swipe/SwipeBackLayout.kt | 48 +++-- .../kotlin/ca/allanwang/kau/swipe/SwipeBackPage.kt | 23 +- .../kotlin/ca/allanwang/kau/swipe/SwipeListener.kt | 17 +- .../kotlin/ca/allanwang/kau/ui/ProgressAnimator.kt | 17 +- .../ca/allanwang/kau/ui/SimpleRippleDrawable.kt | 17 +- .../kau/ui/views/CollapsibleViewDelegate.kt | 32 ++- .../allanwang/kau/ui/views/MeasureSpecDelegate.kt | 25 ++- .../ca/allanwang/kau/ui/views/RippleCanvas.kt | 49 +++-- .../kotlin/ca/allanwang/kau/utils/ActivityUtils.kt | 57 +++-- .../kotlin/ca/allanwang/kau/utils/AnimHolder.kt | 18 +- .../kotlin/ca/allanwang/kau/utils/AnimUtils.kt | 66 +++++- .../kotlin/ca/allanwang/kau/utils/BundleUtils.kt | 58 +++-- .../kotlin/ca/allanwang/kau/utils/ColorUtils.kt | 88 +++++--- .../main/kotlin/ca/allanwang/kau/utils/Const.kt | 18 +- .../kotlin/ca/allanwang/kau/utils/ContextUtils.kt | 94 +++++--- .../kotlin/ca/allanwang/kau/utils/DrawableUtils.kt | 17 +- .../kotlin/ca/allanwang/kau/utils/FileUtils.kt | 18 +- .../kotlin/ca/allanwang/kau/utils/FontUtils.kt | 23 +- .../kotlin/ca/allanwang/kau/utils/FragmentUtils.kt | 17 +- .../kotlin/ca/allanwang/kau/utils/IIconUtils.kt | 24 ++- .../kotlin/ca/allanwang/kau/utils/Kotterknife.kt | 236 +++++++++------------ .../kotlin/ca/allanwang/kau/utils/NetworkUtils.kt | 17 +- .../ca/allanwang/kau/utils/NotificationUtils.kt | 18 +- .../kotlin/ca/allanwang/kau/utils/PackageUtils.kt | 17 +- .../kotlin/ca/allanwang/kau/utils/RecyclerUtils.kt | 17 +- .../ca/allanwang/kau/utils/TransitionUtils.kt | 24 ++- .../main/kotlin/ca/allanwang/kau/utils/Utils.kt | 20 +- .../kotlin/ca/allanwang/kau/utils/ViewUtils.kt | 86 +++++--- .../main/kotlin/ca/allanwang/kau/xml/Changelog.kt | 32 ++- core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt | 42 +++- .../kotlin/ca/allanwang/kau/kotlin/DebounceTest.kt | 18 +- .../ca/allanwang/kau/kotlin/LazyResettableTest.kt | 18 +- .../kotlin/ca/allanwang/kau/kotlin/StreamsTest.kt | 18 +- .../test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt | 21 +- .../kotlin/ca/allanwang/kau/utils/UtilsTest.kt | 17 +- docs/Changelog.md | 3 +- .../ca/allanwang/kau/kpref/activity/KClick.kt | 17 +- .../allanwang/kau/kpref/activity/KPrefActivity.kt | 49 ++++- .../ca/allanwang/kau/kpref/activity/KPrefBinder.kt | 126 +++++++---- .../kau/kpref/activity/items/KPrefCheckbox.kt | 20 +- .../kau/kpref/activity/items/KPrefColorPicker.kt | 29 ++- .../kau/kpref/activity/items/KPrefHeader.kt | 18 +- .../kau/kpref/activity/items/KPrefItemBase.kt | 29 ++- .../kau/kpref/activity/items/KPrefItemCore.kt | 56 +++-- .../kau/kpref/activity/items/KPrefPlainText.kt | 22 +- .../kau/kpref/activity/items/KPrefSeekbar.kt | 26 ++- .../kau/kpref/activity/items/KPrefSubItems.kt | 24 ++- .../kau/kpref/activity/items/KPrefText.kt | 26 ++- .../kau/kpref/activity/items/KPrefTimePicker.kt | 29 ++- .../allanwang/kau/mediapicker/BlurredImageView.kt | 29 ++- .../ca/allanwang/kau/mediapicker/GlideHelper.kt | 17 +- .../allanwang/kau/mediapicker/MediaActionItem.kt | 41 +++- .../ca/allanwang/kau/mediapicker/MediaItem.kt | 81 ++++--- .../ca/allanwang/kau/mediapicker/MediaItemBasic.kt | 71 +++++-- .../ca/allanwang/kau/mediapicker/MediaModel.kt | 66 +++--- .../kau/mediapicker/MediaPickerActivityBase.kt | 31 ++- .../mediapicker/MediaPickerActivityOverlayBase.kt | 21 +- .../allanwang/kau/mediapicker/MediaPickerBinder.kt | 25 ++- .../allanwang/kau/mediapicker/MediaPickerCore.kt | 33 ++- .../ca/allanwang/kau/mediapicker/MediaType.kt | 47 ++-- .../ca/allanwang/kau/mediapicker/MediaUtils.kt | 22 +- .../ca/allanwang/kau/sample/ColorPickerTest.kt | 34 ++- .../ca/allanwang/kau/sample/KPrefViewTest.kt | 43 ++-- .../ca/allanwang/kau/sample/utils/EspressoUtils.kt | 33 ++- .../ca/allanwang/kau/sample/AboutActivity.kt | 17 +- .../ca/allanwang/kau/sample/AdapterActivity.kt | 23 +- .../kotlin/ca/allanwang/kau/sample/AnimActivity.kt | 30 ++- .../kotlin/ca/allanwang/kau/sample/KPrefSample.kt | 20 +- .../kotlin/ca/allanwang/kau/sample/MainActivity.kt | 139 +++++++----- .../kotlin/ca/allanwang/kau/sample/MediaPicker.kt | 28 ++- .../ca/allanwang/kau/sample/PermissionCheckbox.kt | 21 +- .../kotlin/ca/allanwang/kau/sample/SampleApp.kt | 17 +- .../ca/allanwang/kau/sample/SwipeActivity.kt | 35 ++- .../ca/allanwang/kau/searchview/SearchItem.kt | 49 +++-- .../ca/allanwang/kau/searchview/SearchView.kt | 131 +++++++++--- .../allanwang/kau/searchview/SearchViewHolder.kt | 18 +- spotless.gradle | 11 + spotless.license.kt | 15 ++ 133 files changed, 3486 insertions(+), 1167 deletions(-) create mode 100644 spotless.gradle create mode 100644 spotless.license.kt (limited to 'buildSrc') diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt b/about/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt index 9667f47..79077c5 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.about import android.graphics.drawable.Drawable @@ -32,7 +47,8 @@ import kotlinx.android.synthetic.main.kau_activity_about.* * Note that for the auto detection to work, the R fields must be excluded from Proguard * Manual lib listings and other extra modifications can be done so by overriding the open functions */ -abstract class AboutActivityBase(val rClass: Class<*>?, private val configBuilder: Configs.() -> Unit = {}) : KauBaseActivity(), ViewPager.OnPageChangeListener { +abstract class AboutActivityBase(val rClass: Class<*>?, private val configBuilder: Configs.() -> Unit = {}) : + KauBaseActivity(), ViewPager.OnPageChangeListener { val currentPage: Int get() = about_pager.currentItem @@ -73,7 +89,7 @@ abstract class AboutActivityBase(val rClass: Class<*>?, private val configBuilde about_draggable_frame.addListener(object : ElasticDragDismissFrameLayout.SystemChromeFader(this) { override fun onDragDismissed() { window.returnTransition = TransitionInflater.from(this@AboutActivityBase) - .inflateTransition(if (about_draggable_frame.translationY > 0) R.transition.kau_exit_slide_bottom else R.transition.kau_exit_slide_top) + .inflateTransition(if (about_draggable_frame.translationY > 0) R.transition.kau_exit_slide_bottom else R.transition.kau_exit_slide_top) panels[currentPage].recycler?.stopScroll() finishAfterTransition() } @@ -113,7 +129,6 @@ abstract class AboutActivityBase(val rClass: Class<*>?, private val configBuilde * Feel free to add your own items to the adapter in here */ open fun postInflateMainPage(adapter: FastItemThemedAdapter>) { - } /** @@ -123,7 +138,7 @@ abstract class AboutActivityBase(val rClass: Class<*>?, private val configBuilde * This is fetched asynchronously and you may override it to customize the list */ open fun getLibraries(libs: Libs): List = - libs.prepareLibraries(this, null, null, true, true, true)!! + libs.prepareLibraries(this, null, null, true, true, true)!! /* * ------------------------------------------------------------------- @@ -156,7 +171,7 @@ abstract class AboutActivityBase(val rClass: Class<*>?, private val configBuilde */ private fun getPage(position: Int, parent: ViewGroup): View { if (views[position] == null) views[position] = panels[position] - .inflatePage(this@AboutActivityBase, parent, position) + .inflatePage(this@AboutActivityBase, parent, position) return views[position]!! } } @@ -174,4 +189,4 @@ abstract class AboutActivityBase(val rClass: Class<*>?, private val configBuilde AnimHolder.decelerateInterpolator.invalidate() //clear the reference to the interpolators we've used super.onDestroy() } -} \ No newline at end of file +} diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/AboutBinder.kt b/about/src/main/kotlin/ca/allanwang/kau/about/AboutBinder.kt index c99f7c2..1183113 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/AboutBinder.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/AboutBinder.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.about import android.content.Context @@ -12,6 +27,6 @@ import ca.allanwang.kau.utils.withSceneTransitionAnimation * About activity launcher */ inline fun Context.kauLaunchAbout() = - startActivity(bundleBuilder = { - withSceneTransitionAnimation(this@kauLaunchAbout) - }) \ No newline at end of file + startActivity(bundleBuilder = { + withSceneTransitionAnimation(this@kauLaunchAbout) + }) diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt b/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt index 6698dba..35c1322 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt @@ -1,15 +1,37 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.about -import androidx.recyclerview.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.adapters.FastItemThemedAdapter import ca.allanwang.kau.animators.FadeScaleAnimatorAdd import ca.allanwang.kau.animators.KauAnimator import ca.allanwang.kau.animators.NoAnimatorChange import ca.allanwang.kau.iitems.HeaderIItem -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.AnimHolder +import ca.allanwang.kau.utils.KAU_BOTTOM +import ca.allanwang.kau.utils.colorToForeground +import ca.allanwang.kau.utils.drawable +import ca.allanwang.kau.utils.fullLinearRecycler +import ca.allanwang.kau.utils.postDelayed +import ca.allanwang.kau.utils.string +import ca.allanwang.kau.utils.withMarginDecoration import ca.allanwang.kau.xml.kauParseFaq import com.mikepenz.aboutlibraries.Libs import com.mikepenz.fastadapter.IItem @@ -76,8 +98,8 @@ abstract class AboutPanelRecycler : AboutPanelContract { override fun onInflatingPage(activity: AboutActivityBase, recycler: RecyclerView, position: Int) { recycler.adapter = adapter recycler.itemAnimator = KauAnimator( - addAnimator = FadeScaleAnimatorAdd(scaleFactor = 0.7f, itemDelayFactor = 0.2f), - changeAnimator = NoAnimatorChange() + addAnimator = FadeScaleAnimatorAdd(scaleFactor = 0.7f, itemDelayFactor = 0.2f), + changeAnimator = NoAnimatorChange() ).apply { addDuration = 300; interpolator = AnimHolder.decelerateInterpolator(recycler.context) } } @@ -136,7 +158,6 @@ open class AboutPanelMain : AboutPanelRecycler() { } override fun addItemsImpl(activity: AboutActivityBase, position: Int) {} - } /** @@ -155,7 +176,8 @@ open class AboutPanelLibs : AboutPanelRecycler() { override fun loadItems(activity: AboutActivityBase, position: Int) { doAsync { with(activity) { - items = getLibraries(if (rClass == null) Libs(activity) else Libs(this, Libs.toStringArray(rClass.fields))) + items = + getLibraries(if (rClass == null) Libs(activity) else Libs(this, Libs.toStringArray(rClass.fields))) .map(::LibraryIItem) if (pageStatus[position] == 1) uiThread { addItems(activity, position) } @@ -166,7 +188,7 @@ open class AboutPanelLibs : AboutPanelRecycler() { override fun addItemsImpl(activity: AboutActivityBase, position: Int) { with(activity.configs) { adapter.add(HeaderIItem(text = libPageTitle, textRes = libPageTitleRes)) - .add(items) + .add(items) } } } @@ -191,8 +213,7 @@ open class AboutPanelFaqs : AboutPanelRecycler() { override fun addItemsImpl(activity: AboutActivityBase, position: Int) { with(activity.configs) { adapter.add(HeaderIItem(text = faqPageTitle, textRes = faqPageTitleRes)) - .add(items) + .add(items) } } - -} \ No newline at end of file +} diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/CollapsibleTextView.kt b/about/src/main/kotlin/ca/allanwang/kau/about/CollapsibleTextView.kt index 3dbb87e..c9b8b93 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/CollapsibleTextView.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/CollapsibleTextView.kt @@ -1,9 +1,24 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.about import android.content.Context import android.content.res.Configuration -import androidx.appcompat.widget.AppCompatTextView import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatTextView import ca.allanwang.kau.ui.views.CollapsibleView import ca.allanwang.kau.ui.views.CollapsibleViewDelegate @@ -12,7 +27,9 @@ import ca.allanwang.kau.ui.views.CollapsibleViewDelegate * */ class CollapsibleTextView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 ) : AppCompatTextView(context, attrs, defStyleAttr), CollapsibleView by CollapsibleViewDelegate() { init { @@ -29,4 +46,4 @@ class CollapsibleTextView @JvmOverloads constructor( val result = getCollapsibleDimension() setMeasuredDimension(result.first, result.second) } -} \ No newline at end of file +} diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/CutoutIItem.kt b/about/src/main/kotlin/ca/allanwang/kau/about/CutoutIItem.kt index 630a48e..b51c9c8 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/CutoutIItem.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/CutoutIItem.kt @@ -1,7 +1,22 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.about -import androidx.recyclerview.widget.RecyclerView import android.view.View +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.adapters.ThemableIItem import ca.allanwang.kau.adapters.ThemableIItemDelegate import ca.allanwang.kau.iitems.KauIItem @@ -13,7 +28,7 @@ import ca.allanwang.kau.ui.views.CutoutView * Just a cutout item with some defaults in [R.layout.kau_iitem_cutout] */ class CutoutIItem(val config: CutoutView.() -> Unit = {}) : KauIItem( - R.layout.kau_iitem_cutout, ::ViewHolder, R.id.kau_item_cutout + R.layout.kau_iitem_cutout, ::ViewHolder, R.id.kau_item_cutout ), ThemableIItem by ThemableIItemDelegate() { override fun isSelectable(): Boolean = false @@ -37,5 +52,4 @@ class CutoutIItem(val config: CutoutView.() -> Unit = {}) : KauIItem( - R.layout.kau_iitem_faq, ::ViewHolder, R.id.kau_item_faq + R.layout.kau_iitem_faq, ::ViewHolder, R.id.kau_item_faq ), ThemableIItem by ThemableIItemDelegate() { companion object { fun bindEvents(fastAdapter: FastAdapter>) { fastAdapter.withSelectable(false) - .withEventHook(object : ClickEventHook>() { + .withEventHook(object : ClickEventHook>() { - override fun onBind(viewHolder: RecyclerView.ViewHolder): View? = (viewHolder as? ViewHolder)?.questionContainer + override fun onBind(viewHolder: RecyclerView.ViewHolder): View? = + (viewHolder as? ViewHolder)?.questionContainer - override fun onClick(v: View, position: Int, adapter: FastAdapter>, item: IItem<*, *>) { - if (item !is FaqIItem) return - item.isExpanded = !item.isExpanded - v.parentViewGroup.findViewById(R.id.faq_item_answer).setExpanded(item.isExpanded) - } - - }) + override fun onClick(v: View, position: Int, adapter: FastAdapter>, item: IItem<*, *>) { + if (item !is FaqIItem) return + item.isExpanded = !item.isExpanded + v.parentViewGroup.findViewById(R.id.faq_item_answer) + .setExpanded(item.isExpanded) + } + }) } } @@ -83,5 +99,4 @@ class FaqIItem(val content: FaqItem) : KauIItem( - R.layout.kau_iitem_library, ::ViewHolder, R.id.kau_item_library + R.layout.kau_iitem_library, ::ViewHolder, R.id.kau_item_library ), ThemableIItem by ThemableIItemDelegate() { companion object { fun bindEvents(fastAdapter: FastAdapter>) { fastAdapter.withSelectable(false) - .withOnClickListener { v, _, item, _ -> - if (item !is LibraryIItem) - false - else - with(item.lib) { - v!!.context.startLink(libraryWebsite, repositoryLink, authorWebsite) - true - } - } + .withOnClickListener { v, _, item, _ -> + if (item !is LibraryIItem) + false + else + with(item.lib) { + v!!.context.startLink(libraryWebsite, repositoryLink, authorWebsite) + true + } + } } } @@ -48,7 +63,10 @@ class LibraryIItem(val lib: Library) : KauIItem lib.libraryDescription - Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> Html.fromHtml(lib.libraryDescription, Html.FROM_HTML_MODE_LEGACY) + Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> Html.fromHtml( + lib.libraryDescription, + Html.FROM_HTML_MODE_LEGACY + ) else -> Html.fromHtml(lib.libraryDescription) } bottomDivider.gone() @@ -90,5 +108,4 @@ class LibraryIItem(val lib: Library) : KauIItem> fastAdapter(vararg adapter: IAdapter) = - FastAdapter.with>(adapter.toList())!! + FastAdapter.with>(adapter.toList())!! inline fun , Item : IItem<*, *>> FastAdapter.getExtension(): T? = - getExtension(T::class.java) + getExtension(T::class.java) /** * Returns selection size, or -1 if selection is disabled diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/adapters/FastItemThemedAdapter.kt b/adapter/src/main/kotlin/ca/allanwang/kau/adapters/FastItemThemedAdapter.kt index 75cf876..152982f 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/adapters/FastItemThemedAdapter.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/adapters/FastItemThemedAdapter.kt @@ -1,11 +1,26 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.adapters import android.content.res.ColorStateList import android.os.Build -import androidx.annotation.RequiresApi import android.view.View import android.widget.ImageView import android.widget.TextView +import androidx.annotation.RequiresApi import ca.allanwang.kau.ui.createSimpleRippleDrawable import ca.allanwang.kau.utils.adjustAlpha import com.mikepenz.fastadapter.IItem @@ -21,9 +36,9 @@ import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter * If that item extends [ThemableIItem], then the colors will be set */ class FastItemThemedAdapter>( - textColor: Int? = null, - backgroundColor: Int? = null, - accentColor: Int? = null + textColor: Int? = null, + backgroundColor: Int? = null, + accentColor: Int? = null ) : FastItemAdapter() { constructor(colors: ThemableIItemColors) : this(colors.textColor, colors.backgroundColor, colors.accentColor) @@ -183,4 +198,4 @@ class ThemableIItemDelegate : ThemableIItem, ThemableIItemColors by ThemableIIte val color = accentColor ?: textColor ?: return views.forEach { it?.drawable?.setTintList(ColorStateList.valueOf(color)) } } -} \ No newline at end of file +} diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/adapters/RepeatedClickListener.kt b/adapter/src/main/kotlin/ca/allanwang/kau/adapters/RepeatedClickListener.kt index a23ac37..40b4774 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/adapters/RepeatedClickListener.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/adapters/RepeatedClickListener.kt @@ -1,7 +1,22 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.adapters -import androidx.annotation.IntRange import android.view.View +import androidx.annotation.IntRange import com.mikepenz.fastadapter.FastAdapter import com.mikepenz.fastadapter.IAdapter import com.mikepenz.fastadapter.IItem @@ -10,10 +25,12 @@ import com.mikepenz.fastadapter.listeners.OnClickListener /** * Created by Allan Wang on 26/12/17. */ -fun > FastAdapter.withOnRepeatedClickListener(count: Int, - duration: Long, - event: OnClickListener) = - withOnClickListener(RepeatedClickListener(count, duration, event)) +fun > FastAdapter.withOnRepeatedClickListener( + count: Int, + duration: Long, + event: OnClickListener +) = + withOnClickListener(RepeatedClickListener(count, duration, event)) /** * Registers and skips each click until the designated [count] clicks are triggered, @@ -21,9 +38,10 @@ fun > FastAdapter.withOnRepeatedClickListener(count: In * Only then will the [event] be fired, and everything will be reset. */ private class RepeatedClickListener>( - @IntRange(from = 1) val count: Int, - @IntRange(from = 1) val duration: Long, - val event: OnClickListener) : OnClickListener { + @IntRange(from = 1) val count: Int, + @IntRange(from = 1) val duration: Long, + val event: OnClickListener +) : OnClickListener { init { if (count <= 0) @@ -49,4 +67,4 @@ private class RepeatedClickListener>( } return false } -} \ No newline at end of file +} diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/animators/AnimatorInterfaces.kt b/adapter/src/main/kotlin/ca/allanwang/kau/animators/AnimatorInterfaces.kt index 15c3b41..b83a2d0 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/animators/AnimatorInterfaces.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/animators/AnimatorInterfaces.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.animators import android.view.View @@ -25,7 +40,11 @@ interface KauAnimatorRemove { } interface KauAnimatorChange { - fun changeOldAnimation(holder: RecyclerView.ViewHolder, changeInfo: BaseItemAnimator.ChangeInfo): ViewPropertyAnimator.() -> Unit + fun changeOldAnimation( + holder: RecyclerView.ViewHolder, + changeInfo: BaseItemAnimator.ChangeInfo + ): ViewPropertyAnimator.() -> Unit + fun changeNewAnimation(holder: RecyclerView.ViewHolder): ViewPropertyAnimator.() -> Unit fun changeAnimationCleanup(holder: RecyclerView.ViewHolder): View.() -> Unit } diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/animators/DefaultAnimator.kt b/adapter/src/main/kotlin/ca/allanwang/kau/animators/DefaultAnimator.kt index f2b6353..4e342ab 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/animators/DefaultAnimator.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/animators/DefaultAnimator.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.animators import android.view.ViewPropertyAnimator @@ -59,5 +74,4 @@ open class DefaultAnimator : BaseItemAnimator() { override fun changeAnimationCleanup(holder: RecyclerView.ViewHolder) { holder.itemView.alpha = 1f } - -} \ No newline at end of file +} diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/animators/FadeScaleAnimator.kt b/adapter/src/main/kotlin/ca/allanwang/kau/animators/FadeScaleAnimator.kt index dec5f79..9113b0e 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/animators/FadeScaleAnimator.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/animators/FadeScaleAnimator.kt @@ -1,14 +1,30 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.animators -import androidx.recyclerview.widget.RecyclerView import android.view.View import android.view.ViewPropertyAnimator +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.utils.scaleXY /** * Created by Allan Wang on 2017-07-11. */ -class FadeScaleAnimatorAdd(val scaleFactor: Float = 1.0f, override var itemDelayFactor: Float = 0.125f) : KauAnimatorAdd { +class FadeScaleAnimatorAdd(val scaleFactor: Float = 1.0f, override var itemDelayFactor: Float = 0.125f) : + KauAnimatorAdd { override fun animationPrepare(holder: RecyclerView.ViewHolder): View.() -> Unit = { scaleXY = scaleFactor @@ -26,10 +42,10 @@ class FadeScaleAnimatorAdd(val scaleFactor: Float = 1.0f, override var itemDelay } override fun getDelay(remove: Long, move: Long, change: Long): Long = 0L - } -class FadeScaleAnimatorRemove(val scaleFactor: Float = 1.0f, override var itemDelayFactor: Float = 0.125f) : KauAnimatorRemove { +class FadeScaleAnimatorRemove(val scaleFactor: Float = 1.0f, override var itemDelayFactor: Float = 0.125f) : + KauAnimatorRemove { override fun animation(holder: RecyclerView.ViewHolder): ViewPropertyAnimator.() -> Unit = { scaleXY(scaleFactor) @@ -46,10 +62,12 @@ class FadeScaleAnimatorRemove(val scaleFactor: Float = 1.0f, override var itemDe class FadeAnimatorChange : KauAnimatorChange { - override fun changeOldAnimation(holder: RecyclerView.ViewHolder, changeInfo: BaseItemAnimator.ChangeInfo): ViewPropertyAnimator.() -> Unit = { alpha(0f) } + override fun changeOldAnimation( + holder: RecyclerView.ViewHolder, + changeInfo: BaseItemAnimator.ChangeInfo + ): ViewPropertyAnimator.() -> Unit = { alpha(0f) } override fun changeNewAnimation(holder: RecyclerView.ViewHolder): ViewPropertyAnimator.() -> Unit = { alpha(1f) } override fun changeAnimationCleanup(holder: RecyclerView.ViewHolder): View.() -> Unit = { alpha = 1f } - -} \ No newline at end of file +} diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/animators/KauAnimator.kt b/adapter/src/main/kotlin/ca/allanwang/kau/animators/KauAnimator.kt index a088273..b9df946 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/animators/KauAnimator.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/animators/KauAnimator.kt @@ -1,7 +1,22 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.animators -import androidx.recyclerview.widget.RecyclerView import android.view.ViewPropertyAnimator +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.utils.KAU_BOTTOM import ca.allanwang.kau.utils.KAU_RIGHT @@ -9,12 +24,13 @@ import ca.allanwang.kau.utils.KAU_RIGHT * Created by Allan Wang on 2017-06-27. */ open class KauAnimator( - val addAnimator: KauAnimatorAdd = SlideAnimatorAdd(KAU_BOTTOM), - val removeAnimator: KauAnimatorRemove = SlideAnimatorRemove(KAU_RIGHT), - val changeAnimator: KauAnimatorChange = FadeAnimatorChange() + val addAnimator: KauAnimatorAdd = SlideAnimatorAdd(KAU_BOTTOM), + val removeAnimator: KauAnimatorRemove = SlideAnimatorRemove(KAU_RIGHT), + val changeAnimator: KauAnimatorChange = FadeAnimatorChange() ) : BaseItemAnimator() { - open fun startDelay(holder: RecyclerView.ViewHolder, duration: Long, factor: Float) = Math.max(0L, (holder.adapterPosition * duration * factor).toLong()) + open fun startDelay(holder: RecyclerView.ViewHolder, duration: Long, factor: Float) = + Math.max(0L, (holder.adapterPosition * duration * factor).toLong()) override fun removeAnimation(holder: RecyclerView.ViewHolder): ViewPropertyAnimator { return holder.itemView.animate().apply { @@ -29,7 +45,8 @@ open class KauAnimator( holder.itemView.apply { removeAnimator.animationCleanup(holder)() } } - override fun getRemoveDelay(remove: Long, move: Long, change: Long): Long = removeAnimator.getDelay(remove, move, change) + override fun getRemoveDelay(remove: Long, move: Long, change: Long): Long = + removeAnimator.getDelay(remove, move, change) override fun addAnimationPrepare(holder: RecyclerView.ViewHolder) { holder.itemView.apply { addAnimator.animationPrepare(holder)() } @@ -69,5 +86,4 @@ open class KauAnimator( override fun changeAnimationCleanup(holder: RecyclerView.ViewHolder) { holder.itemView.apply { changeAnimator.changeAnimationCleanup(holder)() } } - -} \ No newline at end of file +} diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/animators/NoAnimator.kt b/adapter/src/main/kotlin/ca/allanwang/kau/animators/NoAnimator.kt index ea0c123..cca8a25 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/animators/NoAnimator.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/animators/NoAnimator.kt @@ -1,8 +1,23 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.animators -import androidx.recyclerview.widget.RecyclerView import android.view.View import android.view.ViewPropertyAnimator +import androidx.recyclerview.widget.RecyclerView /** * Created by Allan Wang on 2017-08-02. @@ -16,7 +31,6 @@ class NoAnimatorAdd(override var itemDelayFactor: Float = 0f) : KauAnimatorAdd { override fun animationCleanup(holder: RecyclerView.ViewHolder): View.() -> Unit = { } override fun getDelay(remove: Long, move: Long, change: Long): Long = 0L - } class NoAnimatorRemove(override var itemDelayFactor: Float = 0f) : KauAnimatorRemove { @@ -30,10 +44,12 @@ class NoAnimatorRemove(override var itemDelayFactor: Float = 0f) : KauAnimatorRe class NoAnimatorChange : KauAnimatorChange { - override fun changeOldAnimation(holder: RecyclerView.ViewHolder, changeInfo: BaseItemAnimator.ChangeInfo): ViewPropertyAnimator.() -> Unit = { } + override fun changeOldAnimation( + holder: RecyclerView.ViewHolder, + changeInfo: BaseItemAnimator.ChangeInfo + ): ViewPropertyAnimator.() -> Unit = { } override fun changeNewAnimation(holder: RecyclerView.ViewHolder): ViewPropertyAnimator.() -> Unit = { } override fun changeAnimationCleanup(holder: RecyclerView.ViewHolder): View.() -> Unit = { alpha = 1f } - -} \ No newline at end of file +} diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/animators/SlideAnimator.kt b/adapter/src/main/kotlin/ca/allanwang/kau/animators/SlideAnimator.kt index 01ad1ff..55d5b2e 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/animators/SlideAnimator.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/animators/SlideAnimator.kt @@ -1,8 +1,23 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.animators -import androidx.recyclerview.widget.RecyclerView import android.view.View import android.view.ViewPropertyAnimator +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.utils.KAU_BOTTOM import ca.allanwang.kau.utils.KAU_LEFT import ca.allanwang.kau.utils.KAU_RIGHT @@ -11,7 +26,8 @@ import ca.allanwang.kau.utils.KAU_TOP /** * Created by Allan Wang on 2017-07-11. */ -class SlideAnimatorAdd(val fromEdge: Int, val slideFactor: Float = 1f, override var itemDelayFactor: Float = 0.125f) : KauAnimatorAdd { +class SlideAnimatorAdd(val fromEdge: Int, val slideFactor: Float = 1f, override var itemDelayFactor: Float = 0.125f) : + KauAnimatorAdd { override fun animationPrepare(holder: RecyclerView.ViewHolder): View.() -> Unit = { when (fromEdge) { @@ -37,10 +53,13 @@ class SlideAnimatorAdd(val fromEdge: Int, val slideFactor: Float = 1f, override } override fun getDelay(remove: Long, move: Long, change: Long): Long = 0L - } -class SlideAnimatorRemove(val fromEdge: Int, val slideFactor: Float = 1f, override var itemDelayFactor: Float = 0.125f) : KauAnimatorRemove { +class SlideAnimatorRemove( + val fromEdge: Int, + val slideFactor: Float = 1f, + override var itemDelayFactor: Float = 0.125f +) : KauAnimatorRemove { override fun animation(holder: RecyclerView.ViewHolder): ViewPropertyAnimator.() -> Unit = { with(holder.itemView) { when (fromEdge) { @@ -61,4 +80,4 @@ class SlideAnimatorRemove(val fromEdge: Int, val slideFactor: Float = 1f, overri } override fun getDelay(remove: Long, move: Long, change: Long): Long = 0L -} \ No newline at end of file +} diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/iitems/CardIItem.kt b/adapter/src/main/kotlin/ca/allanwang/kau/iitems/CardIItem.kt index 784dd3c..6e33833 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/iitems/CardIItem.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/iitems/CardIItem.kt @@ -1,18 +1,38 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.iitems import android.graphics.Color import android.graphics.drawable.Drawable -import androidx.recyclerview.widget.RecyclerView import android.view.View import android.widget.Button import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import androidx.cardview.widget.CardView +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.adapter.R import ca.allanwang.kau.adapters.ThemableIItem import ca.allanwang.kau.adapters.ThemableIItemDelegate -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.INVALID_ID +import ca.allanwang.kau.utils.drawable +import ca.allanwang.kau.utils.gone +import ca.allanwang.kau.utils.string +import ca.allanwang.kau.utils.toDrawable +import ca.allanwang.kau.utils.visible import com.mikepenz.fastadapter.FastAdapter import com.mikepenz.fastadapter.IItem import com.mikepenz.fastadapter.listeners.ClickEventHook @@ -25,9 +45,9 @@ import com.mikepenz.iconics.typeface.IIcon * The icon and button are hidden by default unless values are given */ class CardIItem( - val builder: Config.() -> Unit = {} + val builder: Config.() -> Unit = {} ) : KauIItem( - R.layout.kau_iitem_card, ::ViewHolder, R.id.kau_item_card + R.layout.kau_iitem_card, ::ViewHolder, R.id.kau_item_card ), ThemableIItem by ThemableIItemDelegate() { companion object { @@ -83,7 +103,7 @@ class CardIItem( } val icon = drawable(imageRes) { imageIIcon?.toDrawable(this@context, sizeDp = 24, color = imageIIconColor) - ?: image + ?: image } if (icon != null) holder.icon.visible().setImageDrawable(icon) } @@ -117,5 +137,4 @@ class CardIItem( val bottomRow: LinearLayout = v.findViewById(R.id.kau_card_bottom_row) val button: Button = v.findViewById(R.id.kau_card_button) } - -} \ No newline at end of file +} diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/iitems/HeaderIItem.kt b/adapter/src/main/kotlin/ca/allanwang/kau/iitems/HeaderIItem.kt index 098f017..2c488b1 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/iitems/HeaderIItem.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/iitems/HeaderIItem.kt @@ -1,9 +1,24 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.iitems -import androidx.recyclerview.widget.RecyclerView import android.view.View import android.widget.TextView import androidx.cardview.widget.CardView +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.adapter.R import ca.allanwang.kau.adapters.ThemableIItem import ca.allanwang.kau.adapters.ThemableIItemDelegate @@ -17,9 +32,10 @@ import ca.allanwang.kau.utils.string * Contains only one text view */ class HeaderIItem( - text: String? = null, var textRes: Int = INVALID_ID + text: String? = null, + var textRes: Int = INVALID_ID ) : KauIItem( - R.layout.kau_iitem_header, { ViewHolder(it) }, R.id.kau_item_header_big_margin_top + R.layout.kau_iitem_header, { ViewHolder(it) }, R.id.kau_item_header_big_margin_top ), ThemableIItem by ThemableIItemDelegate() { var text: String = text ?: "Header Placeholder" @@ -40,5 +56,4 @@ class HeaderIItem( val text: TextView = v.findViewById(R.id.kau_header_text) val container: CardView = v.findViewById(R.id.kau_header_container) } - -} \ No newline at end of file +} diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/iitems/KauIItem.kt b/adapter/src/main/kotlin/ca/allanwang/kau/iitems/KauIItem.kt index 205d388..c66dc01 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/iitems/KauIItem.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/iitems/KauIItem.kt @@ -1,9 +1,24 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.iitems import android.annotation.SuppressLint +import android.view.View import androidx.annotation.LayoutRes import androidx.recyclerview.widget.RecyclerView -import android.view.View import com.mikepenz.fastadapter.IClickable import com.mikepenz.fastadapter.IItem import com.mikepenz.fastadapter.items.AbstractItem @@ -15,13 +30,13 @@ import com.mikepenz.fastadapter.items.AbstractItem * If only one iitem type extends the given [layoutRes], you may use it as the type and not worry about another id */ open class KauIItem( - @param:LayoutRes private val layoutRes: Int, - private val viewHolder: (v: View) -> VH, - private val type: Int = layoutRes + @param:LayoutRes private val layoutRes: Int, + private val viewHolder: (v: View) -> VH, + private val type: Int = layoutRes ) : AbstractItem() where Item : IItem<*, *>, Item : IClickable<*> { @SuppressLint("ResourceType") final override fun getType(): Int = type final override fun getViewHolder(v: View): VH = viewHolder(v) final override fun getLayoutRes(): Int = layoutRes -} \ No newline at end of file +} diff --git a/build.gradle b/build.gradle index 3ddfb9c..5ec6404 100644 --- a/build.gradle +++ b/build.gradle @@ -15,6 +15,7 @@ buildscript { classpath kauPlugin.playPublisher classpath kauPlugin.dexCount classpath kauPlugin.gitVersion + classpath kauPlugin.spotless } wrapper.setDistributionType(Wrapper.DistributionType.ALL) @@ -37,6 +38,8 @@ subprojects { apply plugin: 'com.gladed.androidgitversion' + apply from: '../spotless.gradle' + repositories { google() jcenter() diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/Plugins.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/Plugins.groovy index c1ecba6..89182f1 100644 --- a/buildSrc/src/main/groovy/ca/allanwang/kau/Plugins.groovy +++ b/buildSrc/src/main/groovy/ca/allanwang/kau/Plugins.groovy @@ -14,4 +14,5 @@ class Plugins { def dexCount = "com.getkeepsafe.dexcount:dexcount-gradle-plugin:${Versions.dexCountPlugin}" static def gitVersion = "gradle.plugin.com.gladed.gradle.androidgitversion:gradle-android-git-version:${Versions.gitVersionPlugin}" + static def spotless = "com.diffplug.spotless:spotless-plugin-gradle:${Versions.spotless}" } \ No newline at end of file diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy index 637ae68..a85fe97 100644 --- a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy +++ b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy @@ -63,6 +63,9 @@ class Versions { // https://mvnrepository.com/artifact/androidx.test/rules?repo=google static def testRules = '1.1.1' + // https://github.com/diffplug/spotless/blob/master/plugin-gradle/CHANGES.md + static def spotless = '3.17.0' + // https://mvnrepository.com/artifact/com.android.tools.build/gradle?repo=google static def gradlePlugin = '3.2.1' static def mavenPlugin = '2.1' diff --git a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/CircleView.kt b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/CircleView.kt index bdd6eed..29257d8 100644 --- a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/CircleView.kt +++ b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/CircleView.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.colorpicker import android.animation.ValueAnimator @@ -13,15 +28,15 @@ import android.graphics.drawable.ShapeDrawable import android.graphics.drawable.StateListDrawable import android.graphics.drawable.shapes.OvalShape import android.os.Build +import android.util.AttributeSet +import android.view.Gravity +import android.widget.FrameLayout +import android.widget.Toast import androidx.annotation.ColorInt import androidx.annotation.ColorRes import androidx.annotation.FloatRange import androidx.core.view.GravityCompat import androidx.core.view.ViewCompat -import android.util.AttributeSet -import android.view.Gravity -import android.widget.FrameLayout -import android.widget.Toast import ca.allanwang.kau.utils.getDip import ca.allanwang.kau.utils.setBackgroundColorRes import ca.allanwang.kau.utils.toColor @@ -33,7 +48,8 @@ import ca.allanwang.kau.utils.toHSV * An extension of MaterialDialog's CircleView with animation selection * [https://github.com/afollestad/material-dialogs/blob/master/commons/src/main/java/com/afollestad/materialdialogs/color/CircleView.java] */ -class CircleView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : FrameLayout(context, attrs, defStyleAttr) { +class CircleView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : + FrameLayout(context, attrs, defStyleAttr) { private val borderWidthMicro: Float = context.getDip(1f) private val borderWidthSmall: Float = context.getDip(3f) @@ -108,14 +124,14 @@ class CircleView @JvmOverloads constructor(context: Context, attrs: AttributeSet fun animateSelected(selected: Boolean) { if (this.selected == selected) return this.selected = selected // We need to draw the other bands - val range = if (selected) Pair(-borderWidthSmall, borderWidthLarge) else Pair(borderWidthLarge, -borderWidthSmall) + val range = + if (selected) Pair(-borderWidthSmall, borderWidthLarge) else Pair(borderWidthLarge, -borderWidthSmall) ValueAnimator.ofFloat(range.first, range.second).apply { reverse() duration = 150L addUpdateListener { animation -> whiteOuterBound = animation.animatedValue as Float invalidate() - } start() } @@ -137,12 +153,22 @@ class CircleView @JvmOverloads constructor(context: Context, attrs: AttributeSet if (whiteRadius >= centerWidth) { canvas.drawCircle(centerWidth, centerHeight, centerWidth, whitePaint) } else { - canvas.drawCircle(centerWidth, centerHeight, if (withBorder) centerWidth - borderWidthMicro else centerWidth, outerPaint) + canvas.drawCircle( + centerWidth, + centerHeight, + if (withBorder) centerWidth - borderWidthMicro else centerWidth, + outerPaint + ) canvas.drawCircle(centerWidth, centerHeight, whiteRadius, whitePaint) } canvas.drawCircle(centerWidth, centerHeight, innerRadius, innerPaint) } else { - canvas.drawCircle(centerWidth, centerHeight, if (withBorder) centerWidth - borderWidthMicro else centerWidth, innerPaint) + canvas.drawCircle( + centerWidth, + centerHeight, + if (withBorder) centerWidth - borderWidthMicro else centerWidth, + innerPaint + ) } } @@ -169,11 +195,13 @@ class CircleView @JvmOverloads constructor(context: Context, attrs: AttributeSet referenceX = screenWidth - referenceX // mirror } val cheatSheet = Toast - .makeText(context, String.format("#%06X", 0xFFFFFF and color), Toast.LENGTH_SHORT) + .makeText(context, String.format("#%06X", 0xFFFFFF and color), Toast.LENGTH_SHORT) if (midy < displayFrame.height()) { // Show along the top; follow action buttons - cheatSheet.setGravity(Gravity.TOP or GravityCompat.END, referenceX, - screenPos[1] + height - displayFrame.top) + cheatSheet.setGravity( + Gravity.TOP or GravityCompat.END, referenceX, + screenPos[1] + height - displayFrame.top + ) } else { // Show along the bottom center cheatSheet.setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL, 0, height) @@ -194,8 +222,10 @@ class CircleView @JvmOverloads constructor(context: Context, attrs: AttributeSet } @ColorInt - fun shiftColor(@ColorInt color: Int, - @FloatRange(from = 0.0, to = 2.0) by: Float): Int { + fun shiftColor( + @ColorInt color: Int, + @FloatRange(from = 0.0, to = 2.0) by: Float + ): Int { if (by == 1f) return color val hsv = color.toHSV() hsv[2] *= by // value component @@ -208,4 +238,4 @@ class CircleView @JvmOverloads constructor(context: Context, attrs: AttributeSet @ColorInt fun shiftColorUp(@ColorInt color: Int): Int = shiftColor(color, 1.1f) } -} \ No newline at end of file +} diff --git a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPalette.kt b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPalette.kt index 68e3461..d9db160 100644 --- a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPalette.kt +++ b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPalette.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.colorpicker import android.graphics.Color @@ -9,29 +24,31 @@ internal object ColorPalette { val PRIMARY_COLORS: IntArray by lazy { colorArrayOf( - "#F44336", - "#E91E63", - "#9C27B0", - "#673AB7", - "#3F51B5", - "#2196F3", - "#03A9F4", - "#00BCD4", - "#009688", - "#4CAF50", - "#8BC34A", - "#CDDC39", - "#FFEB3B", - "#FFC107", - "#FF9800", - "#FF5722", - "#795548", - "#9E9E9E", - "#607D8B") + "#F44336", + "#E91E63", + "#9C27B0", + "#673AB7", + "#3F51B5", + "#2196F3", + "#03A9F4", + "#00BCD4", + "#009688", + "#4CAF50", + "#8BC34A", + "#CDDC39", + "#FFEB3B", + "#FFC107", + "#FF9800", + "#FF5722", + "#795548", + "#9E9E9E", + "#607D8B" + ) } val PRIMARY_COLORS_SUB: Array by lazy { - arrayOf(colorArrayOf( + arrayOf( + colorArrayOf( "#FFEBEE", "#FFCDD2", "#EF9A9A", @@ -42,7 +59,7 @@ internal object ColorPalette { "#D32F2F", "#C62828", "#B71C1C" - ), colorArrayOf( + ), colorArrayOf( "#FCE4EC", "#F8BBD0", "#F48FB1", @@ -53,7 +70,7 @@ internal object ColorPalette { "#C2185B", "#AD1457", "#880E4F" - ), colorArrayOf( + ), colorArrayOf( "#F3E5F5", "#E1BEE7", "#CE93D8", @@ -64,7 +81,7 @@ internal object ColorPalette { "#7B1FA2", "#6A1B9A", "#4A148C" - ), colorArrayOf( + ), colorArrayOf( "#EDE7F6", "#D1C4E9", "#B39DDB", @@ -75,7 +92,7 @@ internal object ColorPalette { "#512DA8", "#4527A0", "#311B92" - ), colorArrayOf( + ), colorArrayOf( "#E8EAF6", "#C5CAE9", "#9FA8DA", @@ -86,7 +103,7 @@ internal object ColorPalette { "#303F9F", "#283593", "#1A237E" - ), colorArrayOf( + ), colorArrayOf( "#E3F2FD", "#BBDEFB", "#90CAF9", @@ -97,7 +114,7 @@ internal object ColorPalette { "#1976D2", "#1565C0", "#0D47A1" - ), colorArrayOf( + ), colorArrayOf( "#E1F5FE", "#B3E5FC", "#81D4FA", @@ -108,7 +125,7 @@ internal object ColorPalette { "#0288D1", "#0277BD", "#01579B" - ), colorArrayOf( + ), colorArrayOf( "#E0F7FA", "#B2EBF2", "#80DEEA", @@ -119,7 +136,7 @@ internal object ColorPalette { "#0097A7", "#00838F", "#006064" - ), colorArrayOf( + ), colorArrayOf( "#E0F2F1", "#B2DFDB", "#80CBC4", @@ -130,7 +147,7 @@ internal object ColorPalette { "#00796B", "#00695C", "#004D40" - ), colorArrayOf( + ), colorArrayOf( "#E8F5E9", "#C8E6C9", "#A5D6A7", @@ -141,7 +158,7 @@ internal object ColorPalette { "#388E3C", "#2E7D32", "#1B5E20" - ), colorArrayOf( + ), colorArrayOf( "#F1F8E9", "#DCEDC8", "#C5E1A5", @@ -152,7 +169,7 @@ internal object ColorPalette { "#689F38", "#558B2F", "#33691E" - ), colorArrayOf( + ), colorArrayOf( "#F9FBE7", "#F0F4C3", "#E6EE9C", @@ -163,7 +180,7 @@ internal object ColorPalette { "#AFB42B", "#9E9D24", "#827717" - ), colorArrayOf( + ), colorArrayOf( "#FFFDE7", "#FFF9C4", "#FFF59D", @@ -174,7 +191,7 @@ internal object ColorPalette { "#FBC02D", "#F9A825", "#F57F17" - ), colorArrayOf( + ), colorArrayOf( "#FFF8E1", "#FFECB3", "#FFE082", @@ -185,7 +202,7 @@ internal object ColorPalette { "#FFA000", "#FF8F00", "#FF6F00" - ), colorArrayOf( + ), colorArrayOf( "#FFF3E0", "#FFE0B2", "#FFCC80", @@ -196,7 +213,7 @@ internal object ColorPalette { "#F57C00", "#EF6C00", "#E65100" - ), colorArrayOf( + ), colorArrayOf( "#FBE9E7", "#FFCCBC", "#FFAB91", @@ -207,7 +224,7 @@ internal object ColorPalette { "#E64A19", "#D84315", "#BF360C" - ), colorArrayOf( + ), colorArrayOf( "#EFEBE9", "#D7CCC8", "#BCAAA4", @@ -218,7 +235,7 @@ internal object ColorPalette { "#5D4037", "#4E342E", "#3E2723" - ), colorArrayOf( + ), colorArrayOf( "#FAFAFA", "#F5F5F5", "#EEEEEE", @@ -229,7 +246,7 @@ internal object ColorPalette { "#616161", "#424242", "#212121" - ), colorArrayOf( + ), colorArrayOf( "#ECEFF1", "#CFD8DC", "#B0BEC5", @@ -239,111 +256,117 @@ internal object ColorPalette { "#546E7A", "#455A64", "#37474F", - "#263238")) + "#263238" + ) + ) } val ACCENT_COLORS: IntArray by lazy { colorArrayOf( - "#FF1744", - "#F50057", - "#D500F9", - "#651FFF", - "#3D5AFE", - "#2979FF", - "#00B0FF", - "#00E5FF", - "#1DE9B6", - "#00E676", - "#76FF03", - "#C6FF00", - "#FFEA00", - "#FFC400", - "#FF9100", - "#FF3D00") + "#FF1744", + "#F50057", + "#D500F9", + "#651FFF", + "#3D5AFE", + "#2979FF", + "#00B0FF", + "#00E5FF", + "#1DE9B6", + "#00E676", + "#76FF03", + "#C6FF00", + "#FFEA00", + "#FFC400", + "#FF9100", + "#FF3D00" + ) } val ACCENT_COLORS_SUB: Array by lazy { - arrayOf(colorArrayOf("#FF8A80", + arrayOf( + colorArrayOf( + "#FF8A80", "#FF5252", "#FF1744", "#D50000" - ), colorArrayOf( + ), colorArrayOf( "#FF80AB", "#FF4081", "#F50057", "#C51162" - ), colorArrayOf( + ), colorArrayOf( "#EA80FC", "#E040FB", "#D500F9", "#AA00FF" - ), colorArrayOf( + ), colorArrayOf( "#B388FF", "#7C4DFF", "#651FFF", "#6200EA" - ), colorArrayOf( + ), colorArrayOf( "#8C9EFF", "#536DFE", "#3D5AFE", "#304FFE" - ), colorArrayOf( + ), colorArrayOf( "#82B1FF", "#448AFF", "#2979FF", "#2962FF" - ), colorArrayOf( + ), colorArrayOf( "#80D8FF", "#40C4FF", "#00B0FF", "#0091EA" - ), colorArrayOf( + ), colorArrayOf( "#84FFFF", "#18FFFF", "#00E5FF", "#00B8D4" - ), colorArrayOf( + ), colorArrayOf( "#A7FFEB", "#64FFDA", "#1DE9B6", "#00BFA5" - ), colorArrayOf( + ), colorArrayOf( "#B9F6CA", "#69F0AE", "#00E676", "#00C853" - ), colorArrayOf( + ), colorArrayOf( "#CCFF90", "#B2FF59", "#76FF03", "#64DD17" - ), colorArrayOf( + ), colorArrayOf( "#F4FF81", "#EEFF41", "#C6FF00", "#AEEA00" - ), colorArrayOf( + ), colorArrayOf( "#FFFF8D", "#FFFF00", "#FFEA00", "#FFD600" - ), colorArrayOf( + ), colorArrayOf( "#FFE57F", "#FFD740", "#FFC400", "#FFAB00" - ), colorArrayOf( + ), colorArrayOf( "#FFD180", "#FFAB40", "#FF9100", "#FF6D00" - ), colorArrayOf( + ), colorArrayOf( "#FF9E80", "#FF6E40", "#FF3D00", - "#DD2C00")) + "#DD2C00" + ) + ) } private fun colorArrayOf(vararg colors: String) = colors.map { Color.parseColor(it) }.toIntArray() } - diff --git a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerDialog.kt b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerDialog.kt index 6c4ad92..4202db1 100644 --- a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerDialog.kt +++ b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerDialog.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.colorpicker import android.content.Context @@ -86,4 +101,4 @@ fun Context.colorPickerDialog(contract: ColorContract): MaterialDialog { } view.bind(contract, dialog) return dialog -} \ No newline at end of file +} diff --git a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerView.kt b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerView.kt index 5174089..ab0b149 100644 --- a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerView.kt +++ b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerView.kt @@ -1,22 +1,54 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.colorpicker import android.annotation.SuppressLint import android.content.Context import android.graphics.Color -import androidx.annotation.ColorInt -import androidx.core.content.res.ResourcesCompat import android.text.Editable import android.text.InputFilter import android.text.TextWatcher import android.util.AttributeSet import android.view.View import android.view.ViewGroup -import android.widget.* -import ca.allanwang.kau.utils.* +import android.widget.AbsListView +import android.widget.BaseAdapter +import android.widget.EditText +import android.widget.LinearLayout +import android.widget.ScrollView +import android.widget.SeekBar +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.core.content.res.ResourcesCompat +import ca.allanwang.kau.utils.colorToForeground +import ca.allanwang.kau.utils.dimen +import ca.allanwang.kau.utils.fadeIn +import ca.allanwang.kau.utils.fadeOut +import ca.allanwang.kau.utils.gone +import ca.allanwang.kau.utils.isColorDark +import ca.allanwang.kau.utils.isColorVisibleOn +import ca.allanwang.kau.utils.isVisible +import ca.allanwang.kau.utils.resolveColor +import ca.allanwang.kau.utils.tint +import ca.allanwang.kau.utils.toHexString +import ca.allanwang.kau.utils.visible import com.afollestad.materialdialogs.DialogAction import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.color.FillGridView -import java.util.* +import java.util.Locale /** * Created by Allan Wang on 2017-06-08. @@ -24,7 +56,9 @@ import java.util.* * ColorPicker component of the ColorPickerDialog */ internal class ColorPickerView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 ) : ScrollView(context, attrs, defStyleAttr) { val selectedColor: Int get() = _selectedColor @@ -33,8 +67,10 @@ internal class ColorPickerView @JvmOverloads constructor( private var isInCustom: Boolean = false private var circleSize: Int = context.dimen(R.dimen.kau_color_circle_size).toInt() @SuppressLint("PrivateResource") - private val backgroundColor = context.resolveColor(R.attr.md_background_color, - if (context.resolveColor(android.R.attr.textColorPrimary).isColorDark) Color.WHITE else 0xff424242.toInt()) + private val backgroundColor = context.resolveColor( + R.attr.md_background_color, + if (context.resolveColor(android.R.attr.textColorPrimary).isColorDark) Color.WHITE else 0xff424242.toInt() + ) private val backgroundColorTint = backgroundColor.colorToForeground() private lateinit var dialog: MaterialDialog private lateinit var builder: ColorContract @@ -175,13 +211,17 @@ internal class ColorPickerView @JvmOverloads constructor( override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { if (fromUser) { val color = if (builder.allowCustomAlpha) - Color.argb(alphaSeekbar.progress, - redSeekbar.progress, - greenSeekbar.progress, - blueSeekbar.progress) - else Color.rgb(redSeekbar.progress, + Color.argb( + alphaSeekbar.progress, + redSeekbar.progress, greenSeekbar.progress, - blueSeekbar.progress) + blueSeekbar.progress + ) + else Color.rgb( + redSeekbar.progress, + greenSeekbar.progress, + blueSeekbar.progress + ) hexInput.setText(color.toHexString(builder.allowCustomAlpha, false)) } @@ -279,8 +319,8 @@ internal class ColorPickerView @JvmOverloads constructor( } private fun circleAt(index: Int): CircleView? = - if (index == -1) null - else gridView.getChildAt(index) as? CircleView + if (index == -1) null + else gridView.getChildAt(index) as? CircleView private val View.tagData: Pair? get() { @@ -316,4 +356,4 @@ internal class ColorPickerView @JvmOverloads constructor( } } } -} \ No newline at end of file +} diff --git a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/activities/ElasticRecyclerActivity.kt b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/activities/ElasticRecyclerActivity.kt index 5b0e97b..aff4d1c 100644 --- a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/activities/ElasticRecyclerActivity.kt +++ b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/activities/ElasticRecyclerActivity.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.ui.activities import android.os.Build @@ -43,7 +58,7 @@ abstract class ElasticRecyclerActivity : KauBaseActivity() { kau_draggable.addListener(object : ElasticDragDismissFrameLayout.SystemChromeFader(this) { override fun onDragDismissed() { window.returnTransition = TransitionInflater.from(this@ElasticRecyclerActivity) - .inflateTransition(if (kau_draggable.translationY > 0) configs.exitTransitionBottom else configs.exitTransitionTop) + .inflateTransition(if (kau_draggable.translationY > 0) configs.exitTransitionBottom else configs.exitTransitionTop) kau_recycler.stopScroll() finishAfterTransition() } @@ -64,6 +79,4 @@ abstract class ElasticRecyclerActivity : KauBaseActivity() { fun setOutsideTapListener(listener: () -> Unit) { kau_draggable.setOnClickListener { listener() } } - } - diff --git a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/BoundedCardView.kt b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/BoundedCardView.kt index 25a05df..9433d17 100644 --- a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/BoundedCardView.kt +++ b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/BoundedCardView.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.ui.views import android.content.Context @@ -7,7 +22,6 @@ import androidx.cardview.widget.CardView import ca.allanwang.kau.ui.R import ca.allanwang.kau.utils.parentViewGroup - /** * Created by Allan Wang on 2017-06-26. * @@ -16,7 +30,9 @@ import ca.allanwang.kau.utils.parentViewGroup * Defaults to at most the parent's visible height */ class BoundedCardView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 ) : CardView(context, attrs, defStyleAttr) { /** @@ -48,5 +64,4 @@ class BoundedCardView @JvmOverloads constructor( val trueHeightMeasureSpec = MeasureSpec.makeMeasureSpec(maxMeasureHeight, MeasureSpec.AT_MOST) super.onMeasure(widthMeasureSpec, trueHeightMeasureSpec) } - -} \ No newline at end of file +} diff --git a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/CutoutView.kt b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/CutoutView.kt index eeaac6e..6da65a3 100644 --- a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/CutoutView.kt +++ b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/CutoutView.kt @@ -1,11 +1,11 @@ /* - * Copyright 2015 Google Inc. + * Copyright 2018 Allan Wang * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,11 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package ca.allanwang.kau.ui.views import android.content.Context -import android.graphics.* +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.PorterDuff +import android.graphics.PorterDuffXfermode +import android.graphics.Rect import android.graphics.drawable.Drawable import android.text.TextPaint import android.util.AttributeSet @@ -32,9 +36,13 @@ import ca.allanwang.kau.utils.toBitmap /** * A view which punches out some text from an opaque color block, allowing you to see through it. + * + * Inspired by Plaid */ class CutoutView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { companion object { @@ -107,8 +115,10 @@ class CutoutView @JvmOverloads constructor( private fun calculateTextPosition() { val targetWidth = width / PHI - textSize = getSingleLineTextSize(text!!, paint, targetWidth, 0f, maxTextSize, - 0.5f, resources.displayMetrics) + textSize = getSingleLineTextSize( + text!!, paint, targetWidth, 0f, maxTextSize, + 0.5f, resources.displayMetrics + ) paint.textSize = textSize // measuring text is fun :] see: https://chris.banes.me/2014/03/27/measuring-text/ @@ -145,13 +155,15 @@ class CutoutView @JvmOverloads constructor( * Adapted from https://github.com/grantland/android-autofittextview */ - fun getSingleLineTextSize(text: String, - paint: TextPaint, - targetWidth: Float, - low: Float, - high: Float, - precision: Float, - metrics: DisplayMetrics): Float { + fun getSingleLineTextSize( + text: String, + paint: TextPaint, + targetWidth: Float, + low: Float, + high: Float, + precision: Float, + metrics: DisplayMetrics + ): Float { val mid = (low + high) / 2.0f paint.textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, mid, metrics) @@ -180,7 +192,12 @@ class CutoutView @JvmOverloads constructor( cutoutCanvas.drawText(text!!, cutoutX, cutoutY, paint) } TYPE_DRAWABLE -> { - cutoutCanvas.drawBitmap(drawable!!.toBitmap(bitmapScaling, Bitmap.Config.ALPHA_8), cutoutX, cutoutY, paint) + cutoutCanvas.drawBitmap( + drawable!!.toBitmap(bitmapScaling, Bitmap.Config.ALPHA_8), + cutoutX, + cutoutY, + paint + ) } TYPE_EMPTY -> { // do nothing @@ -193,5 +210,4 @@ class CutoutView @JvmOverloads constructor( } override fun hasOverlappingRendering(): Boolean = true - } diff --git a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/MeasuredImageView.kt b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/MeasuredImageView.kt index 5cb4329..ef95ed3 100644 --- a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/MeasuredImageView.kt +++ b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/views/MeasuredImageView.kt @@ -1,14 +1,31 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.ui.views import android.content.Context -import androidx.appcompat.widget.AppCompatImageView import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatImageView /** * Created by Allan Wang on 2017-07-14. */ class MeasuredImageView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 ) : AppCompatImageView(context, attrs, defStyleAttr), MeasureSpecContract by MeasureSpecDelegate() { init { @@ -19,5 +36,4 @@ class MeasuredImageView @JvmOverloads constructor( val result = onMeasure(this, widthMeasureSpec, heightMeasureSpec) super.onMeasure(result.first, result.second) } - -} \ No newline at end of file +} diff --git a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/ElasticDragDismissFrameLayout.kt b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/ElasticDragDismissFrameLayout.kt index b89373e..f4578f2 100644 --- a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/ElasticDragDismissFrameLayout.kt +++ b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/ElasticDragDismissFrameLayout.kt @@ -1,11 +1,11 @@ /* - * Copyright 2015 Google Inc. + * Copyright 2018 Allan Wang * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,22 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package ca.allanwang.kau.ui.widgets import android.app.Activity import android.content.Context import android.graphics.Color import android.os.Build -import androidx.annotation.RequiresApi import android.transition.TransitionInflater import android.util.AttributeSet import android.view.MotionEvent import android.view.View import android.widget.FrameLayout +import androidx.annotation.RequiresApi import ca.allanwang.kau.logging.KL import ca.allanwang.kau.ui.R -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.AnimHolder +import ca.allanwang.kau.utils.dimen +import ca.allanwang.kau.utils.dpToPx +import ca.allanwang.kau.utils.isNavBarOnBottom +import ca.allanwang.kau.utils.navigationBarColor +import ca.allanwang.kau.utils.scaleXY +import ca.allanwang.kau.utils.statusBarColor +import ca.allanwang.kau.utils.withAlpha /** * A [FrameLayout] which responds to nested scrolls to create drag-dismissable layouts. @@ -37,7 +43,10 @@ import ca.allanwang.kau.utils.* */ @RequiresApi(Build.VERSION_CODES.LOLLIPOP) class ElasticDragDismissFrameLayout @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0 + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + defStyleRes: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr, defStyleRes) { // configurable attribs @@ -62,8 +71,11 @@ class ElasticDragDismissFrameLayout @JvmOverloads constructor( init { if (attrs != null) { val a = getContext().obtainStyledAttributes(attrs, R.styleable.ElasticDragDismissFrameLayout, 0, 0) - dragDismissDistance = a.getDimensionPixelSize(R.styleable.ElasticDragDismissFrameLayout_dragDismissDistance, Int.MAX_VALUE).toFloat() - dragDismissFraction = a.getFloat(R.styleable.ElasticDragDismissFrameLayout_dragDismissFraction, dragDismissFraction) + dragDismissDistance = + a.getDimensionPixelSize(R.styleable.ElasticDragDismissFrameLayout_dragDismissDistance, Int.MAX_VALUE) + .toFloat() + dragDismissFraction = + a.getFloat(R.styleable.ElasticDragDismissFrameLayout_dragDismissFraction, dragDismissFraction) dragDismissScale = a.getFloat(R.styleable.ElasticDragDismissFrameLayout_dragDismissScale, dragDismissScale) dragElacticity = a.getFloat(R.styleable.ElasticDragDismissFrameLayout_dragElasticity, dragElacticity) a.recycle() @@ -74,27 +86,27 @@ class ElasticDragDismissFrameLayout @JvmOverloads constructor( /** * Called for each drag event. - - * @param elasticOffset Indicating the drag offset with elasticity applied i.e. may - * * exceed 1. - * * + * @param elasticOffset Indicating the drag offset with elasticity applied i.e. may exceed 1. + * * @param elasticOffsetPixels The elastically scaled drag distance in pixels. - * * - * @param rawOffset Value from [0, 1] indicating the raw drag offset i.e. - * * without elasticity applied. A value of 1 indicates that the - * * dismiss distance has been reached. - * * - * @param rawOffsetPixels The raw distance the user has dragged + * + * @param rawOffset Value from [0, 1] indicating the raw drag offset i.e. without elasticity applied. + * A value of 1 indicates that the dismiss distance has been reached. + * + * @param rawOffsetPixels The raw distance the user has dragged */ - internal open fun onDrag(elasticOffset: Float, elasticOffsetPixels: Float, - rawOffset: Float, rawOffsetPixels: Float) { + internal open fun onDrag( + elasticOffset: Float, + elasticOffsetPixels: Float, + rawOffset: Float, + rawOffsetPixels: Float + ) { } /** * Called when dragging is released and has exceeded the threshold dismiss distance. */ internal open fun onDragDismissed() {} - } override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { @@ -114,8 +126,13 @@ class ElasticDragDismissFrameLayout @JvmOverloads constructor( } } - override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, - dxUnconsumed: Int, dyUnconsumed: Int) { + override fun onNestedScroll( + target: View, + dxConsumed: Int, + dyConsumed: Int, + dxUnconsumed: Int, + dyUnconsumed: Int + ) { dragScale(dyUnconsumed) } @@ -129,12 +146,12 @@ class ElasticDragDismissFrameLayout @JvmOverloads constructor( scaleXY = 1f } else { animate() - .translationY(0f) - .scaleXY(1f) - .setDuration(200L) - .setInterpolator(AnimHolder.fastOutSlowInInterpolator(context)) - .setListener(null) - .start() + .translationY(0f) + .scaleXY(1f) + .setDuration(200L) + .setInterpolator(AnimHolder.fastOutSlowInInterpolator(context)) + .setListener(null) + .start() } totalDrag = 0f @@ -201,15 +218,23 @@ class ElasticDragDismissFrameLayout @JvmOverloads constructor( translationY = 0f scaleXY = 1f } - dispatchDragCallback(dragFraction, dragTo, - Math.min(1f, Math.abs(totalDrag) / dragDismissDistance), totalDrag) + dispatchDragCallback( + dragFraction, dragTo, + Math.min(1f, Math.abs(totalDrag) / dragDismissDistance), totalDrag + ) } - private fun dispatchDragCallback(elasticOffset: Float, elasticOffsetPixels: Float, - rawOffset: Float, rawOffsetPixels: Float) { + private fun dispatchDragCallback( + elasticOffset: Float, + elasticOffsetPixels: Float, + rawOffset: Float, + rawOffsetPixels: Float + ) { callbacks.forEach { - it.onDrag(elasticOffset, elasticOffsetPixels, - rawOffset, rawOffsetPixels) + it.onDrag( + elasticOffset, elasticOffsetPixels, + rawOffset, rawOffsetPixels + ) } } @@ -227,8 +252,12 @@ class ElasticDragDismissFrameLayout @JvmOverloads constructor( private val navBarAlpha: Int = Color.alpha(activity.navigationBarColor) private val fadeNavBar: Boolean = activity.isNavBarOnBottom - public override fun onDrag(elasticOffset: Float, elasticOffsetPixels: Float, - rawOffset: Float, rawOffsetPixels: Float) { + public override fun onDrag( + elasticOffset: Float, + elasticOffsetPixels: Float, + rawOffset: Float, + rawOffsetPixels: Float + ) { if (elasticOffsetPixels > 0) { // dragging downward, fade the status bar in proportion activity.statusBarColor = activity.statusBarColor.withAlpha(((1f - rawOffset) * statusBarAlpha).toInt()) @@ -238,7 +267,8 @@ class ElasticDragDismissFrameLayout @JvmOverloads constructor( activity.navigationBarColor = activity.navigationBarColor.withAlpha(navBarAlpha) } else if (fadeNavBar) { // dragging upward, fade the navigation bar in proportion - activity.navigationBarColor = activity.navigationBarColor.withAlpha(((1f - rawOffset) * navBarAlpha).toInt()) + activity.navigationBarColor = + activity.navigationBarColor.withAlpha(((1f - rawOffset) * navBarAlpha).toInt()) } } @@ -247,15 +277,18 @@ class ElasticDragDismissFrameLayout @JvmOverloads constructor( } } - fun addExitListener(activity: Activity, transitionBottom: Int = R.transition.kau_exit_slide_bottom, transitionTop: Int = R.transition.kau_exit_slide_top) { + fun addExitListener( + activity: Activity, + transitionBottom: Int = R.transition.kau_exit_slide_bottom, + transitionTop: Int = R.transition.kau_exit_slide_top + ) { addListener(object : ElasticDragDismissFrameLayout.SystemChromeFader(activity) { override fun onDragDismissed() { KL.v { "New transition" } activity.window.returnTransition = TransitionInflater.from(activity) - .inflateTransition(if (translationY > 0) transitionBottom else transitionTop) + .inflateTransition(if (translationY > 0) transitionBottom else transitionTop) activity.finishAfterTransition() } }) } - } diff --git a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/TextSlider.kt b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/TextSlider.kt index a53ee9d..51f7ab9 100644 --- a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/TextSlider.kt +++ b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/TextSlider.kt @@ -1,8 +1,22 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.ui.widgets import android.content.Context import android.graphics.Color -import androidx.core.widget.TextViewCompat import android.text.TextUtils import android.util.AttributeSet import android.view.Gravity @@ -10,8 +24,10 @@ import android.view.animation.Animation import android.view.animation.AnimationUtils import android.widget.TextSwitcher import android.widget.TextView +import androidx.core.widget.TextViewCompat import ca.allanwang.kau.ui.R -import java.util.* +import java.util.EmptyStackException +import java.util.Stack /** * Created by Allan Wang on 2017-06-21. @@ -19,7 +35,9 @@ import java.util.* * Text switcher with global text color and embedded sliding animations * Also has a stack to keep track of title changes */ -class TextSlider @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null +class TextSlider @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null ) : TextSwitcher(context, attrs) { val titleStack: Stack = Stack() @@ -28,20 +46,26 @@ class TextSlider @JvmOverloads constructor(context: Context, attrs: AttributeSet * Holds a mapping of animation types to their respective animations */ val animationMap = mapOf( - ANIMATION_NONE to null, - ANIMATION_SLIDE_HORIZONTAL to AnimationBundle( - R.anim.kau_slide_in_right, R.anim.kau_slide_out_left, - R.anim.kau_slide_in_left, R.anim.kau_slide_out_right), - ANIMATION_SLIDE_VERTICAL to AnimationBundle( - R.anim.kau_slide_in_bottom, R.anim.kau_slide_out_top, - R.anim.kau_slide_in_top, R.anim.kau_slide_out_bottom - ) + ANIMATION_NONE to null, + ANIMATION_SLIDE_HORIZONTAL to AnimationBundle( + R.anim.kau_slide_in_right, R.anim.kau_slide_out_left, + R.anim.kau_slide_in_left, R.anim.kau_slide_out_right + ), + ANIMATION_SLIDE_VERTICAL to AnimationBundle( + R.anim.kau_slide_in_bottom, R.anim.kau_slide_out_top, + R.anim.kau_slide_in_top, R.anim.kau_slide_out_bottom + ) ) /** * Holds lazy instances of the animations */ - inner class AnimationBundle(private val nextIn: Int, private val nextOut: Int, private val prevIn: Int, private val prevOut: Int) { + inner class AnimationBundle( + private val nextIn: Int, + private val nextOut: Int, + private val prevIn: Int, + private val prevOut: Int + ) { val NEXT_IN: Animation by lazy { AnimationUtils.loadAnimation(context, nextIn) } val NEXT_OUT: Animation by lazy { AnimationUtils.loadAnimation(context, nextOut) } val PREV_IN: Animation by lazy { AnimationUtils.loadAnimation(context, prevIn) } @@ -122,4 +146,4 @@ class TextSlider @JvmOverloads constructor(context: Context, attrs: AttributeSet } } } -} \ No newline at end of file +} diff --git a/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt index 52f344b..29f5af1 100644 --- a/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt +++ b/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref import android.annotation.SuppressLint @@ -84,11 +99,9 @@ class KPrefTest { assertEquals(-1, pref.one, "Kpref did not refetch from shared prefs upon reset") } - @Test fun single() { assertTrue(pref.oneShot) assertFalse(pref.oneShot) } - -} \ No newline at end of file +} diff --git a/core/src/androidTest/kotlin/ca/allanwang/kau/utils/KotterknifeTest.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/utils/KotterknifeTest.kt index 13a3c77..96ebd3a 100644 --- a/core/src/androidTest/kotlin/ca/allanwang/kau/utils/KotterknifeTest.kt +++ b/core/src/androidTest/kotlin/ca/allanwang/kau/utils/KotterknifeTest.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.content.Context @@ -197,4 +212,4 @@ class KotterknifeTest { view.id = id return view } -} \ No newline at end of file +} diff --git a/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt index 7a6d2e0..2d02dbc 100644 --- a/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt +++ b/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.xml import android.content.Context @@ -25,7 +40,11 @@ class FaqTest { assertEquals(2, data.size, "FAQ size is incorrect") assertEquals("1. This is a question", data.first().question.toString(), "First question does not match") assertEquals("This is an answer", data.first().answer.toString(), "First answer does not match") - assertEquals("2. This is another question", data.last().question.toString(), "Second question does not match") + assertEquals( + "2. This is another question", + data.last().question.toString(), + "Second question does not match" + ) assertEquals("This is another answer", data.last().answer.toString(), "Second answer does not match") } } @@ -40,5 +59,4 @@ class FaqTest { assertEquals("This is another answer", data.last().answer.toString(), "Second answer does not match") } } - -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/email/EmailBuilder.kt b/core/src/main/kotlin/ca/allanwang/kau/email/EmailBuilder.kt index 0184b9a..e6ad97a 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/email/EmailBuilder.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/email/EmailBuilder.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.email import android.app.Activity @@ -6,12 +21,15 @@ import android.content.Intent import android.content.pm.PackageManager import android.net.Uri import android.os.Build -import androidx.annotation.StringRes import android.util.DisplayMetrics +import androidx.annotation.StringRes import ca.allanwang.kau.R import ca.allanwang.kau.logging.KL -import ca.allanwang.kau.utils.* - +import ca.allanwang.kau.utils.boolean +import ca.allanwang.kau.utils.installerPackageName +import ca.allanwang.kau.utils.isAppInstalled +import ca.allanwang.kau.utils.string +import ca.allanwang.kau.utils.toast /** * Created by Allan Wang on 2017-06-20. @@ -28,7 +46,7 @@ class EmailBuilder(val email: String, val subject: String) { private var attachment: Uri? = null fun checkPackage(packageName: String, appName: String) = - packages.add(Package(packageName, appName)) + packages.add(Package(packageName, appName)) fun addItem(key: String, value: String) = pairs.put(key, value) @@ -45,19 +63,19 @@ class EmailBuilder(val email: String, val subject: String) { fun getIntent(context: Context): Intent { val intent = Intent(Intent.ACTION_SEND) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .putExtra(Intent.EXTRA_EMAIL, arrayOf(email)) - .putExtra(Intent.EXTRA_SUBJECT, subject) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .putExtra(Intent.EXTRA_EMAIL, arrayOf(email)) + .putExtra(Intent.EXTRA_SUBJECT, subject) val emailBuilder = StringBuilder() emailBuilder.append(message).append("\n\n") if (deviceDetails) { val deviceItems = mutableMapOf( - "OS Version" to "${System.getProperty("os.version")} (${Build.VERSION.INCREMENTAL})", - "OS SDK" to Build.VERSION.SDK_INT, - "Device (Manufacturer)" to "${Build.DEVICE} (${Build.MANUFACTURER})", - "Model (Product)" to "${Build.MODEL} (${Build.PRODUCT})", - "Package Installer" to (context.installerPackageName ?: "None"), - "Tablet" to context.boolean(R.bool.kau_is_tablet) + "OS Version" to "${System.getProperty("os.version")} (${Build.VERSION.INCREMENTAL})", + "OS SDK" to Build.VERSION.SDK_INT, + "Device (Manufacturer)" to "${Build.DEVICE} (${Build.MANUFACTURER})", + "Model (Product)" to "${Build.MODEL} (${Build.PRODUCT})", + "Package Installer" to (context.installerPackageName ?: "None"), + "Tablet" to context.boolean(R.bool.kau_is_tablet) ) if (context is Activity) { val metric = DisplayMetrics() @@ -75,8 +93,8 @@ class EmailBuilder(val email: String, val subject: String) { appInfo.versionCode.toString() } emailBuilder.append("\nApp: ").append(context.packageName) - .append("\nApp Version Name: ").append(appInfo.versionName) - .append("\nApp Version Code: ").append(versionCode).append("\n") + .append("\nApp Version Name: ").append(appInfo.versionName) + .append("\nApp Version Code: ").append(versionCode).append("\n") } catch (e: PackageManager.NameNotFoundException) { KL.e { "EmailBuilder packageInfo not found" } } @@ -111,7 +129,7 @@ class EmailBuilder(val email: String, val subject: String) { val intent = getIntent(context) intent.extras() val packageName = intent.resolveActivity(context.packageManager)?.packageName - ?: return context.toast(R.string.kau_error_no_email, log = true) + ?: return context.toast(R.string.kau_error_no_email, log = true) val attachment = this.attachment if (attachment != null) { @@ -123,12 +141,12 @@ class EmailBuilder(val email: String, val subject: String) { } } -fun Context.sendEmail(@StringRes emailId: Int, @StringRes subjectId: Int, builder: EmailBuilder.() -> Unit = {}) = sendEmail(string(emailId), string(subjectId), builder) - +fun Context.sendEmail(@StringRes emailId: Int, @StringRes subjectId: Int, builder: EmailBuilder.() -> Unit = {}) = + sendEmail(string(emailId), string(subjectId), builder) fun Context.sendEmail(email: String, subject: String, builder: EmailBuilder.() -> Unit = {}) { EmailBuilder(email, subject).apply { builder() execute(this@sendEmail) } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt b/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt index c71761d..85e711b 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.internal import androidx.appcompat.app.AppCompatActivity @@ -18,4 +33,4 @@ abstract class KauBaseActivity : AppCompatActivity() { super.onRequestPermissionsResult(requestCode, permissions, grantResults) kauOnRequestPermissionsResult(permissions, grantResults) } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Debouncer.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Debouncer.kt index de5d148..ea13f73 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Debouncer.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Debouncer.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kotlin import ca.allanwang.kau.logging.KL @@ -56,7 +71,6 @@ open class Debouncer(var interval: Long) { task = null } } - } /* diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/FlyWeight.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/FlyWeight.kt index 03e98d2..165295a 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/FlyWeight.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kotlin/FlyWeight.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kotlin /** @@ -36,5 +51,4 @@ class FlyWeight(private val creator: (key: K) -> V) : Map(private val initializer: (context: Context) -> T, lock: } } } - -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyResettable.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyResettable.kt index 979f7a7..ee38d48 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyResettable.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyResettable.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kotlin import java.io.Serializable @@ -80,4 +95,4 @@ class LazyResettableRegistry : ILazyResettableRegistry { override fun invalidateAll() = lazyRegistry.forEach { it.invalidate() } override fun clear() = lazyRegistry.clear() -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Streams.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Streams.kt index 303153f..bfa73fd 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Streams.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Streams.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kotlin /** @@ -27,4 +42,4 @@ inline fun Iterator.firstOrNull(predicate: (T) -> Boolean): T? { if (predicate(data)) return data } return null -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Utils.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Utils.kt index 1ba1de6..1e35ecf 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Utils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Utils.kt @@ -1,6 +1,21 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kotlin /** * Created by Allan Wang on 07/04/18. */ -inline fun javaClass(): Class = T::class.java \ No newline at end of file +inline fun javaClass(): Class = T::class.java diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt index 17ae5e5..b767b30 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kotlin import org.jetbrains.anko.doAsync @@ -48,7 +63,8 @@ class ZipEmptyCallback(val onReceived: () -> Unit) : ZipCallbackBase() { * ALl tasks must invoke the task callback for [onFinished] to execute */ inline fun Collection<(ZipCallback) -> Unit>.zip( - defaultResult: T, crossinline onFinished: (results: Array) -> Unit + defaultResult: T, + crossinline onFinished: (results: Array) -> Unit ) { val result = Array(size) { defaultResult } val countDown = AtomicInteger(size) diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt index 12f9606..7a6330f 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref import android.content.Context @@ -47,5 +62,4 @@ open class KPref { operator fun get(key: String): ILazyResettable<*>? = prefMap[key] open fun deleteKeys(): Array = arrayOf() - -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt index b80479e..9813f24 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt @@ -1,31 +1,47 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref import ca.allanwang.kau.kotlin.ILazyResettable - fun KPref.kpref(key: String, fallback: Boolean, postSetter: (value: Boolean) -> Unit = {}) = - KPrefDelegate(key, fallback, this, KPrefBooleanTransaction, postSetter) + KPrefDelegate(key, fallback, this, KPrefBooleanTransaction, postSetter) fun KPref.kpref(key: String, fallback: Float, postSetter: (value: Float) -> Unit = {}) = - KPrefDelegate(key, fallback, this, KPrefFloatTransaction, postSetter) + KPrefDelegate(key, fallback, this, KPrefFloatTransaction, postSetter) -@Deprecated("Double is not supported in SharedPreferences; cast to float yourself", - ReplaceWith("kpref(key, fallback.toFloat(), postSetter)"), - DeprecationLevel.WARNING) +@Deprecated( + "Double is not supported in SharedPreferences; cast to float yourself", + ReplaceWith("kpref(key, fallback.toFloat(), postSetter)"), + DeprecationLevel.WARNING +) fun KPref.kpref(key: String, fallback: Double, postSetter: (value: Float) -> Unit = {}) = - kpref(key, fallback.toFloat(), postSetter) + kpref(key, fallback.toFloat(), postSetter) fun KPref.kpref(key: String, fallback: Int, postSetter: (value: Int) -> Unit = {}) = - KPrefDelegate(key, fallback, this, KPrefIntTransaction, postSetter) + KPrefDelegate(key, fallback, this, KPrefIntTransaction, postSetter) fun KPref.kpref(key: String, fallback: Long, postSetter: (value: Long) -> Unit = {}) = - KPrefDelegate(key, fallback, this, KPrefLongTransaction, postSetter) + KPrefDelegate(key, fallback, this, KPrefLongTransaction, postSetter) fun KPref.kpref(key: String, fallback: Set, postSetter: (value: Set) -> Unit = {}) = - KPrefDelegate(key, fallback, this, KPrefSetTransaction, postSetter) + KPrefDelegate(key, fallback, this, KPrefSetTransaction, postSetter) fun KPref.kpref(key: String, fallback: String, postSetter: (value: String) -> Unit = {}) = - KPrefDelegate(key, fallback, this, KPrefStringTransaction, postSetter) + KPrefDelegate(key, fallback, this, KPrefStringTransaction, postSetter) /** * Created by Allan Wang on 2017-06-07. @@ -35,11 +51,11 @@ fun KPref.kpref(key: String, fallback: String, postSetter: (value: String) -> Un * Also contains an optional mutable postSetter that will be called every time a new value is given */ class KPrefDelegate internal constructor( - private val key: String, - private val fallback: T, - private val pref: KPref, - private val transaction: KPrefTransaction, - private var postSetter: (value: T) -> Unit = {} + private val key: String, + private val fallback: T, + private val pref: KPref, + private val transaction: KPrefTransaction, + private var postSetter: (value: T) -> Unit = {} ) : ILazyResettable { private object UNINITIALIZED @@ -91,4 +107,4 @@ class KPrefDelegate internal constructor( } } -class KPrefException(message: String) : IllegalAccessException(message) \ No newline at end of file +class KPrefException(message: String) : IllegalAccessException(message) diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefSingleDelegate.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefSingleDelegate.kt index ed30a44..204e07e 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefSingleDelegate.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefSingleDelegate.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref import ca.allanwang.kau.kotlin.ILazyResettable @@ -12,7 +27,8 @@ fun KPref.kprefSingle(key: String) = KPrefSingleDelegate(key, this) * All subsequent retrievals will be [false] * This is useful for one time toggles such as showcasing items */ -class KPrefSingleDelegate internal constructor(private val key: String, private val pref: KPref, lock: Any? = null) : ILazyResettable { +class KPrefSingleDelegate internal constructor(private val key: String, private val pref: KPref, lock: Any? = null) : + ILazyResettable { @Volatile private var _value: Boolean? = null @@ -52,5 +68,4 @@ class KPrefSingleDelegate internal constructor(private val key: String, private override fun isInitialized(): Boolean = _value != null override fun toString(): String = if (isInitialized()) value.toString() else "Lazy kPref $key not initialized yet." - -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefTransaction.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefTransaction.kt index 773d208..1070e11 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefTransaction.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefTransaction.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref import android.content.SharedPreferences @@ -9,7 +24,7 @@ internal interface KPrefTransaction { internal object KPrefBooleanTransaction : KPrefTransaction { override fun get(prefs: SharedPreferences, key: String, fallback: Boolean) = - prefs.getBoolean(key, fallback) + prefs.getBoolean(key, fallback) override fun set(editor: SharedPreferences.Editor, key: String, data: Boolean) { editor.putBoolean(key, data) @@ -18,7 +33,7 @@ internal object KPrefBooleanTransaction : KPrefTransaction { internal object KPrefIntTransaction : KPrefTransaction { override fun get(prefs: SharedPreferences, key: String, fallback: Int) = - prefs.getInt(key, fallback) + prefs.getInt(key, fallback) override fun set(editor: SharedPreferences.Editor, key: String, data: Int) { editor.putInt(key, data) @@ -27,7 +42,7 @@ internal object KPrefIntTransaction : KPrefTransaction { internal object KPrefLongTransaction : KPrefTransaction { override fun get(prefs: SharedPreferences, key: String, fallback: Long) = - prefs.getLong(key, fallback) + prefs.getLong(key, fallback) override fun set(editor: SharedPreferences.Editor, key: String, data: Long) { editor.putLong(key, data) @@ -36,7 +51,7 @@ internal object KPrefLongTransaction : KPrefTransaction { internal object KPrefFloatTransaction : KPrefTransaction { override fun get(prefs: SharedPreferences, key: String, fallback: Float) = - prefs.getFloat(key, fallback) + prefs.getFloat(key, fallback) override fun set(editor: SharedPreferences.Editor, key: String, data: Float) { editor.putFloat(key, data) @@ -45,7 +60,7 @@ internal object KPrefFloatTransaction : KPrefTransaction { internal object KPrefStringTransaction : KPrefTransaction { override fun get(prefs: SharedPreferences, key: String, fallback: String) = - prefs.getString(key, fallback) + prefs.getString(key, fallback) override fun set(editor: SharedPreferences.Editor, key: String, data: String) { editor.putString(key, data) @@ -54,11 +69,9 @@ internal object KPrefStringTransaction : KPrefTransaction { internal object KPrefSetTransaction : KPrefTransaction> { override fun get(prefs: SharedPreferences, key: String, fallback: Set) = - prefs.getStringSet(key, fallback)!! + prefs.getStringSet(key, fallback)!! override fun set(editor: SharedPreferences.Editor, key: String, data: Set) { editor.putStringSet(key, data) } } - - diff --git a/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt b/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt index 9f48ab5..f92edb3 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.logging import ca.allanwang.kau.BuildConfig @@ -7,4 +22,4 @@ import ca.allanwang.kau.BuildConfig * * Internal KAU logger */ -object KL : KauLogger("KAU", { BuildConfig.DEBUG }) \ No newline at end of file +object KL : KauLogger("KAU", { BuildConfig.DEBUG }) diff --git a/core/src/main/kotlin/ca/allanwang/kau/logging/KauLogger.kt b/core/src/main/kotlin/ca/allanwang/kau/logging/KauLogger.kt index 799d32f..d01859f 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/logging/KauLogger.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/logging/KauLogger.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ @file:Suppress("NOTHING_TO_INLINE") package ca.allanwang.kau.logging @@ -25,15 +40,15 @@ import android.util.Log * for production builds */ open class KauLogger( - /** - * Tag to be used for each log - */ - val tag: String, - /** - * Toggle to dictate whether a message should be logged - */ - var shouldLog: (priority: Int) -> Boolean = { true }) { - + /** + * Tag to be used for each log + */ + val tag: String, + /** + * Toggle to dictate whether a message should be logged + */ + var shouldLog: (priority: Int) -> Boolean = { true } +) { inline fun v(message: () -> Any?) = log(Log.VERBOSE, message) @@ -96,11 +111,11 @@ class KauLoggerExtension(val tag: String, val logger: KauLogger) { } inline fun log(priority: Int, message: () -> Any?, t: Throwable? = null) = - logger.log(priority, { - val msg = message()?.toString() - if (msg == null) null - else "$tag: $msg" - }, t) + logger.log(priority, { + val msg = message()?.toString() + if (msg == null) null + else "$tag: $msg" + }, t) inline fun checkThread(id: Int) { d { diff --git a/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt b/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt index 922dc09..57a6f42 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.permissions import android.app.Activity @@ -12,7 +27,6 @@ import ca.allanwang.kau.utils.hasPermission import ca.allanwang.kau.utils.toast import java.lang.ref.WeakReference - /** * Created by Allan Wang on 2017-07-03. * @@ -30,13 +44,17 @@ internal object PermissionManager { private val manifestPermission = lazyContext> { try { it.packageManager.getPackageInfo(it.packageName, PackageManager.GET_PERMISSIONS)?.requestedPermissions - ?: emptyArray() + ?: emptyArray() } catch (e: Exception) { emptyArray() } } - operator fun invoke(context: Context, permissions: Array, callback: (granted: Boolean, deniedPerm: String?) -> Unit) { + operator fun invoke( + context: Context, + permissions: Array, + callback: (granted: Boolean, deniedPerm: String?) -> Unit + ) { KL.d { "Permission manager for: ${permissions.contentToString()}" } if (!buildIsMarshmallowAndUp) return callback(true, null) val missingPermissions = permissions.filter { !context.hasPermission(it) } @@ -58,7 +76,7 @@ internal object PermissionManager { } } val activity = (context as? Activity) - ?: throw KauException("Context is not an instance of an activity; cannot request permissions") + ?: throw KauException("Context is not an instance of an activity; cannot request permissions") KL.i { "Requesting permissions ${permissions.contentToString()}" } ActivityCompat.requestPermissions(activity, permissions, 1) } @@ -89,5 +107,4 @@ internal object PermissionManager { } KL.i { "Post on permission result: pending ${pendingResults.size}" } } - -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionResult.kt b/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionResult.kt index ba3e6dd..8888c91 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionResult.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionResult.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.permissions import android.content.pm.PackageManager @@ -25,4 +40,4 @@ class PermissionResult(permissions: Array, val callback: (granted: B callback(true, null) return true } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt b/core/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt index 83cd2ed..3c90b05 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/permissions/Permissions.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.permissions import android.Manifest @@ -6,7 +21,6 @@ import android.content.Context import android.os.Build import androidx.annotation.RequiresApi - /** * Created by Allan Wang on 2017-07-02. * @@ -22,7 +36,8 @@ import androidx.annotation.RequiresApi /** * Hook that should be added inside all [Activity.onRequestPermissionsResult] so that the Permission manager can handle the responses */ -fun Activity.kauOnRequestPermissionsResult(permissions: Array, grantResults: IntArray) = PermissionManager.onRequestPermissionsResult(this, permissions, grantResults) +fun Activity.kauOnRequestPermissionsResult(permissions: Array, grantResults: IntArray) = + PermissionManager.onRequestPermissionsResult(this, permissions, grantResults) /** * Request a permission with a callback @@ -31,7 +46,10 @@ fun Activity.kauOnRequestPermissionsResult(permissions: Array, grant * The [callback] returns [granted], which is true if all permissions are granted * [deniedPerm] is the first denied permission, if granted is false */ -fun Context.kauRequestPermissions(vararg permissions: String, callback: (granted: Boolean, deniedPerm: String?) -> Unit) = PermissionManager(this, permissions, callback) +fun Context.kauRequestPermissions( + vararg permissions: String, + callback: (granted: Boolean, deniedPerm: String?) -> Unit +) = PermissionManager(this, permissions, callback) /** * See http://developer.android.com/guide/topics/security/permissions.html#normal-dangerous for a @@ -72,4 +90,4 @@ const val PERMISSION_RECEIVE_MMS = Manifest.permission.RECEIVE_MMS const val PERMISSION_READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE const val PERMISSION_WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE -const val PERMISSION_SYSTEM_ALERT_WINDOW = Manifest.permission.SYSTEM_ALERT_WINDOW \ No newline at end of file +const val PERMISSION_SYSTEM_ALERT_WINDOW = Manifest.permission.SYSTEM_ALERT_WINDOW diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/RelativeSlider.kt b/core/src/main/kotlin/ca/allanwang/kau/swipe/RelativeSlider.kt index f14f5cf..0b1dd88 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/swipe/RelativeSlider.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/RelativeSlider.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.swipe /** @@ -30,10 +45,14 @@ internal class RelativeSlider(var curPage: SwipeBackPage) : SwipeListener { return } when (edgeFlag) { - SWIPE_EDGE_LEFT -> page.swipeBackLayout.x = Math.min(-offset * Math.max(1 - percent, 0f) + DEFAULT_OFFSET, 0f) - SWIPE_EDGE_RIGHT -> page.swipeBackLayout.x = Math.min(offset * Math.max(1 - percent, 0f) - DEFAULT_OFFSET, 0f) - SWIPE_EDGE_TOP -> page.swipeBackLayout.y = Math.min(-offset * Math.max(1 - percent, 0f) + DEFAULT_OFFSET, 0f) - SWIPE_EDGE_BOTTOM -> page.swipeBackLayout.y = Math.min(offset * Math.max(1 - percent, 0f) - DEFAULT_OFFSET, 0f) + SWIPE_EDGE_LEFT -> page.swipeBackLayout.x = + Math.min(-offset * Math.max(1 - percent, 0f) + DEFAULT_OFFSET, 0f) + SWIPE_EDGE_RIGHT -> page.swipeBackLayout.x = + Math.min(offset * Math.max(1 - percent, 0f) - DEFAULT_OFFSET, 0f) + SWIPE_EDGE_TOP -> page.swipeBackLayout.y = + Math.min(-offset * Math.max(1 - percent, 0f) + DEFAULT_OFFSET, 0f) + SWIPE_EDGE_BOTTOM -> page.swipeBackLayout.y = + Math.min(offset * Math.max(1 - percent, 0f) - DEFAULT_OFFSET, 0f) } } diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.kt b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.kt index 018d7c7..1c6de12 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.swipe import android.app.Activity @@ -5,7 +20,7 @@ import ca.allanwang.kau.R import ca.allanwang.kau.kotlin.kauRemoveIf import ca.allanwang.kau.logging.KL import ca.allanwang.kau.swipe.SwipeBackHelper.onDestroy -import java.util.* +import java.util.Stack /** * Singleton to hold our swipe stack @@ -16,7 +31,8 @@ internal object SwipeBackHelper { private val pageStack = Stack() - private operator fun get(activity: Activity): SwipeBackPage? = pageStack.firstOrNull { it.activityRef.get() === activity } + private operator fun get(activity: Activity): SwipeBackPage? = + pageStack.firstOrNull { it.activityRef.get() === activity } fun onCreate(activity: Activity, builder: SwipeBackContract.() -> Unit = {}) { val page = this[activity] ?: pageStack.push(SwipeBackPage(activity).apply { builder() }) @@ -93,4 +109,4 @@ const val SWIPE_EDGE_RIGHT = ViewDragHelper.EDGE_RIGHT const val SWIPE_EDGE_TOP = ViewDragHelper.EDGE_TOP -const val SWIPE_EDGE_BOTTOM = ViewDragHelper.EDGE_BOTTOM \ No newline at end of file +const val SWIPE_EDGE_BOTTOM = ViewDragHelper.EDGE_BOTTOM diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.kt b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.kt index 4d7142c..1f564ce 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.kt @@ -1,15 +1,30 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.swipe import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.graphics.Canvas -import androidx.core.view.ViewCompat import android.util.AttributeSet import android.view.MotionEvent import android.view.View import android.view.ViewGroup import android.widget.FrameLayout +import androidx.core.view.ViewCompat import ca.allanwang.kau.logging.KL import ca.allanwang.kau.utils.adjustAlpha import ca.allanwang.kau.utils.navigationBarColor @@ -23,7 +38,10 @@ import java.lang.ref.WeakReference * If an edge detection occurs, this layout consumes all the touch events * Use the [swipeEnabled] toggle if you need the scroll events on the same axis */ -internal class SwipeBackLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0 +internal class SwipeBackLayout @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyle: Int = 0 ) : FrameLayout(context, attrs, defStyle), SwipeBackContract, SwipeBackContractInternal { override val swipeBackLayout: SwipeBackLayout @@ -96,11 +114,9 @@ internal class SwipeBackLayout @JvmOverloads constructor(context: Context, attrs override fun onEdgeTouch() {} override fun onScrollToClose(edgeFlag: Int) {} - } } - private var inLayout: Boolean = false override var edgeSize: Int @@ -158,7 +174,8 @@ internal class SwipeBackLayout @JvmOverloads constructor(context: Context, attrs } override fun setEdgeSizePercent(swipeEdgePercent: Float) { - edgeSize = ((if (horizontal) resources.displayMetrics.widthPixels else resources.displayMetrics.heightPixels) * swipeEdgePercent).toInt() + edgeSize = + ((if (horizontal) resources.displayMetrics.widthPixels else resources.displayMetrics.heightPixels) * swipeEdgePercent).toInt() } /** @@ -206,7 +223,7 @@ internal class SwipeBackLayout @JvmOverloads constructor(context: Context, attrs */ override fun scrollToFinishActivity() { val contentView = contentViewRef.get() - ?: return KL.e { "KauSwipe cannot scroll to finish as contentView is null. Is onPostCreate called?" } + ?: return KL.e { "KauSwipe cannot scroll to finish as contentView is null. Is onPostCreate called?" } val swipeWidth = contentView.width + OVERSCROLL_DISTANCE val swipeHeight = contentView.height + OVERSCROLL_DISTANCE var top = 0 @@ -243,7 +260,7 @@ internal class SwipeBackLayout @JvmOverloads constructor(context: Context, attrs override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { val contentView = contentViewRef.get() - ?: return KL.e { "KauSwipe cannot change layout as contentView is null. Is onPostCreate called?" } + ?: return KL.e { "KauSwipe cannot change layout as contentView is null. Is onPostCreate called?" } inLayout = true val xOffset: Int val yOffset: Int @@ -346,11 +363,12 @@ internal class SwipeBackLayout @JvmOverloads constructor(context: Context, attrs override fun onViewPositionChanged(changedView: View, left: Int, top: Int, dx: Int, dy: Int) { super.onViewPositionChanged(changedView, left, top, dx, dy) val contentView = contentViewRef.get() - ?: return KL.e { "KauSwipe cannot change view position as contentView is null; is onPostCreate called?" } + ?: return KL.e { "KauSwipe cannot change view position as contentView is null; is onPostCreate called?" } //make sure that we are using the proper axis scrollPercent = Math.abs( - if (horizontal) left.toFloat() / contentView.width - else (top.toFloat() / contentView.height)) + if (horizontal) left.toFloat() / contentView.width + else (top.toFloat() / contentView.height) + ) contentOffset = if (horizontal) left else top invalidate() if (scrollPercent < scrollThreshold && !isScrollOverValid) @@ -375,10 +393,11 @@ internal class SwipeBackLayout @JvmOverloads constructor(context: Context, attrs var result = Pair(0, 0) if (scrollPercent <= scrollThreshold) { //threshold not met; check velocities - if ((edgeFlag == SWIPE_EDGE_LEFT && xvel > MIN_FLING_VELOCITY) - || (edgeFlag == SWIPE_EDGE_RIGHT && xvel < -MIN_FLING_VELOCITY) - || (edgeFlag == SWIPE_EDGE_TOP && yvel > MIN_FLING_VELOCITY) - || (edgeFlag == SWIPE_EDGE_BOTTOM && yvel < -MIN_FLING_VELOCITY)) + if ((edgeFlag == SWIPE_EDGE_LEFT && xvel > MIN_FLING_VELOCITY) || + (edgeFlag == SWIPE_EDGE_RIGHT && xvel < -MIN_FLING_VELOCITY) || + (edgeFlag == SWIPE_EDGE_TOP && yvel > MIN_FLING_VELOCITY) || + (edgeFlag == SWIPE_EDGE_BOTTOM && yvel < -MIN_FLING_VELOCITY) + ) result = exitCaptureOffsets(edgeFlag, releasedChild) } else { //threshold met; fling to designated side @@ -431,6 +450,5 @@ internal class SwipeBackLayout @JvmOverloads constructor(context: Context, attrs const val DEFAULT_SCROLL_THRESHOLD = 0.3f const val OVERSCROLL_DISTANCE = 10 - } } diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.kt b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.kt index 4dba622..bc5b459 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.swipe import android.app.Activity @@ -24,7 +39,8 @@ internal class SwipeBackPage(activity: Activity) : SwipeBackContractInternal by init { activity.window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) activity.window.decorView.setBackgroundColor(Color.TRANSPARENT) - swipeBackLayout.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + swipeBackLayout.layoutParams = + ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) slider = RelativeSlider(this) } @@ -41,7 +57,7 @@ internal class SwipeBackPage(activity: Activity) : SwipeBackContractInternal by private fun handleLayout() { val activity = activityRef.get() - ?: return KL.v { "KauSwipe activity ref gone during handleLayout" } + ?: return KL.v { "KauSwipe activity ref gone during handleLayout" } if (swipeEnabled) swipeBackLayout.attachToActivity(activity) else swipeBackLayout.removeFromActivity(activity) } @@ -50,7 +66,6 @@ internal class SwipeBackPage(activity: Activity) : SwipeBackContractInternal by swipeBackLayout.scrollThreshold = percent return this } - } internal interface SwipeBackContractInternal : SwipeBackContract { @@ -104,4 +119,4 @@ interface SwipeBackContract { fun removeListener(listener: SwipeListener) fun hasListener(listener: SwipeListener): Boolean fun scrollToFinishActivity() -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.kt b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.kt index 3ea62b5..07f8eb8 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.swipe interface SwipeListener { @@ -16,4 +31,4 @@ interface SwipeListener { * Invoked when scroll percent over the threshold for the first time */ fun onScrollToClose(edgeFlag: Int) -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/ui/ProgressAnimator.kt b/core/src/main/kotlin/ca/allanwang/kau/ui/ProgressAnimator.kt index e37e59f..6f8bbc1 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/ui/ProgressAnimator.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/ui/ProgressAnimator.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.ui import android.animation.Animator @@ -86,4 +101,4 @@ class ProgressAnimator private constructor(private vararg val values: Float) { start() } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/ui/SimpleRippleDrawable.kt b/core/src/main/kotlin/ca/allanwang/kau/ui/SimpleRippleDrawable.kt index 4700162..684a11c 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/ui/SimpleRippleDrawable.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/ui/SimpleRippleDrawable.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.ui import android.content.res.ColorStateList @@ -19,4 +34,4 @@ fun createSimpleRippleDrawable(@ColorInt foregroundColor: Int, @ColorInt backgro val content = ColorDrawable(backgroundColor) val mask = ColorDrawable(foregroundColor.adjustAlpha(0.16f)) return RippleDrawable(states, content, mask) -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/ui/views/CollapsibleViewDelegate.kt b/core/src/main/kotlin/ca/allanwang/kau/ui/views/CollapsibleViewDelegate.kt index 8923775..b2a0d27 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/ui/views/CollapsibleViewDelegate.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/ui/views/CollapsibleViewDelegate.kt @@ -1,8 +1,27 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.ui.views import android.animation.ValueAnimator import android.view.View -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.KAU_COLLAPSED +import ca.allanwang.kau.utils.KAU_COLLAPSING +import ca.allanwang.kau.utils.KAU_EXPANDED +import ca.allanwang.kau.utils.KAU_EXPANDING +import ca.allanwang.kau.utils.goneIf import java.lang.ref.WeakReference /** @@ -48,10 +67,10 @@ class CollapsibleViewDelegate : CollapsibleView { if (v > 1) v = 1f else if (v < 0) v = 0f stateHolder = - if (v == 0f) KAU_COLLAPSED - else if (v == 1f) KAU_EXPANDED - else if (v - field < 0) KAU_COLLAPSING - else KAU_EXPANDING + if (v == 0f) KAU_COLLAPSED + else if (v == 1f) KAU_EXPANDED + else if (v - field < 0) KAU_COLLAPSING + else KAU_EXPANDING field = v view?.goneIf(state == KAU_COLLAPSED) view?.requestLayout() @@ -101,5 +120,4 @@ class CollapsibleViewDelegate : CollapsibleView { val target = if (expand) 1f else 0f if (animate) animateSize(target) else expansion = target } - -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/ui/views/MeasureSpecDelegate.kt b/core/src/main/kotlin/ca/allanwang/kau/ui/views/MeasureSpecDelegate.kt index 716fd71..6481306 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/ui/views/MeasureSpecDelegate.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/ui/views/MeasureSpecDelegate.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.ui.views import android.content.Context @@ -84,10 +99,13 @@ class MeasureSpecDelegate : MeasureSpecContract { val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.MeasureSpecDelegate) relativeWidth = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_relativeWidth, relativeWidth) relativeHeight = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_relativeHeight, relativeHeight) - relativeWidthToParent = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_relativeWidthToParent, relativeWidthToParent) - relativeHeightToParent = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_relativeHeightToParent, relativeHeightToParent) + relativeWidthToParent = + styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_relativeWidthToParent, relativeWidthToParent) + relativeHeightToParent = + styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_relativeHeightToParent, relativeHeightToParent) postRelativeWidth = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_postRelativeWidth, postRelativeWidth) - postRelativeHeight = styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_postRelativeHeight, postRelativeHeight) + postRelativeHeight = + styledAttrs.getFloat(R.styleable.MeasureSpecDelegate_postRelativeHeight, postRelativeHeight) styledAttrs.recycle() } @@ -115,5 +133,4 @@ class MeasureSpecDelegate : MeasureSpecContract { private val Float.measureSpec: Int get() = View.MeasureSpec.makeMeasureSpec(this.toInt(), View.MeasureSpec.EXACTLY) - } diff --git a/core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt b/core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt index 3d86419..176b9ea 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/ui/views/RippleCanvas.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.ui.views import android.animation.Animator @@ -5,7 +20,11 @@ import android.animation.AnimatorListenerAdapter import android.animation.ArgbEvaluator import android.animation.ValueAnimator import android.content.Context -import android.graphics.* +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.PorterDuff +import android.graphics.PorterDuffXfermode import android.util.AttributeSet import android.view.View @@ -17,7 +36,9 @@ import android.view.View * Supports multiple ripples from varying locations */ class RippleCanvas @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { private val paint: Paint = Paint().apply { isAntiAlias = true @@ -53,11 +74,13 @@ class RippleCanvas @JvmOverloads constructor( /** * Creates a ripple effect from the given starting values */ - fun ripple(color: Int, - startX: Float = 0f, - startY: Float = 0f, - duration: Long = 600L, - callback: (() -> Unit)? = null) { + fun ripple( + color: Int, + startX: Float = 0f, + startY: Float = 0f, + duration: Long = 600L, + callback: (() -> Unit)? = null + ) { val w = width.toFloat() val h = height.toFloat() val x = when (startX) { @@ -112,11 +135,13 @@ class RippleCanvas @JvmOverloads constructor( animator.start() } - internal class Ripple(val color: Int, - val x: Float, - val y: Float, - var radius: Float, - val maxRadius: Float) + internal class Ripple( + val color: Int, + val x: Float, + val y: Float, + var radius: Float, + val maxRadius: Float + ) companion object { const val MIDDLE = -1.0f diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt index eab9536..a655e5b 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ @file:Suppress("NOTHING_TO_INLINE") package ca.allanwang.kau.utils @@ -36,19 +51,22 @@ annotation class KauActivity */ @Suppress("DEPRECATION") inline fun Activity.startActivityForResult( - requestCode: Int, - bundleBuilder: Bundle.() -> Unit = {}, - intentBuilder: Intent.() -> Unit = {} + requestCode: Int, + bundleBuilder: Bundle.() -> Unit = {}, + intentBuilder: Intent.() -> Unit = {} ) = startActivityForResult(T::class.java, requestCode, bundleBuilder, intentBuilder) -@Deprecated("Use reified generic instead of passing class", - ReplaceWith("startActivityForResult(requestCode, bundleBuilder, intentBuilder)"), - DeprecationLevel.WARNING) +@Deprecated( + "Use reified generic instead of passing class", + ReplaceWith("startActivityForResult(requestCode, bundleBuilder, intentBuilder)"), + DeprecationLevel.WARNING +) inline fun Activity.startActivityForResult( - clazz: Class, - requestCode: Int, - bundleBuilder: Bundle.() -> Unit = {}, - intentBuilder: Intent.() -> Unit = {}) { + clazz: Class, + requestCode: Int, + bundleBuilder: Bundle.() -> Unit = {}, + intentBuilder: Intent.() -> Unit = {} +) { val intent = Intent(this, clazz) intent.intentBuilder() val bundle = Bundle() @@ -72,7 +90,6 @@ inline fun Activity.restart(intentBuilder: Intent.() -> Unit = {}) { overridePendingTransition(R.anim.kau_fade_in, R.anim.kau_fade_out) } - /** * Force restart an entire application */ @@ -119,8 +136,8 @@ inline var Activity.statusBarLight: Boolean if (buildIsMarshmallowAndUp) { val flags = window.decorView.systemUiVisibility window.decorView.systemUiVisibility = - if (value) flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR - else flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() + if (value) flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR + else flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() } } @@ -143,6 +160,14 @@ inline fun Activity.showKeyboard() { currentFocus?.showKeyboard() } -inline fun Activity.snackbar(text: String, duration: Int = Snackbar.LENGTH_LONG, noinline builder: Snackbar.() -> Unit = {}) = contentView!!.snackbar(text, duration, builder) - -inline fun Activity.snackbar(@StringRes textId: Int, duration: Int = Snackbar.LENGTH_LONG, noinline builder: Snackbar.() -> Unit = {}) = contentView!!.snackbar(textId, duration, builder) \ No newline at end of file +inline fun Activity.snackbar( + text: String, + duration: Int = Snackbar.LENGTH_LONG, + noinline builder: Snackbar.() -> Unit = {} +) = contentView!!.snackbar(text, duration, builder) + +inline fun Activity.snackbar( + @StringRes textId: Int, + duration: Int = Snackbar.LENGTH_LONG, + noinline builder: Snackbar.() -> Unit = {} +) = contentView!!.snackbar(textId, duration, builder) diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/AnimHolder.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/AnimHolder.kt index b988085..0062361 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/AnimHolder.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/AnimHolder.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.os.Build @@ -14,5 +29,4 @@ object AnimHolder { @RequiresApi(Build.VERSION_CODES.LOLLIPOP) val fastOutSlowInInterpolator = lazyInterpolator(android.R.interpolator.fast_out_linear_in) val decelerateInterpolator = lazyInterpolator(android.R.interpolator.decelerate_cubic) - -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt index d8e4681..0a548ce 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/AnimUtils.kt @@ -1,15 +1,30 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.annotation.SuppressLint -import androidx.annotation.StringRes import android.view.View import android.view.ViewAnimationUtils import android.view.ViewPropertyAnimator import android.view.animation.Animation import android.view.animation.AnimationUtils import android.widget.TextView +import androidx.annotation.StringRes /** * Created by Allan Wang on 2017-06-01. @@ -19,7 +34,15 @@ import android.widget.TextView @SuppressLint("NewApi") @KauUtils -fun View.circularReveal(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float = -1.0f, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { +fun View.circularReveal( + x: Int = 0, + y: Int = 0, + offset: Long = 0L, + radius: Float = -1.0f, + duration: Long = 500L, + onStart: (() -> Unit)? = null, + onFinish: (() -> Unit)? = null +) { if (!isAttachedToWindow) { onStart?.invoke() visible() @@ -29,7 +52,10 @@ fun View.circularReveal(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float if (!buildIsLollipopAndUp) return fadeIn(offset, duration, onStart, onFinish) val r = if (radius >= 0) radius - else Math.max(Math.hypot(x.toDouble(), y.toDouble()), Math.hypot((width - x.toDouble()), (height - y.toDouble()))).toFloat() + else Math.max( + Math.hypot(x.toDouble(), y.toDouble()), + Math.hypot((width - x.toDouble()), (height - y.toDouble())) + ).toFloat() val anim = ViewAnimationUtils.createCircularReveal(this, x, y, 0f, r).setDuration(duration) anim.startDelay = offset @@ -47,7 +73,15 @@ fun View.circularReveal(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float @SuppressLint("NewApi") @KauUtils -fun View.circularHide(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float = -1.0f, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { +fun View.circularHide( + x: Int = 0, + y: Int = 0, + offset: Long = 0L, + radius: Float = -1.0f, + duration: Long = 500L, + onStart: (() -> Unit)? = null, + onFinish: (() -> Unit)? = null +) { if (!isAttachedToWindow) { onStart?.invoke() invisible() @@ -57,7 +91,10 @@ fun View.circularHide(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float = if (!buildIsLollipopAndUp) return fadeOut(offset, duration, onStart, onFinish) val r = if (radius >= 0) radius - else Math.max(Math.hypot(x.toDouble(), y.toDouble()), Math.hypot((width - x.toDouble()), (height - y.toDouble()))).toFloat() + else Math.max( + Math.hypot(x.toDouble(), y.toDouble()), + Math.hypot((width - x.toDouble()), (height - y.toDouble())) + ).toFloat() val anim = ViewAnimationUtils.createCircularReveal(this, x, y, r, 0f).setDuration(duration) anim.startDelay = offset @@ -75,7 +112,12 @@ fun View.circularHide(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float = } @KauUtils -fun View.fadeIn(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { +fun View.fadeIn( + offset: Long = 0L, + duration: Long = 200L, + onStart: (() -> Unit)? = null, + onFinish: (() -> Unit)? = null +) { if (!isAttachedToWindow) { onStart?.invoke() visible() @@ -97,7 +139,12 @@ fun View.fadeIn(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? } @KauUtils -fun View.fadeOut(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { +fun View.fadeOut( + offset: Long = 0L, + duration: Long = 200L, + onStart: (() -> Unit)? = null, + onFinish: (() -> Unit)? = null +) { if (!isAttachedToWindow) { onStart?.invoke() invisible() @@ -130,7 +177,8 @@ fun TextView.setTextWithFade(text: String, duration: Long = 200, onFinish: (() - } @KauUtils -fun TextView.setTextWithFade(@StringRes textId: Int, duration: Long = 200, onFinish: (() -> Unit)? = null) = setTextWithFade(context.getString(textId), duration, onFinish) +fun TextView.setTextWithFade(@StringRes textId: Int, duration: Long = 200, onFinish: (() -> Unit)? = null) = + setTextWithFade(context.getString(textId), duration, onFinish) @KauUtils -fun ViewPropertyAnimator.scaleXY(value: Float) = scaleX(value).scaleY(value) \ No newline at end of file +fun ViewPropertyAnimator.scaleXY(value: Float) = scaleX(value).scaleY(value) diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt index d628214..314ca60 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.annotation.SuppressLint @@ -5,9 +20,9 @@ import android.app.Activity import android.app.ActivityOptions import android.content.Context import android.os.Bundle -import androidx.annotation.AnimRes import android.util.Pair import android.view.View +import androidx.annotation.AnimRes import ca.allanwang.kau.R /** @@ -36,9 +51,9 @@ fun Bundle.withSceneTransitionAnimation(context: Context) { * create a scene transition animation */ fun Bundle.withSceneTransitionAnimation(parent: View, data: Map) = - withSceneTransitionAnimation(parent.context, data.mapKeys { (id, _) -> - parent.findViewById(id) - }) + withSceneTransitionAnimation(parent.context, data.mapKeys { (id, _) -> + parent.findViewById(id) + }) /** * Given a mapping of views to tags, @@ -48,22 +63,33 @@ fun Bundle.withSceneTransitionAnimation(parent: View, data: Map) = fun Bundle.withSceneTransitionAnimation(context: Context, data: Map) { if (context !is Activity || !buildIsLollipopAndUp) return val options = ActivityOptions.makeSceneTransitionAnimation(context, - *data.map { (view, tag) -> Pair(view, tag) }.toTypedArray()) + *data.map { (view, tag) -> Pair(view, tag) }.toTypedArray() + ) putAll(options.toBundle()) } -fun Bundle.withCustomAnimation(context: Context, - @AnimRes enterResId: Int, - @AnimRes exitResId: Int) { - this with ActivityOptions.makeCustomAnimation(context, - enterResId, exitResId).toBundle() +fun Bundle.withCustomAnimation( + context: Context, + @AnimRes enterResId: Int, + @AnimRes exitResId: Int +) { + this with ActivityOptions.makeCustomAnimation( + context, + enterResId, exitResId + ).toBundle() } -fun Bundle.withSlideIn(context: Context) = withCustomAnimation(context, - R.anim.kau_slide_in_right, R.anim.kau_fade_out) +fun Bundle.withSlideIn(context: Context) = withCustomAnimation( + context, + R.anim.kau_slide_in_right, R.anim.kau_fade_out +) -fun Bundle.withSlideOut(context: Context) = withCustomAnimation(context, - R.anim.kau_fade_in, R.anim.kau_slide_out_right_top) +fun Bundle.withSlideOut(context: Context) = withCustomAnimation( + context, + R.anim.kau_fade_in, R.anim.kau_slide_out_right_top +) -fun Bundle.withFade(context: Context) = withCustomAnimation(context, - android.R.anim.fade_in, android.R.anim.fade_out) \ No newline at end of file +fun Bundle.withFade(context: Context) = withCustomAnimation( + context, + android.R.anim.fade_in, android.R.anim.fade_out +) diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt index f010c6f..9e1832f 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.annotation.SuppressLint @@ -7,15 +22,21 @@ import android.graphics.Color import android.graphics.PorterDuff import android.graphics.drawable.Drawable import android.os.Build +import android.widget.CheckBox +import android.widget.EditText +import android.widget.ImageButton +import android.widget.ProgressBar +import android.widget.RadioButton +import android.widget.SeekBar +import android.widget.TextView import androidx.annotation.ColorInt import androidx.annotation.FloatRange import androidx.annotation.IntRange -import androidx.core.graphics.drawable.DrawableCompat import androidx.appcompat.widget.AppCompatEditText import androidx.appcompat.widget.Toolbar -import android.widget.* +import androidx.core.graphics.drawable.DrawableCompat import com.afollestad.materialdialogs.R -import java.util.* +import java.util.Random /** * Created by Allan Wang on 2017-06-08. @@ -38,7 +59,7 @@ inline val Int.isColorDark: Boolean get() = isColorDark(0.5f) fun Int.isColorDark(minDarkness: Float): Boolean = - ((0.299 * Color.red(this) + 0.587 * Color.green(this) + 0.114 * Color.blue(this)) / 255.0) < minDarkness + ((0.299 * Color.red(this) + 0.587 * Color.green(this) + 0.114 * Color.blue(this)) / 255.0) < minDarkness fun Int.toHexString(withAlpha: Boolean = false, withHexPrefix: Boolean = true): String { val hex = if (withAlpha) String.format("#%08X", this) @@ -46,7 +67,8 @@ fun Int.toHexString(withAlpha: Boolean = false, withHexPrefix: Boolean = true): return if (withHexPrefix) hex else hex.substring(1) } -fun Int.toRgbaString(): String = "rgba(${Color.red(this)}, ${Color.green(this)}, ${Color.blue(this)}, ${(Color.alpha(this) / 255f).round(3)})" +fun Int.toRgbaString(): String = + "rgba(${Color.red(this)}, ${Color.green(this)}, ${Color.blue(this)}, ${(Color.alpha(this) / 255f).round(3)})" fun Int.toHSV(): FloatArray { val hsv = FloatArray(3) @@ -59,13 +81,15 @@ inline val Int.isColorOpaque: Boolean fun FloatArray.toColor(): Int = Color.HSVToColor(this) -fun Int.isColorVisibleOn(@ColorInt color: Int, @IntRange(from = 0L, to = 255L) delta: Int = 25, - @IntRange(from = 0L, to = 255L) minAlpha: Int = 50): Boolean = - if (Color.alpha(this) < minAlpha) false - else !(Math.abs(Color.red(this) - Color.red(color)) < delta - && Math.abs(Color.green(this) - Color.green(color)) < delta - && Math.abs(Color.blue(this) - Color.blue(color)) < delta) - +fun Int.isColorVisibleOn( + @ColorInt color: Int, + @IntRange(from = 0L, to = 255L) delta: Int = 25, + @IntRange(from = 0L, to = 255L) minAlpha: Int = 50 +): Boolean = + if (Color.alpha(this) < minAlpha) false + else !(Math.abs(Color.red(this) - Color.red(color)) < delta && + Math.abs(Color.green(this) - Color.green(color)) < delta && + Math.abs(Color.blue(this) - Color.blue(color)) < delta) @ColorInt fun Context.getDisabledColor(): Int { @@ -94,30 +118,34 @@ fun Int.blendWith(@ColorInt color: Int, @FloatRange(from = 0.0, to = 1.0) ratio: } @ColorInt -fun Int.withAlpha(@IntRange(from = 0L, to = 255L) alpha: Int): Int = Color.argb(alpha, Color.red(this), Color.green(this), Color.blue(this)) +fun Int.withAlpha(@IntRange(from = 0L, to = 255L) alpha: Int): Int = + Color.argb(alpha, Color.red(this), Color.green(this), Color.blue(this)) @ColorInt -fun Int.withMinAlpha(@IntRange(from = 0L, to = 255L) alpha: Int): Int = Color.argb(Math.max(alpha, Color.alpha(this)), Color.red(this), Color.green(this), Color.blue(this)) +fun Int.withMinAlpha(@IntRange(from = 0L, to = 255L) alpha: Int): Int = + Color.argb(Math.max(alpha, Color.alpha(this)), Color.red(this), Color.green(this), Color.blue(this)) @ColorInt fun Int.lighten(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int { val (red, green, blue) = intArrayOf(Color.red(this), Color.green(this), Color.blue(this)) - .map { (it * (1f - factor) + 255f * factor).toInt() } + .map { (it * (1f - factor) + 255f * factor).toInt() } return Color.argb(Color.alpha(this), red, green, blue) } @ColorInt fun Int.darken(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int { val (red, green, blue) = intArrayOf(Color.red(this), Color.green(this), Color.blue(this)) - .map { (it * (1f - factor)).toInt() } + .map { (it * (1f - factor)).toInt() } return Color.argb(Color.alpha(this), red, green, blue) } @ColorInt -fun Int.colorToBackground(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int = if (isColorDark) darken(factor) else lighten(factor) +fun Int.colorToBackground(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int = + if (isColorDark) darken(factor) else lighten(factor) @ColorInt -fun Int.colorToForeground(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int = if (isColorDark) lighten(factor) else darken(factor) +fun Int.colorToForeground(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int = + if (isColorDark) lighten(factor) else darken(factor) @Throws(IllegalArgumentException::class) fun String.toColor(): Int { @@ -132,11 +160,15 @@ fun String.toColor(): Int { //Get ColorStateList fun Context.colorStateList(@ColorInt color: Int): ColorStateList { val disabledColor = color.adjustAlpha(0.3f) - return ColorStateList(arrayOf(intArrayOf(android.R.attr.state_enabled, -android.R.attr.state_checked), + return ColorStateList( + arrayOf( + intArrayOf(android.R.attr.state_enabled, -android.R.attr.state_checked), intArrayOf(android.R.attr.state_enabled, android.R.attr.state_checked), intArrayOf(-android.R.attr.state_enabled, -android.R.attr.state_checked), - intArrayOf(-android.R.attr.state_enabled, android.R.attr.state_checked)), - intArrayOf(color.adjustAlpha(0.8f), color, disabledColor, disabledColor)) + intArrayOf(-android.R.attr.state_enabled, android.R.attr.state_checked) + ), + intArrayOf(color.adjustAlpha(0.8f), color, disabledColor, disabledColor) + ) } /* @@ -203,14 +235,14 @@ fun ProgressBar.tint(@ColorInt color: Int, skipIndeterminate: Boolean = false) { fun Context.textColorStateList(@ColorInt color: Int): ColorStateList { val states = arrayOf( - intArrayOf(-android.R.attr.state_enabled), - intArrayOf(-android.R.attr.state_pressed, -android.R.attr.state_focused), - intArrayOf() + intArrayOf(-android.R.attr.state_enabled), + intArrayOf(-android.R.attr.state_pressed, -android.R.attr.state_focused), + intArrayOf() ) val colors = intArrayOf( - resolveColor(R.attr.colorControlNormal), - resolveColor(R.attr.colorControlNormal), - color + resolveColor(R.attr.colorControlNormal), + resolveColor(R.attr.colorControlNormal), + color ) return ColorStateList(states, colors) } @@ -254,4 +286,4 @@ fun Toolbar.tint(@ColorInt color: Int, tintTitle: Boolean = true) { setSubtitleTextColor(color) } (0 until childCount).asSequence().forEach { (getChildAt(it) as? ImageButton)?.setColorFilter(color) } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/Const.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/Const.kt index eb09093..9dca16c 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/Const.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/Const.kt @@ -1,8 +1,22 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import androidx.customview.widget.ViewDragHelper - /** * Created by Allan Wang on 2017-06-08. */ @@ -21,4 +35,4 @@ const val KAU_COLLAPSING = 1 const val KAU_EXPANDING = 2 const val KAU_EXPANDED = 3 -const val KAU_ELLIPSIS = '\u2026' \ No newline at end of file +const val KAU_ELLIPSIS = '\u2026' diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt index f6e9ac7..134126d 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ @file:Suppress("NOTHING_TO_INLINE") package ca.allanwang.kau.utils @@ -11,17 +26,26 @@ import android.content.pm.PackageManager import android.graphics.drawable.Drawable import android.net.Uri import android.os.Bundle -import androidx.annotation.* -import androidx.core.content.ContextCompat import android.util.TypedValue import android.view.View import android.view.animation.AnimationUtils import android.widget.Toast +import androidx.annotation.AnimRes +import androidx.annotation.AttrRes +import androidx.annotation.BoolRes +import androidx.annotation.ColorInt +import androidx.annotation.ColorRes +import androidx.annotation.DimenRes +import androidx.annotation.DrawableRes +import androidx.annotation.IntegerRes +import androidx.annotation.InterpolatorRes +import androidx.annotation.PluralsRes +import androidx.annotation.StringRes +import androidx.core.content.ContextCompat import ca.allanwang.kau.R import ca.allanwang.kau.logging.KL import com.afollestad.materialdialogs.MaterialDialog - /** * Created by Allan Wang on 2017-06-03. */ @@ -33,19 +57,22 @@ import com.afollestad.materialdialogs.MaterialDialog */ @Suppress("DEPRECATION") inline fun Context.startActivity( - clearStack: Boolean = false, - bundleBuilder: Bundle.() -> Unit = {}, - intentBuilder: Intent.() -> Unit = {} + clearStack: Boolean = false, + bundleBuilder: Bundle.() -> Unit = {}, + intentBuilder: Intent.() -> Unit = {} ) = startActivity(T::class.java, clearStack, bundleBuilder, intentBuilder) -@Deprecated("Use reified generic instead of passing class", - ReplaceWith("startActivity(clearStack, bundleBuilder, intentBuilder)"), - DeprecationLevel.WARNING) +@Deprecated( + "Use reified generic instead of passing class", + ReplaceWith("startActivity(clearStack, bundleBuilder, intentBuilder)"), + DeprecationLevel.WARNING +) inline fun Context.startActivity( - clazz: Class, - clearStack: Boolean = false, - bundleBuilder: Bundle.() -> Unit = {}, - intentBuilder: Intent.() -> Unit = {}) { + clazz: Class, + clearStack: Boolean = false, + bundleBuilder: Bundle.() -> Unit = {}, + intentBuilder: Intent.() -> Unit = {} +) { val intent = Intent(this, clazz) if (clearStack) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) intent.intentBuilder() @@ -55,7 +82,6 @@ inline fun Context.startActivity( if (clearStack && this is Activity) finish() } - fun Context.startPlayStoreLink(@StringRes packageIdRes: Int) = startPlayStoreLink(string(packageIdRes)) fun Context.startPlayStoreLink(packageId: String) { @@ -82,11 +108,14 @@ fun Context.startLink(vararg url: String?) { fun Context.startLink(@StringRes url: Int) = startLink(string(url)) //Toast helpers -inline fun View.toast(@StringRes id: Int, duration: Int = Toast.LENGTH_LONG, log: Boolean = false) = context.toast(id, duration, log) +inline fun View.toast(@StringRes id: Int, duration: Int = Toast.LENGTH_LONG, log: Boolean = false) = + context.toast(id, duration, log) -inline fun Context.toast(@StringRes id: Int, duration: Int = Toast.LENGTH_LONG, log: Boolean = false) = toast(this.string(id), duration, log) +inline fun Context.toast(@StringRes id: Int, duration: Int = Toast.LENGTH_LONG, log: Boolean = false) = + toast(this.string(id), duration, log) -inline fun View.toast(text: String, duration: Int = Toast.LENGTH_LONG, log: Boolean = false) = context.toast(text, duration, log) +inline fun View.toast(text: String, duration: Int = Toast.LENGTH_LONG, log: Boolean = false) = + context.toast(text, duration, log) inline fun Context.toast(text: String, duration: Int = Toast.LENGTH_LONG, log: Boolean = false) { Toast.makeText(this, text, duration).show() @@ -98,24 +127,33 @@ const val INVALID_ID = 0 //Resource retrievers inline fun Context.string(@StringRes id: Int): String = getString(id) -inline fun Context.string(@StringRes id: Int, fallback: String?): String? = if (id != INVALID_ID) string(id) else fallback -inline fun Context.string(@StringRes id: Int, fallback: () -> String?): String? = if (id != INVALID_ID) string(id) else fallback() +inline fun Context.string(@StringRes id: Int, fallback: String?): String? = + if (id != INVALID_ID) string(id) else fallback + +inline fun Context.string(@StringRes id: Int, fallback: () -> String?): String? = + if (id != INVALID_ID) string(id) else fallback() + inline fun Context.color(@ColorRes id: Int): Int = ContextCompat.getColor(this, id) inline fun Context.boolean(@BoolRes id: Int): Boolean = resources.getBoolean(id) inline fun Context.integer(@IntegerRes id: Int): Int = resources.getInteger(id) inline fun Context.dimen(@DimenRes id: Int): Float = resources.getDimension(id) inline fun Context.dimenPixelSize(@DimenRes id: Int): Int = resources.getDimensionPixelSize(id) inline fun Context.drawable(@DrawableRes id: Int): Drawable = ContextCompat.getDrawable(this, id) - ?: throw KauException("Drawable with id $id not found") + ?: throw KauException("Drawable with id $id not found") + +inline fun Context.drawable(@DrawableRes id: Int, fallback: Drawable?): Drawable? = + if (id != INVALID_ID) drawable(id) else fallback + +inline fun Context.drawable(@DrawableRes id: Int, fallback: () -> Drawable?): Drawable? = + if (id != INVALID_ID) drawable(id) else fallback() -inline fun Context.drawable(@DrawableRes id: Int, fallback: Drawable?): Drawable? = if (id != INVALID_ID) drawable(id) else fallback -inline fun Context.drawable(@DrawableRes id: Int, fallback: () -> Drawable?): Drawable? = if (id != INVALID_ID) drawable(id) else fallback() inline fun Context.interpolator(@InterpolatorRes id: Int) = AnimationUtils.loadInterpolator(this, id)!! inline fun Context.animation(@AnimRes id: Int) = AnimationUtils.loadAnimation(this, id)!! /** * Returns plural form of res. The quantity is also passed to the formatter as an int */ -inline fun Context.plural(@PluralsRes id: Int, quantity: Number) = resources.getQuantityString(id, quantity.toInt(), quantity.toInt())!! +inline fun Context.plural(@PluralsRes id: Int, quantity: Number) = + resources.getQuantityString(id, quantity.toInt(), quantity.toInt())!! //Attr retrievers fun Context.resolveColor(@AttrRes attr: Int, @ColorInt fallback: Int = 0): Int { @@ -164,7 +202,8 @@ inline fun Context.materialDialog(action: MaterialDialog.Builder.() -> Unit): Ma return builder.show() } -fun Context.getDip(value: Float): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, resources.displayMetrics) +fun Context.getDip(value: Float): Float = + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, resources.displayMetrics) inline val Context.isRtl: Boolean get() = resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL @@ -181,7 +220,10 @@ inline val Context.isNavBarOnBottom: Boolean return !canMove || dm.widthPixels < dm.heightPixels } -fun Context.hasPermission(permissions: String) = !buildIsMarshmallowAndUp || ContextCompat.checkSelfPermission(this, permissions) == PackageManager.PERMISSION_GRANTED +fun Context.hasPermission(permissions: String) = !buildIsMarshmallowAndUp || ContextCompat.checkSelfPermission( + this, + permissions +) == PackageManager.PERMISSION_GRANTED fun Context.copyToClipboard(text: String?, label: String = "Copied Text", showToast: Boolean = true) { val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager @@ -207,4 +249,4 @@ fun Context.shareText(text: String?) { * As of now, it is only checked when tied to an activity */ inline val Context.isFinishing: Boolean - get() = (this as? Activity)?.isFinishing ?: false \ No newline at end of file + get() = (this as? Activity)?.isFinishing ?: false diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/DrawableUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/DrawableUtils.kt index 59e684a..6950f2f 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/DrawableUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/DrawableUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.content.res.ColorStateList @@ -17,4 +32,4 @@ fun Drawable.tint(state: ColorStateList): Drawable { val drawable = DrawableCompat.wrap(mutate()) DrawableCompat.setTintList(drawable, state) return drawable -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/FileUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/FileUtils.kt index bfbc009..1d27bfc 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/FileUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/FileUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import java.io.File @@ -6,4 +21,5 @@ import java.io.InputStream /** * Created by Allan Wang on 2017-08-04. */ -fun File.copyFromInputStream(inputStream: InputStream) = inputStream.use { input -> outputStream().use { output -> input.copyTo(output) } } \ No newline at end of file +fun File.copyFromInputStream(inputStream: InputStream) = + inputStream.use { input -> outputStream().use { output -> input.copyTo(output) } } diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/FontUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/FontUtils.kt index 1db7694..064d70b 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/FontUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/FontUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.content.Context @@ -14,17 +29,17 @@ object FontUtils { synchronized(sTypefaceCache) { if (!sTypefaceCache.containsKey(font)) { val tf = Typeface.createFromAsset( - context.applicationContext.assets, "fonts/$font.ttf") + context.applicationContext.assets, "fonts/$font.ttf" + ) sTypefaceCache.put(font, tf) } return sTypefaceCache.get(font) - ?: throw IllegalArgumentException("Font error; typeface does not exist at assets/fonts$font.ttf") + ?: throw IllegalArgumentException("Font error; typeface does not exist at assets/fonts$font.ttf") } } fun getName(typeface: Typeface): String? = sTypefaceCache.entries.firstOrNull { it.value == typeface }?.key - } fun Context.getFont(font: String) = FontUtils.get(this, font) -fun Context.getFontName(typeface: Typeface) = FontUtils.getName(typeface) \ No newline at end of file +fun Context.getFontName(typeface: Typeface) = FontUtils.getName(typeface) diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt index f99b342..1c97900 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import androidx.fragment.app.Fragment @@ -9,4 +24,4 @@ import org.jetbrains.anko.bundleOf fun T.withArguments(vararg params: Pair): T { arguments = bundleOf(*params) return this -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/IIconUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/IIconUtils.kt index 66c56f8..8b40352 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/IIconUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/IIconUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.content.Context @@ -12,10 +27,15 @@ import com.mikepenz.iconics.typeface.IIcon * Created by Allan Wang on 2017-05-29. */ @KauUtils -fun IIcon.toDrawable(c: Context, sizeDp: Int = 24, @ColorInt color: Int = Color.WHITE, builder: IconicsDrawable.() -> Unit = {}): Drawable { +fun IIcon.toDrawable( + c: Context, + sizeDp: Int = 24, + @ColorInt color: Int = Color.WHITE, + builder: IconicsDrawable.() -> Unit = {} +): Drawable { val state = ColorStateList.valueOf(color) val icon = IconicsDrawable(c).icon(this).color(state) if (sizeDp > 0) icon.sizeDp(sizeDp) icon.builder() return icon -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt index 3cbd93d..1c22f62 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ @file:Suppress("UNCHECKED_CAST", "DEPRECATION") package ca.allanwang.kau.utils @@ -21,107 +36,76 @@ import android.app.Fragment import android.view.View import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.ViewHolder -import java.util.* +import java.util.Collections +import java.util.WeakHashMap import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty import androidx.fragment.app.DialogFragment as SupportDialogFragment import androidx.fragment.app.Fragment as SupportFragment -fun View.bindView(id: Int) - : ReadOnlyProperty = required(id, viewFinder) +fun View.bindView(id: Int): ReadOnlyProperty = required(id, viewFinder) -fun Activity.bindView(id: Int) - : ReadOnlyProperty = required(id, viewFinder) +fun Activity.bindView(id: Int): ReadOnlyProperty = required(id, viewFinder) -fun Dialog.bindView(id: Int) - : ReadOnlyProperty = required(id, viewFinder) +fun Dialog.bindView(id: Int): ReadOnlyProperty = required(id, viewFinder) -fun DialogFragment.bindView(id: Int) - : ReadOnlyProperty = required(id, viewFinder) +fun DialogFragment.bindView(id: Int): ReadOnlyProperty = required(id, viewFinder) -fun SupportDialogFragment.bindView(id: Int) - : ReadOnlyProperty = required(id, viewFinder) +fun SupportDialogFragment.bindView(id: Int): ReadOnlyProperty = required(id, viewFinder) -fun Fragment.bindView(id: Int) - : ReadOnlyProperty = required(id, viewFinder) +fun Fragment.bindView(id: Int): ReadOnlyProperty = required(id, viewFinder) -fun SupportFragment.bindView(id: Int) - : ReadOnlyProperty = required(id, viewFinder) +fun SupportFragment.bindView(id: Int): ReadOnlyProperty = required(id, viewFinder) -fun RecyclerView.ViewHolder.bindView(id: Int) - : ReadOnlyProperty = required(id, viewFinder) +fun RecyclerView.ViewHolder.bindView(id: Int): ReadOnlyProperty = required(id, viewFinder) -fun View.bindOptionalView(id: Int) - : ReadOnlyProperty = optional(id, viewFinder) +fun View.bindOptionalView(id: Int): ReadOnlyProperty = optional(id, viewFinder) -fun Activity.bindOptionalView(id: Int) - : ReadOnlyProperty = optional(id, viewFinder) +fun Activity.bindOptionalView(id: Int): ReadOnlyProperty = optional(id, viewFinder) -fun Dialog.bindOptionalView(id: Int) - : ReadOnlyProperty = optional(id, viewFinder) +fun Dialog.bindOptionalView(id: Int): ReadOnlyProperty = optional(id, viewFinder) -fun DialogFragment.bindOptionalView(id: Int) - : ReadOnlyProperty = optional(id, viewFinder) +fun DialogFragment.bindOptionalView(id: Int): ReadOnlyProperty = optional(id, viewFinder) -fun SupportDialogFragment.bindOptionalView(id: Int) - : ReadOnlyProperty = optional(id, viewFinder) +fun SupportDialogFragment.bindOptionalView(id: Int): ReadOnlyProperty = optional(id, viewFinder) -fun Fragment.bindOptionalView(id: Int) - : ReadOnlyProperty = optional(id, viewFinder) +fun Fragment.bindOptionalView(id: Int): ReadOnlyProperty = optional(id, viewFinder) -fun SupportFragment.bindOptionalView(id: Int) - : ReadOnlyProperty = optional(id, viewFinder) +fun SupportFragment.bindOptionalView(id: Int): ReadOnlyProperty = optional(id, viewFinder) -fun RecyclerView.ViewHolder.bindOptionalView(id: Int) - : ReadOnlyProperty = optional(id, viewFinder) +fun RecyclerView.ViewHolder.bindOptionalView(id: Int): ReadOnlyProperty = optional(id, viewFinder) -fun View.bindViews(vararg ids: Int) - : ReadOnlyProperty> = required(ids, viewFinder) +fun View.bindViews(vararg ids: Int): ReadOnlyProperty> = required(ids, viewFinder) -fun Activity.bindViews(vararg ids: Int) - : ReadOnlyProperty> = required(ids, viewFinder) +fun Activity.bindViews(vararg ids: Int): ReadOnlyProperty> = required(ids, viewFinder) -fun Dialog.bindViews(vararg ids: Int) - : ReadOnlyProperty> = required(ids, viewFinder) +fun Dialog.bindViews(vararg ids: Int): ReadOnlyProperty> = required(ids, viewFinder) -fun DialogFragment.bindViews(vararg ids: Int) - : ReadOnlyProperty> = required(ids, viewFinder) +fun DialogFragment.bindViews(vararg ids: Int): ReadOnlyProperty> = required(ids, viewFinder) -fun SupportDialogFragment.bindViews(vararg ids: Int) - : ReadOnlyProperty> = required(ids, viewFinder) +fun SupportDialogFragment.bindViews(vararg ids: Int): ReadOnlyProperty> = required(ids, viewFinder) -fun Fragment.bindViews(vararg ids: Int) - : ReadOnlyProperty> = required(ids, viewFinder) +fun Fragment.bindViews(vararg ids: Int): ReadOnlyProperty> = required(ids, viewFinder) -fun SupportFragment.bindViews(vararg ids: Int) - : ReadOnlyProperty> = required(ids, viewFinder) +fun SupportFragment.bindViews(vararg ids: Int): ReadOnlyProperty> = required(ids, viewFinder) -fun ViewHolder.bindViews(vararg ids: Int) - : ReadOnlyProperty> = required(ids, viewFinder) +fun ViewHolder.bindViews(vararg ids: Int): ReadOnlyProperty> = required(ids, viewFinder) -fun View.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty> = optional(ids, viewFinder) +fun View.bindOptionalViews(vararg ids: Int): ReadOnlyProperty> = optional(ids, viewFinder) -fun Activity.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty> = optional(ids, viewFinder) +fun Activity.bindOptionalViews(vararg ids: Int): ReadOnlyProperty> = optional(ids, viewFinder) -fun Dialog.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty> = optional(ids, viewFinder) +fun Dialog.bindOptionalViews(vararg ids: Int): ReadOnlyProperty> = optional(ids, viewFinder) -fun DialogFragment.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty> = optional(ids, viewFinder) +fun DialogFragment.bindOptionalViews(vararg ids: Int): ReadOnlyProperty> = optional(ids, viewFinder) -fun SupportDialogFragment.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty> = optional(ids, viewFinder) +fun SupportDialogFragment.bindOptionalViews(vararg ids: Int): ReadOnlyProperty> = optional(ids, viewFinder) -fun Fragment.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty> = optional(ids, viewFinder) +fun Fragment.bindOptionalViews(vararg ids: Int): ReadOnlyProperty> = optional(ids, viewFinder) -fun SupportFragment.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty> = optional(ids, viewFinder) +fun SupportFragment.bindOptionalViews(vararg ids: Int): ReadOnlyProperty> = optional(ids, viewFinder) -fun ViewHolder.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty> = optional(ids, viewFinder) +fun ViewHolder.bindOptionalViews(vararg ids: Int): ReadOnlyProperty> = optional(ids, viewFinder) private inline val View.viewFinder: View.(Int) -> View? get() = { findViewById(it) } @@ -141,7 +125,7 @@ private inline val ViewHolder.viewFinder: ViewHolder.(Int) -> View? get() = { itemView.findViewById(it) } private fun viewNotFound(id: Int, desc: KProperty<*>): Nothing = - throw IllegalStateException("View ID $id for '${desc.name}' not found.") + throw IllegalStateException("View ID $id for '${desc.name}' not found.") private fun required(id: Int, finder: T.(Int) -> View?) = Lazy { t: T, desc -> (t.finder(id) as V?)?.apply { } ?: viewNotFound(id, desc) @@ -155,19 +139,20 @@ private fun required(ids: IntArray, finder: T.(Int) -> View?) = La } } -private fun optional(ids: IntArray, finder: T.(Int) -> View?) = Lazy { t: T, _ -> ids.map { t.finder(it) as V? }.filterNotNull() } +private fun optional(ids: IntArray, finder: T.(Int) -> View?) = + Lazy { t: T, _ -> ids.map { t.finder(it) as V? }.filterNotNull() } // Like Kotlin's lazy delegate but the initializer gets the target and metadata passed to it private open class Lazy(private val initializer: (T, KProperty<*>) -> V) : ReadOnlyProperty { protected object EMPTY -protected var value: Any? = EMPTY + protected var value: Any? = EMPTY -override fun getValue(thisRef: T, property: KProperty<*>): V { + override fun getValue(thisRef: T, property: KProperty<*>): V { if (value == EMPTY) value = initializer(thisRef, property) -return value as V + return value as V } } @@ -181,107 +166,76 @@ return value as V * Credits to MichaelRocks */ -fun View.bindViewResettable(id: Int) - : ReadOnlyProperty = requiredResettable(id, viewFinder) +fun View.bindViewResettable(id: Int): ReadOnlyProperty = requiredResettable(id, viewFinder) -fun Activity.bindViewResettable(id: Int) - : ReadOnlyProperty = requiredResettable(id, viewFinder) +fun Activity.bindViewResettable(id: Int): ReadOnlyProperty = requiredResettable(id, viewFinder) -fun Dialog.bindViewResettable(id: Int) - : ReadOnlyProperty = requiredResettable(id, viewFinder) +fun Dialog.bindViewResettable(id: Int): ReadOnlyProperty = requiredResettable(id, viewFinder) -fun DialogFragment.bindViewResettable(id: Int) - : ReadOnlyProperty = requiredResettable(id, viewFinder) +fun DialogFragment.bindViewResettable(id: Int): ReadOnlyProperty = requiredResettable(id, viewFinder) -fun SupportDialogFragment.bindViewResettable(id: Int) - : ReadOnlyProperty = requiredResettable(id, viewFinder) +fun SupportDialogFragment.bindViewResettable(id: Int): ReadOnlyProperty = requiredResettable(id, viewFinder) -fun Fragment.bindViewResettable(id: Int) - : ReadOnlyProperty = requiredResettable(id, viewFinder) +fun Fragment.bindViewResettable(id: Int): ReadOnlyProperty = requiredResettable(id, viewFinder) -fun SupportFragment.bindViewResettable(id: Int) - : ReadOnlyProperty = requiredResettable(id, viewFinder) +fun SupportFragment.bindViewResettable(id: Int): ReadOnlyProperty = requiredResettable(id, viewFinder) -fun ViewHolder.bindViewResettable(id: Int) - : ReadOnlyProperty = requiredResettable(id, viewFinder) +fun ViewHolder.bindViewResettable(id: Int): ReadOnlyProperty = requiredResettable(id, viewFinder) -fun View.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty = optionalResettable(id, viewFinder) +fun View.bindOptionalViewResettable(id: Int): ReadOnlyProperty = optionalResettable(id, viewFinder) -fun Activity.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty = optionalResettable(id, viewFinder) +fun Activity.bindOptionalViewResettable(id: Int): ReadOnlyProperty = optionalResettable(id, viewFinder) -fun Dialog.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty = optionalResettable(id, viewFinder) +fun Dialog.bindOptionalViewResettable(id: Int): ReadOnlyProperty = optionalResettable(id, viewFinder) -fun DialogFragment.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty = optionalResettable(id, viewFinder) +fun DialogFragment.bindOptionalViewResettable(id: Int): ReadOnlyProperty = optionalResettable(id, viewFinder) -fun SupportDialogFragment.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty = optionalResettable(id, viewFinder) +fun SupportDialogFragment.bindOptionalViewResettable(id: Int): ReadOnlyProperty = optionalResettable(id, viewFinder) -fun Fragment.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty = optionalResettable(id, viewFinder) +fun Fragment.bindOptionalViewResettable(id: Int): ReadOnlyProperty = optionalResettable(id, viewFinder) -fun SupportFragment.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty = optionalResettable(id, viewFinder) +fun SupportFragment.bindOptionalViewResettable(id: Int): ReadOnlyProperty = optionalResettable(id, viewFinder) -fun ViewHolder.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty = optionalResettable(id, viewFinder) +fun ViewHolder.bindOptionalViewResettable(id: Int): ReadOnlyProperty = optionalResettable(id, viewFinder) -fun View.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = requiredResettable(ids, viewFinder) +fun View.bindViewsResettable(vararg ids: Int): ReadOnlyProperty> = requiredResettable(ids, viewFinder) -fun Activity.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = requiredResettable(ids, viewFinder) +fun Activity.bindViewsResettable(vararg ids: Int): ReadOnlyProperty> = requiredResettable(ids, viewFinder) -fun Dialog.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = requiredResettable(ids, viewFinder) +fun Dialog.bindViewsResettable(vararg ids: Int): ReadOnlyProperty> = requiredResettable(ids, viewFinder) -fun DialogFragment.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = requiredResettable(ids, viewFinder) +fun DialogFragment.bindViewsResettable(vararg ids: Int): ReadOnlyProperty> = requiredResettable(ids, viewFinder) -fun SupportDialogFragment.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = requiredResettable(ids, viewFinder) +fun SupportDialogFragment.bindViewsResettable(vararg ids: Int): ReadOnlyProperty> = requiredResettable(ids, viewFinder) -fun Fragment.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = requiredResettable(ids, viewFinder) +fun Fragment.bindViewsResettable(vararg ids: Int): ReadOnlyProperty> = requiredResettable(ids, viewFinder) -fun SupportFragment.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = requiredResettable(ids, viewFinder) +fun SupportFragment.bindViewsResettable(vararg ids: Int): ReadOnlyProperty> = requiredResettable(ids, viewFinder) -fun ViewHolder.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = requiredResettable(ids, viewFinder) +fun ViewHolder.bindViewsResettable(vararg ids: Int): ReadOnlyProperty> = requiredResettable(ids, viewFinder) -fun View.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = optionalResettable(ids, viewFinder) +fun View.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty> = optionalResettable(ids, viewFinder) -fun Activity.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = optionalResettable(ids, viewFinder) +fun Activity.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty> = optionalResettable(ids, viewFinder) -fun Dialog.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = optionalResettable(ids, viewFinder) +fun Dialog.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty> = optionalResettable(ids, viewFinder) -fun DialogFragment.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = optionalResettable(ids, viewFinder) +fun DialogFragment.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty> = optionalResettable(ids, viewFinder) -fun SupportDialogFragment.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = optionalResettable(ids, viewFinder) +fun SupportDialogFragment.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty> = optionalResettable(ids, viewFinder) -fun Fragment.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = optionalResettable(ids, viewFinder) +fun Fragment.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty> = optionalResettable(ids, viewFinder) -fun SupportFragment.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = optionalResettable(ids, viewFinder) +fun SupportFragment.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty> = optionalResettable(ids, viewFinder) -fun ViewHolder.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty> = optionalResettable(ids, viewFinder) +fun ViewHolder.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty> = optionalResettable(ids, viewFinder) private fun requiredResettable(id: Int, finder: T.(Int) -> View?) = LazyResettable { t: T, desc -> (t.finder(id) as V?)?.apply { } ?: viewNotFound(id, desc) } -private fun optionalResettable(id: Int, finder: T.(Int) -> View?) = LazyResettable { t: T, _ -> t.finder(id) as V? } +private fun optionalResettable(id: Int, finder: T.(Int) -> View?) = + LazyResettable { t: T, _ -> t.finder(id) as V? } private fun requiredResettable(ids: IntArray, finder: T.(Int) -> View?) = LazyResettable { t: T, desc -> ids.map { @@ -289,7 +243,8 @@ private fun requiredResettable(ids: IntArray, finder: T.(Int) -> V } } -private fun optionalResettable(ids: IntArray, finder: T.(Int) -> View?) = LazyResettable { t: T, _ -> ids.map { t.finder(it) as V? }.filterNotNull() } +private fun optionalResettable(ids: IntArray, finder: T.(Int) -> View?) = + LazyResettable { t: T, _ -> ids.map { t.finder(it) as V? }.filterNotNull() } //Like Kotterknife's lazy delegate but is resettable private class LazyResettable(initializer: (T, KProperty<*>) -> V) : Lazy(initializer) { @@ -298,7 +253,7 @@ private class LazyResettable(initializer: (T, KProperty<*>) -> V) : return super.getValue(thisRef, property) } -fun reset() { + fun reset() { value = EMPTY } } @@ -312,7 +267,8 @@ object Kotterknife { private object KotterknifeRegistry { private val lazyMap = WeakHashMap>>() -fun register(target: Any, lazy: LazyResettable<*, *>) = lazyMap.getOrPut(target, { Collections.newSetFromMap(WeakHashMap()) }).add(lazy) + fun register(target: Any, lazy: LazyResettable<*, *>) = + lazyMap.getOrPut(target, { Collections.newSetFromMap(WeakHashMap()) }).add(lazy) -fun reset(target: Any) = lazyMap[target]?.forEach(LazyResettable<*, *>::reset) -} \ No newline at end of file + fun reset(target: Any) = lazyMap[target]?.forEach(LazyResettable<*, *>::reset) +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/NetworkUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/NetworkUtils.kt index 2271c16..260e90f 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/NetworkUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/NetworkUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.annotation.SuppressLint @@ -29,4 +44,4 @@ inline val Context.isMobileDataConnected: Boolean val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val activeNetworkInfo = connectivityManager.activeNetworkInfo return (activeNetworkInfo?.type ?: -1) == ConnectivityManager.TYPE_MOBILE - } \ No newline at end of file + } diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/NotificationUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/NotificationUtils.kt index 016f3d2..126b133 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/NotificationUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/NotificationUtils.kt @@ -1,10 +1,24 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.content.Context import androidx.core.app.NotificationManagerCompat - /** * Created by Allan Wang on 2017-08-04. */ -fun Context.cancelNotification(notifId: Int) = NotificationManagerCompat.from(this).cancel(notifId) \ No newline at end of file +fun Context.cancelNotification(notifId: Int) = NotificationManagerCompat.from(this).cancel(notifId) diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt index 77750d3..4055847 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.content.ActivityNotFoundException @@ -70,4 +85,4 @@ inline val Context.isFromGooglePlay: Boolean get() { val installer = installerPackageName return arrayOf(INSTALLER_GOOGLE_PLAY_FEEDBACK, INSTALLER_GOOGLE_PLAY_VENDING).any { it == installer } - } \ No newline at end of file + } diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/RecyclerUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/RecyclerUtils.kt index 1c336f9..11494b3 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/RecyclerUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/RecyclerUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.graphics.Rect @@ -22,4 +37,4 @@ class MarginItemDecoration(sizeDp: Int, val edgeFlags: Int) : RecyclerView.ItemD if (edgeFlags and KAU_RIGHT > 0) outRect.right += sizePx if (edgeFlags and KAU_BOTTOM > 0) outRect.bottom += sizePx } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/TransitionUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/TransitionUtils.kt index 1d12fd3..523a586 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/TransitionUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/TransitionUtils.kt @@ -1,13 +1,28 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.os.Build +import android.transition.Transition +import android.view.ViewGroup import androidx.annotation.RequiresApi import androidx.annotation.TransitionRes import androidx.transition.AutoTransition import androidx.transition.TransitionInflater import androidx.transition.TransitionManager -import android.transition.Transition -import android.view.ViewGroup import androidx.transition.Transition as SupportTransition /** @@ -29,7 +44,8 @@ fun Transition.addEndListener(onEnd: (transition: Transition) -> Unit) { } @RequiresApi(Build.VERSION_CODES.LOLLIPOP) -class SupportTransitionEndListener(val onEnd: (transition: SupportTransition) -> Unit) : SupportTransition.TransitionListener { +class SupportTransitionEndListener(val onEnd: (transition: SupportTransition) -> Unit) : + SupportTransition.TransitionListener { override fun onTransitionEnd(transition: SupportTransition) = onEnd(transition) override fun onTransitionResume(transition: SupportTransition) {} override fun onTransitionPause(transition: SupportTransition) {} @@ -57,4 +73,4 @@ fun ViewGroup.transitionDelayed(@TransitionRes id: Int, builder: androidx.transi val transition = TransitionInflater.from(context).inflateTransition(id) transition.builder() TransitionManager.beginDelayedTransition(this, transition) -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt index c8d5d2a..da4feb8 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.content.Context @@ -13,7 +28,6 @@ import ca.allanwang.kau.R import java.math.RoundingMode import java.text.DecimalFormat - /** * Created by Allan Wang on 2017-05-28. */ @@ -132,5 +146,5 @@ inline val kauIsMainThread: Boolean class KauException(message: String) : RuntimeException(message) fun String.withMaxLength(n: Int): String = - if (length <= n) this - else substring(0, n - 1) + KAU_ELLIPSIS \ No newline at end of file + if (length <= n) this + else substring(0, n - 1) + KAU_ELLIPSIS diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt index 956df48..186d125 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ @file:Suppress("NOTHING_TO_INLINE") package ca.allanwang.kau.utils @@ -7,10 +22,6 @@ import android.annotation.SuppressLint import android.content.Context import android.graphics.Color import android.os.Build -import androidx.annotation.ColorInt -import androidx.annotation.ColorRes -import androidx.annotation.RequiresApi -import androidx.annotation.StringRes import android.view.LayoutInflater import android.view.MotionEvent import android.view.View @@ -18,6 +29,10 @@ import android.view.ViewGroup import android.view.inputmethod.InputMethodManager import android.widget.EditText import android.widget.ImageView +import androidx.annotation.ColorInt +import androidx.annotation.ColorRes +import androidx.annotation.RequiresApi +import androidx.annotation.StringRes import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.ui.createSimpleRippleDrawable @@ -27,7 +42,6 @@ import com.google.android.material.textfield.TextInputEditText import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.IIcon - /** * Created by Allan Wang on 2017-05-31. */ @@ -81,10 +95,16 @@ fun View.snackbar(text: String, duration: Int = Snackbar.LENGTH_LONG, builder: S return snackbar } -fun View.snackbar(@StringRes textId: Int, duration: Int = Snackbar.LENGTH_LONG, builder: Snackbar.() -> Unit = {}) = snackbar(context.string(textId), duration, builder) +fun View.snackbar(@StringRes textId: Int, duration: Int = Snackbar.LENGTH_LONG, builder: Snackbar.() -> Unit = {}) = + snackbar(context.string(textId), duration, builder) @KauUtils -fun ImageView.setIcon(icon: IIcon?, sizeDp: Int = 24, @ColorInt color: Int = Color.WHITE, builder: IconicsDrawable.() -> Unit = {}) { +fun ImageView.setIcon( + icon: IIcon?, + sizeDp: Int = 24, + @ColorInt color: Int = Color.WHITE, + builder: IconicsDrawable.() -> Unit = {} +) { if (icon == null) return setImageDrawable(icon.toDrawable(context, sizeDp = sizeDp, color = color, builder = builder)) } @@ -98,7 +118,8 @@ fun FloatingActionButton.showIf(show: Boolean) = if (show) show() else hide() fun FloatingActionButton.hideIf(hide: Boolean) = if (hide) hide() else show() @KauUtils -fun ViewGroup.inflate(layoutId: Int, attachToRoot: Boolean = false): View = LayoutInflater.from(context).inflate(layoutId, this, attachToRoot) +fun ViewGroup.inflate(layoutId: Int, attachToRoot: Boolean = false): View = + LayoutInflater.from(context).inflate(layoutId, this, attachToRoot) /** * Set left margin to a value in px @@ -150,10 +171,10 @@ fun View.setMargin(margin: Int) = setMargins(margin, KAU_ALL) private fun View.setMargins(margin: Int, flag: Int): Boolean { val p = (layoutParams as? ViewGroup.MarginLayoutParams) ?: return false p.setMargins( - if (flag and KAU_LEFT > 0) margin else p.leftMargin, - if (flag and KAU_TOP > 0) margin else p.topMargin, - if (flag and KAU_RIGHT > 0) margin else p.rightMargin, - if (flag and KAU_BOTTOM > 0) margin else p.bottomMargin + if (flag and KAU_LEFT > 0) margin else p.leftMargin, + if (flag and KAU_TOP > 0) margin else p.topMargin, + if (flag and KAU_RIGHT > 0) margin else p.rightMargin, + if (flag and KAU_BOTTOM > 0) margin else p.bottomMargin ) return true } @@ -206,26 +227,31 @@ fun View.setPadding(padding: Int) = setPadding(padding, KAU_ALL) @KauUtils private fun View.setPadding(padding: Int, flag: Int) { setPadding( - if (flag and KAU_LEFT > 0) padding else paddingLeft, - if (flag and KAU_TOP > 0) padding else paddingTop, - if (flag and KAU_RIGHT > 0) padding else paddingRight, - if (flag and KAU_BOTTOM > 0) padding else paddingBottom + if (flag and KAU_LEFT > 0) padding else paddingLeft, + if (flag and KAU_TOP > 0) padding else paddingTop, + if (flag and KAU_RIGHT > 0) padding else paddingRight, + if (flag and KAU_BOTTOM > 0) padding else paddingBottom ) } @KauUtils fun View.hideKeyboard() { clearFocus() - (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(windowToken, 0) + (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow( + windowToken, + 0 + ) } @KauUtils fun View.showKeyboard() { requestFocus() - (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).showSoftInput(this, InputMethodManager.SHOW_IMPLICIT) + (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).showSoftInput( + this, + InputMethodManager.SHOW_IMPLICIT + ) } - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) @KauUtils fun View.setRippleBackground(@ColorInt foregroundColor: Int, @ColorInt backgroundColor: Int) { @@ -243,12 +269,14 @@ inline val TextInputEditText.value: String get() = text.toString().trim() /** * Generates a recycler view with match parent and a linearlayoutmanager, since it's so commonly used */ -fun Context.fullLinearRecycler(rvAdapter: RecyclerView.Adapter<*>? = null, configs: RecyclerView.() -> Unit = {}) = RecyclerView(this).apply { - layoutManager = LinearLayoutManager(this@fullLinearRecycler) - layoutParams = RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.MATCH_PARENT) - if (rvAdapter != null) adapter = rvAdapter - configs() -} +fun Context.fullLinearRecycler(rvAdapter: RecyclerView.Adapter<*>? = null, configs: RecyclerView.() -> Unit = {}) = + RecyclerView(this).apply { + layoutManager = LinearLayoutManager(this@fullLinearRecycler) + layoutParams = + RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.MATCH_PARENT) + if (rvAdapter != null) adapter = rvAdapter + configs() + } /** * Sets a linear layout manager along with an adapter @@ -263,7 +291,11 @@ fun RecyclerView.withLinearAdapter(rvAdapter: RecyclerView.Adapter<*>) = apply { * If it is not shown, the action will be invoked directly and no further actions will be made * If it is already shown, scaling and alpha animations will be added to the action */ -inline fun T.fadeScaleTransition(duration: Long = 500L, minScale: Float = 0.7f, crossinline action: T.() -> Unit) { +inline fun T.fadeScaleTransition( + duration: Long = 500L, + minScale: Float = 0.7f, + crossinline action: T.() -> Unit +) { if (!isVisible) action() else { var transitioned = false @@ -324,4 +356,4 @@ inline fun View.setOnSingleTapListener(crossinline onSingleTap: (v: View, event: else -> false } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt b/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt index 3955a77..6a75aa9 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt @@ -1,14 +1,29 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.xml import android.content.Context import android.content.res.XmlResourceParser -import androidx.annotation.ColorInt -import androidx.annotation.LayoutRes -import androidx.annotation.XmlRes import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.LayoutRes +import androidx.annotation.XmlRes import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.R import ca.allanwang.kau.utils.materialDialog @@ -18,7 +33,6 @@ import org.jetbrains.anko.doAsync import org.jetbrains.anko.uiThread import org.xmlpull.v1.XmlPullParser - /** * Created by Allan Wang on 2017-05-28. * @@ -42,10 +56,13 @@ fun Context.showChangelog(@XmlRes xmlRes: Int, @ColorInt textColor: Int? = null, * Internals of the changelog dialog * Contains an mainAdapter for each item, as well as the tags to parse */ -internal class ChangelogAdapter(val items: List>, @ColorInt val textColor: Int? = null) : RecyclerView.Adapter() { +internal class ChangelogAdapter(val items: List>, @ColorInt val textColor: Int? = null) : + RecyclerView.Adapter() { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ChangelogVH(LayoutInflater.from(parent.context) - .inflate(items[viewType].second.layout, parent, false)) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ChangelogVH( + LayoutInflater.from(parent.context) + .inflate(items[viewType].second.layout, parent, false) + ) override fun onBindViewHolder(holder: ChangelogVH, position: Int) { holder.text.text = items[position].first @@ -98,4 +115,3 @@ internal enum class ChangelogType(val tag: String, val attr: String, @LayoutRes return true } } - diff --git a/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt b/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt index bbe9425..cb57216 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt @@ -1,10 +1,25 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.xml import android.content.Context import android.content.res.XmlResourceParser -import androidx.annotation.XmlRes import android.text.Html import android.text.Spanned +import androidx.annotation.XmlRes import ca.allanwang.kau.utils.use import org.jetbrains.anko.doAsync import org.jetbrains.anko.uiThread @@ -20,12 +35,13 @@ import org.xmlpull.v1.XmlPullParser */ @Suppress("DEPRECATION") fun Context.kauParseFaq( - @XmlRes xmlRes: Int, - /** - * If \n is used, it will automatically be converted to
- */ - parseNewLine: Boolean = true, - callback: (items: List) -> Unit) { + @XmlRes xmlRes: Int, + /** + * If \n is used, it will automatically be converted to
+ */ + parseNewLine: Boolean = true, + callback: (items: List) -> Unit +) { doAsync { val items = mutableListOf() resources.getXml(xmlRes).use { parser: XmlResourceParser -> @@ -46,10 +62,14 @@ fun Context.kauParseFaq( flag = -1 } 1 -> { - items.add(FaqItem(items.size + 1, + items.add( + FaqItem( + items.size + 1, question - ?: throw IllegalArgumentException("KAU FAQ answer found without a question"), - Html.fromHtml(parser.text.replace("\n", if (parseNewLine) "
" else "")))) + ?: throw IllegalArgumentException("KAU FAQ answer found without a question"), + Html.fromHtml(parser.text.replace("\n", if (parseNewLine) "
" else "")) + ) + ) question = null flag = -1 } @@ -62,4 +82,4 @@ fun Context.kauParseFaq( } } -data class FaqItem(val number: Int, val question: Spanned, val answer: Spanned) \ No newline at end of file +data class FaqItem(val number: Int, val question: Spanned, val answer: Spanned) diff --git a/core/src/test/kotlin/ca/allanwang/kau/kotlin/DebounceTest.kt b/core/src/test/kotlin/ca/allanwang/kau/kotlin/DebounceTest.kt index 8ccdab3..c406901 100644 --- a/core/src/test/kotlin/ca/allanwang/kau/kotlin/DebounceTest.kt +++ b/core/src/test/kotlin/ca/allanwang/kau/kotlin/DebounceTest.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kotlin import org.junit.Test @@ -48,5 +63,4 @@ class DebounceTest { Thread.sleep(30) assertEquals(10, i) } - -} \ No newline at end of file +} diff --git a/core/src/test/kotlin/ca/allanwang/kau/kotlin/LazyResettableTest.kt b/core/src/test/kotlin/ca/allanwang/kau/kotlin/LazyResettableTest.kt index 2025422..eaaaacb 100644 --- a/core/src/test/kotlin/ca/allanwang/kau/kotlin/LazyResettableTest.kt +++ b/core/src/test/kotlin/ca/allanwang/kau/kotlin/LazyResettableTest.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kotlin import org.junit.Before @@ -33,5 +48,4 @@ class LazyResettableTest { assertEquals(t1, t2, "Lazy resettable not returning same value after second call") assertNotEquals(t1, t3, "Lazy resettable not invalidated by registry") } - -} \ No newline at end of file +} diff --git a/core/src/test/kotlin/ca/allanwang/kau/kotlin/StreamsTest.kt b/core/src/test/kotlin/ca/allanwang/kau/kotlin/StreamsTest.kt index 1c40f57..4dc4a34 100644 --- a/core/src/test/kotlin/ca/allanwang/kau/kotlin/StreamsTest.kt +++ b/core/src/test/kotlin/ca/allanwang/kau/kotlin/StreamsTest.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kotlin import org.junit.Test @@ -38,5 +53,4 @@ class StreamsTest { items.kauRemoveIf { it == thePotato } //removal by equality assertEquals(result.size - 1, items.size, "Invalid list removal based on equality") } - -} \ No newline at end of file +} diff --git a/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt b/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt index 7eeffaf..1fbc38f 100644 --- a/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt +++ b/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt @@ -1,8 +1,23 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kotlin import org.jetbrains.anko.doAsync import org.junit.Test -import java.util.* +import java.util.Random import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import kotlin.test.assertTrue @@ -40,7 +55,6 @@ class ZipTest { assertTrue((0..10).toList().toTypedArray().contentEquals(results), "Basic zip results do not match") assertTrue(finish - start < 1000L, "Basic zip does not seem to be running asynchronously") latch.countDown() - } latch.await(1100, TimeUnit.MILLISECONDS) } @@ -66,5 +80,4 @@ class ZipTest { } latch.await(1100, TimeUnit.MILLISECONDS) } - -} \ No newline at end of file +} diff --git a/core/src/test/kotlin/ca/allanwang/kau/utils/UtilsTest.kt b/core/src/test/kotlin/ca/allanwang/kau/utils/UtilsTest.kt index ce2b757..1cce9ae 100644 --- a/core/src/test/kotlin/ca/allanwang/kau/utils/UtilsTest.kt +++ b/core/src/test/kotlin/ca/allanwang/kau/utils/UtilsTest.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.utils import android.graphics.Color @@ -22,4 +37,4 @@ class UtilsTest { assertEquals("22.466", 22.465920439.round(3)) assertEquals("22", 22f.round(3)) } -} \ No newline at end of file +} diff --git a/docs/Changelog.md b/docs/Changelog.md index 704e9c3..1e1b0d8 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -1,7 +1,8 @@ # Changelog ## v4.0.0-alpha01 -* Migrated to androidx. See migration for external dependency changes. +* Migrate to androidx. See migration for external dependency changes. +* :core: Remove deprecation warning for Kotterknife ## v3.8.0 * Update everything to Android Studio 3.1 diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KClick.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KClick.kt index c02b024..119f5eb 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KClick.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KClick.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref.activity import android.content.Context @@ -24,4 +39,4 @@ interface KClick { * The item holding the data */ val item: KPrefItemBase -} \ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt index 132c27a..02b6e98 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt @@ -1,22 +1,41 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref.activity import android.annotation.SuppressLint import android.os.Bundle +import android.view.View import androidx.annotation.StringRes import androidx.appcompat.widget.Toolbar -import android.view.View import ca.allanwang.kau.animators.KauAnimator import ca.allanwang.kau.animators.SlideAnimatorAdd import ca.allanwang.kau.animators.SlideAnimatorRemove import ca.allanwang.kau.internal.KauBaseActivity import ca.allanwang.kau.kpref.activity.items.KPrefItemCore import ca.allanwang.kau.ui.views.RippleCanvas -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.KAU_LEFT +import ca.allanwang.kau.utils.KAU_RIGHT +import ca.allanwang.kau.utils.resolveColor +import ca.allanwang.kau.utils.statusBarColor +import ca.allanwang.kau.utils.withLinearAdapter import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter import kotlinx.android.synthetic.main.kau_pref_activity.* import org.jetbrains.anko.doAsync import org.jetbrains.anko.uiThread -import java.util.* +import java.util.Stack abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract { @@ -32,12 +51,16 @@ abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract { var animate: Boolean = true private val recyclerAnimatorNext: KauAnimator by lazy { - KauAnimator(SlideAnimatorAdd(KAU_RIGHT, itemDelayFactor = 0f), - SlideAnimatorRemove(KAU_LEFT, itemDelayFactor = 0f)) + KauAnimator( + SlideAnimatorAdd(KAU_RIGHT, itemDelayFactor = 0f), + SlideAnimatorRemove(KAU_LEFT, itemDelayFactor = 0f) + ) } private val recyclerAnimatorPrev: KauAnimator by lazy { - KauAnimator(SlideAnimatorAdd(KAU_LEFT, itemDelayFactor = 0f), - SlideAnimatorRemove(KAU_RIGHT, itemDelayFactor = 0f)) + KauAnimator( + SlideAnimatorAdd(KAU_LEFT, itemDelayFactor = 0f), + SlideAnimatorRemove(KAU_RIGHT, itemDelayFactor = 0f) + ) } /** @@ -69,13 +92,18 @@ abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract { globalOptions = GlobalOptions(core, this) kau_recycler.withLinearAdapter(adapter) adapter.withSelectable(false) - .withOnClickListener { v, _, item, _ -> item.onClick(v!!); true } + .withOnClickListener { v, _, item, _ -> item.onClick(v!!); true } showNextPrefs(R.string.kau_settings, onCreateKPrefs(savedInstanceState), true) } - override fun showNextPrefs(@StringRes toolbarTitleRes: Int, builder: KPrefAdapterBuilder.() -> Unit) = showNextPrefs(toolbarTitleRes, builder, false) + override fun showNextPrefs(@StringRes toolbarTitleRes: Int, builder: KPrefAdapterBuilder.() -> Unit) = + showNextPrefs(toolbarTitleRes, builder, false) - private fun showNextPrefs(@StringRes toolbarTitleRes: Int, builder: KPrefAdapterBuilder.() -> Unit, first: Boolean) { + private fun showNextPrefs( + @StringRes toolbarTitleRes: Int, + builder: KPrefAdapterBuilder.() -> Unit, + first: Boolean + ) { doAsync { val items = KPrefAdapterBuilder(globalOptions) builder(items) @@ -162,4 +190,3 @@ abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract { return false } } - diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefBinder.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefBinder.kt index 4b50ee4..cf2a12f 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefBinder.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefBinder.kt @@ -1,7 +1,31 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref.activity import androidx.annotation.StringRes -import ca.allanwang.kau.kpref.activity.items.* +import ca.allanwang.kau.kpref.activity.items.KPrefCheckbox +import ca.allanwang.kau.kpref.activity.items.KPrefColorPicker +import ca.allanwang.kau.kpref.activity.items.KPrefHeader +import ca.allanwang.kau.kpref.activity.items.KPrefItemBase +import ca.allanwang.kau.kpref.activity.items.KPrefItemCore +import ca.allanwang.kau.kpref.activity.items.KPrefPlainText +import ca.allanwang.kau.kpref.activity.items.KPrefSeekbar +import ca.allanwang.kau.kpref.activity.items.KPrefSubItems +import ca.allanwang.kau.kpref.activity.items.KPrefText +import ca.allanwang.kau.kpref.activity.items.KPrefTimePicker /** * Created by Allan Wang on 2017-06-08. @@ -35,11 +59,11 @@ interface KPrefActivityContract { fun reloadByTitle(@StringRes vararg title: Int) } - -class GlobalOptions(core: CoreAttributeContract, activity: KPrefActivityContract +class GlobalOptions( + core: CoreAttributeContract, + activity: KPrefActivityContract ) : CoreAttributeContract by core, KPrefActivityContract by activity - /** * Builder for kpref items * Contains DSLs for every possible item @@ -56,51 +80,79 @@ class KPrefAdapterBuilder(val globalOptions: GlobalOptions) { fun header(@StringRes title: Int) = list.add(KPrefHeader(KPrefItemCore.CoreBuilder(globalOptions, title))) @KPrefMarker - fun checkbox(@StringRes title: Int, - getter: (() -> Boolean), - setter: ((value: Boolean) -> Unit), - builder: KPrefItemBase.BaseContract.() -> Unit = {}) = list.add(KPrefCheckbox(KPrefItemBase.BaseBuilder(globalOptions, title, getter, setter) - .apply { builder() })) + fun checkbox( + @StringRes title: Int, + getter: (() -> Boolean), + setter: ((value: Boolean) -> Unit), + builder: KPrefItemBase.BaseContract.() -> Unit = {} + ) = list.add( + KPrefCheckbox(KPrefItemBase.BaseBuilder(globalOptions, title, getter, setter) + .apply { builder() }) + ) @KPrefMarker - fun colorPicker(@StringRes title: Int, - getter: (() -> Int), - setter: ((value: Int) -> Unit), - builder: KPrefColorPicker.KPrefColorContract.() -> Unit = {}) = list.add(KPrefColorPicker(KPrefColorPicker.KPrefColorBuilder(globalOptions, title, getter, setter) - .apply { builder() })) + fun colorPicker( + @StringRes title: Int, + getter: (() -> Int), + setter: ((value: Int) -> Unit), + builder: KPrefColorPicker.KPrefColorContract.() -> Unit = {} + ) = list.add( + KPrefColorPicker(KPrefColorPicker.KPrefColorBuilder(globalOptions, title, getter, setter) + .apply { builder() }) + ) @KPrefMarker - fun text(@StringRes title: Int, - getter: (() -> T), - setter: ((value: T) -> Unit), - builder: KPrefText.KPrefTextContract.() -> Unit = {}) = list.add(KPrefText(KPrefText.KPrefTextBuilder(globalOptions, title, getter, setter) - .apply { builder() })) + fun text( + @StringRes title: Int, + getter: (() -> T), + setter: ((value: T) -> Unit), + builder: KPrefText.KPrefTextContract.() -> Unit = {} + ) = list.add( + KPrefText(KPrefText.KPrefTextBuilder(globalOptions, title, getter, setter) + .apply { builder() }) + ) @KPrefMarker - fun subItems(@StringRes title: Int, - itemBuilder: KPrefAdapterBuilder.() -> Unit, - builder: KPrefSubItems.KPrefSubItemsContract.() -> Unit) = list.add(KPrefSubItems(KPrefSubItems.KPrefSubItemsBuilder(globalOptions, title, itemBuilder) - .apply { builder() })) + fun subItems( + @StringRes title: Int, + itemBuilder: KPrefAdapterBuilder.() -> Unit, + builder: KPrefSubItems.KPrefSubItemsContract.() -> Unit + ) = list.add( + KPrefSubItems(KPrefSubItems.KPrefSubItemsBuilder(globalOptions, title, itemBuilder) + .apply { builder() }) + ) @KPrefMarker - fun plainText(@StringRes title: Int, - builder: KPrefItemBase.BaseContract.() -> Unit = {}) = list.add(KPrefPlainText(KPrefPlainText.KPrefPlainTextBuilder(globalOptions, title) - .apply { builder() })) + fun plainText( + @StringRes title: Int, + builder: KPrefItemBase.BaseContract.() -> Unit = {} + ) = list.add( + KPrefPlainText(KPrefPlainText.KPrefPlainTextBuilder(globalOptions, title) + .apply { builder() }) + ) @KPrefMarker - fun seekbar(@StringRes title: Int, - getter: (() -> Int), - setter: ((value: Int) -> Unit), - builder: KPrefSeekbar.KPrefSeekbarContract.() -> Unit = {}) = list.add(KPrefSeekbar(KPrefSeekbar.KPrefSeekbarBuilder(globalOptions, title, getter, setter) - .apply { builder() })) + fun seekbar( + @StringRes title: Int, + getter: (() -> Int), + setter: ((value: Int) -> Unit), + builder: KPrefSeekbar.KPrefSeekbarContract.() -> Unit = {} + ) = list.add( + KPrefSeekbar(KPrefSeekbar.KPrefSeekbarBuilder(globalOptions, title, getter, setter) + .apply { builder() }) + ) @KPrefMarker - fun timePicker(@StringRes title: Int, - getter: (() -> Int), - setter: ((value: Int) -> Unit), - builder: KPrefTimePicker.KPrefTimeContract.() -> Unit = {}) = list.add(KPrefTimePicker(KPrefTimePicker.KPrefTimeBuilder(globalOptions, title, getter, setter) - .apply { builder() })) + fun timePicker( + @StringRes title: Int, + getter: (() -> Int), + setter: ((value: Int) -> Unit), + builder: KPrefTimePicker.KPrefTimeContract.() -> Unit = {} + ) = list.add( + KPrefTimePicker(KPrefTimePicker.KPrefTimeBuilder(globalOptions, title, getter, setter) + .apply { builder() }) + ) @KPrefMarker val list: MutableList = mutableListOf() -} \ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefCheckbox.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefCheckbox.kt index 0a7922e..0f025a6 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefCheckbox.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefCheckbox.kt @@ -1,7 +1,22 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref.activity.items -import androidx.appcompat.widget.AppCompatCheckBox import android.widget.CheckBox +import androidx.appcompat.widget.AppCompatCheckBox import ca.allanwang.kau.kpref.activity.KClick import ca.allanwang.kau.kpref.activity.R import ca.allanwang.kau.utils.tint @@ -28,5 +43,4 @@ open class KPrefCheckbox(builder: BaseContract) : KPrefItemBase Int, - setter: (value: Int) -> Unit + class KPrefColorBuilder( + globalOptions: GlobalOptions, + titleId: Int, + getter: () -> Int, + setter: (value: Int) -> Unit ) : KPrefColorContract, BaseContract by BaseBuilder(globalOptions, titleId, getter, setter), - ColorContract by ColorBuilder() { + ColorContract by ColorBuilder() { override var showPreview: Boolean = true } override fun getType(): Int = R.id.kau_item_pref_color_picker - -} \ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefHeader.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefHeader.kt index 9b63a52..7d73322 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefHeader.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefHeader.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref.activity.items import ca.allanwang.kau.kpref.activity.R @@ -18,5 +33,4 @@ open class KPrefHeader(builder: CoreContract) : KPrefItemCore(builder) { } override fun getType() = R.id.kau_item_pref_header - -} \ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemBase.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemBase.kt index aa60fcd..6690574 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemBase.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemBase.kt @@ -1,7 +1,22 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref.activity.items -import androidx.annotation.CallSuper import android.view.View +import androidx.annotation.CallSuper import ca.allanwang.kau.kpref.activity.GlobalOptions import ca.allanwang.kau.kpref.activity.KClick import ca.allanwang.kau.kpref.activity.R @@ -84,14 +99,14 @@ abstract class KPrefItemBase(protected val base: BaseContract) : KPrefItem /** * Default implementation of [BaseContract] */ - class BaseBuilder(globalOptions: GlobalOptions, - titleId: Int, - override val getter: () -> T, - override val setter: (value: T) -> Unit + class BaseBuilder( + globalOptions: GlobalOptions, + titleId: Int, + override val getter: () -> T, + override val setter: (value: T) -> Unit ) : CoreContract by CoreBuilder(globalOptions, titleId), BaseContract { override var enabler: () -> Boolean = { true } override var onClick: (KClick.() -> Unit)? = null override var onDisabledClick: (KClick.() -> Unit)? = null } - -} \ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemCore.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemCore.kt index 4e8ecbe..fc632ce 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemCore.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemCore.kt @@ -1,23 +1,43 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref.activity.items import android.annotation.SuppressLint -import androidx.annotation.CallSuper -import androidx.annotation.IdRes -import androidx.annotation.LayoutRes -import androidx.annotation.StringRes -import androidx.recyclerview.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView +import androidx.annotation.CallSuper +import androidx.annotation.IdRes +import androidx.annotation.LayoutRes +import androidx.annotation.StringRes +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.adapters.ThemableIItem import ca.allanwang.kau.adapters.ThemableIItemDelegate import ca.allanwang.kau.kpref.activity.GlobalOptions import ca.allanwang.kau.kpref.activity.KPrefMarker import ca.allanwang.kau.kpref.activity.R -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.INVALID_ID +import ca.allanwang.kau.utils.adjustAlpha +import ca.allanwang.kau.utils.buildIsLollipopAndUp +import ca.allanwang.kau.utils.gone +import ca.allanwang.kau.utils.setIcon +import ca.allanwang.kau.utils.visible import com.mikepenz.fastadapter.items.AbstractItem import com.mikepenz.iconics.typeface.IIcon @@ -28,7 +48,7 @@ import com.mikepenz.iconics.typeface.IIcon */ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem(), - ThemableIItem by ThemableIItemDelegate() { + ThemableIItem by ThemableIItemDelegate() { final override fun getViewHolder(v: View) = ViewHolder(v) @@ -69,13 +89,15 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem Unit) = - withColor(core.globalOptions.accentColor, action) + withColor(core.globalOptions.accentColor, action) protected inline fun withTextColor(action: (color: Int) -> Unit) = - withColor(core.globalOptions.textColor, action) + withColor(core.globalOptions.textColor, action) - protected inline fun withColor(noinline supplier: (() -> Int)?, - action: (color: Int) -> Unit) { + protected inline fun withColor( + noinline supplier: (() -> Int)?, + action: (color: Int) -> Unit + ) { val color = supplier?.invoke() ?: return action(color) } @@ -116,8 +138,10 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem bindInnerView(@LayoutRes id: Int, onFirstBind: (T) -> Unit): T { val innerFrame = this.innerFrame - ?: throw IllegalStateException("Cannot bind inner view when innerFrame does not exist") + ?: throw IllegalStateException("Cannot bind inner view when innerFrame does not exist") if (innerView !is T) { innerFrame.removeAllViews() LayoutInflater.from(innerFrame.context).inflate(id, innerFrame) @@ -162,7 +186,7 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem bindLowerView(@LayoutRes id: Int, onFirstBind: (T) -> Unit): T { val lowerFrame = this.lowerFrame - ?: throw IllegalStateException("Cannot bind inner view when lowerContent does not exist") + ?: throw IllegalStateException("Cannot bind inner view when lowerContent does not exist") if (lowerContent !is T) { lowerFrame.removeAllViews() LayoutInflater.from(lowerFrame.context).inflate(id, lowerFrame) @@ -173,4 +197,4 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem.defaultOnClick() = Unit class KPrefPlainTextBuilder( - globalOptions: GlobalOptions, - titleId: Int + globalOptions: GlobalOptions, + titleId: Int ) : BaseContract by BaseBuilder(globalOptions, titleId, {}, {}) override fun getType(): Int = R.id.kau_item_pref_plain_text - -} \ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSeekbar.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSeekbar.kt index ce61e8f..e70a374 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSeekbar.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSeekbar.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref.activity.items import android.widget.SeekBar @@ -67,10 +82,10 @@ open class KPrefSeekbar(val builder: KPrefSeekbarContract) : KPrefItemBase( * Default implementation of [KPrefSeekbarContract] */ class KPrefSeekbarBuilder( - globalOptions: GlobalOptions, - titleId: Int, - getter: () -> Int, - setter: (value: Int) -> Unit + globalOptions: GlobalOptions, + titleId: Int, + getter: () -> Int, + setter: (value: Int) -> Unit ) : KPrefSeekbarContract, BaseContract by BaseBuilder(globalOptions, titleId, getter, setter) { override var min: Int = 0 @@ -103,5 +118,4 @@ open class KPrefSeekbar(val builder: KPrefSeekbarContract) : KPrefItemBase( get() = this * increment + min override fun getType(): Int = R.id.kau_item_pref_seekbar - -} \ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSubItems.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSubItems.kt index 6753142..1fa528b 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSubItems.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSubItems.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref.activity.items import android.view.View @@ -31,11 +46,10 @@ open class KPrefSubItems(open val builder: KPrefSubItemsContract) : KPrefItemCor * Default implementation of [KPrefTextContract] */ class KPrefSubItemsBuilder( - globalOptions: GlobalOptions, - titleId: Int, - override val itemBuilder: KPrefAdapterBuilder.() -> Unit + globalOptions: GlobalOptions, + titleId: Int, + override val itemBuilder: KPrefAdapterBuilder.() -> Unit ) : KPrefSubItemsContract, CoreContract by CoreBuilder(globalOptions, titleId) override fun getType(): Int = R.id.kau_item_pref_sub_item - -} \ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefText.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefText.kt index 2ab911b..ac8416d 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefText.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefText.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref.activity.items import android.widget.TextView @@ -48,14 +63,13 @@ open class KPrefText(open val builder: KPrefTextContract) : KPrefItemBase< * Default implementation of [KPrefTextContract] */ class KPrefTextBuilder( - globalOptions: GlobalOptions, - titleId: Int, - getter: () -> T, - setter: (value: T) -> Unit + globalOptions: GlobalOptions, + titleId: Int, + getter: () -> T, + setter: (value: T) -> Unit ) : KPrefTextContract, BaseContract by BaseBuilder(globalOptions, titleId, getter, setter) { override var textGetter: (T) -> String? = { it?.toString() } } override fun getType(): Int = R.id.kau_item_pref_text - -} \ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefTimePicker.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefTimePicker.kt index f6fc40a..7242bbe 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefTimePicker.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefTimePicker.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.kpref.activity.items import android.app.TimePickerDialog @@ -5,7 +20,7 @@ import android.widget.TimePicker import ca.allanwang.kau.kpref.activity.GlobalOptions import ca.allanwang.kau.kpref.activity.KClick import ca.allanwang.kau.kpref.activity.R -import java.util.* +import java.util.Locale /** * Created by Allan Wang on 2017-06-14. @@ -30,10 +45,10 @@ open class KPrefTimePicker(override val builder: KPrefTimeContract) : KPrefText< * Default implementation of [KPrefTimeContract] */ class KPrefTimeBuilder( - globalOptions: GlobalOptions, - titleId: Int, - getter: () -> Int, - setter: (value: Int) -> Unit + globalOptions: GlobalOptions, + titleId: Int, + getter: () -> Int, + setter: (value: Int) -> Unit ) : KPrefTimeContract, BaseContract by BaseBuilder(globalOptions, titleId, getter, setter) { override var use24HourFormat: Boolean = false @@ -50,15 +65,13 @@ open class KPrefTimePicker(override val builder: KPrefTimeContract) : KPrefText< else String.format(Locale.CANADA, "%d:%02d %s", hour % 12, min, if (hour >= 12) "PM" else "AM") } - } override fun getType(): Int = R.id.kau_item_pref_time_picker - } private val Int.splitTime: Pair get() = Pair(this / 100, this % 100) private val Pair.mergeTime: Int - get() = first * 100 + second \ No newline at end of file + get() = first * 100 + second diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/BlurredImageView.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/BlurredImageView.kt index f1e32d1..739bf47 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/BlurredImageView.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/BlurredImageView.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.content.Context @@ -8,7 +23,11 @@ import android.widget.FrameLayout import android.widget.ImageView import ca.allanwang.kau.ui.views.MeasureSpecContract import ca.allanwang.kau.ui.views.MeasureSpecDelegate -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.inflate +import ca.allanwang.kau.utils.scaleXY +import ca.allanwang.kau.utils.setBackgroundColorRes +import ca.allanwang.kau.utils.setIcon +import ca.allanwang.kau.utils.visible import com.mikepenz.google_material_typeface_library.GoogleMaterial import jp.wasabeef.blurry.internal.BlurFactor import jp.wasabeef.blurry.internal.BlurTask @@ -24,7 +43,9 @@ import kotlinx.android.synthetic.main.kau_blurred_imageview.view.* * The foreground by default contains a white checkmark, but can be customized or hidden depending on the situation */ class BlurredImageView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr), MeasureSpecContract by MeasureSpecDelegate() { private var blurred = false @@ -51,7 +72,6 @@ class BlurredImageView @JvmOverloads constructor( private fun View.scaleAnimate(scale: Float) = animate().scaleXY(scale).setDuration(ANIMATION_DURATION) private fun View.alphaAnimate(alpha: Float) = animate().alpha(alpha).setDuration(ANIMATION_DURATION) - fun isBlurred(): Boolean { return blurred } @@ -104,7 +124,6 @@ class BlurredImageView @JvmOverloads constructor( image_foreground.alphaAnimate(0f).start() } - /** * Clear all animations and unblur the image */ @@ -154,4 +173,4 @@ class BlurredImageView @JvmOverloads constructor( action(image_blur) action(image_foreground) } -} \ No newline at end of file +} diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/GlideHelper.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/GlideHelper.kt index 8bb341c..21a1e9d 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/GlideHelper.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/GlideHelper.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.view.View @@ -15,4 +30,4 @@ internal interface GlideContract { internal class GlideDelegate : GlideContract { override fun glide(v: View) = ((v.context as? MediaPickerCore<*>)?.glide ?: Glide.with(v))!! -} \ No newline at end of file +} diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaActionItem.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaActionItem.kt index 0cf6340..ca879ef 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaActionItem.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaActionItem.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.app.Activity @@ -15,14 +30,17 @@ import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.typeface.IIcon import java.io.File - /** * Created by Allan Wang on 2017-08-17. */ class MediaActionItem( - val action: MediaAction, - val mediaType: MediaType -) : KauIItem(R.layout.kau_iitem_image_basic, { MediaItemBasic.ViewHolder(it) }, R.id.kau_item_media_action) { + val action: MediaAction, + val mediaType: MediaType +) : KauIItem( + R.layout.kau_iitem_image_basic, + { MediaItemBasic.ViewHolder(it) }, + R.id.kau_item_media_action +) { override fun isSelectable(): Boolean = false @@ -60,7 +78,7 @@ internal const val MEDIA_ACTION_REQUEST_PICKER = 101 * If you just wish to use videos, see [MediaActionCameraVideo] */ abstract class MediaActionCamera( - override var color: Int = MediaPickerCore.accentColor + override var color: Int = MediaPickerCore.accentColor ) : MediaAction { abstract fun createFile(context: Context): File @@ -105,7 +123,7 @@ abstract class MediaActionCamera( * Basic camera action just for videos */ class MediaActionCameraVideo( - override var color: Int = MediaPickerCore.accentColor + override var color: Int = MediaPickerCore.accentColor ) : MediaAction { override fun iicon(item: MediaActionItem) = GoogleMaterial.Icon.gmd_videocam override operator fun invoke(c: Context, item: MediaActionItem) { @@ -126,8 +144,8 @@ class MediaActionCameraVideo( * The type will be added programmatically */ class MediaActionGallery( - val multiple: Boolean = false, - override var color: Int = MediaPickerCore.accentColor + val multiple: Boolean = false, + override var color: Int = MediaPickerCore.accentColor ) : MediaAction { override fun iicon(item: MediaActionItem) = when (item.mediaType) { @@ -144,9 +162,10 @@ class MediaActionGallery( putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple) } (c as Activity).startActivityForResult( - Intent.createChooser(intent, c.string(R.string.kau_select_media)), - MEDIA_ACTION_REQUEST_PICKER) + Intent.createChooser(intent, c.string(R.string.kau_select_media)), + MEDIA_ACTION_REQUEST_PICKER + ) } } } -} \ No newline at end of file +} diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItem.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItem.kt index db4d18b..5d3e7b9 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItem.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItem.kt @@ -1,8 +1,23 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.graphics.drawable.Drawable -import androidx.recyclerview.widget.RecyclerView import android.view.View +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.iitems.KauIItem import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.engine.GlideException @@ -13,22 +28,23 @@ import com.mikepenz.fastadapter.FastAdapter /** * Created by Allan Wang on 2017-07-04. */ -class MediaItem(val data: MediaModel) - : KauIItem(R.layout.kau_iitem_image, { ViewHolder(it) }), GlideContract by GlideDelegate() { +class MediaItem(val data: MediaModel) : + KauIItem(R.layout.kau_iitem_image, { ViewHolder(it) }), + GlideContract by GlideDelegate() { private var failedToLoad = false companion object { fun bindEvents(fastAdapter: FastAdapter) { fastAdapter.withMultiSelect(true) - .withSelectable(true) - //adapter selector occurs before the on click event - .withOnClickListener { v, _, item, _ -> - val image = v as BlurredImageView - if (item.isSelected) image.blur() - else image.removeBlur() - true - } + .withSelectable(true) + //adapter selector occurs before the on click event + .withOnClickListener { v, _, item, _ -> + val image = v as BlurredImageView + if (item.isSelected) image.blur() + else image.removeBlur() + true + } } } @@ -37,22 +53,33 @@ class MediaItem(val data: MediaModel) override fun bindView(holder: ViewHolder, payloads: List) { super.bindView(holder, payloads) glide(holder.itemView) - .load(data.data) - .applyMediaOptions(holder.itemView.context) - .listener(object : RequestListener { - override fun onLoadFailed(e: GlideException?, model: Any, target: Target, isFirstResource: Boolean): Boolean { - failedToLoad = true - holder.container.imageBase.setImageDrawable(MediaPickerCore.getErrorDrawable(holder.itemView.context)) - return true - } + .load(data.data) + .applyMediaOptions(holder.itemView.context) + .listener(object : RequestListener { + override fun onLoadFailed( + e: GlideException?, + model: Any, + target: Target, + isFirstResource: Boolean + ): Boolean { + failedToLoad = true + holder.container.imageBase.setImageDrawable(MediaPickerCore.getErrorDrawable(holder.itemView.context)) + return true + } - override fun onResourceReady(resource: Drawable, model: Any, target: Target, dataSource: DataSource, isFirstResource: Boolean): Boolean { - holder.container.imageBase.setImageDrawable(resource) - if (isSelected) holder.container.blurInstantly() - return true - } - }) - .into(holder.container.imageBase) + override fun onResourceReady( + resource: Drawable, + model: Any, + target: Target, + dataSource: DataSource, + isFirstResource: Boolean + ): Boolean { + holder.container.imageBase.setImageDrawable(resource) + if (isSelected) holder.container.blurInstantly() + return true + } + }) + .into(holder.container.imageBase) } override fun unbindView(holder: ViewHolder) { @@ -65,4 +92,4 @@ class MediaItem(val data: MediaModel) class ViewHolder(v: View) : RecyclerView.ViewHolder(v) { val container: BlurredImageView = v.findViewById(R.id.kau_image) } -} \ No newline at end of file +} diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItemBasic.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItemBasic.kt index 29babe2..73647b8 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItemBasic.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaItemBasic.kt @@ -1,10 +1,25 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.annotation.SuppressLint import android.app.Activity import android.graphics.drawable.Drawable -import androidx.recyclerview.widget.RecyclerView import android.view.View +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.iitems.KauIItem import ca.allanwang.kau.ui.views.MeasuredImageView import com.bumptech.glide.load.DataSource @@ -16,18 +31,19 @@ import com.mikepenz.fastadapter.FastAdapter /** * Created by Allan Wang on 2017-07-04. */ -class MediaItemBasic(val data: MediaModel) - : KauIItem(R.layout.kau_iitem_image_basic, { ViewHolder(it) }), GlideContract by GlideDelegate() { +class MediaItemBasic(val data: MediaModel) : + KauIItem(R.layout.kau_iitem_image_basic, { ViewHolder(it) }), + GlideContract by GlideDelegate() { companion object { @SuppressLint("NewApi") fun bindEvents(activity: Activity, fastAdapter: FastAdapter) { fastAdapter.withSelectable(false) - //add image data and return right away - .withOnClickListener { _, _, item, _ -> - activity.finish(arrayListOf(item.data)) - true - } + //add image data and return right away + .withOnClickListener { _, _, item, _ -> + activity.finish(arrayListOf(item.data)) + true + } } } @@ -36,19 +52,30 @@ class MediaItemBasic(val data: MediaModel) override fun bindView(holder: ViewHolder, payloads: List) { super.bindView(holder, payloads) glide(holder.itemView) - .load(data.data) - .applyMediaOptions(holder.itemView.context) - .listener(object : RequestListener { - override fun onLoadFailed(e: GlideException?, model: Any, target: Target, isFirstResource: Boolean): Boolean { - holder.image.setImageDrawable(MediaPickerCore.getErrorDrawable(holder.itemView.context)) - return true - } - - override fun onResourceReady(resource: Drawable, model: Any, target: Target, dataSource: DataSource, isFirstResource: Boolean): Boolean { - return false - } - }) - .into(holder.image) + .load(data.data) + .applyMediaOptions(holder.itemView.context) + .listener(object : RequestListener { + override fun onLoadFailed( + e: GlideException?, + model: Any, + target: Target, + isFirstResource: Boolean + ): Boolean { + holder.image.setImageDrawable(MediaPickerCore.getErrorDrawable(holder.itemView.context)) + return true + } + + override fun onResourceReady( + resource: Drawable, + model: Any, + target: Target, + dataSource: DataSource, + isFirstResource: Boolean + ): Boolean { + return false + } + }) + .into(holder.image) } override fun unbindView(holder: ViewHolder) { @@ -59,4 +86,4 @@ class MediaItemBasic(val data: MediaModel) class ViewHolder(v: View) : RecyclerView.ViewHolder(v) { val image: MeasuredImageView = v.findViewById(R.id.kau_image) } -} \ No newline at end of file +} diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaModel.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaModel.kt index 9fc83f9..edd6199 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaModel.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaModel.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.database.Cursor @@ -9,38 +24,42 @@ import android.provider.MediaStore import androidx.annotation.NonNull import java.io.File - /** * Created by Allan Wang on 2017-07-14. */ data class MediaModel( - val data: String, val mimeType: String, val size: Long, val dateModified: Long, val displayName: String? + val data: String, + val mimeType: String, + val size: Long, + val dateModified: Long, + val displayName: String? ) : Parcelable { @Throws(SQLException::class) constructor(@NonNull cursor: Cursor) : this( - cursor.getString(0), - cursor.getString(1) ?: "", - cursor.getLong(2), - cursor.getLong(3), - cursor.getString(4) + cursor.getString(0), + cursor.getString(1) ?: "", + cursor.getLong(2), + cursor.getLong(3), + cursor.getString(4) ) constructor(f: File) : this( - f.absolutePath, - f.extension, // this isn't a mime type, but it does give some info - f.length(), - f.lastModified(), - f.nameWithoutExtension + f.absolutePath, + f.extension, // this isn't a mime type, but it does give some info + f.length(), + f.lastModified(), + f.nameWithoutExtension ) constructor(parcel: Parcel) : this( - parcel.readString()!!, - parcel.readString()!!, - parcel.readLong(), - parcel.readLong(), - parcel.readString()) + parcel.readString()!!, + parcel.readString()!!, + parcel.readLong(), + parcel.readLong(), + parcel.readString() + ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeString(this.data) @@ -67,11 +86,11 @@ data class MediaModel( companion object CREATOR : Parcelable.Creator { val projection = arrayOf( - MediaStore.MediaColumns.DATA, - MediaStore.MediaColumns.MIME_TYPE, - MediaStore.MediaColumns.SIZE, - MediaStore.MediaColumns.DATE_MODIFIED, - MediaStore.MediaColumns.DISPLAY_NAME + MediaStore.MediaColumns.DATA, + MediaStore.MediaColumns.MIME_TYPE, + MediaStore.MediaColumns.SIZE, + MediaStore.MediaColumns.DATE_MODIFIED, + MediaStore.MediaColumns.DISPLAY_NAME ) override fun createFromParcel(parcel: Parcel): MediaModel { @@ -82,5 +101,4 @@ data class MediaModel( return arrayOfNulls(size) } } - -} \ No newline at end of file +} diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerActivityBase.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerActivityBase.kt index b915cc8..5e5d1ed 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerActivityBase.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerActivityBase.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.database.Cursor @@ -22,8 +37,8 @@ import kotlinx.android.synthetic.main.kau_activity_image_picker.* * Having three layered images makes this slightly slower than [MediaPickerActivityOverlayBase] */ abstract class MediaPickerActivityBase( - mediaType: MediaType, - mediaActions: List = emptyList() + mediaType: MediaType, + mediaActions: List = emptyList() ) : MediaPickerCore(mediaType, mediaActions) { override fun onCreate(savedInstanceState: Bundle?) { @@ -78,19 +93,21 @@ abstract class MediaPickerActivityBase( private fun setToolbarScrollable(scrollable: Boolean) { val params = kau_toolbar.layoutParams as AppBarLayout.LayoutParams if (scrollable) - params.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS or AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL + params.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS or + AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL else params.scrollFlags = 0 } override fun onLoadFinished(loader: Loader, data: Cursor?) { super.onLoadFinished(loader, data) - setToolbarScrollable((kau_recyclerview.layoutManager as LinearLayoutManager) - .findLastCompletelyVisibleItemPosition() < adapter.adapterItemCount - 1) + setToolbarScrollable( + (kau_recyclerview.layoutManager as LinearLayoutManager) + .findLastCompletelyVisibleItemPosition() < adapter.adapterItemCount - 1 + ) } override fun onStatusChange(loaded: Boolean) { setToolbarScrollable(loaded) } - -} \ No newline at end of file +} diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerActivityOverlayBase.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerActivityOverlayBase.kt index 2700780..a7ee63d 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerActivityOverlayBase.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerActivityOverlayBase.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.os.Build @@ -16,8 +31,8 @@ import kotlinx.android.synthetic.main.kau_activity_image_picker_overlay.* */ @RequiresApi(Build.VERSION_CODES.LOLLIPOP) abstract class MediaPickerActivityOverlayBase( - mediaType: MediaType, - mediaActions: List = emptyList() + mediaType: MediaType, + mediaActions: List = emptyList() ) : MediaPickerCore(mediaType, mediaActions) { override fun onCreate(savedInstanceState: Bundle?) { @@ -46,4 +61,4 @@ abstract class MediaPickerActivityOverlayBase( override fun onBackPressed() { finishAfterTransition() } -} \ No newline at end of file +} diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerBinder.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerBinder.kt index 50fe7ae..ac43f9f 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerBinder.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerBinder.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.app.Activity @@ -31,7 +46,8 @@ inline fun > Activity.kauLaunchMediaPicker(reques * call under [Activity.onActivityResult] * and make sure that the requestCode matches first */ -fun Activity.kauOnMediaPickerResult(resultCode: Int, data: Intent?) = MediaPickerCore.onMediaPickerResult(resultCode, data) +fun Activity.kauOnMediaPickerResult(resultCode: Int, data: Intent?) = + MediaPickerCore.onMediaPickerResult(resultCode, data) internal const val LOADER_ID = 42 internal const val MEDIA_PICKER_RESULT = "media_picker_result" @@ -39,5 +55,8 @@ internal const val MEDIA_PICKER_RESULT = "media_picker_result" internal const val ANIMATION_DURATION = 200L internal const val ANIMATION_SCALE = 0.95f -internal fun RequestBuilder.applyMediaOptions(context: Context) = apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.RESOURCE).centerCrop().override(MediaPickerCore.viewSize(context))) - +internal fun RequestBuilder.applyMediaOptions(context: Context) = apply( + RequestOptions().diskCacheStrategy(DiskCacheStrategy.RESOURCE).centerCrop().override( + MediaPickerCore.viewSize(context) + ) +) diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt index 1092158..abdc266 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.Manifest @@ -45,8 +60,8 @@ import java.util.concurrent.Future * Container for the main logic behind the both pickers */ abstract class MediaPickerCore>( - val mediaType: MediaType, - val mediaActions: List + val mediaType: MediaType, + val mediaActions: List ) : KauBaseActivity(), LoaderManager.LoaderCallbacks { companion object { @@ -79,10 +94,10 @@ abstract class MediaPickerCore>( fun getIconDrawable(context: Context, iicon: IIcon, color: Int): Drawable { val sizePx = MediaPickerCore.computeViewSize(context) return IconicsDrawable(context, iicon) - .sizePx(sizePx) - .backgroundColor(color) - .paddingPx(sizePx / 3) - .color(Color.WHITE) + .sizePx(sizePx) + .backgroundColor(color) + .paddingPx(sizePx / 3) + .color(Color.WHITE) } var accentColor: Int = 0xff666666.toInt() @@ -183,8 +198,8 @@ abstract class MediaPickerCore>( prefetcher = doAsync { models.subList(0, Math.min(models.size, 50)).map { it.data }.forEach { val target = glide.load(it) - .applyMediaOptions(this@MediaPickerCore) - .submit() + .applyMediaOptions(this@MediaPickerCore) + .submit() try { target.get() } catch (ignored: InterruptedException) { @@ -314,4 +329,4 @@ abstract class MediaPickerCore>( } } } -} \ No newline at end of file +} diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaType.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaType.kt index 0af4c2e..a42095f 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaType.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaType.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.net.Uri @@ -7,17 +22,23 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy /** * Created by Allan Wang on 2017-07-30. */ -enum class MediaType(val cacheStrategy: DiskCacheStrategy, - val mimeType: String, - val captureType: String, - val contentUri: Uri) { - IMAGE(DiskCacheStrategy.AUTOMATIC, - "image/*", - MediaStore.ACTION_IMAGE_CAPTURE, - MediaStore.Images.Media.EXTERNAL_CONTENT_URI), +enum class MediaType( + val cacheStrategy: DiskCacheStrategy, + val mimeType: String, + val captureType: String, + val contentUri: Uri +) { + IMAGE( + DiskCacheStrategy.AUTOMATIC, + "image/*", + MediaStore.ACTION_IMAGE_CAPTURE, + MediaStore.Images.Media.EXTERNAL_CONTENT_URI + ), - VIDEO(DiskCacheStrategy.AUTOMATIC, - "video/*", - MediaStore.ACTION_VIDEO_CAPTURE, - MediaStore.Video.Media.EXTERNAL_CONTENT_URI) -} \ No newline at end of file + VIDEO( + DiskCacheStrategy.AUTOMATIC, + "video/*", + MediaStore.ACTION_VIDEO_CAPTURE, + MediaStore.Video.Media.EXTERNAL_CONTENT_URI + ) +} diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaUtils.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaUtils.kt index 1976172..32e64e4 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaUtils.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.mediapicker import android.annotation.SuppressLint @@ -11,8 +26,9 @@ import ca.allanwang.kau.utils.buildIsLollipopAndUp import java.io.File import java.io.IOException import java.text.SimpleDateFormat -import java.util.* - +import java.util.ArrayList +import java.util.Date +import java.util.Locale /** * Created by Allan Wang on 2017-08-17. @@ -55,4 +71,4 @@ fun Context.scanMedia(f: File) { val contentUri = Uri.fromFile(f) mediaScanIntent.data = contentUri sendBroadcast(mediaScanIntent) -} \ No newline at end of file +} diff --git a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/ColorPickerTest.kt b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/ColorPickerTest.kt index 3b7f932..ef53817 100644 --- a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/ColorPickerTest.kt +++ b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/ColorPickerTest.kt @@ -1,5 +1,21 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.sample +import android.view.View import androidx.test.espresso.DataInteraction import androidx.test.espresso.Espresso.onData import androidx.test.espresso.Espresso.onView @@ -7,10 +23,9 @@ import androidx.test.espresso.ViewAssertion import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.MediumTest import androidx.test.rule.ActivityTestRule -import android.view.View -import androidx.test.ext.junit.runners.AndroidJUnit4 import ca.allanwang.kau.colorpicker.CircleView import org.hamcrest.Matchers.anything import org.junit.Rule @@ -19,7 +34,6 @@ import org.junit.runner.RunWith import kotlin.test.assertEquals import kotlin.test.fail - /** * Created by Allan Wang on 22/02/2018. * @@ -33,11 +47,15 @@ class ColorPickerTest { val activity: ActivityTestRule = ActivityTestRule(MainActivity::class.java) private fun DataInteraction.click(position: Int) = - atPosition(position).perform(click()) + atPosition(position).perform(click()) private fun View.colorSelected(selected: Boolean) { val circle = this as? CircleView ?: fail("View is not a CircleView") - assertEquals(selected, circle.colorSelected, "CircleView ${circle.tag} ${if (selected) "is not" else "is"} actually selected") + assertEquals( + selected, + circle.colorSelected, + "CircleView ${circle.tag} ${if (selected) "is not" else "is"} actually selected" + ) } private val colorSelected = ViewAssertion { view, _ -> view.colorSelected(true) } @@ -53,11 +71,9 @@ class ColorPickerTest { colors.click(0).check(colorSelected) // click first grid item colors.atPosition(1).check(colorNotSelected) colors.atPosition(2).check(colorNotSelected) - .perform(click()).check(colorSelected) + .perform(click()).check(colorSelected) colors.atPosition(0).check(colorNotSelected) - .perform(click()).check(colorSelected) + .perform(click()).check(colorSelected) // first item is now selected } - - } diff --git a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt index 31dfcb3..72199cf 100644 --- a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt +++ b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.sample import android.view.View @@ -21,7 +36,6 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith - /** * Created by Allan Wang on 21/12/2018. * @@ -37,16 +51,19 @@ class KPrefViewTest { fun verifyCheck(checked: Boolean): Matcher { return object : BoundedMatcher(View::class.java) { - override fun describeTo(description: Description) { description.appendText("Checkbox is ${if (checked) "checked" else "not checked"}") } - override fun matchesSafely(item: View): Boolean = item.findViewById(R.id.kau_pref_inner_content).isChecked == checked + override fun matchesSafely(item: View): Boolean = + item.findViewById(R.id.kau_pref_inner_content).isChecked == checked } } - inline fun ViewInteraction.checkInnerContent(desc: String, crossinline matcher: (T) -> Boolean): ViewInteraction { + inline fun ViewInteraction.checkInnerContent( + desc: String, + crossinline matcher: (T) -> Boolean + ): ViewInteraction { val viewMatcher = object : BaseMatcher() { override fun describeTo(description: Description) { description.appendText(desc) @@ -55,7 +72,7 @@ class KPrefViewTest { override fun matches(item: Any?): Boolean { val view = item as? View ?: return false val inner = view.findViewById(R.id.kau_pref_inner_content) as? T - ?: return false + ?: return false return matcher(inner) } } @@ -63,14 +80,14 @@ class KPrefViewTest { } fun ViewInteraction.verifyCheck(tag: String, checked: Boolean, enabled: Boolean = true) = - checkInnerContent("$tag should be ${if (checked) "checked" else "not checked"}") { - it.isChecked == checked - }.check { view, _ -> - ((view.alpha == 1f) == enabled) - } + checkInnerContent("$tag should be ${if (checked) "checked" else "not checked"}") { + it.isChecked == checked + }.check { view, _ -> + ((view.alpha == 1f) == enabled) + } fun onCheckboxView(vararg matchers: Matcher) = - onView(allOf(*matchers, withChild(withChild(instanceOf(CheckBox::class.java))))) + onView(allOf(*matchers, withChild(withChild(instanceOf(CheckBox::class.java))))) @Test fun basicCheckboxToggle() { @@ -89,7 +106,8 @@ class KPrefViewTest { @Test fun dependentCheckboxToggle() { val checkbox2 = onCheckboxView(withChild(withText(R.string.checkbox_2))) - val checkbox3 = onCheckboxView(withChild(withText(R.string.checkbox_3)), withChild(withText(R.string.desc_dependent))) + val checkbox3 = + onCheckboxView(withChild(withText(R.string.checkbox_3)), withChild(withText(R.string.desc_dependent))) // normalize so that both are checked if (!KPrefSample.check2) @@ -108,5 +126,4 @@ class KPrefViewTest { checkbox3.perform(click()) checkbox3.verifyCheck("checkbox3 after disabled click", false, false) } - } diff --git a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/utils/EspressoUtils.kt b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/utils/EspressoUtils.kt index 2acdc4d..09ad00a 100644 --- a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/utils/EspressoUtils.kt +++ b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/utils/EspressoUtils.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.sample.utils import org.hamcrest.BaseMatcher @@ -5,18 +20,18 @@ import org.hamcrest.Description import org.hamcrest.Matcher fun index(index: Int, matcher: Matcher): Matcher = - object : BaseMatcher() { + object : BaseMatcher() { - var current = 0 + var current = 0 - override fun describeTo(description: Description) { - description.appendText("Should return item at index $index") - } + override fun describeTo(description: Description) { + description.appendText("Should return item at index $index") + } - override fun matches(item: Any?): Boolean { - println("AA") - return matcher.matches(item) && current++ == index - } + override fun matches(item: Any?): Boolean { + println("AA") + return matcher.matches(item) && current++ == index } + } fun first(matcher: Matcher): Matcher = index(0, matcher) diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/AboutActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/AboutActivity.kt index 78f31ae..928070e 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/AboutActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/AboutActivity.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.sample import ca.allanwang.kau.about.AboutActivityBase @@ -24,4 +39,4 @@ class AboutActivity : AboutActivityBase(R.string::class.java, { descRes = R.string.about_kau }) } -} \ No newline at end of file +} diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/AdapterActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/AdapterActivity.kt index ada60ca..a11a672 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/AdapterActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/AdapterActivity.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.sample import android.os.Bundle @@ -17,7 +32,8 @@ class AdapterActivity : ElasticRecyclerActivity() { override fun onCreate(savedInstanceState: Bundle?, configs: Configs): Boolean { val adapter = ItemAdapter>() recycler.adapter = fastAdapter(adapter) - adapter.add(listOf( + adapter.add( + listOf( CardIItem { titleRes = R.string.kau_text_copied descRes = R.string.kau_lorem_ipsum @@ -43,8 +59,9 @@ class AdapterActivity : ElasticRecyclerActivity() { titleRes = R.string.kau_text_copied button = "Test" buttonClick = { toast("HI") } - })) + }) + ) setOutsideTapListener { finishAfterTransition() } return true } -} \ No newline at end of file +} diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt index c0f928f..349e3d1 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.sample import android.os.Bundle @@ -10,7 +25,11 @@ import ca.allanwang.kau.permissions.kauRequestPermissions import ca.allanwang.kau.swipe.SWIPE_EDGE_LEFT import ca.allanwang.kau.swipe.kauSwipeOnCreate import ca.allanwang.kau.swipe.kauSwipeOnDestroy -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.fullLinearRecycler +import ca.allanwang.kau.utils.startActivity +import ca.allanwang.kau.utils.toast +import ca.allanwang.kau.utils.withAlpha +import ca.allanwang.kau.utils.withSlideOut import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter /** @@ -27,9 +46,9 @@ class AnimActivity : KauBaseActivity() { setContentView(fullLinearRecycler(adapter).apply { setBackgroundColor(KPrefSample.bgColor.withAlpha(255)) }) adapter.add(listOf( - PERMISSION_ACCESS_COARSE_LOCATION, - PERMISSION_ACCESS_FINE_LOCATION, - PERMISSION_CAMERA + PERMISSION_ACCESS_COARSE_LOCATION, + PERMISSION_ACCESS_FINE_LOCATION, + PERMISSION_CAMERA ).map { PermissionCheckbox(it) }) adapter.withOnClickListener { _, _, item, _ -> KL.d { "Perm Click" } @@ -54,5 +73,4 @@ class AnimActivity : KauBaseActivity() { withSlideOut(this@AnimActivity) }) } - -} \ No newline at end of file +} diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt index 0c243e4..0f20880 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.sample import android.graphics.Color @@ -8,7 +23,7 @@ import ca.allanwang.kau.kpref.kpref * Created by Allan Wang on 2017-06-07. */ object KPrefSample : KPref() { - var version: Int by kpref("version", -1) + var version: Int by kpref("version", -1) var textColor: Int by kpref("TEXT_COLOR", Color.WHITE) var accentColor: Int by kpref("ACCENT_COLOR", 0xffff8900.toInt()) var bgColor: Int by kpref("BG_COLOR", 0xff303030.toInt()) @@ -19,5 +34,4 @@ object KPrefSample : KPref() { var seekbar: Int by kpref("seekbar", 20) var time12: Int by kpref("time_12", 315) var time24: Int by kpref("time_24", 2220) - -} \ No newline at end of file +} diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt index 6cd9776..25b5c16 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.sample import android.content.Context @@ -17,11 +32,15 @@ import ca.allanwang.kau.searchview.SearchView import ca.allanwang.kau.searchview.bindSearchView import ca.allanwang.kau.swipe.SWIPE_EDGE_LEFT import ca.allanwang.kau.ui.views.RippleCanvas -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.materialDialog +import ca.allanwang.kau.utils.navigationBarColor +import ca.allanwang.kau.utils.startActivity +import ca.allanwang.kau.utils.string +import ca.allanwang.kau.utils.toast +import ca.allanwang.kau.utils.withSceneTransitionAnimation import ca.allanwang.kau.xml.showChangelog import com.mikepenz.google_material_typeface_library.GoogleMaterial - class MainActivity : KPrefActivity() { var searchView: SearchView? = null @@ -30,51 +49,53 @@ class MainActivity : KPrefActivity() { //some of the most common english words for show val wordBank: List by lazy { - listOf("the", "name", "of", "very", "to", "through", - "and", "just", "a", "form", "in", "much", "is", "great", "it", "think", "you", "say", - "that", "help", "he", "low", "was", "line", "for", "before", "on", "turn", "are", "cause", - "with", "same", "as", "mean", "I", "differ", "his", "move", "they", "right", "be", "boy", - "at", "old", "one", "too", "have", "does", "this", "tell", "from", "sentence", "or", "set", - "had", "three", "by", "want", "hot", "air", "but", "well", "some", "also", "what", "play", - "there", "small", "we", "end", "can", "put", "out", "home", "other", "read", "were", "hand", - "all", "port", "your", "large", "when", "spell", "up", "add", "use", "even", "word", "land", - "how", "here", "said", "must", "an", "big", "each", "high", "she", "such", "which", "follow", - "do", "act", "their", "why", "time", "ask", "if", "men", "will", "change", "way", "went", - "about", "light", "many", "kind", "then", "off", "them", "need", "would", "house", "write", - "picture", "like", "try", "so", "us", "these", "again", "her", "animal", "long", "point", - "make", "mother", "thing", "world", "see", "near", "him", "build", "two", "self", "has", - "earth", "look", "father", "more", "head", "day", "stand", "could", "own", "go", "page", - "come", "should", "did", "country", "my", "found", "sound", "answer", "no", "school", "most", - "grow", "number", "study", "who", "still", "over", "learn", "know", "plant", "water", "cover", - "than", "food", "call", "sun", "first", "four", "people", "thought", "may", "let", "down", "keep", - "side", "eye", "been", "never", "now", "last", "find", "door", "any", "between", "new", "city", - "work", "tree", "part", "cross", "take", "since", "get", "hard", "place", "start", "made", - "might", "live", "story", "where", "saw", "after", "far", "back", "sea", "little", "draw", - "only", "left", "round", "late", "man", "run", "year", "don't", "came", "while", "show", - "press", "every", "close", "good", "night", "me", "real", "give", "life", "our", "few", "under", - "stopRankWordRankWord", "open", "ten", "seem", "simple", "together", "several", "next", - "vowel", "white", "toward", "children", "war", "begin", "lay", "got", "against", "walk", "pattern", - "example", "slow", "ease", "center", "paper", "love", "often", "person", "always", "money", - "music", "serve", "those", "appear", "both", "road", "mark", "map", "book", "science", "letter", - "rule", "until", "govern", "mile", "pull", "river", "cold", "car", "notice", "feet", "voice", - "care", "fall", "second", "power", "group", "town", "carry", "fine", "took", "certain", "rain", - "fly", "eat", "unit", "room", "lead", "friend", "cry", "began", "dark", "idea", "machine", - "fish", "note", "mountain", "wait", "north", "plan", "once", "figure", "base", "star", "hear", - "box", "horse", "noun", "cut", "field", "sure", "rest", "watch", "correct", "color", "able", - "face", "pound", "wood", "done", "main", "beauty", "enough", "drive", "plain", "stood", "girl", - "contain", "usual", "front", "young", "teach", "ready", "week", "above", "final", "ever", "gave", - "red", "green", "list", "oh", "though", "quick", "feel", "develop", "talk", "sleep", "bird", - "warm", "soon", "free", "body", "minute", "dog", "strong", "family", "special", "direct", "mind", - "pose", "behind", "leave", "clear", "song", "tail", "measure", "produce", "state", "fact", "product", - "street", "black", "inch", "short", "lot", "numeral", "nothing", "class", "course", "wind", "stay", - "question", "wheel", "happen", "full", "complete", "force", "ship", "blue", "area", "object", "half", - "decide", "rock", "surface", "order", "deep", "fire", "moon", "south", "island", "problem", "foot", - "piece", "yet", "told", "busy", "knew", "test", "pass", "record", "farm", "boat", "top", "common", - "whole", "gold", "king", "possible", "size", "plane", "heard", "age", "best", "dry", "hour", "wonder", - "better", "laugh", "true.", "thousand", "during", "ago", "hundred", "ran", "am", "check", "remember", - "game", "step", "shape", "early", "yes", "hold", "hot", "west", "miss", "ground", "brought", "interest", - "heat", "reach", "snow", "fast", "bed", "five", "bring", "sing", "sit", "listen", "perhaps", "six", - "fill", "table", "east", "travel", "weight", "less", "language", "morning", "among") + listOf( + "the", "name", "of", "very", "to", "through", + "and", "just", "a", "form", "in", "much", "is", "great", "it", "think", "you", "say", + "that", "help", "he", "low", "was", "line", "for", "before", "on", "turn", "are", "cause", + "with", "same", "as", "mean", "I", "differ", "his", "move", "they", "right", "be", "boy", + "at", "old", "one", "too", "have", "does", "this", "tell", "from", "sentence", "or", "set", + "had", "three", "by", "want", "hot", "air", "but", "well", "some", "also", "what", "play", + "there", "small", "we", "end", "can", "put", "out", "home", "other", "read", "were", "hand", + "all", "port", "your", "large", "when", "spell", "up", "add", "use", "even", "word", "land", + "how", "here", "said", "must", "an", "big", "each", "high", "she", "such", "which", "follow", + "do", "act", "their", "why", "time", "ask", "if", "men", "will", "change", "way", "went", + "about", "light", "many", "kind", "then", "off", "them", "need", "would", "house", "write", + "picture", "like", "try", "so", "us", "these", "again", "her", "animal", "long", "point", + "make", "mother", "thing", "world", "see", "near", "him", "build", "two", "self", "has", + "earth", "look", "father", "more", "head", "day", "stand", "could", "own", "go", "page", + "come", "should", "did", "country", "my", "found", "sound", "answer", "no", "school", "most", + "grow", "number", "study", "who", "still", "over", "learn", "know", "plant", "water", "cover", + "than", "food", "call", "sun", "first", "four", "people", "thought", "may", "let", "down", "keep", + "side", "eye", "been", "never", "now", "last", "find", "door", "any", "between", "new", "city", + "work", "tree", "part", "cross", "take", "since", "get", "hard", "place", "start", "made", + "might", "live", "story", "where", "saw", "after", "far", "back", "sea", "little", "draw", + "only", "left", "round", "late", "man", "run", "year", "don't", "came", "while", "show", + "press", "every", "close", "good", "night", "me", "real", "give", "life", "our", "few", "under", + "stopRankWordRankWord", "open", "ten", "seem", "simple", "together", "several", "next", + "vowel", "white", "toward", "children", "war", "begin", "lay", "got", "against", "walk", "pattern", + "example", "slow", "ease", "center", "paper", "love", "often", "person", "always", "money", + "music", "serve", "those", "appear", "both", "road", "mark", "map", "book", "science", "letter", + "rule", "until", "govern", "mile", "pull", "river", "cold", "car", "notice", "feet", "voice", + "care", "fall", "second", "power", "group", "town", "carry", "fine", "took", "certain", "rain", + "fly", "eat", "unit", "room", "lead", "friend", "cry", "began", "dark", "idea", "machine", + "fish", "note", "mountain", "wait", "north", "plan", "once", "figure", "base", "star", "hear", + "box", "horse", "noun", "cut", "field", "sure", "rest", "watch", "correct", "color", "able", + "face", "pound", "wood", "done", "main", "beauty", "enough", "drive", "plain", "stood", "girl", + "contain", "usual", "front", "young", "teach", "ready", "week", "above", "final", "ever", "gave", + "red", "green", "list", "oh", "though", "quick", "feel", "develop", "talk", "sleep", "bird", + "warm", "soon", "free", "body", "minute", "dog", "strong", "family", "special", "direct", "mind", + "pose", "behind", "leave", "clear", "song", "tail", "measure", "produce", "state", "fact", "product", + "street", "black", "inch", "short", "lot", "numeral", "nothing", "class", "course", "wind", "stay", + "question", "wheel", "happen", "full", "complete", "force", "ship", "blue", "area", "object", "half", + "decide", "rock", "surface", "order", "deep", "fire", "moon", "south", "island", "problem", "foot", + "piece", "yet", "told", "busy", "knew", "test", "pass", "record", "farm", "boat", "top", "common", + "whole", "gold", "king", "possible", "size", "plane", "heard", "age", "best", "dry", "hour", "wonder", + "better", "laugh", "true.", "thousand", "during", "ago", "hundred", "ran", "am", "check", "remember", + "game", "step", "shape", "early", "yes", "hold", "hot", "west", "miss", "ground", "brought", "interest", + "heat", "reach", "snow", "fast", "bed", "five", "bring", "sing", "sit", "listen", "perhaps", "six", + "fill", "table", "east", "travel", "weight", "less", "language", "morning", "among" + ) } const val REQUEST_MEDIA = 27 @@ -93,14 +114,17 @@ class MainActivity : KPrefActivity() { * This is how the setup looks like with all the proper tags */ checkbox(title = R.string.checkbox_1, getter = KPrefSample::check1, setter = { KPrefSample.check1 = it }, - builder = { - descRes = R.string.desc - }) + builder = { + descRes = R.string.desc + }) /** * Since we know the order, we may omit the tags */ - checkbox(R.string.checkbox_2, KPrefSample::check2, { KPrefSample.check2 = it; reloadByTitle(R.string.checkbox_3) }) + checkbox( + R.string.checkbox_2, + KPrefSample::check2, + { KPrefSample.check2 = it; reloadByTitle(R.string.checkbox_3) }) /** * Since the builder is the last argument and is a lambda, we may write the setup cleanly like so: @@ -143,7 +167,6 @@ class MainActivity : KPrefActivity() { input("Type here", item.pref, { _, input -> item.pref = input.toString() }) inputRange(0, 20) } - } } @@ -189,7 +212,10 @@ class MainActivity : KPrefActivity() { * Showcases a little trick. The id for reloading is [R.string.checkbox_2], * but the title displayed is still [R.string.checkbox_3] */ - checkbox(R.string.checkbox_2, KPrefSample::check2, { KPrefSample.check2 = it; reloadByTitle(R.string.checkbox_3) }) { + checkbox( + R.string.checkbox_2, + KPrefSample::check2, + { KPrefSample.check2 = it; reloadByTitle(R.string.checkbox_3) }) { titleFun = { R.string.checkbox_3 } descRes = R.string.kau_lorem_ipsum } @@ -208,7 +234,6 @@ class MainActivity : KPrefActivity() { descRes = R.string.time_desc_24 use24HourFormat = true } - } fun subPrefs(): KPrefAdapterBuilder.() -> Unit = { @@ -297,6 +322,6 @@ class MainActivity : KPrefActivity() { } inline fun Context.kauLaunchAbout() = - startActivity(bundleBuilder = { - withSceneTransitionAnimation(this@kauLaunchAbout) - }) \ No newline at end of file + startActivity(bundleBuilder = { + withSceneTransitionAnimation(this@kauLaunchAbout) + }) diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/MediaPicker.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/MediaPicker.kt index 820d22f..0e6b22f 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/MediaPicker.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/MediaPicker.kt @@ -1,9 +1,29 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.sample import android.content.Context import android.net.Uri import androidx.core.content.FileProvider -import ca.allanwang.kau.mediapicker.* +import ca.allanwang.kau.mediapicker.MediaActionCamera +import ca.allanwang.kau.mediapicker.MediaActionGallery +import ca.allanwang.kau.mediapicker.MediaPickerActivityBase +import ca.allanwang.kau.mediapicker.MediaPickerActivityOverlayBase +import ca.allanwang.kau.mediapicker.MediaType +import ca.allanwang.kau.mediapicker.createMediaFile import java.io.File /** @@ -13,8 +33,8 @@ private fun actions(multiple: Boolean) = listOf(object : MediaActionCamera() { override fun createFile(context: Context): File = createMediaFile("KAU", ".jpg") - override fun createUri(context: Context, file: File): Uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file) - + override fun createUri(context: Context, file: File): Uri = + FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file) }, MediaActionGallery(multiple)) class ImagePickerActivity : MediaPickerActivityBase(MediaType.IMAGE, actions(true)) @@ -23,4 +43,4 @@ class ImagePickerActivityOverlay : MediaPickerActivityOverlayBase(MediaType.IMAG class VideoPickerActivity : MediaPickerActivityBase(MediaType.VIDEO, actions(true)) -class VideoPickerActivityOverlay : MediaPickerActivityOverlayBase(MediaType.VIDEO, actions(false)) \ No newline at end of file +class VideoPickerActivityOverlay : MediaPickerActivityOverlayBase(MediaType.VIDEO, actions(false)) diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/PermissionCheckbox.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/PermissionCheckbox.kt index 09401cd..025179d 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/PermissionCheckbox.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/PermissionCheckbox.kt @@ -1,9 +1,24 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.sample -import androidx.recyclerview.widget.RecyclerView import android.view.View import android.widget.CheckBox import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.iitems.KauIItem import ca.allanwang.kau.utils.hasPermission @@ -11,7 +26,7 @@ import ca.allanwang.kau.utils.hasPermission * Created by Allan Wang on 2017-07-03. */ class PermissionCheckbox(val permission: String) : KauIItem( - R.layout.permission_checkbox, { ViewHolder(it) }) { + R.layout.permission_checkbox, { ViewHolder(it) }) { override fun bindView(holder: ViewHolder, payloads: MutableList) { super.bindView(holder, payloads) @@ -25,4 +40,4 @@ class PermissionCheckbox(val permission: String) : KauIItem button.setOnClickListener { startActivityWithEdge(edge) } } + .zip(listOf(SWIPE_EDGE_LEFT, SWIPE_EDGE_RIGHT, SWIPE_EDGE_TOP, SWIPE_EDGE_BOTTOM)) + .forEach { (button, edge) -> button.setOnClickListener { startActivityWithEdge(edge) } } val flag = intent.getIntExtra(SWIPE_EDGE, -1) swipe_toolbar.title = when (flag) { SWIPE_EDGE_LEFT -> "Left Edge Swipe" @@ -54,4 +79,4 @@ class SwipeActivity : KauBaseActivity() { override fun onBackPressed() { kauSwipeFinish() } -} \ No newline at end of file +} diff --git a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt index 86ed83d..7d754c8 100644 --- a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt +++ b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchItem.kt @@ -1,8 +1,22 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.searchview import android.graphics.Typeface import android.graphics.drawable.Drawable -import androidx.recyclerview.widget.RecyclerView import android.text.Spannable import android.text.SpannableStringBuilder import android.text.style.StyleSpan @@ -10,8 +24,13 @@ import android.view.View import android.widget.ImageView import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.iitems.KauIItem -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.adjustAlpha +import ca.allanwang.kau.utils.gone +import ca.allanwang.kau.utils.setIcon +import ca.allanwang.kau.utils.setRippleBackground +import ca.allanwang.kau.utils.visible import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.typeface.IIcon @@ -22,15 +41,16 @@ import com.mikepenz.iconics.typeface.IIcon * Contains a [key] which acts as a unique identifier (eg url) * and a [content] which is displayed in the item */ -class SearchItem(val key: String, - val content: String = key, - val description: String? = null, - val iicon: IIcon? = GoogleMaterial.Icon.gmd_search, - val image: Drawable? = null +class SearchItem( + val key: String, + val content: String = key, + val description: String? = null, + val iicon: IIcon? = GoogleMaterial.Icon.gmd_search, + val image: Drawable? = null ) : KauIItem( - R.layout.kau_search_iitem, - { ViewHolder(it) }, - R.id.kau_item_search + R.layout.kau_search_iitem, + { ViewHolder(it) }, + R.id.kau_item_search ) { companion object { @@ -48,7 +68,12 @@ class SearchItem(val key: String, val index = content.indexOf(subText, ignoreCase = true) if (index == -1) return styledContent = SpannableStringBuilder(content) - styledContent!!.setSpan(StyleSpan(Typeface.BOLD), index, index + subText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + styledContent!!.setSpan( + StyleSpan(Typeface.BOLD), + index, + index + subText.length, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) } override fun bindView(holder: ViewHolder, payloads: MutableList) { @@ -77,4 +102,4 @@ class SearchItem(val key: String, val desc: TextView = v.findViewById(R.id.kau_search_desc) val container: ConstraintLayout = v.findViewById(R.id.kau_search_item_frame) } -} \ No newline at end of file +} diff --git a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt index fecf6c5..11880cd 100644 --- a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt +++ b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt @@ -1,34 +1,72 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.searchview import android.app.Activity import android.content.Context import android.content.res.ColorStateList import android.graphics.Color -import androidx.annotation.ColorInt -import androidx.annotation.IdRes -import androidx.transition.ChangeBounds -import androidx.transition.TransitionManager -import androidx.transition.TransitionSet -import androidx.recyclerview.widget.RecyclerView import android.text.Editable import android.text.TextWatcher import android.util.AttributeSet -import android.view.* +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.view.ViewTreeObserver import android.view.inputmethod.EditorInfo import android.widget.FrameLayout import android.widget.ImageView +import androidx.annotation.ColorInt +import androidx.annotation.IdRes +import androidx.recyclerview.widget.RecyclerView +import androidx.transition.ChangeBounds +import androidx.transition.TransitionManager +import androidx.transition.TransitionSet import ca.allanwang.kau.kotlin.Debouncer2 import ca.allanwang.kau.kotlin.debounce import ca.allanwang.kau.logging.KL import ca.allanwang.kau.searchview.SearchView.Configs -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.INVALID_ID +import ca.allanwang.kau.utils.addEndListener +import ca.allanwang.kau.utils.adjustAlpha +import ca.allanwang.kau.utils.circularHide +import ca.allanwang.kau.utils.circularReveal +import ca.allanwang.kau.utils.fadeIn +import ca.allanwang.kau.utils.fadeOut +import ca.allanwang.kau.utils.gone +import ca.allanwang.kau.utils.goneIf +import ca.allanwang.kau.utils.hideKeyboard +import ca.allanwang.kau.utils.invisibleIf +import ca.allanwang.kau.utils.isVisible +import ca.allanwang.kau.utils.parentViewGroup +import ca.allanwang.kau.utils.setIcon +import ca.allanwang.kau.utils.setMarginTop +import ca.allanwang.kau.utils.showKeyboard +import ca.allanwang.kau.utils.string +import ca.allanwang.kau.utils.tint +import ca.allanwang.kau.utils.toDrawable +import ca.allanwang.kau.utils.visible +import ca.allanwang.kau.utils.withLinearAdapter import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.typeface.IIcon import kotlinx.android.synthetic.main.kau_search_view.view.* import org.jetbrains.anko.runOnUiThread - /** * Created by Allan Wang on 2017-06-23. * @@ -41,7 +79,9 @@ import org.jetbrains.anko.runOnUiThread * https://github.com/lapism/SearchView */ class SearchView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr) { /** @@ -162,13 +202,15 @@ class SearchView @JvmOverloads constructor( * Click event for suggestion items * This event is only triggered when [key] is not blank (like in [noResultsFound] */ - var onItemClick: (position: Int, key: String, content: String, searchView: SearchView) -> Unit = { _, _, _, _ -> } + var onItemClick: (position: Int, key: String, content: String, searchView: SearchView) -> Unit = + { _, _, _, _ -> } /** * Long click event for suggestion items * This event is only triggered when [key] is not blank (like in [noResultsFound] */ - var onItemLongClick: (position: Int, key: String, content: String, searchView: SearchView) -> Unit = { _, _, _, _ -> } + var onItemLongClick: (position: Int, key: String, content: String, searchView: SearchView) -> Unit = + { _, _, _, _ -> } /** * If a [SearchItem]'s title contains the submitted query, make that portion bold @@ -229,7 +271,8 @@ class SearchView @JvmOverloads constructor( private val configs = Configs() // views - private var textCallback: Debouncer2 = debounce(0) { query, _ -> KL.d { "Search query $query found; set your own textCallback" } } + private var textCallback: Debouncer2 = + debounce(0) { query, _ -> KL.d { "Search query $query found; set your own textCallback" } } private val adapter = FastItemAdapter() private var menuItem: MenuItem? = null val isOpen: Boolean @@ -274,7 +317,12 @@ class SearchView @JvmOverloads constructor( if (item.key.isNotBlank()) configs.onItemClick(position, item.key, item.content, this@SearchView); true } withOnLongClickListener { _, _, item, position -> - if (item.key.isNotBlank()) configs.onItemLongClick(position, item.key, item.content, this@SearchView); true + if (item.key.isNotBlank()) configs.onItemLongClick( + position, + item.key, + item.content, + this@SearchView + ); true } } kau_search_edit_text.addTextChangedListener(object : TextWatcher { @@ -293,8 +341,11 @@ class SearchView @JvmOverloads constructor( }) kau_search_edit_text.setOnEditorActionListener { _, actionId, _ -> if (actionId == EditorInfo.IME_ACTION_SEARCH) { - if (configs.searchCallback(kau_search_edit_text.text?.toString() - ?: "", this)) revealClose() + if (configs.searchCallback( + kau_search_edit_text.text?.toString() + ?: "", this + ) + ) revealClose() else kau_search_edit_text.hideKeyboard() return@setOnEditorActionListener true } @@ -309,12 +360,12 @@ class SearchView @JvmOverloads constructor( internal fun cardTransition(builder: TransitionSet.() -> Unit = {}) { TransitionManager.beginDelayedTransition(kau_search_cardview, - //we are only using change bounds, as the recyclerview items may be animated as well, - //which causes a measure IllegalStateException - TransitionSet().addTransition(ChangeBounds()).apply { - duration = configs.transitionDuration - builder() - }) + //we are only using change bounds, as the recyclerview items may be animated as well, + //which causes a measure IllegalStateException + TransitionSet().addTransition(ChangeBounds()).apply { + duration = configs.transitionDuration + builder() + }) } /** @@ -330,10 +381,15 @@ class SearchView @JvmOverloads constructor( * This is assuming that SearchView has already been added to a ViewGroup * If not, see the extension function [bindSearchView] */ - fun bind(menu: Menu, @IdRes id: Int, @ColorInt menuIconColor: Int = Color.WHITE, config: Configs.() -> Unit = {}): SearchView { + fun bind( + menu: Menu, + @IdRes id: Int, + @ColorInt menuIconColor: Int = Color.WHITE, + config: Configs.() -> Unit = {} + ): SearchView { config(config) val menuItem = menu.findItem(id) - ?: throw IllegalArgumentException("Menu item with given id doesn't exist") + ?: throw IllegalArgumentException("Menu item with given id doesn't exist") if (menuItem.icon == null) menuItem.icon = GoogleMaterial.Icon.gmd_search.toDrawable(context, 18, menuIconColor) kau_search_cardview.gone() menuItem.setOnMenuItemClickListener { revealOpen(); true } @@ -430,17 +486,16 @@ class SearchView @JvmOverloads constructor( cardTransition { addEndListener { kau_search_cardview.circularHide(menuX, menuHalfHeight, duration = configs.revealDuration, - onFinish = { - configs.closeListener?.invoke(this@SearchView) - if (configs.shouldClearOnClose) kau_search_edit_text.text?.clear() - }) + onFinish = { + configs.closeListener?.invoke(this@SearchView) + if (configs.shouldClearOnClose) kau_search_edit_text.text?.clear() + }) } } kau_search_recycler.gone() kau_search_edit_text.hideKeyboard() } } - } @DslMarker @@ -450,7 +505,12 @@ annotation class KauSearch * Helper function that binds to an activity's main view */ @KauSearch -fun Activity.bindSearchView(menu: Menu, @IdRes id: Int, @ColorInt menuIconColor: Int = Color.WHITE, config: SearchView.Configs.() -> Unit = {}): SearchView = findViewById(android.R.id.content).bindSearchView(menu, id, menuIconColor, config) +fun Activity.bindSearchView( + menu: Menu, + @IdRes id: Int, + @ColorInt menuIconColor: Int = Color.WHITE, + config: SearchView.Configs.() -> Unit = {} +): SearchView = findViewById(android.R.id.content).bindSearchView(menu, id, menuIconColor, config) /** * Bind searchView to a menu item; call this in [Activity.onCreateOptionsMenu] @@ -458,11 +518,16 @@ fun Activity.bindSearchView(menu: Menu, @IdRes id: Int, @ColorInt menuIconColor: * it may be worthwhile to hold a reference to the searchview and only bind it if it hasn't been bound before */ @KauSearch -fun ViewGroup.bindSearchView(menu: Menu, @IdRes id: Int, @ColorInt menuIconColor: Int = Color.WHITE, config: SearchView.Configs.() -> Unit = {}): SearchView { +fun ViewGroup.bindSearchView( + menu: Menu, + @IdRes id: Int, + @ColorInt menuIconColor: Int = Color.WHITE, + config: SearchView.Configs.() -> Unit = {} +): SearchView { val searchView = SearchView(context) - searchView.layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT) + searchView.layoutParams = + FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT) addView(searchView) searchView.bind(menu, id, menuIconColor, config) return searchView } - diff --git a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchViewHolder.kt b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchViewHolder.kt index 3f81dd0..a33b09b 100644 --- a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchViewHolder.kt +++ b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchViewHolder.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package ca.allanwang.kau.searchview import android.view.MenuItem @@ -21,5 +36,4 @@ interface SearchViewHolder { searchView?.unBind(replacementMenuItemClickListener) searchView = null } - -} \ No newline at end of file +} diff --git a/spotless.gradle b/spotless.gradle new file mode 100644 index 0000000..22dba3a --- /dev/null +++ b/spotless.gradle @@ -0,0 +1,11 @@ +apply plugin: "com.diffplug.gradle.spotless" + +spotless { + kotlin { + target "**/*.kt" + ktlint() + licenseHeaderFile '../spotless.license.kt' + trimTrailingWhitespace() + endWithNewline() + } +} \ No newline at end of file diff --git a/spotless.license.kt b/spotless.license.kt new file mode 100644 index 0000000..ce8139e --- /dev/null +++ b/spotless.license.kt @@ -0,0 +1,15 @@ +/* + * Copyright $YEAR Allan Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file -- cgit v1.2.3 From 8447b1ae8ce89b3f1bbe79dbae8847d901831c12 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Mon, 24 Dec 2018 20:05:06 -0500 Subject: Enhancement/coroutines (#180) * Add coroutine dependency * Add coroutines to kprefactivity * Change base job to supervisor * Update coroutines for faq * Update changelog * Use preloading in media picker core * Make test logging internal * Remove anko --- README.md | 3 +- .../ca/allanwang/kau/about/AboutPanelDelegate.kt | 24 +++-- .../main/groovy/ca/allanwang/kau/Versions.groovy | 6 +- core/README.md | 4 +- core/build.gradle | 4 +- .../ca/allanwang/kau/internal/KauBaseActivity.kt | 30 +++++- .../src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt | 105 --------------------- .../src/main/kotlin/ca/allanwang/kau/logging/KL.kt | 7 +- .../kotlin/ca/allanwang/kau/utils/ActivityUtils.kt | 13 ++- .../kotlin/ca/allanwang/kau/utils/BundleUtils.kt | 55 ++++++++++- .../kotlin/ca/allanwang/kau/utils/ContextUtils.kt | 27 +++++- .../kotlin/ca/allanwang/kau/utils/FragmentUtils.kt | 3 +- .../main/kotlin/ca/allanwang/kau/xml/Changelog.kt | 21 ++--- core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt | 71 +++++++------- .../test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt | 83 ---------------- docs/Changelog.md | 6 ++ docs/Migration.md | 13 +++ .../allanwang/kau/kpref/activity/KPrefActivity.kt | 31 +++--- .../allanwang/kau/mediapicker/MediaPickerCore.kt | 33 ++----- sample/src/main/res/xml/kau_changelog.xml | 10 ++ .../ca/allanwang/kau/searchview/SearchView.kt | 2 +- 21 files changed, 250 insertions(+), 301 deletions(-) delete mode 100644 core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt delete mode 100644 core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt (limited to 'buildSrc') diff --git a/README.md b/README.md index 4143ca8..6fe7590 100644 --- a/README.md +++ b/README.md @@ -103,10 +103,9 @@ This means that you'll need to explicitly include each submodule you'd like to u * [Extension Functions](core#extension-functions) * [Lazy Resettable](core#lazy-resettable) * Includes -[`AppCompat`](https://developer.android.com/topic/libraries/support-library/index.html), +[`AndroidX Components`](https://developer.android.com/topic/libraries/support-library/index.html), [`Material Dialogs (core)`](https://github.com/afollestad/material-dialogs), [`Iconics`](https://github.com/mikepenz/Android-Iconics), -[`Anko`](https://github.com/Kotlin/anko), [`Kotlin stdlib`](https://kotlinlang.org/api/latest/jvm/stdlib/) ## [Core UI](core-ui#readme) diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt b/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt index 35c1322..f77bcf2 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt @@ -35,8 +35,9 @@ import ca.allanwang.kau.utils.withMarginDecoration import ca.allanwang.kau.xml.kauParseFaq import com.mikepenz.aboutlibraries.Libs import com.mikepenz.fastadapter.IItem -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.uiThread +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.launch /** * Created by Allan Wang on 2017-08-02. @@ -174,13 +175,16 @@ open class AboutPanelLibs : AboutPanelRecycler() { } override fun loadItems(activity: AboutActivityBase, position: Int) { - doAsync { - with(activity) { - items = - getLibraries(if (rClass == null) Libs(activity) else Libs(this, Libs.toStringArray(rClass.fields))) - .map(::LibraryIItem) + with(activity) { + launch { + items = async { + getLibraries( + if (rClass == null) Libs(activity) + else Libs(activity, Libs.toStringArray(rClass.fields)) + ).map(::LibraryIItem) + }.await() if (pageStatus[position] == 1) - uiThread { addItems(activity, position) } + addItems(activity, position) } } } @@ -202,8 +206,8 @@ open class AboutPanelFaqs : AboutPanelRecycler() { override fun loadItems(activity: AboutActivityBase, position: Int) { with(activity) { - kauParseFaq(configs.faqXmlRes, configs.faqParseNewLine) { - items = it.map(::FaqIItem) + launch { + items = async { kauParseFaq(configs.faqXmlRes, configs.faqParseNewLine) }.await().map(::FaqIItem) if (pageStatus[position] == 1) addItems(activity, position) } diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy index a85fe97..e6f3cd7 100644 --- a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy +++ b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy @@ -26,12 +26,12 @@ class Versions { // https://kotlinlang.org/docs/reference/using-gradle.html static def kotlin = '1.3.11' + // https://github.com/Kotlin/kotlinx.coroutines/releases + static def coroutines = '1.0.1' + // https://github.com/mikepenz/AboutLibraries/releases static def aboutLibraries = '6.2.0' - // https://github.com/Kotlin/anko/releases - static def anko = '0.10.5' - // https://github.com/wasabeef/Blurry/releases static def blurry = '2.1.1' diff --git a/core/README.md b/core/README.md index 39899dd..b9a10f5 100644 --- a/core/README.md +++ b/core/README.md @@ -131,6 +131,9 @@ These variants are weakly held in the private `KotterknifeRegistry` object, and values through the `Kotterknife.reset` method. This is typically useful for Fragments, as they do not follow the same lifecycle as Activities and Views. +Note that this is useful for views that have ids in multiple layout files or in `id.xml` files. +Kotlin has another solution, [`kotlin-android-extensions`](https://kotlinlang.org/docs/tutorials/android-plugin.html), which is more convenient. + ## Ripple Canvas Ripple canvas provides a way to create simultaneous ripples against a background color. @@ -210,7 +213,6 @@ Include your email and subject, along with other optional configurations such as ## Extension Functions > "[Extensions](https://kotlinlang.org/docs/reference/extensions.html) provide the ability to extend a class with new functionality without having to inherit from the class" -
Note that since KAU depends on [ANKO](https://github.com/Kotlin/anko), all of the extensions in its core package is also in KAU. KAU's vast collection of extensions is one of its strongest features. There are too many to explain here, but you may check out the [utils package](https://github.com/AllanWang/KAU/tree/master/core/src/main/kotlin/ca/allanwang/kau/utils) diff --git a/core/build.gradle b/core/build.gradle index a57ee6e..3ac4f36 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -11,12 +11,12 @@ dependencies { api "androidx.constraintlayout:constraintlayout:${kau.constraintLayout}" api "com.google.android.material:material:${kau.googleMaterial}" + api "org.jetbrains.kotlinx:kotlinx-coroutines-android:${kau.coroutines}" + api "com.mikepenz:iconics-core:${kau.iconics}@aar" api "com.mikepenz:google-material-typeface:${kau.iconicsGoogle}.original@aar" api "com.afollestad.material-dialogs:core:${kau.materialDialog}" - - api "org.jetbrains.anko:anko-commons:${kau.anko}" } apply from: '../artifacts.gradle' diff --git a/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt b/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt index 85e711b..bf977f2 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt @@ -15,8 +15,14 @@ */ package ca.allanwang.kau.internal +import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.SupervisorJob +import kotlin.coroutines.CoroutineContext /** * Created by Allan Wang on 2017-08-01. @@ -26,11 +32,31 @@ import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult * Ensures that some singleton methods are called. * This is simply a convenience class; * you can always copy and paste this to your own class. + * + * This also implements [CoroutineScope] that adheres to the activity lifecycle. + * Note that by default, [SupervisorJob] is used, to avoid exceptions in one child from affecting that of another. + * The default job can be overridden within [defaultJob] */ -abstract class KauBaseActivity : AppCompatActivity() { +abstract class KauBaseActivity : AppCompatActivity(), CoroutineScope { + + open lateinit var job: Job + override val coroutineContext: CoroutineContext + get() = Dispatchers.Main + job + + open fun defaultJob(): Job = SupervisorJob() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + job = defaultJob() + } + + override fun onDestroy() { + job.cancel() + super.onDestroy() + } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) kauOnRequestPermissionsResult(permissions, grantResults) } -} +} \ No newline at end of file diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt deleted file mode 100644 index b767b30..0000000 --- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2018 Allan Wang - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ca.allanwang.kau.kotlin - -import org.jetbrains.anko.doAsync -import java.util.concurrent.atomic.AtomicInteger - -/** - * Created by Allan Wang on 2017-08-06. - * - * Collection of zip methods that aim to replicate - * Reactive Zips - * For unit returning functions - * - * Typically, the functions will execute asynchronously and call their given callbacks when finished. - * Once all callbacks are called, the final onFinish callback will be executed. - * - * There is also a helper zipper to wrap synchronous functions with Anko's doAsync to achieve the same results - * - * Note that not wrapping synchronous functions will render these methods useless, - * as you can simply define an inline callback after all functions are finished - */ - -/** - * Callback which will only execute the first time - */ -open class ZipCallbackBase { - var completed: Boolean = false - - inline operator fun invoke(callback: () -> Unit) { - if (completed) return - completed = true - callback() - } -} - -class ZipCallback(val onReceived: (T) -> Unit) : ZipCallbackBase() { - operator fun invoke(result: T) = invoke { onReceived(result) } -} - -class ZipEmptyCallback(val onReceived: () -> Unit) : ZipCallbackBase() { - operator fun invoke() = invoke(onReceived) -} - -/** - * Given a default result, a series of tasks, and a finished callback, - * this method will run all tasks and wait until all tasks emit a response - * The response will then be sent back to the callback - * - * ALl tasks must invoke the task callback for [onFinished] to execute - */ -inline fun Collection<(ZipCallback) -> Unit>.zip( - defaultResult: T, - crossinline onFinished: (results: Array) -> Unit -) { - val result = Array(size) { defaultResult } - val countDown = AtomicInteger(size) - forEachIndexed { index, asyncFun -> - asyncFun(ZipCallback { - result[index] = it - if (countDown.decrementAndGet() <= 0) - onFinished(result) - }) - } -} - -/** - * Simplified zip method with no finished callback arguments - */ -inline fun Collection<(ZipEmptyCallback) -> Unit>.zip(crossinline onFinished: () -> Unit) { - val countDown = AtomicInteger(size) - forEach { asyncFun -> - asyncFun(ZipEmptyCallback { - if (countDown.decrementAndGet() <= 0) - onFinished() - }) - } -} - -/** - * Converts a collection of synchronous tasks to asynchronous tasks with a common callback - */ -inline fun Collection<() -> Unit>.zipAsync(crossinline onFinished: () -> Unit) { - map { synchronousFun -> - { callback: ZipEmptyCallback -> - doAsync { - synchronousFun() - callback() - }; Unit - } - }.zip(onFinished) -} diff --git a/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt b/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt index f92edb3..52e5415 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt @@ -22,4 +22,9 @@ import ca.allanwang.kau.BuildConfig * * Internal KAU logger */ -object KL : KauLogger("KAU", { BuildConfig.DEBUG }) +object KL : KauLogger("KAU", { BuildConfig.DEBUG }) { + internal inline fun test(message: () -> Any?) { + if (BuildConfig.DEBUG) + d { "Test1234 ${message()}" } + } +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt index a655e5b..3dd4bb9 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt @@ -28,13 +28,13 @@ import android.os.Build import android.os.Bundle import android.view.Menu import android.view.View +import android.view.ViewGroup import androidx.annotation.ColorInt import androidx.annotation.RequiresApi import androidx.annotation.StringRes import ca.allanwang.kau.R import com.google.android.material.snackbar.Snackbar import com.mikepenz.iconics.typeface.IIcon -import org.jetbrains.anko.contentView /** * Created by Allan Wang on 2017-06-21. @@ -160,6 +160,17 @@ inline fun Activity.showKeyboard() { currentFocus?.showKeyboard() } +/** + * Gets the view set by [Activity.setContentView] if it exists. + * + * Taken courtesy of Anko + * + * Previously, Anko was a dependency in KAU, but has been removed on 12/24/2018 + * as most of the methods weren't used + */ +inline val Activity.contentView: View? + get() = (findViewById(android.R.id.content) as? ViewGroup)?.getChildAt(0) + inline fun Activity.snackbar( text: String, duration: Int = Snackbar.LENGTH_LONG, diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt index 314ca60..5b4b188 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt @@ -20,10 +20,12 @@ import android.app.Activity import android.app.ActivityOptions import android.content.Context import android.os.Bundle +import android.os.Parcelable import android.util.Pair import android.view.View import androidx.annotation.AnimRes import ca.allanwang.kau.R +import java.io.Serializable /** * Created by Allan Wang on 10/12/17. @@ -36,6 +38,56 @@ infix fun Bundle.with(bundle: Bundle?): Bundle { return this } +/** + * Saves all bundle args based on their respective types. + * + * Taken courtesy of Anko + * + * Previously, Anko was a dependency in KAU, but has been removed on 12/24/2018 + * as most of the methods weren't used + */ +fun bundleOf(vararg params: kotlin.Pair): Bundle { + val b = Bundle() + for (p in params) { + val (k, v) = p + when (v) { + null -> b.putSerializable(k, null) + is Boolean -> b.putBoolean(k, v) + is Byte -> b.putByte(k, v) + is Char -> b.putChar(k, v) + is Short -> b.putShort(k, v) + is Int -> b.putInt(k, v) + is Long -> b.putLong(k, v) + is Float -> b.putFloat(k, v) + is Double -> b.putDouble(k, v) + is String -> b.putString(k, v) + is CharSequence -> b.putCharSequence(k, v) + is Parcelable -> b.putParcelable(k, v) + is Serializable -> b.putSerializable(k, v) + is BooleanArray -> b.putBooleanArray(k, v) + is ByteArray -> b.putByteArray(k, v) + is CharArray -> b.putCharArray(k, v) + is DoubleArray -> b.putDoubleArray(k, v) + is FloatArray -> b.putFloatArray(k, v) + is IntArray -> b.putIntArray(k, v) + is LongArray -> b.putLongArray(k, v) + is Array<*> -> { + @Suppress("UNCHECKED_CAST") + when { + v.isArrayOf() -> b.putParcelableArray(k, v as Array) + v.isArrayOf() -> b.putCharSequenceArray(k, v as Array) + v.isArrayOf() -> b.putStringArray(k, v as Array) + else -> throw KauException("Unsupported bundle component (${v.javaClass})") + } + } + is ShortArray -> b.putShortArray(k, v) + is Bundle -> b.putBundle(k, v) + else -> throw KauException("Unsupported bundle component (${v.javaClass})") + } + } + return b +} + /** * Adds transition bundle if context is activity and build is lollipop+ */ @@ -62,7 +114,8 @@ fun Bundle.withSceneTransitionAnimation(parent: View, data: Map) = @SuppressLint("NewApi") fun Bundle.withSceneTransitionAnimation(context: Context, data: Map) { if (context !is Activity || !buildIsLollipopAndUp) return - val options = ActivityOptions.makeSceneTransitionAnimation(context, + val options = ActivityOptions.makeSceneTransitionAnimation( + context, *data.map { (view, tag) -> Pair(view, tag) }.toTypedArray() ) putAll(options.toBundle()) diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt index 134126d..60ef236 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018 Allan Wang + * Copyright 2017 Allan Wang * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,8 @@ import android.content.pm.PackageManager import android.graphics.drawable.Drawable import android.net.Uri import android.os.Bundle +import android.os.Handler +import android.os.Looper import android.util.TypedValue import android.view.View import android.view.animation.AnimationUtils @@ -45,10 +47,33 @@ import androidx.core.content.ContextCompat import ca.allanwang.kau.R import ca.allanwang.kau.logging.KL import com.afollestad.materialdialogs.MaterialDialog +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlin.coroutines.CoroutineContext /** * Created by Allan Wang on 2017-06-03. */ +private object ContextHelper: CoroutineScope { + + val handler = Handler(Looper.getMainLooper()) + + override val coroutineContext: CoroutineContext + get() = Dispatchers.Main +} + +/** + * Most context items implement [CoroutineScope] by default. + * We will add a fallback just in case. + * It is expected that the scope returned always has the Android main dispatcher as part of the context. + */ +internal inline val Context.ctxCoroutine: CoroutineScope + get() = this as? CoroutineScope ?: ContextHelper + +fun Context.runOnUiThread(f: Context.() -> Unit) { + if (Looper.getMainLooper() === Looper.myLooper()) f() else ContextHelper.handler.post { f() } +} /** * Helper class to launch an activity from a context diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt index 1c97900..75dc1c1 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt @@ -16,12 +16,11 @@ package ca.allanwang.kau.utils import androidx.fragment.app.Fragment -import org.jetbrains.anko.bundleOf /** * Created by Allan Wang on 2017-07-02. */ -fun T.withArguments(vararg params: Pair): T { +fun T.withArguments(vararg params: Pair): T { arguments = bundleOf(*params) return this } diff --git a/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt b/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt index 6a75aa9..51e63f9 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt @@ -26,11 +26,12 @@ import androidx.annotation.LayoutRes import androidx.annotation.XmlRes import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.R +import ca.allanwang.kau.utils.ctxCoroutine import ca.allanwang.kau.utils.materialDialog import ca.allanwang.kau.utils.use import com.afollestad.materialdialogs.MaterialDialog -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.uiThread +import kotlinx.coroutines.async +import kotlinx.coroutines.launch import org.xmlpull.v1.XmlPullParser /** @@ -39,15 +40,13 @@ import org.xmlpull.v1.XmlPullParser * Easy changelog loader */ fun Context.showChangelog(@XmlRes xmlRes: Int, @ColorInt textColor: Int? = null, customize: MaterialDialog.Builder.() -> Unit = {}) { - doAsync { - val items = parse(this@showChangelog, xmlRes) - uiThread { - materialDialog { - title(R.string.kau_changelog) - positiveText(R.string.kau_great) - adapter(ChangelogAdapter(items, textColor), null) - customize() - } + ctxCoroutine.launch { + val items = async { parse(this@showChangelog, xmlRes) }.await() + materialDialog { + title(R.string.kau_changelog) + positiveText(R.string.kau_great) + adapter(ChangelogAdapter(items, textColor), null) + customize() } } } diff --git a/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt b/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt index cb57216..73d7d6c 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt @@ -21,8 +21,6 @@ import android.text.Html import android.text.Spanned import androidx.annotation.XmlRes import ca.allanwang.kau.utils.use -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.uiThread import org.xmlpull.v1.XmlPullParser /** @@ -30,8 +28,8 @@ import org.xmlpull.v1.XmlPullParser */ /** - * Parse an xml asynchronously with two tags, Text and Text, - * and invoke the [callback] on the ui thread + * Parse an xml asynchronously with two tags, Text and Text. + * Note that this should executed in a background thread. */ @Suppress("DEPRECATION") fun Context.kauParseFaq( @@ -39,47 +37,44 @@ fun Context.kauParseFaq( /** * If \n is used, it will automatically be converted to
*/ - parseNewLine: Boolean = true, - callback: (items: List) -> Unit -) { - doAsync { - val items = mutableListOf() - resources.getXml(xmlRes).use { parser: XmlResourceParser -> - var eventType = parser.eventType - var question: Spanned? = null - var flag = -1 //-1, 0, 1 -> invalid, question, answer - while (eventType != XmlPullParser.END_DOCUMENT) { - if (eventType == XmlPullParser.START_TAG) { - flag = when (parser.name) { - "question" -> 0 - "answer" -> 1 - else -> -1 + parseNewLine: Boolean = true +): List { + val items = mutableListOf() + resources.getXml(xmlRes).use { parser: XmlResourceParser -> + var eventType = parser.eventType + var question: Spanned? = null + var flag = -1 //-1, 0, 1 -> invalid, question, answer + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + flag = when (parser.name) { + "question" -> 0 + "answer" -> 1 + else -> -1 + } + } else if (eventType == XmlPullParser.TEXT) { + when (flag) { + 0 -> { + question = Html.fromHtml(parser.text.replace("\n", if (parseNewLine) "
" else "")) + flag = -1 } - } else if (eventType == XmlPullParser.TEXT) { - when (flag) { - 0 -> { - question = Html.fromHtml(parser.text.replace("\n", if (parseNewLine) "
" else "")) - flag = -1 - } - 1 -> { - items.add( - FaqItem( - items.size + 1, - question - ?: throw IllegalArgumentException("KAU FAQ answer found without a question"), - Html.fromHtml(parser.text.replace("\n", if (parseNewLine) "
" else "")) - ) + 1 -> { + items.add( + FaqItem( + items.size + 1, + question + ?: throw IllegalArgumentException("KAU FAQ answer found without a question"), + Html.fromHtml(parser.text.replace("\n", if (parseNewLine) "
" else "")) ) - question = null - flag = -1 - } + ) + question = null + flag = -1 } } - eventType = parser.next() } + eventType = parser.next() } - uiThread { callback(items) } } + return items } data class FaqItem(val number: Int, val question: Spanned, val answer: Spanned) diff --git a/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt b/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt deleted file mode 100644 index 1fbc38f..0000000 --- a/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2018 Allan Wang - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ca.allanwang.kau.kotlin - -import org.jetbrains.anko.doAsync -import org.junit.Test -import java.util.Random -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit -import kotlin.test.assertTrue - -/** - * Created by Allan Wang on 2017-08-06. - */ -class ZipTest { - - val debug = false - - fun p(text: String) { - if (debug) println(text) - } - - @Test - fun basic() { - val start = System.currentTimeMillis() - val latch = CountDownLatch(1) - val rnd = Random() - (0..10).map { - { callback: ZipCallback -> - doAsync { - val sleepTime = rnd.nextInt(100) + 200L - p("Task $it will sleep for ${sleepTime}ms") - Thread.sleep(sleepTime) - val finish = System.currentTimeMillis() - p("Task $it finished in ${finish - start}ms at $finish") - callback(it) - }; Unit - } - }.zip(-1) { results -> - val finish = System.currentTimeMillis() - println("Results ${results.contentToString()} received in ${finish - start}ms at $finish") - assertTrue((0..10).toList().toTypedArray().contentEquals(results), "Basic zip results do not match") - assertTrue(finish - start < 1000L, "Basic zip does not seem to be running asynchronously") - latch.countDown() - } - latch.await(1100, TimeUnit.MILLISECONDS) - } - - @Test - fun basicAsync() { - val start = System.currentTimeMillis() - val latch = CountDownLatch(1) - val rnd = Random() - (0..10).map { - { - val sleepTime = rnd.nextInt(100) + 200L - p("Task $it will sleep for ${sleepTime}ms") - Thread.sleep(sleepTime) - val finish = System.currentTimeMillis() - p("Task $it finished in ${finish - start}ms at $finish") - } - }.zipAsync { - val finish = System.currentTimeMillis() - println("Results received in ${finish - start}ms at $finish") - assertTrue(finish - start < 1000L, "BasicAsync does not seem to be wrapping the tasks asynchronously") - latch.countDown() - } - latch.await(1100, TimeUnit.MILLISECONDS) - } -} diff --git a/docs/Changelog.md b/docs/Changelog.md index 1e1b0d8..283759d 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -1,5 +1,11 @@ # Changelog +## v4.0.0-alpha02 +* :core: Remove anko dependency. Methods that used it now use coroutines; see the migration doc for minor changes +* :core: Add default CoroutineScope implementation to KauBaseActivity +* :core: Remove zip class. Coroutines and join can be used as an alternative +* :mediapicker: Use video preloading instead of full async loading + ## v4.0.0-alpha01 * Migrate to androidx. See migration for external dependency changes. * :core: Remove deprecation warning for Kotterknife diff --git a/docs/Migration.md b/docs/Migration.md index 8c5e016..cdaca4c 100644 --- a/docs/Migration.md +++ b/docs/Migration.md @@ -2,6 +2,19 @@ Below are some highlights on major refactoring/breaking changes +# v4.0.1-alpha02 + +* `kauParseFaq` is now synchronous. + +## Anko has been removed + +A lot of the methods are already implemented in KAU, and it was primarily imported for its `doAsync` methods. Now, they have been replaced with coroutines. +Some methods have been copied over: + +* import org.jetbrains.anko.runOnUiThread > import ca.allanwang.kau.utils.runOnUiThread +* import org.jetbrains.anko.contentView > import ca.allanwang.kau.utils.contentView +* import org.jetbrains.anko.bundleOf > import ca.allanwang.kau.utils.bundleOf + # v4.0.0-alpha01 This is the first introduction of androidx. The goal is to just do a migration with minimal changes. diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt index 02b6e98..450bc6e 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt @@ -33,8 +33,8 @@ import ca.allanwang.kau.utils.statusBarColor import ca.allanwang.kau.utils.withLinearAdapter import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter import kotlinx.android.synthetic.main.kau_pref_activity.* -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.uiThread +import kotlinx.coroutines.async +import kotlinx.coroutines.launch import java.util.Stack abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract { @@ -104,19 +104,24 @@ abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract { builder: KPrefAdapterBuilder.() -> Unit, first: Boolean ) { - doAsync { - val items = KPrefAdapterBuilder(globalOptions) - builder(items) - kprefStack.push(toolbarTitleRes to items.list) + launch { + val items = async { + val items = KPrefAdapterBuilder(globalOptions) + builder(items) + kprefStack.push(toolbarTitleRes to items.list) + items.list + }.await() kau_recycler.itemAnimator = if (animate && !first) recyclerAnimatorNext else null - uiThread { - adapter.clear() - adapter.add(items.list.filter { it.core.visible() }) - toolbar.setTitle(toolbarTitleRes) - } + show(toolbarTitleRes, items) } } + private fun show(@StringRes toolbarTitleRes: Int, items: List) { + toolbar.setTitle(toolbarTitleRes) + adapter.clear() + adapter.add(items.filter { it.core.visible() }) + } + /** * Pops the stack and loads the next kpref list * Indices are not checked so ensure that this is possible first @@ -125,9 +130,7 @@ abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract { kprefStack.pop() val (title, list) = kprefStack.peek() kau_recycler.itemAnimator = if (animate) recyclerAnimatorPrev else null - adapter.clear() - adapter.add(list.filter { it.core.visible() }) - toolbar.setTitle(title) + show(title, list) } /** diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt index abdc266..7004967 100644 --- a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt +++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt @@ -49,10 +49,8 @@ import com.mikepenz.fastadapter.adapters.ItemAdapter import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.IIcon -import org.jetbrains.anko.doAsync +import kotlinx.coroutines.CancellationException import java.io.File -import java.util.concurrent.ExecutionException -import java.util.concurrent.Future /** * Created by Allan Wang on 2017-07-23. @@ -121,7 +119,6 @@ abstract class MediaPickerCore>( lateinit var glide: RequestManager private var hasPreloaded = false - private var prefetcher: Future<*>? = null val adapter = ItemAdapter() @@ -137,7 +134,7 @@ abstract class MediaPickerCore>( fun initializeRecycler(recycler: RecyclerView) { val adapterHeader = ItemAdapter() - val fulladapter = fastAdapter(adapterHeader, adapter) + val fulladapter = fastAdapter>(adapterHeader, adapter) adapterHeader.add(mediaActions.map { MediaActionItem(it, mediaType) }) recycler.apply { val manager = object : GridLayoutManager(context, computeColumnCount(context)) { @@ -146,7 +143,6 @@ abstract class MediaPickerCore>( } } setItemViewCacheSize(CACHE_SIZE) - isDrawingCacheEnabled = true layoutManager = manager adapter = fulladapter setHasFixedSize(true) @@ -195,18 +191,14 @@ abstract class MediaPickerCore>( addItems(models.map { converter(it) }) if (!hasPreloaded && mediaType == MediaType.VIDEO) { hasPreloaded = true - prefetcher = doAsync { - models.subList(0, Math.min(models.size, 50)).map { it.data }.forEach { - val target = glide.load(it) - .applyMediaOptions(this@MediaPickerCore) - .submit() - try { - target.get() - } catch (ignored: InterruptedException) { - } catch (ignored: ExecutionException) { - } finally { - glide.clear(target) - } + val preloads = models.subList(0, Math.min(models.size, 50)).map { + glide.load(it.data) + .applyMediaOptions(this@MediaPickerCore) + .preload() + } + job.invokeOnCompletion { + if (it is CancellationException) { + preloads.forEach(glide::clear) } } } @@ -242,11 +234,6 @@ abstract class MediaPickerCore>( open fun onStatusChange(loaded: Boolean) {} - override fun onDestroy() { - prefetcher?.cancel(true) - super.onDestroy() - } - /** * Method used to retrieve uri data for API 19+ * See diff --git a/sample/src/main/res/xml/kau_changelog.xml b/sample/src/main/res/xml/kau_changelog.xml index 6c0fea1..3c49078 100644 --- a/sample/src/main/res/xml/kau_changelog.xml +++ b/sample/src/main/res/xml/kau_changelog.xml @@ -6,6 +6,16 @@ --> + + + + + + + + + + diff --git a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt index 11880cd..169e914 100644 --- a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt +++ b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt @@ -53,6 +53,7 @@ import ca.allanwang.kau.utils.hideKeyboard import ca.allanwang.kau.utils.invisibleIf import ca.allanwang.kau.utils.isVisible import ca.allanwang.kau.utils.parentViewGroup +import ca.allanwang.kau.utils.runOnUiThread import ca.allanwang.kau.utils.setIcon import ca.allanwang.kau.utils.setMarginTop import ca.allanwang.kau.utils.showKeyboard @@ -65,7 +66,6 @@ import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.typeface.IIcon import kotlinx.android.synthetic.main.kau_search_view.view.* -import org.jetbrains.anko.runOnUiThread /** * Created by Allan Wang on 2017-06-23. -- cgit v1.2.3 From d61ff7cb4f43d71d2170cdd25ceab2e3edcb81fc Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Fri, 4 Jan 2019 23:03:50 -0500 Subject: Coroutine tests (#185) * Add some coroutine tests for implicit cancellation * Create util test and new helper methods * Remove coroutinescope extension from withcontext * Update dependencies --- .../main/groovy/ca/allanwang/kau/Versions.groovy | 8 +-- .../kotlin/ca/allanwang/kau/utils/ContextUtils.kt | 27 ---------- .../ca/allanwang/kau/utils/CoroutineUtils.kt | 60 ++++++++++++++++++++++ .../ca/allanwang/kau/kotlin/CoroutineTest.kt | 58 +++++++++++++++++++++ docs/Changelog.md | 1 + sample/src/main/res/xml/kau_changelog.xml | 2 +- 6 files changed, 125 insertions(+), 31 deletions(-) create mode 100644 core/src/main/kotlin/ca/allanwang/kau/utils/CoroutineUtils.kt create mode 100644 core/src/test/kotlin/ca/allanwang/kau/kotlin/CoroutineTest.kt (limited to 'buildSrc') diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy index e6f3cd7..4afec82 100644 --- a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy +++ b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy @@ -27,7 +27,7 @@ class Versions { static def kotlin = '1.3.11' // https://github.com/Kotlin/kotlinx.coroutines/releases - static def coroutines = '1.0.1' + static def coroutines = '1.1.0' // https://github.com/mikepenz/AboutLibraries/releases static def aboutLibraries = '6.2.0' @@ -72,6 +72,8 @@ class Versions { static def playPublishPlugin = '1.2.2' // https://github.com/KeepSafe/dexcount-gradle-plugin/releases - static def dexCountPlugin = '0.8.3' - static def gitVersionPlugin = '0.4.4' + static def dexCountPlugin = '0.8.5' + + // https://github.com/gladed/gradle-android-git-version/releases + static def gitVersionPlugin = '0.4.7' } \ No newline at end of file diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt index 09ad4ea..fc8049d 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt @@ -26,7 +26,6 @@ import android.content.pm.PackageManager import android.graphics.drawable.Drawable import android.net.Uri import android.os.Bundle -import android.os.Handler import android.os.Looper import android.util.TypedValue import android.view.View @@ -47,36 +46,10 @@ import androidx.core.content.ContextCompat import ca.allanwang.kau.R import ca.allanwang.kau.logging.KL import com.afollestad.materialdialogs.MaterialDialog -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.android.asCoroutineDispatcher -import kotlin.coroutines.CoroutineContext /** * Created by Allan Wang on 2017-06-03. */ -object ContextHelper : CoroutineScope { - - val looper = Looper.getMainLooper() - - val handler = Handler(looper) - - /** - * Creating dispatcher from main handler to avoid IO - * See https://github.com/Kotlin/kotlinx.coroutines/issues/878 - */ - val dispatcher = handler.asCoroutineDispatcher("kau-main") - - override val coroutineContext: CoroutineContext get() = dispatcher -} - -/** - * Most context items implement [CoroutineScope] by default. - * We will add a fallback just in case. - * It is expected that the scope returned always has the Android main dispatcher as part of the context. - */ -internal inline val Context.ctxCoroutine: CoroutineScope - get() = this as? CoroutineScope ?: ContextHelper - fun Context.runOnUiThread(f: Context.() -> Unit) { if (ContextHelper.looper === Looper.myLooper()) f() else ContextHelper.handler.post { f() } } diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/CoroutineUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/CoroutineUtils.kt new file mode 100644 index 0000000..032c407 --- /dev/null +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/CoroutineUtils.kt @@ -0,0 +1,60 @@ +package ca.allanwang.kau.utils + +import android.content.Context +import android.os.Handler +import android.os.Looper +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.android.asCoroutineDispatcher +import kotlinx.coroutines.async +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext + +object ContextHelper : CoroutineScope { + + val looper = Looper.getMainLooper() + + val handler = Handler(looper) + + /** + * Creating dispatcher from main handler to avoid IO + * See https://github.com/Kotlin/kotlinx.coroutines/issues/878 + */ + val dispatcher = handler.asCoroutineDispatcher("kau-main") + + override val coroutineContext: CoroutineContext get() = dispatcher +} + +/** + * Most context items implement [CoroutineScope] by default. + * We will add a fallback just in case. + * It is expected that the scope returned always has the Android main dispatcher as part of the context. + */ +internal inline val Context.ctxCoroutine: CoroutineScope + get() = this as? CoroutineScope ?: ContextHelper + +/** + * Calls [launch] with an explicit dispatcher for Android's main thread + */ +fun CoroutineScope.launchMain( + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + block: suspend CoroutineScope.() -> Unit +) = launch(ContextHelper.dispatcher + context, start, block) + +/** + * Calls [async] with an explicit dispatcher for Android's main thread + */ +fun CoroutineScope.asyncMain( + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + block: suspend CoroutineScope.() -> Unit +) = async(ContextHelper.dispatcher + context, start, block) + +/** + * Calls [withContext] with an explicit dispatcher for Android's main thread + */ +suspend fun withMainContext(block: suspend CoroutineScope.() -> T) = + withContext(ContextHelper.dispatcher, block) diff --git a/core/src/test/kotlin/ca/allanwang/kau/kotlin/CoroutineTest.kt b/core/src/test/kotlin/ca/allanwang/kau/kotlin/CoroutineTest.kt new file mode 100644 index 0000000..91d0174 --- /dev/null +++ b/core/src/test/kotlin/ca/allanwang/kau/kotlin/CoroutineTest.kt @@ -0,0 +1,58 @@ +package ca.allanwang.kau.kotlin + +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.fail + +/** + * Tests geared towards coroutines + */ +class CoroutineTest { + + /** + * If a job is cancelled, then a switch to a new context will not run + */ + @Test + fun implicitCancellationBefore() { + val job = Job() + var id = 0 + try { + runBlocking(job) { + id++ + job.cancel() + withContext(Dispatchers.IO) { + fail("Context switch should not be reached") + } + } + } catch (ignore: CancellationException) { + } finally { + assertEquals(1, id, "Launcher never executed") + } + } + + /** + * If a job is cancelled, then a switch from a new context will not run + */ + @Test + fun implicitCancellationAfter() { + val job = Job() + var id = 0 + try { + runBlocking(job) { + withContext(Dispatchers.IO) { + id++ + job.cancel() + } + fail("Post context switch should not be reached") + } + } catch (ignore: CancellationException) { + } finally { + assertEquals(1, id, "Context switch never executed") + } + } +} \ No newline at end of file diff --git a/docs/Changelog.md b/docs/Changelog.md index e6d51d2..7291753 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -5,6 +5,7 @@ * :core: Add default CoroutineScope implementation to KauBaseActivity * :core: Remove zip class. Coroutines and join can be used as an alternative * :core: Delete flyweight implementation. Kotlin already has getOrPut +* :core: Introduce ContextHelper, where you can get the default looper, handler, and dispatcher for Android * :mediapicker: Use video preloading instead of full async loading ## v4.0.0-alpha01 diff --git a/sample/src/main/res/xml/kau_changelog.xml b/sample/src/main/res/xml/kau_changelog.xml index 0283d7f..570a0b9 100644 --- a/sample/src/main/res/xml/kau_changelog.xml +++ b/sample/src/main/res/xml/kau_changelog.xml @@ -11,10 +11,10 @@ + - -- cgit v1.2.3 From 35d88ea61f9fa46afa141b5ea36ffe830133ebe3 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Mon, 11 Mar 2019 00:28:56 -0400 Subject: Update versions --- .gitignore | 2 -- .../src/main/groovy/ca/allanwang/kau/Versions.groovy | 18 ++++++++++-------- gradle/wrapper/gradle-wrapper.properties | 3 ++- sample/build.gradle | 5 +---- .../kotlin/ca/allanwang/kau/sample/MainActivity.kt | 14 ++++---------- 5 files changed, 17 insertions(+), 25 deletions(-) (limited to 'buildSrc') diff --git a/.gitignore b/.gitignore index f19a651..ef20a58 100644 --- a/.gitignore +++ b/.gitignore @@ -9,8 +9,6 @@ # Intellij # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff *.iml .idea/**/workspace.xml .idea/**/tasks.xml diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy index 4afec82..0774be1 100644 --- a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy +++ b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy @@ -24,13 +24,13 @@ class Versions { static def constraintLayout = '1.1.3' // https://kotlinlang.org/docs/reference/using-gradle.html - static def kotlin = '1.3.11' + static def kotlin = '1.3.21' // https://github.com/Kotlin/kotlinx.coroutines/releases - static def coroutines = '1.1.0' + static def coroutines = '1.1.1' // https://github.com/mikepenz/AboutLibraries/releases - static def aboutLibraries = '6.2.0' + static def aboutLibraries = '6.2.3' // https://github.com/wasabeef/Blurry/releases static def blurry = '2.1.1' @@ -40,7 +40,7 @@ class Versions { static def fastAdapterCommons = fastAdapter // https://github.com/bumptech/glide/releases - static def glide = '4.8.0' + static def glide = '4.9.0' // https://github.com/mikepenz/Android-Iconics#1-provide-the-gradle-dependency static def iconics = '3.1.0' @@ -64,15 +64,17 @@ class Versions { static def testRules = '1.1.1' // https://github.com/diffplug/spotless/blob/master/plugin-gradle/CHANGES.md - static def spotless = '3.17.0' + static def spotless = '3.18.0' // https://mvnrepository.com/artifact/com.android.tools.build/gradle?repo=google - static def gradlePlugin = '3.2.1' + static def gradlePlugin = '3.3.1' + // https://github.com/dcendents/android-maven-gradle-plugin/releases static def mavenPlugin = '2.1' - static def playPublishPlugin = '1.2.2' + // https://github.com/Triple-T/gradle-play-publisher/releases + static def playPublishPlugin = '2.1.0' // https://github.com/KeepSafe/dexcount-gradle-plugin/releases - static def dexCountPlugin = '0.8.5' + static def dexCountPlugin = '0.8.6' // https://github.com/gladed/gradle-android-git-version/releases static def gitVersionPlugin = '0.4.7' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9a4163a..bc32def 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Mon Mar 11 00:19:22 EDT 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip diff --git a/sample/build.gradle b/sample/build.gradle index e9e5a2e..7316f1e 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -4,11 +4,8 @@ apply plugin: 'kotlin-android-extensions' apply plugin: 'com.github.triplet.play' play { - jsonFile = file('../files/gplay-keys.json') + serviceAccountCredentials = file('../files/gplay-keys.json') track = 'beta' - errorOnSizeLimit = true - uploadImages = false - untrackOld = true } android { diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt index 25b5c16..fccba05 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt @@ -15,12 +15,11 @@ */ package ca.allanwang.kau.sample -import android.content.Context import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem -import ca.allanwang.kau.about.AboutActivityBase +import ca.allanwang.kau.about.kauLaunchAbout import ca.allanwang.kau.email.sendEmail import ca.allanwang.kau.kpref.activity.CoreAttributeContract import ca.allanwang.kau.kpref.activity.KPrefActivity @@ -242,10 +241,10 @@ class MainActivity : KPrefActivity() { onClick = { itemView.context.materialDialog { title("Type Text") - input("Type here", item.pref, { _, input -> + input("Type here", item.pref) { _, input -> item.pref = input.toString() reloadSelf() - }) + } inputRange(0, 20) } } @@ -319,9 +318,4 @@ class MainActivity : KPrefActivity() { REQUEST_MEDIA -> toast("${kauOnMediaPickerResult(resultCode, data).size} items selected") } } -} - -inline fun Context.kauLaunchAbout() = - startActivity(bundleBuilder = { - withSceneTransitionAnimation(this@kauLaunchAbout) - }) +} \ No newline at end of file -- cgit v1.2.3 From 83bc96c0629a2e50352b177ce6a28b6f9141db69 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Tue, 21 May 2019 12:03:36 -0700 Subject: Update versions (#195) --- .idea/codeStyles/Project.xml | 25 ---------------------- .idea/encodings.xml | 4 ++++ .idea/misc.xml | 2 +- .../main/groovy/ca/allanwang/kau/Versions.groovy | 12 +++++------ files/translation_migration.sh | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 6 files changed, 14 insertions(+), 35 deletions(-) create mode 100644 .idea/encodings.xml (limited to 'buildSrc') diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 0290b2f..be6976d 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -13,31 +13,6 @@