diff options
author | Allan Wang <me@allanwang.ca> | 2019-06-07 12:41:00 -0400 |
---|---|---|
committer | Allan Wang <me@allanwang.ca> | 2019-06-07 12:41:00 -0400 |
commit | 5d86d9089697b152192b2786fbe0c708dd8b5e2b (patch) | |
tree | 99b563b8c234330d2bbbc0145f086d8691ee9376 | |
parent | 572d470a2677eec0405a7b16ab9a2cfb954d6832 (diff) | |
parent | 879ac366074697dd0a7fbb2c3d99a48d7aeeb22d (diff) | |
download | kau-5d86d9089697b152192b2786fbe0c708dd8b5e2b.tar.gz kau-5d86d9089697b152192b2786fbe0c708dd8b5e2b.tar.bz2 kau-5d86d9089697b152192b2786fbe0c708dd8b5e2b.zip |
Merge dev
300 files changed, 5480 insertions, 2545 deletions
@@ -1,5 +1,3 @@ -*.iml -/.idea .gradle /crowdin.properties /local.properties @@ -7,4 +5,27 @@ /build /captures .externalNativeBuild -**/public.xml
\ No newline at end of file +**/public.xml + +# Intellij +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 +*.iml +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf +.idea/**/contentModel.xml +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml +.idea/**/gradle.xml +.idea/**/libraries +.idea/**/assetWizardSettings.xml +.idea/**/caches +.idea/modules.xml +.idea/modules
\ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..be6976d --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,136 @@ +<component name="ProjectCodeStyleConfiguration"> + <code_scheme name="Project" version="173"> + <AndroidXmlCodeStyleSettings> + <option name="USE_CUSTOM_SETTINGS" value="true" /> + </AndroidXmlCodeStyleSettings> + <JetCodeStyleSettings> + <option name="PACKAGES_TO_USE_STAR_IMPORTS"> + <value> + <package name="kotlinx.android.synthetic" withSubpackages="true" static="false" /> + </value> + </option> + <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" /> + <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" /> + <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> + </JetCodeStyleSettings> + <XML> + <option name="XML_KEEP_LINE_BREAKS" value="false" /> + <option name="XML_ALIGN_ATTRIBUTES" value="false" /> + <option name="XML_SPACE_INSIDE_EMPTY_TAG" value="true" /> + </XML> + <codeStyleSettings language="XML"> + <option name="FORCE_REARRANGE_MODE" value="1" /> + <indentOptions> + <option name="CONTINUATION_INDENT_SIZE" value="4" /> + </indentOptions> + <arrangement> + <rules> + <section> + <rule> + <match> + <AND> + <NAME>xmlns:android</NAME> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>xmlns:.*</NAME> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*:id</NAME> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*:name</NAME> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>name</NAME> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>style</NAME> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + <order>ANDROID_ATTRIBUTE_ORDER</order> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_NAMESPACE>.*</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + </section> + </rules> + </arrangement> + </codeStyleSettings> + <codeStyleSettings language="kotlin"> + <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> + <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" /> + <option name="KEEP_BLANK_LINES_IN_CODE" value="1" /> + <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" /> + <option name="ALIGN_MULTILINE_PARAMETERS" value="false" /> + <indentOptions> + <option name="CONTINUATION_INDENT_SIZE" value="4" /> + </indentOptions> + </codeStyleSettings> + </code_scheme> +</component>
\ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..0f7bc51 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ +<component name="ProjectCodeStyleConfiguration"> + <state> + <option name="USE_PER_PROJECT_SETTINGS" value="true" /> + </state> +</component> diff --git a/.idea/copyright/Apache.xml b/.idea/copyright/Apache.xml new file mode 100644 index 0000000..124b434 --- /dev/null +++ b/.idea/copyright/Apache.xml @@ -0,0 +1,6 @@ +<component name="CopyrightManager"> + <copyright> + <option name="notice" value="/* * Copyright &#36;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. */" /> + <option name="myName" value="Apache" /> + </copyright> +</component>
\ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="Encoding" addBOMForNewFiles="with NO BOM" /> +</project>
\ No newline at end of file diff --git a/.idea/inspectionProfiles/ktlint.xml b/.idea/inspectionProfiles/ktlint.xml new file mode 100644 index 0000000..7d04a74 --- /dev/null +++ b/.idea/inspectionProfiles/ktlint.xml @@ -0,0 +1,7 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="ktlint" /> + <inspection_tool class="KotlinUnusedImport" enabled="true" level="ERROR" enabled_by_default="true" /> + <inspection_tool class="RedundantSemicolon" enabled="true" level="ERROR" enabled_by_default="true" /> + </profile> +</component> diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..64580d1 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ +<component name="InspectionProjectProfileManager"> + <settings> + <option name="PROJECT_PROFILE" value="ktlint" /> + <version value="1.0" /> + </settings> +</component> diff --git a/.idea/kotlinScripting.xml b/.idea/kotlinScripting.xml new file mode 100644 index 0000000..a6fe551 --- /dev/null +++ b/.idea/kotlinScripting.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="KotlinScriptingSettings"> + <option name="isAutoReloadEnabled" value="true" /> + </component> +</project>
\ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..51fa3e5 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="NullableNotNullManager"> + <option name="myDefaultNullable" value="android.support.annotation.Nullable" /> + <option name="myDefaultNotNull" value="android.support.annotation.NonNull" /> + <option name="myNullables"> + <value> + <list size="10"> + <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" /> + <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" /> + <item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" /> + <item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" /> + <item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" /> + <item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" /> + <item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" /> + <item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" /> + <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" /> + <item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" /> + </list> + </value> + </option> + <option name="myNotNulls"> + <value> + <list size="9"> + <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" /> + <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" /> + <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" /> + <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" /> + <item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" /> + <item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" /> + <item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" /> + <item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" /> + <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" /> + </list> + </value> + </option> + </component> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK"> + <output url="file://$PROJECT_DIR$/build/classes" /> + </component> + <component name="ProjectType"> + <option name="id" value="Android" /> + </component> +</project>
\ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="RunConfigurationProducerService"> + <option name="ignoredProducers"> + <set> + <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" /> + <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" /> + <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" /> + </set> + </option> + </component> +</project>
\ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="" vcs="Git" /> + </component> +</project>
\ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 3dd7449..7bd509f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,22 +4,22 @@ jdk: env: global: - ANDROID_API=28 - - EMULATOR_API=24 + - EMULATOR_API=19 - ANDROID_BUILD_TOOLS=28.0.3 git: depth: 500 android: components: - tools -# - android-$EMULATOR_API - platform-tools - tools - build-tools-$ANDROID_BUILD_TOOLS - android-$ANDROID_API - - extra-android-support +# - android-$EMULATOR_API - extra-android-m2repository - extra-google-m2repository -# - sys-img-armeabi-v7a-android-$EMULATOR_API +# - sys-img-armeabi-v7a-addon-google_apis-google-$ANDROID_API_LEVEL +# - sys-img-armeabi-v7a-addon-google_apis-google-$EMULATOR_API_LEVEL licenses: - ".+" #before_script: @@ -27,8 +27,11 @@ android: #- echo "y" | android update sdk -a --no-ui --filter sys-img-armeabi-v7a-android-$EMULATOR_API #- android list targets | grep -E '^id:' | awk -F '"' '{$1=""; print $2}' # list all targets #- echo no | android create avd --force -n test -t android-$EMULATOR_API --abi armeabi-v7a -#- emulator -avd test -no-skin -no-window & +#- emulator -avd test -skin -no-audio -no-window & #- android-wait-for-emulator +#- adb shell settings put global window_animation_scale 0 & +#- adb shell settings put global transition_animation_scale 0 & +#- adb shell settings put global animator_duration_scale 0 & #- adb shell input keyevent 82 & script: - chmod +x gradlew @@ -52,7 +55,7 @@ cache: - $HOME/.gradle/wrapper/ - $HOME/.android/build-cache before_install: -- yes | sdkmanager "platforms;android-28" +- yes | sdkmanager "platforms;android-$ANDROID_API" - openssl aes-256-cbc -K $encrypted_12e8842891a3_key -iv $encrypted_12e8842891a3_iv -in files/kau.tar.enc -out kau.tar -d - tar xvf kau.tar
\ No newline at end of file @@ -35,8 +35,6 @@ allprojects { } ``` -(If you are using gradle < 4.0, use `maven { url "https://maven.google.com" }` instead of `google()`) - And add the following dependencies (You can use a specific version, commit, or -SNAPSHOT): Note that only `core` is required if you want the basic features. @@ -71,8 +69,6 @@ buildscript { ``` -(If you are using gradle < 4.0, use `compile` instead of `implementation`) - ----------- # Submodules @@ -99,10 +95,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) @@ -148,7 +143,6 @@ This means that you'll need to explicitly include each submodule you'd like to u ![About Activity Gif](https://raw.githubusercontent.com/AllanWang/Storage-Hub/master/kau/kau_about_activity.gif) ![Ink Indicator Gif](https://raw.githubusercontent.com/AllanWang/Storage-Hub/master/kau/kau_ink_indicator.gif) ![Color Picker Gif](https://raw.githubusercontent.com/AllanWang/Storage-Hub/master/kau/kau_color_picker.gif) -![Color Picker Custom Gif](https://raw.githubusercontent.com/AllanWang/Storage-Hub/master/kau/kau_color_picker_custom.gif) ![KPref Items Gif](https://raw.githubusercontent.com/AllanWang/Storage-Hub/master/kau/kau_kpref_items.gif) ![SearchView Gif](https://raw.githubusercontent.com/AllanWang/Storage-Hub/master/kau/kau_search_view.gif) ![Swipe Gif](https://raw.githubusercontent.com/AllanWang/Storage-Hub/master/kau/kau_swipe.gif) @@ -172,7 +166,8 @@ Special thanks to the following awesome people for translating significant porti | Language | Contributors | |----------|--------------| -| Chinese (Simplified) | | +| Chinese (Simplified) | [Alcatelia](https://crowdin.com/profile/Alcatelia) | +| Chinese (Traditional) | [yipinghuang](https://crowdin.com/profile/yipinghuang) • [Su, Jun-Ming](https://crowdin.com/profile/sujunmin) • [Wei](https://crowdin.com/profile/wei4green) | | French | [Vincent Kulak](https://github.com/VonOx) • [Jean-Philippe Gravel](https://crowdin.com/profile/wokija) | | Galician | [Xesús M. Mosquera](https://twitter.com/xesusmmc?lang=en) | | German | [Bushido1992](https://forum.xda-developers.com/member.php?u=5179246) • [Marcel Soehnchen](https://crowdin.com/profile/msoehnchen) • [3LD0mi HA](https://forum.xda-developers.com/member.php?u=5860523) | @@ -180,11 +175,14 @@ Special thanks to the following awesome people for translating significant porti | Italian | [Bonnee](https://github.com/Bonnee) | | Korean | [잇스테이크](https://crowdin.com/profile/bexco2010) | | Norwegian | | -| Polish | | -| Portuguese | [TheusKhan](https://crowdin.com/profile/TheusKhan) | +| Polish | [pantinPL](https://crowdin.com/profile/pantinPL) | +| Portuguese | [Sérgio Marques](https://crowdin.com/profile/smarquespt) • [Miguel Dos Reis](https://crowdin.com/profile/siersod) | +| Portuguese (Brazilian) | [TheusKhan](https://crowdin.com/profile/TheusKhan) | +| Serbian | [Nikola Radmanović](https://crowdin.com/profile/nikoladradmanovic) | | Spanish | [Jahir Fiquitiva](https://jahirfiquitiva.me/) • [Nefi Salazar](https://plus.google.com/u/0/105547968033551087431)| -| Thai | | -| Turkish | | +| Thai | [Thanawat Hanthong](https://crowdin.com/profile/peet6015) | +| Turkish | [zuma17](https://crowdin.com/profile/zuma17) | | Vietnamese | [Alienz](https://crowdin.com/profile/alienyd) | The full activity stream for the translations can be found [here](https://crowdin.com/project/kotlin-android-utils/activity_stream) + diff --git a/_layouts/default.html b/_layouts/default.html index 6868eca..c87a7b7 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -1,22 +1,34 @@ -<!doctype html> -<!--https://help.github.com/articles/repository-metadata-on-github-pages/#available-repository-metadata--> -<html> +<!--See https://github.com/pages-themes/minimal/blob/master/_layouts/default.html--> +<!DOCTYPE html> +<html lang="{{ site.lang | default: "en-US" }}"> <head> - <meta charset="utf-8"> - <meta http-equiv="X-UA-Compatible" content="chrome=1"> - <title>{{ site.title | default: site.github.repository_name }} by {{ site.github.owner_name }}</title> + <meta charset="UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> - <link rel="stylesheet" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}"> - <meta name="viewport" content="width=device-width"> + {% seo %} + <link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}"> + + <!--Begin favicon--> + <link rel="apple-touch-icon" sizes="180x180" href="{{ '/favicon/apple-touch-icon.png' | relative_url }}"> + <link rel="icon" type="image/png" sizes="32x32" href="{{ '/favicon/favicon-32x32.png' | relative_url }}"> + <link rel="icon" type="image/png" sizes="16x16" href="{{ '/favicon/favicon-16x16.png' | relative_url }}"> + <link rel="manifest" href="{{ '/favicon/site.webmanifest' | relative_url }}"> + <link rel="mask-icon" href="{{ '/favicon/safari-pinned-tab.svg' | relative_url }}" color="#3b5998"> + <link rel="shortcut icon" href="{{ '/favicon/favicon.ico' | relative_url }}"> + <meta name="msapplication-TileColor" content="#da532c"> + <meta name="msapplication-config" content="{{ '/favicon/browserconfig.xml' | relative_url }}"> + <meta name="theme-color" content="#ffffff"> + <!--End favicon--> <!--[if lt IE 9]> - <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script> <![endif]--> </head> <body> <div class="wrapper"> <header> <a href="{{ site.github.url }}"><img src="https://cdn.rawgit.com/AllanWang/KAU/master/files/images/logo.svg" alt="KAU" width="30%"/></a> - <!--<h1><a href="{{ site.github.url }}">{{ site.title | default: site.github.repository_name }}</a></h1>--> + <p>{{ site.description | default: site.github.project_tagline }}</p> {% if page.url == '/core/' or @@ -60,18 +72,5 @@ </footer> </div> <script src="{{ '/assets/js/scale.fix.js' | relative_url }}"></script> - - -{% if site.google_analytics %} -<script> - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); - - ga('create', '{{ site.google_analytics }}', 'auto'); - ga('send', 'pageview'); - </script> -{% endif %} </body> </html>
\ No newline at end of file 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 f4ee4c5..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,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.about import android.graphics.drawable.Drawable import android.os.Bundle -import android.support.v4.view.PagerAdapter -import android.support.v4.view.ViewPager import android.transition.TransitionInflater import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.viewpager.widget.PagerAdapter +import androidx.viewpager.widget.ViewPager import ca.allanwang.kau.adapters.FastItemThemedAdapter import ca.allanwang.kau.adapters.ThemableIItemColors import ca.allanwang.kau.adapters.ThemableIItemColorsDelegate @@ -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<IItem<*, *>>) { - } /** @@ -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<Library> = - 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 <reified T : AboutActivityBase> Context.kauLaunchAbout() = - startActivity<T>(bundleBuilder = { - withSceneTransitionAnimation(this@kauLaunchAbout) - })
\ No newline at end of file + startActivity<T>(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 b6ea16b..924a771 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt @@ -1,20 +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.about -import android.support.v7.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 -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.uiThread +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext /** * Created by Allan Wang on 2017-08-02. @@ -76,8 +99,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 +159,6 @@ open class AboutPanelMain : AboutPanelRecycler() { } override fun addItemsImpl(activity: AboutActivityBase, position: Int) {} - } /** @@ -153,12 +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 = withContext(Dispatchers.Default) { + getLibraries( + if (rClass == null) Libs(activity) + else Libs(activity, Libs.toStringArray(rClass.fields)) + ).map(::LibraryIItem) + } if (pageStatus[position] == 1) - uiThread { addItems(activity, position) } + addItems(activity, position) } } } @@ -166,7 +192,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) } } } @@ -180,8 +206,13 @@ open class AboutPanelFaqs : AboutPanelRecycler() { override fun loadItems(activity: AboutActivityBase, position: Int) { with(activity) { - kauParseFaq(configs.faqXmlRes, configs.faqParseNewLine) { - items = it.map(::FaqIItem) + launch { + items = withContext(Dispatchers.IO) { + kauParseFaq( + configs.faqXmlRes, + configs.faqParseNewLine + ) + }.map(::FaqIItem) if (pageStatus[position] == 1) addItems(activity, position) } @@ -191,8 +222,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 f010321..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 android.support.v7.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 37c13d8..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 android.support.v7.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<CutoutIItem, CutoutIItem.ViewHolder>( - 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<CutoutIItem class ViewHolder(v: View) : RecyclerView.ViewHolder(v) { val cutout: CutoutView = v.findViewById(R.id.kau_cutout) } - -}
\ No newline at end of file +} diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/FaqIItem.kt b/about/src/main/kotlin/ca/allanwang/kau/about/FaqIItem.kt index 5cf046e..755ac81 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/FaqIItem.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/FaqIItem.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.about import android.annotation.SuppressLint -import android.support.v7.widget.RecyclerView import android.text.method.LinkMovementMethod import android.view.View import android.view.ViewGroup import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.adapters.ThemableIItem import ca.allanwang.kau.adapters.ThemableIItemDelegate import ca.allanwang.kau.iitems.KauIItem @@ -22,23 +37,24 @@ import com.mikepenz.fastadapter.listeners.ClickEventHook * Created by Allan Wang on 2017-08-02. */ class FaqIItem(val content: FaqItem) : KauIItem<LibraryIItem, FaqIItem.ViewHolder>( - 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<IItem<*, *>>) { fastAdapter.withSelectable(false) - .withEventHook(object : ClickEventHook<IItem<*, *>>() { - - override fun onBind(viewHolder: RecyclerView.ViewHolder): View? = (viewHolder as? ViewHolder)?.questionContainer + .withEventHook(object : ClickEventHook<IItem<*, *>>() { - override fun onClick(v: View, position: Int, adapter: FastAdapter<IItem<*, *>>, item: IItem<*, *>) { - if (item !is FaqIItem) return - item.isExpanded = !item.isExpanded - v.parentViewGroup.findViewById<CollapsibleTextView>(R.id.faq_item_answer).setExpanded(item.isExpanded) - } + override fun onBind(viewHolder: RecyclerView.ViewHolder): View? = + (viewHolder as? ViewHolder)?.questionContainer - }) + override fun onClick(v: View, position: Int, adapter: FastAdapter<IItem<*, *>>, item: IItem<*, *>) { + if (item !is FaqIItem) return + item.isExpanded = !item.isExpanded + v.parentViewGroup.findViewById<CollapsibleTextView>(R.id.faq_item_answer) + .setExpanded(item.isExpanded) + } + }) } } @@ -83,5 +99,4 @@ class FaqIItem(val content: FaqItem) : KauIItem<LibraryIItem, FaqIItem.ViewHolde answer.movementMethod = LinkMovementMethod.getInstance() } } - -}
\ No newline at end of file +} diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/LibraryIItem.kt b/about/src/main/kotlin/ca/allanwang/kau/about/LibraryIItem.kt index 2749c28..33aac09 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/LibraryIItem.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/LibraryIItem.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.about import android.os.Build -import android.support.v7.widget.CardView -import android.support.v7.widget.RecyclerView import android.text.Html import android.view.View import android.widget.TextView +import androidx.cardview.widget.CardView +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.adapters.ThemableIItem import ca.allanwang.kau.adapters.ThemableIItemDelegate import ca.allanwang.kau.iitems.KauIItem @@ -20,21 +35,21 @@ import com.mikepenz.fastadapter.IItem * Created by Allan Wang on 2017-06-27. */ class LibraryIItem(val lib: Library) : KauIItem<LibraryIItem, LibraryIItem.ViewHolder>( - 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<IItem<*, *>>) { 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<LibraryIItem, LibraryIItem.ViewH @Suppress("DEPRECATION") description.text = when { lib.libraryDescription.isBlank() -> 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<LibraryIItem, LibraryIItem.ViewH val divider: View = v.findViewById(R.id.lib_item_top_divider) val bottomDivider: View = v.findViewById(R.id.lib_item_bottom_divider) } - -}
\ No newline at end of file +} diff --git a/about/src/main/res/layout/kau_about_section_libraries.xml b/about/src/main/res/layout/kau_about_section_libraries.xml index c14225e..60d1312 100644 --- a/about/src/main/res/layout/kau_about_section_libraries.xml +++ b/about/src/main/res/layout/kau_about_section_libraries.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/about_library_container" android:layout_width="match_parent" @@ -15,7 +15,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - <android.support.v7.widget.RecyclerView + <androidx.recyclerview.widget.RecyclerView android:id="@+id/about_library_recycler" android:layout_width="0dp" android:layout_height="0dp" @@ -24,4 +24,4 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/about_library_title" /> -</android.support.constraint.ConstraintLayout> +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/about/src/main/res/layout/kau_about_section_main.xml b/about/src/main/res/layout/kau_about_section_main.xml index e7b83a0..7ea0415 100644 --- a/about/src/main/res/layout/kau_about_section_main.xml +++ b/about/src/main/res/layout/kau_about_section_main.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:showIn="@layout/kau_activity_about"> - <android.support.constraint.ConstraintLayout + <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/about_main_container" android:layout_width="match_parent" android:layout_height="wrap_content"> @@ -41,6 +41,6 @@ </FrameLayout> - </android.support.constraint.ConstraintLayout> + </androidx.constraintlayout.widget.ConstraintLayout> -</android.support.v4.widget.NestedScrollView> +</androidx.core.widget.NestedScrollView> diff --git a/about/src/main/res/layout/kau_activity_about.xml b/about/src/main/res/layout/kau_activity_about.xml index 3d1f9ab..626adda 100644 --- a/about/src/main/res/layout/kau_activity_about.xml +++ b/about/src/main/res/layout/kau_activity_about.xml @@ -9,7 +9,7 @@ app:dragDismissScale="0.95" tools:context=".ui.about.AboutActivityBase"> - <android.support.v4.view.ViewPager + <androidx.viewpager.widget.ViewPager android:id="@+id/about_pager" android:layout_width="match_parent" android:layout_height="match_parent" /> diff --git a/about/src/main/res/layout/kau_iitem_library.xml b/about/src/main/res/layout/kau_iitem_library.xml index 47b4e01..4dd5155 100644 --- a/about/src/main/res/layout/kau_iitem_library.xml +++ b/about/src/main/res/layout/kau_iitem_library.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/lib_item_card" @@ -8,7 +8,7 @@ android:clickable="true" android:focusable="true"> - <android.support.constraint.ConstraintLayout + <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="@dimen/kau_padding_normal" @@ -112,6 +112,6 @@ app:layout_constraintTop_toBottomOf="@id/lib_item_bottom_divider" tools:text="License" /> - </android.support.constraint.ConstraintLayout> + </androidx.constraintlayout.widget.ConstraintLayout> -</android.support.v7.widget.CardView>
\ No newline at end of file +</androidx.cardview.widget.CardView>
\ No newline at end of file diff --git a/about/src/main/res/values-da-rDK/strings_about.xml b/about/src/main/res/values-da-rDK/strings_about.xml index 837d419..87fc65b 100644 --- a/about/src/main/res/values-da-rDK/strings_about.xml +++ b/about/src/main/res/values-da-rDK/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Denne app vil ikke være mulig uden de følgende fantastiske biblioteker.</string> <string name="kau_about_faq_intro">Ofte stillede spørgsmål</string> diff --git a/about/src/main/res/values-de-rDE/strings_about.xml b/about/src/main/res/values-de-rDE/strings_about.xml index 5d7bc28..69df4d9 100644 --- a/about/src/main/res/values-de-rDE/strings_about.xml +++ b/about/src/main/res/values-de-rDE/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Diese App wäre nicht möglich ohne die folgenden großartigen Bibliotheken.</string> <string name="kau_about_faq_intro">Häufige Fragen / FAQ</string> diff --git a/about/src/main/res/values-es-rES/strings_about.xml b/about/src/main/res/values-es-rES/strings_about.xml index 3fb0bed..743bc4d 100644 --- a/about/src/main/res/values-es-rES/strings_about.xml +++ b/about/src/main/res/values-es-rES/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Esta aplicación no sería posible sin las siguientes geniales librerías.</string> <string name="kau_about_faq_intro">Preguntas Frecuentes</string> diff --git a/about/src/main/res/values-fr-rFR/strings_about.xml b/about/src/main/res/values-fr-rFR/strings_about.xml index 91db02c..0d50f86 100644 --- a/about/src/main/res/values-fr-rFR/strings_about.xml +++ b/about/src/main/res/values-fr-rFR/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Ce soft ne serait pas possible sans ces super bibliothèques.</string> <string name="kau_about_faq_intro">FAQ</string> diff --git a/about/src/main/res/values-gl-rES/strings_about.xml b/about/src/main/res/values-gl-rES/strings_about.xml index fe64f7f..f0da61f 100644 --- a/about/src/main/res/values-gl-rES/strings_about.xml +++ b/about/src/main/res/values-gl-rES/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Esta aplicación non sería posible sen a existencia destas fantásticas librarías.</string> <string name="kau_about_faq_intro">Preguntas frecuentes</string> diff --git a/about/src/main/res/values-hu-rHU/strings_about.xml b/about/src/main/res/values-hu-rHU/strings_about.xml index d57e13d..e4efded 100644 --- a/about/src/main/res/values-hu-rHU/strings_about.xml +++ b/about/src/main/res/values-hu-rHU/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Ez az app nem jöhetett volna létre a következő könyvtárak nélkül.</string> <string name="kau_about_faq_intro">GyIK</string> diff --git a/about/src/main/res/values-in-rID/strings_about.xml b/about/src/main/res/values-in-rID/strings_about.xml index e2e83a7..5bdee31 100644 --- a/about/src/main/res/values-in-rID/strings_about.xml +++ b/about/src/main/res/values-in-rID/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Aplikasi ini tidak mungkin dilakukan tanpa perpustakaan besar berikut ini.</string> <string name="kau_about_faq_intro">FAQ</string> diff --git a/about/src/main/res/values-it-rIT/strings_about.xml b/about/src/main/res/values-it-rIT/strings_about.xml index 170ff15..5867d94 100644 --- a/about/src/main/res/values-it-rIT/strings_about.xml +++ b/about/src/main/res/values-it-rIT/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Questa applicazione non sarebbe possibile senza queste fantastiche librerie.</string> <string name="kau_about_faq_intro">Domande frequenti</string> diff --git a/about/src/main/res/values-ko-rKR/strings_about.xml b/about/src/main/res/values-ko-rKR/strings_about.xml index f6b4413..00c80e3 100644 --- a/about/src/main/res/values-ko-rKR/strings_about.xml +++ b/about/src/main/res/values-ko-rKR/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">이 앱은 아래의 라이브러리가 없었다면 만들 수 없었습니다.</string> <string name="kau_about_faq_intro">FAQ</string> diff --git a/about/src/main/res/values-nl-rNL/strings_about.xml b/about/src/main/res/values-nl-rNL/strings_about.xml new file mode 100644 index 0000000..570984d --- /dev/null +++ b/about/src/main/res/values-nl-rNL/strings_about.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> +<resources> + <string name="kau_about_libraries_intro">Deze app is mede mogelijk gemaakt door de volgende geweldige libraries.</string> + <string name="kau_about_faq_intro">Veelgestelde vragen</string> +</resources> diff --git a/about/src/main/res/values-no-rNO/strings_about.xml b/about/src/main/res/values-no-rNO/strings_about.xml index 2cffcbc..328fda3 100644 --- a/about/src/main/res/values-no-rNO/strings_about.xml +++ b/about/src/main/res/values-no-rNO/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Denne appens eksistens ville ikke vært mulig uten de flotte, følgende bibliotekene.</string> <string name="kau_about_faq_intro">Spørsmål og svar</string> diff --git a/about/src/main/res/values-pl-rPL/strings_about.xml b/about/src/main/res/values-pl-rPL/strings_about.xml index cfdd1ef..a5daa6d 100644 --- a/about/src/main/res/values-pl-rPL/strings_about.xml +++ b/about/src/main/res/values-pl-rPL/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Aplikacja nie byłaby możliwa bez następujących świetnych bibliotek.</string> <string name="kau_about_faq_intro">FAQ</string> diff --git a/about/src/main/res/values-pt-rBR/strings_about.xml b/about/src/main/res/values-pt-rBR/strings_about.xml index e6feb8d..8e98238 100644 --- a/about/src/main/res/values-pt-rBR/strings_about.xml +++ b/about/src/main/res/values-pt-rBR/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Este aplicativo não seria possível sem as seguintes excelentes bibliotecas.</string> <string name="kau_about_faq_intro">Perguntas Frequentes</string> diff --git a/about/src/main/res/values-pt-rPT/strings_about.xml b/about/src/main/res/values-pt-rPT/strings_about.xml new file mode 100644 index 0000000..d092302 --- /dev/null +++ b/about/src/main/res/values-pt-rPT/strings_about.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> +<resources> + <string name="kau_about_libraries_intro">Esta aplicação não seria possível sem as seguintes bibliotecas.</string> + <string name="kau_about_faq_intro">FAQ</string> +</resources> diff --git a/about/src/main/res/values-sr-rSP/strings_about.xml b/about/src/main/res/values-sr-rSP/strings_about.xml new file mode 100644 index 0000000..550aa9b --- /dev/null +++ b/about/src/main/res/values-sr-rSP/strings_about.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> +<resources> + <string name="kau_about_libraries_intro">Ова апликација не бу била могућа без ових одличних библиотека.</string> + <string name="kau_about_faq_intro">ЧПП</string> +</resources> diff --git a/about/src/main/res/values-sv-rSE/strings_about.xml b/about/src/main/res/values-sv-rSE/strings_about.xml index 02f5417..d8f888f 100644 --- a/about/src/main/res/values-sv-rSE/strings_about.xml +++ b/about/src/main/res/values-sv-rSE/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Den här appen skulle inte varit möjlig utan följande bibliotek.</string> <string name="kau_about_faq_intro">Vanliga frågor</string> diff --git a/about/src/main/res/values-th-rTH/strings_about.xml b/about/src/main/res/values-th-rTH/strings_about.xml index ab1863b..7a3a5ed 100644 --- a/about/src/main/res/values-th-rTH/strings_about.xml +++ b/about/src/main/res/values-th-rTH/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">แอพนี้จะไม่สามารถเกิดขึ้นได้ถ้าไม่ได้ไลบาลี้เหล่านี้</string> <string name="kau_about_faq_intro">ถามตอบ</string> diff --git a/about/src/main/res/values-tr-rTR/strings_about.xml b/about/src/main/res/values-tr-rTR/strings_about.xml index b54bb6e..857aec3 100644 --- a/about/src/main/res/values-tr-rTR/strings_about.xml +++ b/about/src/main/res/values-tr-rTR/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Bu uygulama aşağıdaki büyük kütüphaneler olmadan mümkün olmayacaktır.</string> <string name="kau_about_faq_intro">SSS</string> diff --git a/about/src/main/res/values-uk-rUA/strings_about.xml b/about/src/main/res/values-uk-rUA/strings_about.xml index 1ca3901..d4dca9b 100644 --- a/about/src/main/res/values-uk-rUA/strings_about.xml +++ b/about/src/main/res/values-uk-rUA/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Цей додаток не був би можливим без використання великих бібліотек.</string> <string name="kau_about_faq_intro">FAQ</string> diff --git a/about/src/main/res/values-vi-rVN/strings_about.xml b/about/src/main/res/values-vi-rVN/strings_about.xml index a71d127..4f84966 100644 --- a/about/src/main/res/values-vi-rVN/strings_about.xml +++ b/about/src/main/res/values-vi-rVN/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">Ứng dụng này ra đời nhờ những thư viện tuyệt vời dưới đây.</string> <string name="kau_about_faq_intro">CÂU HỎI THƯỜNG GẶP</string> diff --git a/about/src/main/res/values-zh-rCN/strings_about.xml b/about/src/main/res/values-zh-rCN/strings_about.xml index 8625ef7..cf63c9a 100644 --- a/about/src/main/res/values-zh-rCN/strings_about.xml +++ b/about/src/main/res/values-zh-rCN/strings_about.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_about_libraries_intro">没有以下的大数据库,这个应用程序不会运行。</string> <string name="kau_about_faq_intro">常见问题</string> diff --git a/about/src/main/res/values-zh-rTW/strings_about.xml b/about/src/main/res/values-zh-rTW/strings_about.xml new file mode 100644 index 0000000..a292a93 --- /dev/null +++ b/about/src/main/res/values-zh-rTW/strings_about.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> +<resources> + <string name="kau_about_libraries_intro">若無下述函式庫的幫忙, 本程式無法成真.</string> + <string name="kau_about_faq_intro">常見問題</string> +</resources> diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/adapters/AdapterUtils.kt b/adapter/src/main/kotlin/ca/allanwang/kau/adapters/AdapterUtils.kt index b754cb4..17fd09f 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/adapters/AdapterUtils.kt +++ b/adapter/src/main/kotlin/ca/allanwang/kau/adapters/AdapterUtils.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.adapters import com.mikepenz.fastadapter.FastAdapter @@ -14,10 +29,10 @@ import com.mikepenz.fastadapter.select.SelectExtension * Add kotlin's generic syntax to better support out types */ fun <Item : IItem<*, *>> fastAdapter(vararg adapter: IAdapter<out Item>) = - FastAdapter.with<Item, IAdapter<out Item>>(adapter.toList())!! + FastAdapter.with<Item, IAdapter<out Item>>(adapter.toList())!! inline fun <reified T : IAdapterExtension<Item>, Item : IItem<*, *>> FastAdapter<Item>.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 870861d..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 android.support.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<Item : IItem<*, *>>( - textColor: Int? = null, - backgroundColor: Int? = null, - accentColor: Int? = null + textColor: Int? = null, + backgroundColor: Int? = null, + accentColor: Int? = null ) : FastItemAdapter<Item>() { 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 aeee94c..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 android.support.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 <Item : IItem<*, *>> FastAdapter<Item>.withOnRepeatedClickListener(count: Int, - duration: Long, - event: OnClickListener<Item>) = - withOnClickListener(RepeatedClickListener(count, duration, event)) +fun <Item : IItem<*, *>> FastAdapter<Item>.withOnRepeatedClickListener( + count: Int, + duration: Long, + event: OnClickListener<Item> +) = + withOnClickListener(RepeatedClickListener(count, duration, event)) /** * Registers and skips each click until the designated [count] clicks are triggered, @@ -21,9 +38,10 @@ fun <Item : IItem<*, *>> FastAdapter<Item>.withOnRepeatedClickListener(count: In * Only then will the [event] be fired, and everything will be reset. */ private class RepeatedClickListener<Item : IItem<*, *>>( - @IntRange(from = 1) val count: Int, - @IntRange(from = 1) val duration: Long, - val event: OnClickListener<Item>) : OnClickListener<Item> { + @IntRange(from = 1) val count: Int, + @IntRange(from = 1) val duration: Long, + val event: OnClickListener<Item> +) : OnClickListener<Item> { init { if (count <= 0) @@ -49,4 +67,4 @@ private class RepeatedClickListener<Item : IItem<*, *>>( } 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 3cf13df..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,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 android.support.v7.widget.RecyclerView import android.view.View import android.view.ViewPropertyAnimator +import androidx.recyclerview.widget.RecyclerView /** * Created by Allan Wang on 2017-07-11. @@ -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/BaseItemAnimator.java b/adapter/src/main/kotlin/ca/allanwang/kau/animators/BaseItemAnimator.java index 06b8df6..4ead735 100644 --- a/adapter/src/main/kotlin/ca/allanwang/kau/animators/BaseItemAnimator.java +++ b/adapter/src/main/kotlin/ca/allanwang/kau/animators/BaseItemAnimator.java @@ -26,10 +26,11 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; -import android.support.annotation.NonNull; -import android.support.v4.view.ViewCompat; -import android.support.v7.widget.RecyclerView.ViewHolder; -import android.support.v7.widget.SimpleItemAnimator; +import androidx.annotation.NonNull; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.RecyclerView.ViewHolder; +import androidx.recyclerview.widget.SimpleItemAnimator; + import android.view.View; import android.view.ViewPropertyAnimator; import android.view.animation.Interpolator; @@ -38,11 +39,11 @@ import java.util.ArrayList; import java.util.List; /** - * This implementation of {@link android.support.v7.widget.RecyclerView.ItemAnimator} provides basic + * This implementation of {@link androidx.recyclerview.widget.RecyclerView.ItemAnimator} provides basic * animations on remove, add, and move events that happen to the items in * a RecyclerView. RecyclerView uses a DefaultItemAnimator by default. * - * @see android.support.v7.widget.RecyclerView#setItemAnimator(android.support.v7.widget.RecyclerView.ItemAnimator) + * @see androidx.recyclerview.widget.RecyclerView#setItemAnimator(androidx.recyclerview.widget.RecyclerView.ItemAnimator) */ public abstract class BaseItemAnimator extends SimpleItemAnimator { private static final boolean DEBUG = false; 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 9aeafde..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,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 android.support.v7.widget.RecyclerView import android.view.ViewPropertyAnimator +import androidx.recyclerview.widget.RecyclerView /** * Created by Allan Wang on 2017-06-27. @@ -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 bf38cac..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 android.support.v7.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 7b9b732..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 android.support.v7.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 5ecc937..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 android.support.v7.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 f8f71a5..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 android.support.v7.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 ba969a2..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 android.support.v7.widget.CardView -import android.support.v7.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<CardIItem, CardIItem.ViewHolder>( - 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 2116b34..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 android.support.v7.widget.CardView -import android.support.v7.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<HeaderIItem, HeaderIItem.ViewHolder>( - 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 5174503..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.support.annotation.LayoutRes -import android.support.v7.widget.RecyclerView import android.view.View +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView 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<Item, VH : RecyclerView.ViewHolder>( - @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<Item, VH>() 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/adapter/src/main/res/layout/kau_iitem_card.xml b/adapter/src/main/res/layout/kau_iitem_card.xml index 249f3b8..6bae0fe 100644 --- a/adapter/src/main/res/layout/kau_iitem_card.xml +++ b/adapter/src/main/res/layout/kau_iitem_card.xml @@ -3,7 +3,7 @@ <!-- Generic card with an imageview, title, description, and button --> -<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/kau_card_container" android:layout_width="match_parent" @@ -11,7 +11,7 @@ android:background="?android:selectableItemBackground" android:minHeight="?android:listPreferredItemHeight"> - <android.support.constraint.ConstraintLayout + <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="@dimen/kau_padding_normal"> @@ -69,6 +69,6 @@ </LinearLayout> - </android.support.constraint.ConstraintLayout> + </androidx.constraintlayout.widget.ConstraintLayout> -</android.support.v7.widget.CardView> +</androidx.cardview.widget.CardView> diff --git a/adapter/src/main/res/layout/kau_iitem_header.xml b/adapter/src/main/res/layout/kau_iitem_header.xml index db809eb..b0b2ec8 100644 --- a/adapter/src/main/res/layout/kau_iitem_header.xml +++ b/adapter/src/main/res/layout/kau_iitem_header.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/kau_header_container" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -13,4 +13,4 @@ android:padding="@dimen/kau_padding_normal" android:textAppearance="@style/TextAppearance.AppCompat.Body1" /> -</android.support.v7.widget.CardView>
\ No newline at end of file +</androidx.cardview.widget.CardView>
\ No newline at end of file diff --git a/android-lib.gradle b/android-lib.gradle index 7275347..e8a4c6d 100644 --- a/android-lib.gradle +++ b/android-lib.gradle @@ -31,7 +31,7 @@ android { versionCode androidGitVersion.code() consumerProguardFiles 'progress-proguard.txt' multiDexEnabled true - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { @@ -87,5 +87,6 @@ dependencies { androidTestImplementation kauDependency.kotlinTest androidTestImplementation kauDependency.espresso + androidTestImplementation kauDependency.testRules androidTestImplementation kauDependency.testRunner }
\ No newline at end of file diff --git a/build.gradle b/build.gradle index 3ddfb9c..39aba6f 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) @@ -27,7 +28,7 @@ task clean(type: Delete) { } task generateChangelogMd { - kauChangelog.generate("$project.rootDir/sample/src/main/res/xml/kau_changelog.xml") + kauChangelog.generate("${project.rootDir}/sample/src/main/res/xml/kau_changelog.xml") } subprojects { @@ -37,6 +38,8 @@ subprojects { apply plugin: 'com.gladed.androidgitversion' + apply from: '../spotless.gradle' + repositories { google() jcenter() 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/build.gradle b/buildSrc/build.gradle deleted file mode 100644 index a51e9ae..0000000 --- a/buildSrc/build.gradle +++ /dev/null @@ -1,9 +0,0 @@ -apply plugin: 'groovy' -apply plugin: 'maven' - -group = "ca.allanwang" - -dependencies { - compile gradleApi() - compile localGroovy() -}
\ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..83a3370 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + `kotlin-dsl` + maven +} + +group = "ca.allanwang" + +gradlePlugin { + plugins { + register("kau-plugin") { + id = "ca.allanwang.kau" + implementationClass = "ca.allanwang.kau.KauPlugin" + } + } +} + +repositories { + mavenCentral() +}
\ No newline at end of file diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/buildSrc/settings.gradle.kts diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/ChangelogGenerator.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/ChangelogGenerator.groovy deleted file mode 100644 index bb56fa2..0000000 --- a/buildSrc/src/main/groovy/ca/allanwang/kau/ChangelogGenerator.groovy +++ /dev/null @@ -1,76 +0,0 @@ -package ca.allanwang.kau - -import org.gradle.api.GradleException -import org.gradle.api.Project - -/** - * Given an xml of the format - * - * <?xml version="1.0" encoding="utf-8"?> - * <resources> - * <version title="v0.1" /> - * <item text="Initial Changelog" /> - * <item text="Bullet point here" /> - * <item text="More points" /> - * <item text="" /> <!-- this one is empty and therefore ignored --> - * </resources> - * - * Outputs a changelog in markdown format - */ -class ChangelogGenerator { - - static class ChangelogException extends GradleException { - ChangelogException(String message) { - super(message) - } - } - - private Project project - - ChangelogGenerator(Project project) { - this.project = project - } - - private static void fail(String message) { - throw new ChangelogException(message) - } - - final void generate(String inputUri, String outputUri = "$project.rootDir/docs/Changelog.md") { - def input = new File(inputUri) - if (!input.exists()) - fail("Could not generate changelog from ${input.absolutePath}") - - def output = new File(outputUri) - - if (output.exists()) { - if (output.isDirectory()) - fail("Cannot save changelog at directory ${output.absolutePath}") - - - if (output.isFile() && !output.delete()) - fail("Could not delete changelog at ${output.absolutePath}") - } else { - output.parentFile.mkdirs() - } - - if (!output.createNewFile()) - fail("Could not create changelog file at ${output.absolutePath}") - - def parsedProjectXml = (new XmlParser()).parse(inputUri) - def sw = new StringWriter() - sw.append("# Changelog\n") - parsedProjectXml.depthFirst().each { - switch (it.name()) { - case "version": - sw.append("\n## ${it.@title}\n") - break - case "item": - if (it.@text?.trim()) - sw.append("* ${it.@text}\n") - } - } - output.write(sw.toString()) - println("Generated changelog at ${output.absolutePath}") - } - -}
\ No newline at end of file diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy deleted file mode 100644 index ec3d208..0000000 --- a/buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy +++ /dev/null @@ -1,12 +0,0 @@ -package ca.allanwang.kau - -/** - * Some common dependencies, backed by the supplied versions - */ -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}" -}
\ No newline at end of file diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/KauPlugin.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/KauPlugin.groovy deleted file mode 100644 index e73564c..0000000 --- a/buildSrc/src/main/groovy/ca/allanwang/kau/KauPlugin.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package ca.allanwang.kau - -import org.gradle.api.Plugin -import org.gradle.api.Project - -class KauPlugin implements Plugin<Project> { - - @Override - void apply(Project project) { - project.extensions.create("kau", Versions) - project.extensions.create("kauPlugin", Plugins) - project.extensions.create("kauDependency", Dependencies) - project.extensions.create("kauChangelog", ChangelogGenerator, project) - } - -}
\ No newline at end of file diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/Plugins.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/Plugins.groovy deleted file mode 100644 index c1ecba6..0000000 --- a/buildSrc/src/main/groovy/ca/allanwang/kau/Plugins.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package ca.allanwang.kau - -/** - * Some common buildscript plugins, backed by the supplied versions - */ -class Plugins { - static def android = "com.android.tools.build:gradle:${Versions.gradlePlugin}" - static def kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}" - static - def androidMaven = "com.github.dcendents:android-maven-gradle-plugin:${Versions.mavenPlugin}" - static - def playPublisher = "com.github.triplet.gradle:play-publisher:${Versions.playPublishPlugin}" - static - 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}" -}
\ No newline at end of file diff --git a/buildSrc/src/main/kotlin/ca/allanwang/kau/ChangelogGenerator.kt b/buildSrc/src/main/kotlin/ca/allanwang/kau/ChangelogGenerator.kt new file mode 100644 index 0000000..5e21b7e --- /dev/null +++ b/buildSrc/src/main/kotlin/ca/allanwang/kau/ChangelogGenerator.kt @@ -0,0 +1,105 @@ +package ca.allanwang.kau + +import groovy.util.Node +import groovy.util.XmlParser +import org.gradle.api.GradleException +import org.gradle.api.Project +import java.io.File + +/** + * Given an xml of the format + * + * <?xml version="1.0" encoding="utf-8"?> + * <resources> + * <version title="v0.1" /> + * <item text="Initial Changelog" /> + * <item text="Bullet point here" /> + * <item text="More points" /> + * <item text="" /> <!-- this one is empty and therefore ignored --> + * </resources> + * + * Outputs a changelog in markdown format + */ +open class ChangelogGenerator(private val project: Project) { + + class ChangelogException(message: String) : GradleException(message) + + private fun fail(message: String): Nothing = + throw ChangelogException(message) + + class ChangelogEntry(val version: String, val items: Array<String>) + + private fun Node.forEachNode(action: (Node) -> Unit) { + children().forEach { + action(it as Node) + } + } + + fun read(inputUri: String): List<ChangelogEntry> { + val input = File(inputUri) + if (!input.exists()) { + fail("Could not generate changelog from ${input.absolutePath}") + } + + val parser = XmlParser().parse(inputUri) + + val entries: MutableList<ChangelogEntry> = mutableListOf() + var version: String? = null + val items: MutableList<String> = mutableListOf() + + fun addEntry() { + version?.also { v -> + entries.add(ChangelogEntry(v, items.toTypedArray())) + items.clear() + } + } + + parser.depthFirst().mapNotNull { it as? Node }.forEach { n -> + when (n.name()) { + "version" -> { + addEntry() + version = n.attribute("title")?.toString() ?: "" + } + "item" -> { + n.attribute("text")?.toString()?.takeIf(String::isNotBlank)?.let { + items.add(it) + } + } + } + } + addEntry() + return entries + } + + @JvmOverloads + fun generate(inputUri: String, outputUri: String = "${project.rootDir}/docs/Changelog.md"): List<ChangelogEntry> { + val entries = read(inputUri) + val output = File(outputUri) + if (output.exists()) { + if (output.isDirectory) { + fail("Cannot save changelog at directory ${output.absolutePath}") + } + if (output.isFile && !output.delete()) { + fail("Could not delete changelog at ${output.absolutePath}") + } + } else { + output.parentFile.mkdirs() + } + + if (!output.createNewFile()) { + fail("Could not create changelog file at ${output.absolutePath}") + } + val markdown = buildString { + append("# Changelog\n") + entries.forEach { e -> + append("\n## ${e.version}\n") + e.items.forEach { + append("* $it\n") + } + } + } + output.writeText(markdown) + println("Generated changelog at ${output.absolutePath}") + return entries + } +}
\ No newline at end of file diff --git a/buildSrc/src/main/kotlin/ca/allanwang/kau/Dependencies.kt b/buildSrc/src/main/kotlin/ca/allanwang/kau/Dependencies.kt new file mode 100644 index 0000000..9e23ac4 --- /dev/null +++ b/buildSrc/src/main/kotlin/ca/allanwang/kau/Dependencies.kt @@ -0,0 +1,14 @@ +package ca.allanwang.kau + +/** + * Some common dependencies, backed by the supplied versions + */ +open class Dependencies { + private val v = Versions() + val kotlin = "org.jetbrains.kotlin:kotlin-stdlib:${v.kotlin}" + val kotlinTest = "org.jetbrains.kotlin:kotlin-test-junit:${v.kotlin}" + val junit = "junit:junit:${v.junit}" + val espresso = "androidx.test.espresso:espresso-core:${v.espresso}" + val testRunner = "androidx.test.ext:junit:${v.testRunner}" + val testRules = "androidx.test:rules:${v.testRules}" +}
\ No newline at end of file diff --git a/buildSrc/src/main/kotlin/ca/allanwang/kau/KauPlugin.kt b/buildSrc/src/main/kotlin/ca/allanwang/kau/KauPlugin.kt new file mode 100644 index 0000000..6be15e5 --- /dev/null +++ b/buildSrc/src/main/kotlin/ca/allanwang/kau/KauPlugin.kt @@ -0,0 +1,17 @@ +package ca.allanwang.kau + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.create + +class KauPlugin : Plugin<Project> { + + override fun apply(project: Project) { + project.extensions.run { + create<Versions>("kau") + create<Dependencies>("kauDependency") + create<Plugins>("kauPlugin") + create<ChangelogGenerator>("kauChangelog", project) + } + } +}
\ No newline at end of file diff --git a/buildSrc/src/main/kotlin/ca/allanwang/kau/Plugins.kt b/buildSrc/src/main/kotlin/ca/allanwang/kau/Plugins.kt new file mode 100644 index 0000000..c8265ab --- /dev/null +++ b/buildSrc/src/main/kotlin/ca/allanwang/kau/Plugins.kt @@ -0,0 +1,16 @@ +package ca.allanwang.kau + +/** + * Some common buildscript plugins, backed by the supplied versions + */ +open class Plugins { + private val v = Versions() + val android = "com.android.tools.build:gradle:${v.gradlePlugin}" + val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${v.kotlin}" + val androidMaven = "com.github.dcendents:android-maven-gradle-plugin:${v.mavenPlugin}" + val playPublisher = "com.github.triplet.gradle:play-publisher:${v.playPublishPlugin}" + val dexCount = "com.getkeepsafe.dexcount:dexcount-gradle-plugin:${v.dexCountPlugin}" + val gitVersion = + "gradle.plugin.com.gladed.gradle.androidgitversion:gradle-android-git-version:${v.gitVersionPlugin}" + val spotless = "com.diffplug.spotless:spotless-plugin-gradle:${v.spotless}" +}
\ No newline at end of file diff --git a/buildSrc/src/main/kotlin/ca/allanwang/kau/Versions.kt b/buildSrc/src/main/kotlin/ca/allanwang/kau/Versions.kt new file mode 100644 index 0000000..8c14a92 --- /dev/null +++ b/buildSrc/src/main/kotlin/ca/allanwang/kau/Versions.kt @@ -0,0 +1,80 @@ +package ca.allanwang.kau + +open class Versions { + val coreMinSdk = 19 + val minSdk = 21 + val targetSdk = 28 + + // https://developer.android.com/studio/releases/build-tools + val buildTools = "28.0.3" + + // https://mvnrepository.com/artifact/androidx.appcompat/appcompat?repo=google + val appcompat = "1.0.2" + + // https://mvnrepository.com/artifact/com.google.android.material/material + val googleMaterial = "1.0.0" + + // https://mvnrepository.com/artifact/androidx.recyclerview/recyclerview + val recyclerView = "1.0.0" + + // https://mvnrepository.com/artifact/androidx.cardview/cardview + val cardView = "1.0.0" + + // https://mvnrepository.com/artifact/androidx.constraintlayout/constraintlayout + val constraintLayout = "1.1.3" + + // https://kotlinlang.org/docs/reference/using-gradle.html + val kotlin = "1.3.31" + + // https://github.com/Kotlin/kotlinx.coroutines/releases + val coroutines = "1.2.1" + + // https://github.com/mikepenz/AboutLibraries/releases + val aboutLibraries = "6.2.3" + + // https://github.com/wasabeef/Blurry/releases + val blurry = "3.0.0" + + // https://github.com/mikepenz/FastAdapter#using-maven + val fastAdapter = "3.3.1" + val fastAdapterCommons = fastAdapter + + // https://github.com/bumptech/glide/releases + val glide = "4.9.0" + + // https://github.com/mikepenz/Android-Iconics#1-provide-the-gradle-dependency + val iconics = "3.2.5" + val iconicsGoogle = "3.0.1.3" + val iconicsMaterial = "2.2.0.5" + val iconicsCommunity = "3.5.95.1" + + // https://github.com/afollestad/material-dialogs/releases + val materialDialog = "3.0.0-rc2" + + // https://mvnrepository.com/artifact/androidx.test.espresso/espresso-core?repo=google + val espresso = "3.1.1" + + // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api + val junit = "4.12" + + val testRunner = "1.1.0" + + // https://mvnrepository.com/artifact/androidx.test/rules?repo=google + val testRules = "1.1.1" + + // https://github.com/diffplug/spotless/blob/master/plugin-gradle/CHANGES.md + val spotless = "3.18.0" + + // https://mvnrepository.com/artifact/com.android.tools.build/gradle?repo=google + val gradlePlugin = "3.4.1" + // https://github.com/dcendents/android-maven-gradle-plugin/releases + val mavenPlugin = "2.1" + // https://github.com/Triple-T/gradle-play-publisher/releases + val playPublishPlugin = "2.1.0" + + // https://github.com/KeepSafe/dexcount-gradle-plugin/releases + val dexCountPlugin = "0.8.6" + + // https://github.com/gladed/gradle-android-git-version/releases + val gitVersionPlugin = "0.4.7" +}
\ No newline at end of file diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/ca.allanwang.kau.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/ca.allanwang.kau.properties deleted file mode 100644 index ba824cd..0000000 --- a/buildSrc/src/main/resources/META-INF/gradle-plugins/ca.allanwang.kau.properties +++ /dev/null @@ -1 +0,0 @@ -implementation-class=ca.allanwang.kau.KauPlugin
\ No newline at end of file diff --git a/colorpicker/README.md b/colorpicker/README.md index c90809e..16977a9 100644 --- a/colorpicker/README.md +++ b/colorpicker/README.md @@ -1,10 +1,9 @@ # KAU :colorpicker -Material Dialogs by default contains a color picker, but it requires an activity that also implements the color callback. -KAU's colorpicker decouples the two, so it only needs a context and a separate callback. -The color picker also animates the selection, and uses Kotlin's DSL to provide easy calling. +As of Material Dialog 2.x, `:colorpicker` is effectively a very thin wrapper around [Material Dialog's color picker](https://github.com/afollestad/material-dialogs/blob/master/documentation/COLOR.md). +The main difference is that it exposes an interface internal to KAU, which allows a greater level of consistency within other submodules. +It also contains an extra palette for accent colors. -To use it, call `Context.colorPickerDialog` and specify and configs as required through the builder. +To use it, call `MaterialDialog.kauColorChooser` and specify the configs. ![Color Picker Gif](https://raw.githubusercontent.com/AllanWang/Storage-Hub/master/kau/kau_color_picker.gif) -![Color Picker Custom Gif](https://raw.githubusercontent.com/AllanWang/Storage-Hub/master/kau/kau_color_picker_custom.gif)
\ No newline at end of file diff --git a/colorpicker/build.gradle b/colorpicker/build.gradle index 9b52cd4..4b89e10 100644 --- a/colorpicker/build.gradle +++ b/colorpicker/build.gradle @@ -7,7 +7,7 @@ apply from: '../android-lib.gradle' dependencies { implementation project(':core') - implementation "com.afollestad.material-dialogs:commons:${kau.materialDialog}" + implementation "com.afollestad.material-dialogs:color:${kau.materialDialog}" } apply from: '../artifacts.gradle' 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 310fd53..e748677 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.support.annotation.ColorInt -import android.support.annotation.ColorRes -import android.support.annotation.FloatRange -import android.support.v4.view.GravityCompat -import android.support.v4.view.ViewCompat 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 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 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..113020c 100644 --- a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPalette.kt +++ b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPalette.kt @@ -1,37 +1,56 @@ +/* + * 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 /** * @author Aidan Follestad (afollestad) + * + * Modified by Allan Wang */ 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<IntArray> by lazy { - arrayOf(colorArrayOf( + arrayOf( + colorArrayOf( "#FFEBEE", "#FFCDD2", "#EF9A9A", @@ -42,7 +61,7 @@ internal object ColorPalette { "#D32F2F", "#C62828", "#B71C1C" - ), colorArrayOf( + ), colorArrayOf( "#FCE4EC", "#F8BBD0", "#F48FB1", @@ -53,7 +72,7 @@ internal object ColorPalette { "#C2185B", "#AD1457", "#880E4F" - ), colorArrayOf( + ), colorArrayOf( "#F3E5F5", "#E1BEE7", "#CE93D8", @@ -64,7 +83,7 @@ internal object ColorPalette { "#7B1FA2", "#6A1B9A", "#4A148C" - ), colorArrayOf( + ), colorArrayOf( "#EDE7F6", "#D1C4E9", "#B39DDB", @@ -75,7 +94,7 @@ internal object ColorPalette { "#512DA8", "#4527A0", "#311B92" - ), colorArrayOf( + ), colorArrayOf( "#E8EAF6", "#C5CAE9", "#9FA8DA", @@ -86,7 +105,7 @@ internal object ColorPalette { "#303F9F", "#283593", "#1A237E" - ), colorArrayOf( + ), colorArrayOf( "#E3F2FD", "#BBDEFB", "#90CAF9", @@ -97,7 +116,7 @@ internal object ColorPalette { "#1976D2", "#1565C0", "#0D47A1" - ), colorArrayOf( + ), colorArrayOf( "#E1F5FE", "#B3E5FC", "#81D4FA", @@ -108,7 +127,7 @@ internal object ColorPalette { "#0288D1", "#0277BD", "#01579B" - ), colorArrayOf( + ), colorArrayOf( "#E0F7FA", "#B2EBF2", "#80DEEA", @@ -119,7 +138,7 @@ internal object ColorPalette { "#0097A7", "#00838F", "#006064" - ), colorArrayOf( + ), colorArrayOf( "#E0F2F1", "#B2DFDB", "#80CBC4", @@ -130,7 +149,7 @@ internal object ColorPalette { "#00796B", "#00695C", "#004D40" - ), colorArrayOf( + ), colorArrayOf( "#E8F5E9", "#C8E6C9", "#A5D6A7", @@ -141,7 +160,7 @@ internal object ColorPalette { "#388E3C", "#2E7D32", "#1B5E20" - ), colorArrayOf( + ), colorArrayOf( "#F1F8E9", "#DCEDC8", "#C5E1A5", @@ -152,7 +171,7 @@ internal object ColorPalette { "#689F38", "#558B2F", "#33691E" - ), colorArrayOf( + ), colorArrayOf( "#F9FBE7", "#F0F4C3", "#E6EE9C", @@ -163,7 +182,7 @@ internal object ColorPalette { "#AFB42B", "#9E9D24", "#827717" - ), colorArrayOf( + ), colorArrayOf( "#FFFDE7", "#FFF9C4", "#FFF59D", @@ -174,7 +193,7 @@ internal object ColorPalette { "#FBC02D", "#F9A825", "#F57F17" - ), colorArrayOf( + ), colorArrayOf( "#FFF8E1", "#FFECB3", "#FFE082", @@ -185,7 +204,7 @@ internal object ColorPalette { "#FFA000", "#FF8F00", "#FF6F00" - ), colorArrayOf( + ), colorArrayOf( "#FFF3E0", "#FFE0B2", "#FFCC80", @@ -196,7 +215,7 @@ internal object ColorPalette { "#F57C00", "#EF6C00", "#E65100" - ), colorArrayOf( + ), colorArrayOf( "#FBE9E7", "#FFCCBC", "#FFAB91", @@ -207,7 +226,7 @@ internal object ColorPalette { "#E64A19", "#D84315", "#BF360C" - ), colorArrayOf( + ), colorArrayOf( "#EFEBE9", "#D7CCC8", "#BCAAA4", @@ -218,7 +237,7 @@ internal object ColorPalette { "#5D4037", "#4E342E", "#3E2723" - ), colorArrayOf( + ), colorArrayOf( "#FAFAFA", "#F5F5F5", "#EEEEEE", @@ -229,7 +248,7 @@ internal object ColorPalette { "#616161", "#424242", "#212121" - ), colorArrayOf( + ), colorArrayOf( "#ECEFF1", "#CFD8DC", "#B0BEC5", @@ -239,111 +258,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<IntArray> 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 b264e58..02a1fff 100644 --- a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerDialog.kt +++ b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerDialog.kt @@ -1,89 +1,66 @@ +/* + * 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 +import android.annotation.SuppressLint import android.graphics.Color -import android.support.annotation.DimenRes -import android.support.annotation.StringRes -import ca.allanwang.kau.utils.INVALID_ID -import ca.allanwang.kau.utils.string +import androidx.annotation.ColorInt import com.afollestad.materialdialogs.MaterialDialog -import com.afollestad.materialdialogs.Theme +import com.afollestad.materialdialogs.color.ColorCallback +import com.afollestad.materialdialogs.color.colorChooser + +sealed class ColorOptions(val colors: IntArray, val subColors: Array<IntArray>?) + +object PrimaryColors : ColorOptions(ColorPalette.PRIMARY_COLORS, ColorPalette.PRIMARY_COLORS_SUB) +object AccentColors : ColorOptions(ColorPalette.ACCENT_COLORS, ColorPalette.ACCENT_COLORS_SUB) +class CustomColors(colors: IntArray, subColors: Array<IntArray>? = null) : ColorOptions(colors, subColors) class ColorBuilder : ColorContract { - override var title: String? = null - override var titleRes: Int = INVALID_ID + override var colors: ColorOptions = PrimaryColors override var allowCustom: Boolean = true override var allowCustomAlpha: Boolean = false - override var isAccent: Boolean = false override var defaultColor: Int = Color.BLACK - override var doneText: Int = R.string.kau_done - override var backText: Int = R.string.kau_back - override var cancelText: Int = R.string.kau_cancel - override var presetText: Int = R.string.kau_md_presets - override var customText: Int = R.string.kau_custom - get() = if (allowCustom) field else 0 - override var dynamicButtonColors: Boolean = true - override var circleSizeRes: Int = R.dimen.kau_color_circle_size - override var colorCallback: ((selectedColor: Int) -> Unit)? = null - override var colorsTop: IntArray? = null - override var colorsSub: Array<IntArray>? = null - override var theme: Theme? = null + override var callback: ColorCallback = null } interface ColorContract { - var title: String? - @setparam:StringRes - var titleRes: Int + var colors: ColorOptions var allowCustom: Boolean var allowCustomAlpha: Boolean - var isAccent: Boolean - @setparam:StringRes + @setparam:ColorInt var defaultColor: Int - @setparam:StringRes - var doneText: Int - @setparam:StringRes - var backText: Int - @setparam:StringRes - var cancelText: Int - @setparam:StringRes - var presetText: Int - @setparam:StringRes - var customText: Int - var dynamicButtonColors: Boolean - @setparam:DimenRes - var circleSizeRes: Int - var colorCallback: ((selectedColor: Int) -> Unit)? - var colorsTop: IntArray? - var colorsSub: Array<IntArray>? - var theme: Theme? + var callback: ColorCallback } +@SuppressLint("CheckResult") +fun MaterialDialog.kauColorChooser(action: ColorContract.() -> Unit) = + kauColorChooser(ColorBuilder().apply(action)) + /** - * This is the extension that allows us to initialize the dialog - * Note that this returns just the dialog; you still need to call .show() to show it + * Thin wrapper that exposes color chooser options as [ColorContract] */ -fun Context.colorPickerDialog(action: ColorContract.() -> Unit): MaterialDialog { - val b = ColorBuilder() - b.action() - return colorPickerDialog(b) -} - -fun Context.colorPickerDialog(contract: ColorContract): MaterialDialog { - val view = ColorPickerView(this) - val dialog = with(MaterialDialog.Builder(this)) { - title(string(contract.titleRes, contract.title) ?: string(R.string.kau_md_color_palette)) - customView(view, false) - autoDismiss(false) - positiveText(contract.doneText) - negativeText(contract.cancelText) - if (contract.allowCustom) neutralText(contract.presetText) - onPositive { dialog, _ -> contract.colorCallback?.invoke(view.selectedColor); dialog.dismiss() } - onNegative { _, _ -> view.backOrCancel() } - if (contract.allowCustom) onNeutral { _, _ -> view.toggleCustom() } - showListener { view.refreshColors() } - if (contract.theme != null) theme(contract.theme!!) - build() - } - view.bind(contract, dialog) - return dialog +@SuppressLint("CheckResult") +fun MaterialDialog.kauColorChooser(c: ColorContract) { + colorChooser( + colors = c.colors.colors, + subColors = c.colors.subColors, + initialSelection = c.defaultColor, + allowCustomArgb = c.allowCustom, + showAlphaSelector = c.allowCustomAlpha, + selection = c.callback + ) + positiveButton(R.string.kau_done) }
\ 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 deleted file mode 100644 index b9cea99..0000000 --- a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerView.kt +++ /dev/null @@ -1,319 +0,0 @@ -package ca.allanwang.kau.colorpicker - -import android.annotation.SuppressLint -import android.content.Context -import android.graphics.Color -import android.support.annotation.ColorInt -import android.support.v4.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 com.afollestad.materialdialogs.DialogAction -import com.afollestad.materialdialogs.MaterialDialog -import com.afollestad.materialdialogs.color.FillGridView -import java.util.* - -/** - * Created by Allan Wang on 2017-06-08. - * - * ColorPicker component of the ColorPickerDialog - */ -internal class ColorPickerView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : ScrollView(context, attrs, defStyleAttr) { - val selectedColor: Int - get() = _selectedColor - private var _selectedColor: Int = -1 - private var isInSub: Boolean = false - 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 backgroundColorTint = backgroundColor.colorToForeground() - private lateinit var dialog: MaterialDialog - private lateinit var builder: ColorContract - private lateinit var colorsTop: IntArray - private var colorsSub: Array<IntArray>? = null - private var topIndex: Int = -1 - private var subIndex: Int = -1 - private var colorIndex: Int - get() = if (isInSub) subIndex else topIndex - set(value) { - if (isInSub) subIndex = value - else { - topIndex = value - if (colorsSub != null && colorsSub!!.size > value) { - dialog.setActionButton(DialogAction.NEGATIVE, builder.backText) - isInSub = true - invalidateGrid() - } - } - } - - private val gridView: FillGridView - private val customFrame: LinearLayout - private val customColorIndicator: View - private val hexInput: EditText - private val alphaLabel: TextView - private val alphaSeekbar: SeekBar - private val alphaValue: TextView - private val redSeekbar: SeekBar - private val redValue: TextView - private val greenSeekbar: SeekBar - private val greenValue: TextView - private val blueSeekbar: SeekBar - private val blueValue: TextView - - private var customHexTextWatcher: TextWatcher? = null - private var customRgbListener: SeekBar.OnSeekBarChangeListener? = null - - init { - //noinspection PrivateResource - View.inflate(context, R.layout.md_dialog_colorchooser, this) - gridView = findViewById(R.id.md_grid) - customFrame = findViewById(R.id.md_colorChooserCustomFrame) - customColorIndicator = findViewById(R.id.md_colorIndicator) - hexInput = findViewById(R.id.md_hexInput) - alphaLabel = findViewById(R.id.md_colorALabel) - alphaSeekbar = findViewById(R.id.md_colorA) - alphaValue = findViewById(R.id.md_colorAValue) - redSeekbar = findViewById(R.id.md_colorR) - redValue = findViewById(R.id.md_colorRValue) - greenSeekbar = findViewById(R.id.md_colorG) - greenValue = findViewById(R.id.md_colorGValue) - blueSeekbar = findViewById(R.id.md_colorB) - blueValue = findViewById(R.id.md_colorBValue) - } - - fun bind(builder: ColorContract, dialog: MaterialDialog) { - this.builder = builder - this.dialog = dialog - this.colorsTop = with(builder) { - when { - colorsTop != null -> colorsTop!! - isAccent -> ColorPalette.ACCENT_COLORS - else -> ColorPalette.PRIMARY_COLORS - } - } - this.colorsSub = with(builder) { - when { - colorsTop != null -> colorsSub - isAccent -> ColorPalette.ACCENT_COLORS_SUB - else -> ColorPalette.PRIMARY_COLORS_SUB - } - } - this._selectedColor = builder.defaultColor - if (builder.allowCustom) { - if (!builder.allowCustomAlpha) { - alphaLabel.gone() - alphaSeekbar.gone() - alphaValue.gone() - hexInput.hint = String.format("%06X", _selectedColor) - hexInput.filters = arrayOf(InputFilter.LengthFilter(6)) - } else { - hexInput.hint = String.format("%08X", _selectedColor) - hexInput.filters = arrayOf(InputFilter.LengthFilter(8)) - } - } - if (findColor(_selectedColor) || !builder.allowCustom) isInCustom = true // when toggled this will be false - toggleCustom() - } - - fun backOrCancel() { - if (isInSub) { - dialog.setActionButton(DialogAction.NEGATIVE, builder.cancelText) - //to top - isInSub = false - subIndex = -1 - invalidateGrid() - } else { - dialog.cancel() - } - } - - fun toggleCustom() { - isInCustom = !isInCustom - if (isInCustom) { - isInSub = false - if (builder.allowCustom) dialog.setActionButton(DialogAction.NEUTRAL, builder.presetText) - dialog.setActionButton(DialogAction.NEGATIVE, builder.cancelText) - customHexTextWatcher = object : TextWatcher { - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} - - override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { - _selectedColor = try { - Color.parseColor("#$s") - } catch (e: IllegalArgumentException) { - Color.BLACK - } - customColorIndicator.setBackgroundColor(_selectedColor) - if (alphaSeekbar.isVisible) { - val alpha = Color.alpha(_selectedColor) - alphaSeekbar.progress = alpha - alphaValue.text = String.format(Locale.CANADA, "%d", alpha) - } - redSeekbar.progress = Color.red(_selectedColor) - greenSeekbar.progress = Color.green(_selectedColor) - blueSeekbar.progress = Color.blue(_selectedColor) - isInSub = false - topIndex = -1 - subIndex = -1 - refreshColors() - } - - override fun afterTextChanged(s: Editable?) {} - } - hexInput.setText(_selectedColor.toHexString(builder.allowCustomAlpha, false)) - hexInput.addTextChangedListener(customHexTextWatcher) - customRgbListener = object : SeekBar.OnSeekBarChangeListener { - 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, - greenSeekbar.progress, - blueSeekbar.progress) - - hexInput.setText(color.toHexString(builder.allowCustomAlpha, false)) - } - if (builder.allowCustomAlpha) alphaValue.text = alphaSeekbar.progress.toString() - redValue.text = redSeekbar.progress.toString() - greenValue.text = greenSeekbar.progress.toString() - blueValue.text = blueSeekbar.progress.toString() - } - - override fun onStartTrackingTouch(seekBar: SeekBar) = Unit - - override fun onStopTrackingTouch(seekBar: SeekBar) = Unit - } - redSeekbar.setOnSeekBarChangeListener(customRgbListener) - greenSeekbar.setOnSeekBarChangeListener(customRgbListener) - blueSeekbar.setOnSeekBarChangeListener(customRgbListener) - if (alphaSeekbar.isVisible) - alphaSeekbar.setOnSeekBarChangeListener(customRgbListener) - hexInput.setText(_selectedColor.toHexString(alphaSeekbar.isVisible, false)) - gridView.fadeOut(onFinish = { gridView.gone() }) - customFrame.fadeIn() - } else { - findColor(_selectedColor) - if (builder.allowCustom) dialog.setActionButton(DialogAction.NEUTRAL, builder.customText) - dialog.setActionButton(DialogAction.NEGATIVE, if (isInSub) builder.backText else builder.cancelText) - gridView.fadeIn(onStart = this::invalidateGrid) - customFrame.fadeOut(onFinish = { customFrame.gone() }) - hexInput.removeTextChangedListener(customHexTextWatcher) - customHexTextWatcher = null - alphaSeekbar.setOnSeekBarChangeListener(null) - redSeekbar.setOnSeekBarChangeListener(null) - greenSeekbar.setOnSeekBarChangeListener(null) - blueSeekbar.setOnSeekBarChangeListener(null) - customRgbListener = null - } - } - - fun refreshColors() { - if (!isInCustom) findColor(_selectedColor) - // Ensure that our tinted color is still visible against the background - val visibleColor = if (_selectedColor.isColorVisibleOn(backgroundColor)) _selectedColor else backgroundColorTint - if (builder.dynamicButtonColors) { - dialog.getActionButton(DialogAction.POSITIVE).setTextColor(visibleColor) - dialog.getActionButton(DialogAction.NEGATIVE).setTextColor(visibleColor) - dialog.getActionButton(DialogAction.NEUTRAL).setTextColor(visibleColor) - } - if (!builder.allowCustom || !isInCustom) return - if (builder.allowCustomAlpha) - alphaSeekbar.visible().tint(visibleColor) - redSeekbar.tint(visibleColor) - greenSeekbar.tint(visibleColor) - blueSeekbar.tint(visibleColor) - hexInput.tint(visibleColor) - } - - private fun findColor(@ColorInt color: Int): Boolean { - topIndex = -1 - subIndex = -1 - colorsTop.forEachIndexed { index, topColor -> - // First check for sub colors, then if the top color matches - if (findSubColor(color, index) || topColor == color) { - topIndex = index - return true - } - } - return false - } - - private fun findSubColor(@ColorInt color: Int, topIndex: Int): Boolean { - subIndex = colorsSub?.getOrNull(topIndex)?.indexOfFirst { color == it } ?: -1 - return subIndex != -1 - } - - private fun invalidateGrid() { - if (gridView.adapter == null) { - gridView.adapter = ColorGridAdapter() - gridView.selector = ResourcesCompat.getDrawable(resources, R.drawable.kau_transparent, null) - } else { - (gridView.adapter as BaseAdapter).notifyDataSetChanged() - } - } - - inner class ColorGridAdapter : BaseAdapter(), OnClickListener, OnLongClickListener { - override fun onClick(v: View) { - val (pos, color) = v.tagData ?: return - if (colorIndex == pos && isInSub) - return - circleAt(colorIndex)?.animateSelected(false) - _selectedColor = color - colorIndex = pos - refreshColors() - if (isInSub) - circleAt(colorIndex)?.animateSelected(true) - // Otherwise we are invalidating our grid, so there is no point in animating - } - - private fun circleAt(index: Int): CircleView? = - if (index == -1) null - else gridView.getChildAt(index) as? CircleView - - private val View.tagData: Pair<Int, Int>? - get() { - val tags = (tag as? String)?.split(":") ?: return null - val pos = tags[0].toIntOrNull() ?: return null - val color = tags[1].toIntOrNull() ?: return null - return pos to color - } - - override fun onLongClick(v: View): Boolean { - val (_, color) = v.tagData ?: return false - (v as? CircleView)?.showHint(color) ?: return false - return true - } - - override fun getItem(position: Int): Int = if (isInSub) colorsSub!![topIndex][position] else colorsTop[position] - - override fun getCount(): Int = if (isInSub) colorsSub!![topIndex].size else colorsTop.size - - override fun getItemId(position: Int): Long = position.toLong() - - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - val view: CircleView = convertView as? CircleView ?: CircleView(context).apply { - layoutParams = AbsListView.LayoutParams(circleSize, circleSize) - setOnClickListener(this@ColorGridAdapter) - setOnLongClickListener(this@ColorGridAdapter) - } - val color: Int = getItem(position) - return view.apply { - setBackgroundColor(color) - isSelected = colorIndex == position - tag = "$position:$color" - } - } - } -}
\ No newline at end of file diff --git a/colorpicker/src/main/res/values-da-rDK/strings_colorpicker.xml b/colorpicker/src/main/res/values-da-rDK/strings_colorpicker.xml deleted file mode 100644 index a5f7487..0000000 --- a/colorpicker/src/main/res/values-da-rDK/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Farvepalette</string> - <string name="kau_md_presets">Forhåndsvalg</string> -</resources> diff --git a/colorpicker/src/main/res/values-de-rDE/strings_colorpicker.xml b/colorpicker/src/main/res/values-de-rDE/strings_colorpicker.xml deleted file mode 100644 index 5dd7b38..0000000 --- a/colorpicker/src/main/res/values-de-rDE/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Farbpalette</string> - <string name="kau_md_presets">Vorlagen</string> -</resources> diff --git a/colorpicker/src/main/res/values-es-rES/strings_colorpicker.xml b/colorpicker/src/main/res/values-es-rES/strings_colorpicker.xml deleted file mode 100644 index 56148fd..0000000 --- a/colorpicker/src/main/res/values-es-rES/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Paleta de colores</string> - <string name="kau_md_presets">Ajustes preestablecidos</string> -</resources> diff --git a/colorpicker/src/main/res/values-fr-rFR/strings_colorpicker.xml b/colorpicker/src/main/res/values-fr-rFR/strings_colorpicker.xml deleted file mode 100644 index a044e6e..0000000 --- a/colorpicker/src/main/res/values-fr-rFR/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Palette de couleurs</string> - <string name="kau_md_presets">Réglages prédéfinis</string> -</resources> diff --git a/colorpicker/src/main/res/values-gl-rES/strings_colorpicker.xml b/colorpicker/src/main/res/values-gl-rES/strings_colorpicker.xml deleted file mode 100644 index fbc1d90..0000000 --- a/colorpicker/src/main/res/values-gl-rES/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Paleta de cores</string> - <string name="kau_md_presets">Axustes predefinidos</string> -</resources> diff --git a/colorpicker/src/main/res/values-hu-rHU/strings_colorpicker.xml b/colorpicker/src/main/res/values-hu-rHU/strings_colorpicker.xml deleted file mode 100644 index 42f3700..0000000 --- a/colorpicker/src/main/res/values-hu-rHU/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Színpaletta</string> - <string name="kau_md_presets">Sablonok</string> -</resources> diff --git a/colorpicker/src/main/res/values-in-rID/strings_colorpicker.xml b/colorpicker/src/main/res/values-in-rID/strings_colorpicker.xml deleted file mode 100644 index 52e59bc..0000000 --- a/colorpicker/src/main/res/values-in-rID/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Palet warna</string> - <string name="kau_md_presets">Preset</string> -</resources> diff --git a/colorpicker/src/main/res/values-it-rIT/strings_colorpicker.xml b/colorpicker/src/main/res/values-it-rIT/strings_colorpicker.xml deleted file mode 100644 index 4f3e282..0000000 --- a/colorpicker/src/main/res/values-it-rIT/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Tavolozza dei colori</string> - <string name="kau_md_presets">Preimpostazioni</string> -</resources> diff --git a/colorpicker/src/main/res/values-ko-rKR/strings_colorpicker.xml b/colorpicker/src/main/res/values-ko-rKR/strings_colorpicker.xml deleted file mode 100644 index 7c65db1..0000000 --- a/colorpicker/src/main/res/values-ko-rKR/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">색상 팔레트</string> - <string name="kau_md_presets">사전 설정</string> -</resources> diff --git a/colorpicker/src/main/res/values-no-rNO/strings_colorpicker.xml b/colorpicker/src/main/res/values-no-rNO/strings_colorpicker.xml deleted file mode 100644 index d79a6d8..0000000 --- a/colorpicker/src/main/res/values-no-rNO/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Fargepalett</string> - <string name="kau_md_presets">Forhåndsinnstillinger</string> -</resources> diff --git a/colorpicker/src/main/res/values-pl-rPL/strings_colorpicker.xml b/colorpicker/src/main/res/values-pl-rPL/strings_colorpicker.xml deleted file mode 100644 index 42cb6e0..0000000 --- a/colorpicker/src/main/res/values-pl-rPL/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Paleta kolorów</string> - <string name="kau_md_presets">Zdefiniowane</string> -</resources> diff --git a/colorpicker/src/main/res/values-pt-rBR/strings_colorpicker.xml b/colorpicker/src/main/res/values-pt-rBR/strings_colorpicker.xml deleted file mode 100644 index 0694ed4..0000000 --- a/colorpicker/src/main/res/values-pt-rBR/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Paleta de Cores</string> - <string name="kau_md_presets">Predefinições</string> -</resources> diff --git a/colorpicker/src/main/res/values-sv-rSE/strings_colorpicker.xml b/colorpicker/src/main/res/values-sv-rSE/strings_colorpicker.xml deleted file mode 100644 index 6b06ba9..0000000 --- a/colorpicker/src/main/res/values-sv-rSE/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Färgpalett</string> - <string name="kau_md_presets">Förval</string> -</resources> diff --git a/colorpicker/src/main/res/values-th-rTH/strings_colorpicker.xml b/colorpicker/src/main/res/values-th-rTH/strings_colorpicker.xml deleted file mode 100644 index 7fdf610..0000000 --- a/colorpicker/src/main/res/values-th-rTH/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">ชุดสี</string> - <string name="kau_md_presets">ค่าที่ตั้งไว้</string> -</resources> diff --git a/colorpicker/src/main/res/values-tr-rTR/strings_colorpicker.xml b/colorpicker/src/main/res/values-tr-rTR/strings_colorpicker.xml deleted file mode 100644 index eddc8ad..0000000 --- a/colorpicker/src/main/res/values-tr-rTR/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Renk paleti</string> - <string name="kau_md_presets">Hazır ayarlar</string> -</resources> diff --git a/colorpicker/src/main/res/values-uk-rUA/strings_colorpicker.xml b/colorpicker/src/main/res/values-uk-rUA/strings_colorpicker.xml deleted file mode 100644 index d114ba5..0000000 --- a/colorpicker/src/main/res/values-uk-rUA/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Кольорова палітра</string> - <string name="kau_md_presets">Пресети</string> -</resources> diff --git a/colorpicker/src/main/res/values-vi-rVN/strings_colorpicker.xml b/colorpicker/src/main/res/values-vi-rVN/strings_colorpicker.xml deleted file mode 100644 index f14a044..0000000 --- a/colorpicker/src/main/res/values-vi-rVN/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Bảng màu</string> - <string name="kau_md_presets">Cài đặt sẵn</string> -</resources> diff --git a/colorpicker/src/main/res/values-zh-rCN/strings_colorpicker.xml b/colorpicker/src/main/res/values-zh-rCN/strings_colorpicker.xml deleted file mode 100644 index 9b117f5..0000000 --- a/colorpicker/src/main/res/values-zh-rCN/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">调色板</string> - <string name="kau_md_presets">预设</string> -</resources> diff --git a/colorpicker/src/main/res/values/dimens.xml b/colorpicker/src/main/res/values/dimens.xml deleted file mode 100644 index 193940e..0000000 --- a/colorpicker/src/main/res/values/dimens.xml +++ /dev/null @@ -1,3 +0,0 @@ -<resources> - <dimen name="kau_color_circle_size">56dp</dimen> -</resources> diff --git a/colorpicker/src/main/res/values/strings_colorpicker.xml b/colorpicker/src/main/res/values/strings_colorpicker.xml deleted file mode 100644 index a470390..0000000 --- a/colorpicker/src/main/res/values/strings_colorpicker.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName"> - <string name="kau_md_color_palette">Color Palette</string> - <string name="kau_md_presets">Presets</string> -</resources> 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 3951970..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,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.ui.activities import android.os.Build import android.os.Bundle -import android.support.annotation.RequiresApi -import android.support.v7.widget.RecyclerView -import android.support.v7.widget.Toolbar import android.transition.TransitionInflater +import androidx.annotation.RequiresApi +import androidx.appcompat.widget.Toolbar +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.internal.KauBaseActivity import ca.allanwang.kau.ui.R import ca.allanwang.kau.ui.widgets.ElasticDragDismissFrameLayout @@ -16,7 +31,7 @@ import kotlinx.android.synthetic.main.kau_elastic_recycler_activity.* * * A generic activity comprised of an ElasticDragDismissFrameLayout, CoordinatorLayout, Toolbar, RecyclerView, and Fab * [ca.allanwang.kau.ui.widgets.ElasticDragDismissFrameLayout] - * [android.support.v7.widget.RecyclerView] + * [androidx.recyclerview.widget.RecyclerView] * * The recyclerview defaults to a linearlayoutmanager, and the adapter is automatically bounded * @@ -39,10 +54,11 @@ abstract class ElasticRecyclerActivity : KauBaseActivity() { setContentView(R.layout.kau_elastic_recycler_activity) setSupportActionBar(kau_toolbar) if (!onCreate(savedInstanceState, configs)) return + 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() } @@ -63,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 5fc3e06..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,13 +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.content.Context import android.graphics.Rect -import android.support.v7.widget.CardView import android.util.AttributeSet +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 f6f7864..474d40a 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 <a href="https://github.com/nickbutcher/plaid">Plaid</a> */ 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 5db5eaa..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 android.support.v7.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 f357f79..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 android.support.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/InkPageIndicator.java b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/InkPageIndicator.java index a963556..13381aa 100644 --- a/core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/InkPageIndicator.java +++ b/core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/InkPageIndicator.java @@ -27,14 +27,14 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; -import android.support.annotation.ColorInt; -import android.support.v4.view.ViewPager; +import androidx.annotation.ColorInt; import android.util.AttributeSet; import android.view.View; import android.view.animation.Interpolator; import java.util.Arrays; +import androidx.viewpager.widget.ViewPager; import ca.allanwang.kau.ui.R; import ca.allanwang.kau.utils.AnimHolder; import ca.allanwang.kau.utils.ColorUtilsKt; 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 bcd930f..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 android.support.v4.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<CharSequence?> = 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-ui/src/main/res-public/layout/kau_elastic_recycler_activity.xml b/core-ui/src/main/res-public/layout/kau_elastic_recycler_activity.xml index 9fbe447..5fc151c 100644 --- a/core-ui/src/main/res-public/layout/kau_elastic_recycler_activity.xml +++ b/core-ui/src/main/res-public/layout/kau_elastic_recycler_activity.xml @@ -7,7 +7,7 @@ app:dragDismissDistance="@dimen/kau_drag_dismiss_distance_large" app:dragDismissScale="0.95"> - <android.support.design.widget.CoordinatorLayout + <androidx.coordinatorlayout.widget.CoordinatorLayout android:id="@+id/kau_coordinator" android:layout_width="match_parent" android:layout_height="match_parent" @@ -15,27 +15,27 @@ android:background="?android:colorBackground" android:orientation="vertical"> - <android.support.design.widget.AppBarLayout + <com.google.android.material.appbar.AppBarLayout android:id="@+id/kau_appbar" android:layout_width="match_parent" android:layout_height="wrap_content"> - <android.support.v7.widget.Toolbar + <androidx.appcompat.widget.Toolbar android:id="@+id/kau_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> - </android.support.design.widget.AppBarLayout> + </com.google.android.material.appbar.AppBarLayout> - <android.support.v7.widget.RecyclerView + <androidx.recyclerview.widget.RecyclerView android:id="@+id/kau_recycler" android:layout_width="match_parent" android:layout_height="match_parent" - app:layoutManager="android.support.v7.widget.LinearLayoutManager" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> - <android.support.design.widget.FloatingActionButton + <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/kau_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -47,6 +47,6 @@ app:layout_anchor="@id/kau_recycler" app:layout_anchorGravity="bottom|right|end" /> - </android.support.design.widget.CoordinatorLayout> + </androidx.coordinatorlayout.widget.CoordinatorLayout> </ca.allanwang.kau.ui.widgets.ElasticDragDismissFrameLayout>
\ No newline at end of file diff --git a/core-ui/src/main/res-public/layout/kau_recycler_detached_background.xml b/core-ui/src/main/res-public/layout/kau_recycler_detached_background.xml index 7295d66..2273a20 100644 --- a/core-ui/src/main/res-public/layout/kau_recycler_detached_background.xml +++ b/core-ui/src/main/res-public/layout/kau_recycler_detached_background.xml @@ -15,13 +15,13 @@ <!--defaults to a LinearLayoutManager--> - <android.support.v7.widget.RecyclerView + <androidx.recyclerview.widget.RecyclerView android:id="@+id/kau_recycler_detached" android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="false" android:paddingBottom="@dimen/kau_spacing_normal" android:scrollbars="vertical" - app:layoutManager="android.support.v7.widget.LinearLayoutManager" /> + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" /> </FrameLayout> diff --git a/core-ui/src/main/res-public/layout/kau_recycler_textslider.xml b/core-ui/src/main/res-public/layout/kau_recycler_textslider.xml index eacd5be..d048627 100644 --- a/core-ui/src/main/res-public/layout/kau_recycler_textslider.xml +++ b/core-ui/src/main/res-public/layout/kau_recycler_textslider.xml @@ -1,11 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/kau_container" android:layout_width="match_parent" android:layout_height="match_parent"> - <android.support.v7.widget.Toolbar + <androidx.appcompat.widget.Toolbar android:id="@+id/kau_toolbar" android:layout_width="0dp" android:layout_height="?attr/actionBarSize" @@ -20,9 +20,9 @@ android:gravity="center" app:animation_type="slide_vertical" /> - </android.support.v7.widget.Toolbar> + </androidx.appcompat.widget.Toolbar> - <android.support.v7.widget.RecyclerView + <androidx.recyclerview.widget.RecyclerView android:id="@+id/kau_recycler" android:layout_width="0dp" android:layout_height="0dp" @@ -31,4 +31,4 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/kau_toolbar" /> -</android.support.constraint.ConstraintLayout> +</androidx.constraintlayout.widget.ConstraintLayout> 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" -<br/>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 046a734..3ac4f36 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -5,20 +5,18 @@ apply from: '../android-lib.gradle' dependencies { api kauDependency.kotlin - api "com.android.support:support-annotations:${kau.supportLibs}" - api "com.android.support:appcompat-v7:${kau.supportLibs}" - api "com.android.support:support-v13:${kau.supportLibs}" - api "com.android.support:design:${kau.supportLibs}" - api "com.android.support:recyclerview-v7:${kau.supportLibs}" - api "com.android.support:cardview-v7:${kau.supportLibs}" - api "com.android.support.constraint:constraint-layout:${kau.constraintLayout}" + api "androidx.appcompat:appcompat:${kau.appcompat}" + api "androidx.recyclerview:recyclerview:${kau.recyclerView}" + api "androidx.cardview:cardview:${kau.cardView}" + 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/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt index 2a9263a..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,9 +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.kpref import android.annotation.SuppressLint -import android.support.test.InstrumentationRegistry -import android.support.test.filters.MediumTest -import android.support.test.runner.AndroidJUnit4 +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -23,7 +39,7 @@ class KPrefTest { class TestPref : KPref() { init { - initialize(InstrumentationRegistry.getTargetContext(), "kpref_test_${System.currentTimeMillis()}") + initialize(ApplicationProvider.getApplicationContext<Context>(), "kpref_test_${System.currentTimeMillis()}") } var one by kpref("one", 1) @@ -83,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 1dac92f..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,12 +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.utils import android.content.Context -import android.support.test.InstrumentationRegistry -import android.support.test.filters.MediumTest -import android.support.test.runner.AndroidJUnit4 import android.view.View import android.widget.FrameLayout import android.widget.TextView +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import androidx.test.platform.app.InstrumentationRegistry import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -25,7 +40,7 @@ class KotterknifeTest { @Before fun init() { - context = InstrumentationRegistry.getContext() + context = InstrumentationRegistry.getInstrumentation().context } @Test @@ -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/utils/UtilsAndroidTest.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/utils/UtilsAndroidTest.kt new file mode 100644 index 0000000..665e0b2 --- /dev/null +++ b/core/src/androidTest/kotlin/ca/allanwang/kau/utils/UtilsAndroidTest.kt @@ -0,0 +1,50 @@ +/* + * 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 +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Test +import org.junit.runner.RunWith +import kotlin.test.assertEquals + +/** + * Created by Allan Wang on 2018-12-24. + * + * Misc test code that are dependent on android + */ +@RunWith(AndroidJUnit4::class) +class UtilsAndroidTest { + + @Test + fun colorBlend() { + assertEquals(0x22446688, 0x11335577.blendWith(0x33557799, 0.5f), "Failed to blend with 50% ratio") + assertEquals(0x11335577, 0x11335577.blendWith(0x33557799, 0.0f), "Failed to blend with 0% ratio") + assertEquals(0x33557799, 0x22446688.blendWith(0x33557799, 1.0f), "Failed to blend with 100% ratio") + } + + @Test + fun lighten() { + assertEquals(Color.WHITE, Color.WHITE.lighten(0.35f), "Should not be able to further lighten white") + assertEquals(0xFFEEAAEA.toInt(), 0xFFDD55D5.toInt().lighten(0.5f), "Failed to lighten color by 50%") + } + + @Test + fun darken() { + assertEquals(Color.BLACK, Color.BLACK.darken(0.35f), "Should not be able to further darken black") + assertEquals(0xFF224424.toInt(), 0xFF448848.toInt().darken(0.5f), "Failed to darken color by 50%") + } +} 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 f9ce24b..7ec2a41 100644 --- a/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt +++ b/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt @@ -1,8 +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.support.test.InstrumentationRegistry -import android.support.test.filters.MediumTest -import android.support.test.runner.AndroidJUnit4 +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import ca.allanwang.kau.test.R import org.junit.Test import org.junit.runner.RunWith import kotlin.test.assertEquals @@ -14,26 +31,16 @@ import kotlin.test.assertEquals @MediumTest class FaqTest { - @Test - fun simpleTest() { - InstrumentationRegistry.getTargetContext().kauParseFaq(R.xml.test_faq) { data -> - 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("This is another answer", data.last().answer.toString(), "Second answer does not match") - } - } + val context: Context + get() = ApplicationProvider.getApplicationContext<Context>() @Test - fun withoutNumbering() { - InstrumentationRegistry.getTargetContext().kauParseFaq(R.xml.test_faq, false) { data -> - assertEquals(2, data.size, "FAQ size is incorrect") - assertEquals("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("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") - } + fun simpleTest() { + val data = context.kauParseFaq(R.xml.test_faq, false) + assertEquals(2, data.size, "FAQ size is incorrect") + assertEquals("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("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") } - -}
\ 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 2b9d91c..78661b1 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 android.support.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,24 +63,24 @@ 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 = linkedMapOf( - "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) + val deviceItems = mutableListOf( + "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() context.windowManager.defaultDisplay.getMetrics(metric) - deviceItems["Screen Dimensions"] = "${metric.widthPixels} x ${metric.heightPixels}" + deviceItems.add("Screen Dimensions" to "${metric.widthPixels} x ${metric.heightPixels}") } deviceItems.forEach { (k, v) -> emailBuilder.append("$k: $v\n") } } @@ -76,8 +94,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" } } @@ -112,7 +130,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) { @@ -124,12 +142,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 87d94ce..cb8f4bf 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt @@ -1,7 +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.internal -import android.support.v7.app.AppCompatActivity +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult +import ca.allanwang.kau.utils.ContextHelper +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.SupervisorJob +import kotlin.coroutines.CoroutineContext /** * Created by Allan Wang on 2017-08-01. @@ -11,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() = ContextHelper.dispatcher + 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<out String>, 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/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 deleted file mode 100644 index 03e98d2..0000000 --- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/FlyWeight.kt +++ /dev/null @@ -1,40 +0,0 @@ -package ca.allanwang.kau.kotlin - -/** - * Created by Allan Wang on 26/12/17. - * - * Kotlin implementation of a flyweight design pattern - * Values inside the map will be returned directly - * Otherwise, it will be created with the supplier, saved, and returned - * In the event a default is provided, the default takes precedence - */ -fun <K : Any, V : Any> flyweight(creator: (K) -> V) = FlyWeight(creator) - -class FlyWeight<K : Any, V : Any>(private val creator: (key: K) -> V) : Map<K, V> { - - private val map = mutableMapOf<K, V>() - - override val entries: Set<Map.Entry<K, V>> - get() = map.entries - override val keys: Set<K> - get() = map.keys - override val size: Int - get() = map.size - override val values: Collection<V> - get() = map.values - - override fun containsKey(key: K) = map.containsKey(key) - - override fun containsValue(value: V) = map.containsValue(value) - - override fun getOrDefault(key: K, defaultValue: V) = map.getOrDefault(key, defaultValue) - - override fun isEmpty() = map.isEmpty() - - override fun get(key: K): V { - if (!map.containsKey(key)) - map.put(key, creator(key)) - return map[key]!! - } - -}
\ No newline at end of file diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyContext.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyContext.kt index 0a45b65..e2a59d7 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyContext.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyContext.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.kotlin import android.content.Context -import android.support.annotation.AnimRes -import android.support.annotation.InterpolatorRes import android.view.animation.Animation import android.view.animation.AnimationUtils import android.view.animation.Interpolator +import androidx.annotation.AnimRes +import androidx.annotation.InterpolatorRes /** * Created by Allan Wang on 2017-05-30. @@ -47,5 +62,4 @@ class LazyContext<out T>(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..65d15a7 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 /** @@ -9,7 +24,6 @@ package ca.allanwang.kau.kotlin * Since we don't have access to the internals of our extended class, * We will simply iterate and remove when the filter returns {@code false} */ -@Synchronized inline fun <T, C : MutableIterable<T>> C.kauRemoveIf(filter: (item: T) -> Boolean): C { val iter = iterator() while (iter.hasNext()) @@ -27,4 +41,4 @@ inline fun <T : Any> Iterator<T>.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 <reified T : Any> javaClass(): Class<T> = T::class.java
\ No newline at end of file +inline fun <reified T : Any> javaClass(): Class<T> = 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 deleted file mode 100644 index 17ae5e5..0000000 --- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt +++ /dev/null @@ -1,89 +0,0 @@ -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 - * <a href="http://reactivex.io/documentation/operators/zip.html">Reactive Zips</a> - * 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<T>(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 <reified T> Collection<(ZipCallback<T>) -> Unit>.zip( - defaultResult: T, crossinline onFinished: (results: Array<T>) -> 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/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<String> = 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<String>, postSetter: (value: Set<String>) -> 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<T> internal constructor( - private val key: String, - private val fallback: T, - private val pref: KPref, - private val transaction: KPrefTransaction<T>, - private var postSetter: (value: T) -> Unit = {} + private val key: String, + private val fallback: T, + private val pref: KPref, + private val transaction: KPrefTransaction<T>, + private var postSetter: (value: T) -> Unit = {} ) : ILazyResettable<T> { private object UNINITIALIZED @@ -91,4 +107,4 @@ class KPrefDelegate<T> 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<Boolean> { +class KPrefSingleDelegate internal constructor(private val key: String, private val pref: KPref, lock: Any? = null) : + ILazyResettable<Boolean> { @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<T> { internal object KPrefBooleanTransaction : KPrefTransaction<Boolean> { 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<Boolean> { internal object KPrefIntTransaction : KPrefTransaction<Int> { 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<Int> { internal object KPrefLongTransaction : KPrefTransaction<Long> { 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<Long> { internal object KPrefFloatTransaction : KPrefTransaction<Float> { 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<Float> { internal object KPrefStringTransaction : KPrefTransaction<String> { 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<String> { internal object KPrefSetTransaction : KPrefTransaction<Set<String>> { override fun get(prefs: SharedPreferences, key: String, fallback: Set<String>) = - prefs.getStringSet(key, fallback)!! + prefs.getStringSet(key, fallback)!! override fun set(editor: SharedPreferences.Editor, key: String, data: Set<String>) { 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..9fbc070 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,13 @@ 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 }) { + + /** + * Logger with searchable tag and thread info + */ + inline fun test(message: () -> Any?) { + if (BuildConfig.DEBUG) + d { "Test1234 ${Thread.currentThread().name} ${message()}" } + } +} 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..4562b00 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/logging/KauLogger.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/logging/KauLogger.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. + */ @file:Suppress("NOTHING_TO_INLINE") package ca.allanwang.kau.logging -import android.os.Looper import android.util.Log +import ca.allanwang.kau.utils.kauIsMainThread /** * Created by Allan Wang on 2017-05-28. @@ -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) @@ -67,7 +82,7 @@ open class KauLogger( inline fun checkThread(id: Int) { d { val name = Thread.currentThread().name - val status = if (Looper.myLooper() == Looper.getMainLooper()) "is" else "is not" + val status = if (kauIsMainThread) "is" else "is not" "$id $status in the main thread - thread name: $name" } } @@ -96,16 +111,16 @@ 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 { val name = Thread.currentThread().name - val status = if (Looper.myLooper() == Looper.getMainLooper()) "is" else "is not" + val status = if (kauIsMainThread) "is" else "is not" "$id $status in the main thread - thread name: $name" } } 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 36456ec..96adfa3 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt @@ -1,9 +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.permissions import android.app.Activity import android.content.Context import android.content.pm.PackageManager -import android.support.v4.app.ActivityCompat +import androidx.core.app.ActivityCompat +import ca.allanwang.kau.kotlin.kauRemoveIf import ca.allanwang.kau.kotlin.lazyContext import ca.allanwang.kau.logging.KL import ca.allanwang.kau.utils.KauException @@ -12,43 +28,55 @@ 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. * - * Permission manager that is decoupled from activities - * Keeps track of pending requests, and warns about invalid requests + * Permission manager that is decoupled from activities. + * Keeps track of pending requests, and warns about invalid requests. */ internal object PermissionManager { - private var requestInProgress = false - private val pendingResults: MutableList<WeakReference<PermissionResult>> by lazy { mutableListOf<WeakReference<PermissionResult>>() } + private val pendingResults = mutableListOf<WeakReference<PermissionResult>>() /** * Retrieve permissions requested in our manifest */ - private val manifestPermission = lazyContext<Array<String>> { + private val manifestPermission = lazyContext<Set<String>> { try { - it.packageManager.getPackageInfo(it.packageName, PackageManager.GET_PERMISSIONS)?.requestedPermissions - ?: emptyArray() + it.packageManager.getPackageInfo( + it.packageName, + PackageManager.GET_PERMISSIONS + )?.requestedPermissions?.toSet() + ?: emptySet() } catch (e: Exception) { - emptyArray() + emptySet() } } - operator fun invoke(context: Context, permissions: Array<out String>, callback: (granted: Boolean, deniedPerm: String?) -> Unit) { + /** + * Registers a new permission request. + * It is expected that the callback will be called eventually, unless the parent activity is destroyed. + */ + operator fun invoke( + context: Context, + permissions: Array<out String>, + 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) } if (missingPermissions.isEmpty()) return callback(true, null) pendingResults.add(WeakReference(PermissionResult(permissions, callback = callback))) - if (!requestInProgress) { - requestInProgress = true + if (pendingResults.size == 1) { requestPermissions(context, missingPermissions.toTypedArray()) - } else KL.d { "Request is postponed since another one is still in progress; did you remember to override onRequestPermissionsResult?" } + } else { + KL.d { "Request is postponed since another one is still in progress; did you remember to override onRequestPermissionsResult?" } + } } - @Synchronized + /** + * Checks that the listed permissions can be requested, and submits the request to the provided activity + */ private fun requestPermissions(context: Context, permissions: Array<out String>) { permissions.forEach { if (!manifestPermission(context).contains(it)) { @@ -58,36 +86,27 @@ 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) } /** - * Handles permission result by allowing accepted permissions for all pending requests - * Also cleans up destroyed or completed pending requests + * Handles permission result by allowing accepted permissions for all pending requests. + * Also cleans up destroyed or completed pending requests. */ fun onRequestPermissionsResult(context: Context, permissions: Array<out String>, grantResults: IntArray) { KL.i { "On permission result: pending ${pendingResults.size}" } val count = Math.min(permissions.size, grantResults.size) - val iter = pendingResults.iterator() - while (iter.hasNext()) { - val action = iter.next().get() - if ((0 until count).any { action?.onResult(permissions[it], grantResults[it]) != false }) - iter.remove() + pendingResults.kauRemoveIf { + val action = it.get() + action == null || (0 until count).any { i -> action.onResult(permissions[i], grantResults[i]) } } - if (pendingResults.isEmpty()) - requestInProgress = false - else { - val action = pendingResults.map { it.get() }.firstOrNull { it != null } - if (action == null) { //actions have been unlinked from their weak references - pendingResults.clear() - requestInProgress = false - return - } - requestPermissions(context, action.permissions.toTypedArray()) + val action = pendingResults.asSequence().map { it.get() }.firstOrNull { it != null } + if (action == null) { // actions have been unlinked from their weak references + pendingResults.clear() + return } - KL.i { "Post on permission result: pending ${pendingResults.size}" } + requestPermissions(context, action.permissions.toTypedArray()) } - -}
\ 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..599f6e8 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 @@ -21,8 +36,10 @@ class PermissionResult(permissions: Array<out String>, val callback: (granted: B return true } permissions.remove(permission) - if (permissions.isNotEmpty()) return false + if (permissions.isNotEmpty()) { + return false + } 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 248e484..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,11 +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.permissions import android.Manifest import android.app.Activity import android.content.Context import android.os.Build -import android.support.annotation.RequiresApi - +import androidx.annotation.RequiresApi /** * Created by Allan Wang on 2017-07-02. @@ -22,7 +36,8 @@ import android.support.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<out String>, grantResults: IntArray) = PermissionManager.onRequestPermissionsResult(this, permissions, grantResults) +fun Activity.kauOnRequestPermissionsResult(permissions: Array<out String>, grantResults: IntArray) = + PermissionManager.onRequestPermissionsResult(this, permissions, grantResults) /** * Request a permission with a callback @@ -31,7 +46,10 @@ fun Activity.kauOnRequestPermissionsResult(permissions: Array<out String>, 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<SwipeBackPage>() - 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 a323e6c..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 android.support.v4.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/swipe/ViewDragHelper.java b/core/src/main/kotlin/ca/allanwang/kau/swipe/ViewDragHelper.java index 566e9e5..ac7fb7e 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/swipe/ViewDragHelper.java +++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/ViewDragHelper.java @@ -1,7 +1,7 @@ package ca.allanwang.kau.swipe; import android.content.Context; -import android.support.v4.view.ViewCompat; +import androidx.core.view.ViewCompat; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; @@ -25,7 +25,7 @@ import static ca.allanwang.kau.swipe.SwipeBackHelperKt.SWIPE_EDGE_TOP; * of useful operations and state tracking for allowing a user to drag and reposition * views within their parent ViewGroup. * <p> - * This is an extension of {@link android.support.v4.widget.ViewDragHelper} + * This is an extension of {@link androidx.core.widget.ViewDragHelper} * Along with additional methods defined in {@link ViewDragHelperExtras} */ class ViewDragHelper implements ViewDragHelperExtras { 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 b98a47e..a46e6c5 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/ui/ProgressAnimator.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/ui/ProgressAnimator.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.ui import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.animation.ValueAnimator -import android.support.annotation.VisibleForTesting +import androidx.annotation.VisibleForTesting import ca.allanwang.kau.kotlin.kauRemoveIf /** @@ -37,8 +52,7 @@ class ProgressAnimator private constructor() : ValueAnimator() { isCancelled = false } }) - apply(builder) - } + }.apply(builder) /** * Gets output of a linear function starting at [start] when [progress] is 0 and [end] when [progress] is 1 at point [progress]. @@ -54,7 +68,6 @@ class ProgressAnimator private constructor() : ValueAnimator() { start + (end - start) * trueProgress } } - } private val animators: MutableList<ProgressDisposableAction> = mutableListOf() @@ -69,7 +82,6 @@ class ProgressAnimator private constructor() : ValueAnimator() { val animatorCount get() = animators.size - /** * Converts an action to a disposable action */ @@ -95,13 +107,13 @@ class ProgressAnimator private constructor() : ValueAnimator() { } fun withAnimator(action: ProgressAction) = - withDisposableAnimator(action.asDisposable()) + withDisposableAnimator(action.asDisposable()) /** * Range animator. Multiples the range by the current float progress before emission */ fun withAnimator(from: Float, to: Float, action: ProgressAction) = - withDisposableAnimator(from, to, action.asDisposable()) + withDisposableAnimator(from, to, action.asDisposable()) fun withDisposableAnimator(action: ProgressDisposableAction) = animators.add(action) @@ -170,4 +182,4 @@ class ProgressAnimator private constructor() : ValueAnimator() { private typealias ProgressAction = (Float) -> Unit private typealias ProgressDisposableAction = (Float) -> Boolean private typealias ProgressRunnable = () -> Unit -private typealias ProgressDisposableRunnable = () -> Boolean
\ No newline at end of file +private typealias ProgressDisposableRunnable = () -> Boolean 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 b92b222..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,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.ui import android.content.res.ColorStateList import android.graphics.drawable.ColorDrawable import android.graphics.drawable.RippleDrawable import android.os.Build -import android.support.annotation.ColorInt -import android.support.annotation.RequiresApi +import androidx.annotation.ColorInt +import androidx.annotation.RequiresApi import ca.allanwang.kau.utils.adjustAlpha /** @@ -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 ab0e59f..21141f1 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 @@ -11,15 +26,15 @@ import android.content.Intent import android.graphics.Color import android.os.Build import android.os.Bundle -import android.support.annotation.ColorInt -import android.support.annotation.RequiresApi -import android.support.annotation.StringRes -import android.support.design.widget.Snackbar 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. @@ -36,19 +51,22 @@ annotation class KauActivity */ @Suppress("DEPRECATION") inline fun <reified T : Activity> 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<T>(requestCode, bundleBuilder, intentBuilder)"), - DeprecationLevel.WARNING) +@Deprecated( + "Use reified generic instead of passing class", + ReplaceWith("startActivityForResult<T>(requestCode, bundleBuilder, intentBuilder)"), + DeprecationLevel.WARNING +) inline fun <T : Activity> Activity.startActivityForResult( - clazz: Class<T>, - requestCode: Int, - bundleBuilder: Bundle.() -> Unit = {}, - intentBuilder: Intent.() -> Unit = {}) { + clazz: Class<T>, + requestCode: Int, + bundleBuilder: Bundle.() -> Unit = {}, + intentBuilder: Intent.() -> Unit = {} +) { val intent = Intent(this, clazz) intent.intentBuilder() val bundle = Bundle() @@ -72,13 +90,12 @@ inline fun Activity.restart(intentBuilder: Intent.() -> Unit = {}) { overridePendingTransition(R.anim.kau_fade_in, R.anim.kau_fade_out) } - /** * Force restart an entire application */ @RequiresApi(Build.VERSION_CODES.M) inline fun Activity.restartApplication() { - val intent = packageManager.getLaunchIntentForPackage(packageName) + val intent = packageManager.getLaunchIntentForPackage(packageName)!! intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) val pending = PendingIntent.getActivity(this, 666, intent, PendingIntent.FLAG_CANCEL_CURRENT) val alarm = getSystemService(Context.ALARM_SERVICE) as AlarmManager @@ -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() } } @@ -135,10 +152,33 @@ fun Context.setMenuIcons(menu: Menu, @ColorInt color: Int = Color.WHITE, vararg } } -inline fun Activity.hideKeyboard() = currentFocus.hideKeyboard() - -inline fun Activity.showKeyboard() = currentFocus.showKeyboard() +inline fun Activity.hideKeyboard() { + currentFocus?.hideKeyboard() +} -inline fun Activity.snackbar(text: String, duration: Int = Snackbar.LENGTH_LONG, noinline builder: Snackbar.() -> Unit = {}) = contentView!!.snackbar(text, duration, builder) +inline fun Activity.showKeyboard() { + currentFocus?.showKeyboard() +} -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 +/** + * Gets the view set by [Activity.setContentView] if it exists. + * + * Taken courtesy of <a href="https://github.com/Kotlin/anko">Anko</a> + * + * 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, + 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 2767f04..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,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.utils import android.os.Build -import android.support.annotation.RequiresApi +import androidx.annotation.RequiresApi import ca.allanwang.kau.kotlin.lazyInterpolator /** @@ -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 a287cf2..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 android.support.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 82cd577..40c1c72 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,10 +20,12 @@ import android.app.Activity import android.app.ActivityOptions import android.content.Context import android.os.Bundle -import android.support.annotation.AnimRes +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. @@ -22,6 +39,56 @@ infix fun Bundle.with(bundle: Bundle?): Bundle { } /** + * Saves all bundle args based on their respective types. + * + * Taken courtesy of <a href="https://github.com/Kotlin/anko">Anko</a> + * + * 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<String, Any?>): 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<Parcelable>() -> b.putParcelableArray(k, v as Array<out Parcelable>) + v.isArrayOf<CharSequence>() -> b.putCharSequenceArray(k, v as Array<out CharSequence>) + v.isArrayOf<String>() -> b.putStringArray(k, v as Array<out String>) + 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+ */ @SuppressLint("NewApi") @@ -36,34 +103,46 @@ fun Bundle.withSceneTransitionAnimation(context: Context) { * create a scene transition animation */ fun Bundle.withSceneTransitionAnimation(parent: View, data: Map<Int, String>) = - withSceneTransitionAnimation(parent.context, data.mapKeys { (id, _) -> - parent.findViewById<View>(id) - }) + withSceneTransitionAnimation(parent.context, data.mapKeys { (id, _) -> + parent.findViewById<View>(id) + }) /** * Given a mapping of views to tags, * create a scene transition animation */ @SuppressLint("NewApi") -fun Bundle.withSceneTransitionAnimation(context: Context, data: Map<View, String>) { +fun Bundle.withSceneTransitionAnimation(context: Context, data: Map<out View, String>) { if (context !is Activity || !buildIsLollipopAndUp) return - val options = ActivityOptions.makeSceneTransitionAnimation(context, - *data.map { (view, tag) -> Pair(view, tag) }.toTypedArray()) + val options = ActivityOptions.makeSceneTransitionAnimation( + context, + *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 236f2ca..bbb8953 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.support.annotation.ColorInt -import android.support.annotation.FloatRange -import android.support.annotation.IntRange -import android.support.v4.graphics.drawable.DrawableCompat -import android.support.v7.widget.AppCompatEditText -import android.support.v7.widget.Toolbar -import android.widget.* +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.appcompat.widget.AppCompatEditText +import androidx.appcompat.widget.Toolbar +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,49 +118,58 @@ 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 = 0, to = 0xFF) alpha: Int): Int = + this and 0x00FFFFFF or (alpha shl 24) @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 = 0, to = 0xFF) alpha: Int): Int = + withAlpha(Math.max(alpha, this ushr 24)) @ColorInt -fun Int.lighten(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int { +private inline fun Int.colorFactor(rgbFactor: (Int) -> Float): Int { val (red, green, blue) = intArrayOf(Color.red(this), Color.green(this), Color.blue(this)) - .map { (it * (1f - factor) + 255f * factor).toInt() } + .map { rgbFactor(it).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() } - return Color.argb(Color.alpha(this), red, green, blue) +fun Int.lighten(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int = colorFactor { + (it * (1f - factor) + 255f * factor) } @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.darken(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int = colorFactor { + it * (1f - factor) +} + +@ColorInt +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 { - val toParse: String - if (startsWith("#") && length == 4) - toParse = "#${this[1]}${this[1]}${this[2]}${this[2]}${this[3]}${this[3]}" + val toParse: String = if (startsWith("#") && length == 4) + "#${this[1]}${this[1]}${this[2]}${this[2]}${this[3]}${this[3]}" else - toParse = this + this return Color.parseColor(toParse) } //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 +236,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 +287,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 1eeac1a..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,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.utils -import android.support.v4.widget.ViewDragHelper +import androidx.customview.widget.ViewDragHelper /** * Created by Allan Wang on 2017-06-08. @@ -20,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 6568bf2..82d5608 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 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. + * 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,20 +26,35 @@ import android.content.pm.PackageManager import android.graphics.drawable.Drawable import android.net.Uri import android.os.Bundle -import android.support.annotation.* -import android.support.v4.content.ContextCompat +import android.os.Looper 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.DialogBehavior import com.afollestad.materialdialogs.MaterialDialog - +import com.afollestad.materialdialogs.ModalDialog /** * Created by Allan Wang on 2017-06-03. */ +fun Context.runOnUiThread(f: Context.() -> Unit) { + if (ContextHelper.looper === Looper.myLooper()) f() else ContextHelper.handler.post { f() } +} /** * Helper class to launch an activity from a context @@ -33,19 +63,22 @@ import com.afollestad.materialdialogs.MaterialDialog */ @Suppress("DEPRECATION") inline fun <reified T : Activity> 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<T>(clearStack, bundleBuilder, intentBuilder)"), - DeprecationLevel.WARNING) +@Deprecated( + "Use reified generic instead of passing class", + ReplaceWith("startActivity<T>(clearStack, bundleBuilder, intentBuilder)"), + DeprecationLevel.WARNING +) inline fun <T : Activity> Context.startActivity( - clazz: Class<T>, - clearStack: Boolean = false, - bundleBuilder: Bundle.() -> Unit = {}, - intentBuilder: Intent.() -> Unit = {}) { + clazz: Class<T>, + 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 +88,6 @@ inline fun <T : Activity> Context.startActivity( if (clearStack && this is Activity) finish() } - fun Context.startPlayStoreLink(@StringRes packageIdRes: Int) = startPlayStoreLink(string(packageIdRes)) fun Context.startPlayStoreLink(packageId: String) { @@ -82,11 +114,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 +133,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 { @@ -151,20 +195,24 @@ fun Context.resolveString(@AttrRes attr: Int, fallback: String = ""): String { } /** - * Wrapper function for the MaterialDialog adapterBuilder - * There is no need to call build() or show() as those are done by default + * Wrapper function for MaterialDialog + * + * Mainly handles invalid creations, such as showing a dialog when an activity is finishing + * See https://github.com/afollestad/material-dialogs/issues/1778 */ -inline fun Context.materialDialog(action: MaterialDialog.Builder.() -> Unit): MaterialDialog { - val builder = MaterialDialog.Builder(this) - builder.action() +inline fun Context.materialDialog( + dialogBehavior: DialogBehavior = ModalDialog, + action: MaterialDialog.() -> Unit +) { + val dialog = MaterialDialog(this, dialogBehavior) if (isFinishing) { - KL.d { "Material Dialog triggered from finishing context; did not show" } - return builder.build() + return KL.d { "Material Dialog triggered from finishing context; did not show" } } - return builder.show() + dialog.show(action) } -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 +229,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 +258,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/CoroutineUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/CoroutineUtils.kt new file mode 100644 index 0000000..57a9921 --- /dev/null +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/CoroutineUtils.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2019 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 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 <T> withMainContext(block: suspend CoroutineScope.() -> T) = + withContext(ContextHelper.dispatcher, block) 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 dae3bff..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,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.utils import android.content.res.ColorStateList import android.graphics.drawable.Drawable -import android.support.annotation.ColorInt -import android.support.v4.graphics.drawable.DrawableCompat +import androidx.annotation.ColorInt +import androidx.core.graphics.drawable.DrawableCompat /** * Wrap the color into a state and tint the drawable @@ -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 acc71f2..75dc1c1 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt @@ -1,12 +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.utils -import android.support.v4.app.Fragment -import org.jetbrains.anko.bundleOf +import androidx.fragment.app.Fragment /** * Created by Allan Wang on 2017-07-02. */ -fun <T : Fragment> T.withArguments(vararg params: Pair<String, Any>): T { +fun <T : Fragment> T.withArguments(vararg params: Pair<String, Any?>): 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 51691af..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,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.utils import android.content.Context import android.content.res.ColorStateList import android.graphics.Color import android.graphics.drawable.Drawable -import android.support.annotation.ColorInt +import androidx.annotation.ColorInt import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.IIcon @@ -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 8c7c039..8765c69 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/Kotterknife.kt @@ -1,4 +1,19 @@ -@file:Suppress("UNCHECKED_CAST") +/* + * 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 @@ -8,148 +23,89 @@ package ca.allanwang.kau.utils * Courtesy of Jake Wharton * * https://github.com/JakeWharton/kotterknife/blob/master/src/main/kotlin/kotterknife/ButterKnife.kt + * + * Note that while this is useful for binding ids, there also exists other alternatives, such as + * `kotlin-android-extensions`. + * + * For fragments, make sure that the views are reset after the fragment lifecycle. */ import android.app.Activity import android.app.Dialog import android.app.DialogFragment import android.app.Fragment -import android.support.v7.widget.RecyclerView.ViewHolder import android.view.View -import java.util.* +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerView.ViewHolder +import java.util.Collections +import java.util.WeakHashMap import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty -import android.support.v4.app.DialogFragment as SupportDialogFragment -import android.support.v4.app.Fragment as SupportFragment - -private const val DEPRECATION_MESSAGE = "Kotterknife will be removed in favour of the kotlin_android_extensions plugin" +import androidx.fragment.app.DialogFragment as SupportDialogFragment +import androidx.fragment.app.Fragment as SupportFragment -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> View.bindView(id: Int) - : ReadOnlyProperty<View, V> = required(id, viewFinder) +fun <V : View> View.bindView(id: Int): ReadOnlyProperty<View, V> = required(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Activity.bindView(id: Int) - : ReadOnlyProperty<Activity, V> = required(id, viewFinder) +fun <V : View> Activity.bindView(id: Int): ReadOnlyProperty<Activity, V> = required(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Dialog.bindView(id: Int) - : ReadOnlyProperty<Dialog, V> = required(id, viewFinder) +fun <V : View> Dialog.bindView(id: Int): ReadOnlyProperty<Dialog, V> = required(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> DialogFragment.bindView(id: Int) - : ReadOnlyProperty<DialogFragment, V> = required(id, viewFinder) +fun <V : View> DialogFragment.bindView(id: Int): ReadOnlyProperty<DialogFragment, V> = required(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportDialogFragment.bindView(id: Int) - : ReadOnlyProperty<android.support.v4.app.DialogFragment, V> = required(id, viewFinder) +fun <V : View> SupportDialogFragment.bindView(id: Int): ReadOnlyProperty<SupportDialogFragment, V> = required(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Fragment.bindView(id: Int) - : ReadOnlyProperty<Fragment, V> = required(id, viewFinder) +fun <V : View> Fragment.bindView(id: Int): ReadOnlyProperty<Fragment, V> = required(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportFragment.bindView(id: Int) - : ReadOnlyProperty<android.support.v4.app.Fragment, V> = required(id, viewFinder) +fun <V : View> SupportFragment.bindView(id: Int): ReadOnlyProperty<SupportFragment, V> = required(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> ViewHolder.bindView(id: Int) - : ReadOnlyProperty<ViewHolder, V> = required(id, viewFinder) +fun <V : View> RecyclerView.ViewHolder.bindView(id: Int): ReadOnlyProperty<RecyclerView.ViewHolder, V> = required(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> View.bindOptionalView(id: Int) - : ReadOnlyProperty<View, V?> = optional(id, viewFinder) +fun <V : View> View.bindOptionalView(id: Int): ReadOnlyProperty<View, V?> = optional(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Activity.bindOptionalView(id: Int) - : ReadOnlyProperty<Activity, V?> = optional(id, viewFinder) +fun <V : View> Activity.bindOptionalView(id: Int): ReadOnlyProperty<Activity, V?> = optional(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Dialog.bindOptionalView(id: Int) - : ReadOnlyProperty<Dialog, V?> = optional(id, viewFinder) +fun <V : View> Dialog.bindOptionalView(id: Int): ReadOnlyProperty<Dialog, V?> = optional(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> DialogFragment.bindOptionalView(id: Int) - : ReadOnlyProperty<DialogFragment, V?> = optional(id, viewFinder) +fun <V : View> DialogFragment.bindOptionalView(id: Int): ReadOnlyProperty<DialogFragment, V?> = optional(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportDialogFragment.bindOptionalView(id: Int) - : ReadOnlyProperty<android.support.v4.app.DialogFragment, V?> = optional(id, viewFinder) +fun <V : View> SupportDialogFragment.bindOptionalView(id: Int): ReadOnlyProperty<SupportDialogFragment, V?> = optional(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Fragment.bindOptionalView(id: Int) - : ReadOnlyProperty<Fragment, V?> = optional(id, viewFinder) +fun <V : View> Fragment.bindOptionalView(id: Int): ReadOnlyProperty<Fragment, V?> = optional(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportFragment.bindOptionalView(id: Int) - : ReadOnlyProperty<android.support.v4.app.Fragment, V?> = optional(id, viewFinder) +fun <V : View> SupportFragment.bindOptionalView(id: Int): ReadOnlyProperty<SupportFragment, V?> = optional(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> ViewHolder.bindOptionalView(id: Int) - : ReadOnlyProperty<ViewHolder, V?> = optional(id, viewFinder) +fun <V : View> RecyclerView.ViewHolder.bindOptionalView(id: Int): ReadOnlyProperty<RecyclerView.ViewHolder, V?> = optional(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> View.bindViews(vararg ids: Int) - : ReadOnlyProperty<View, List<V>> = required(ids, viewFinder) +fun <V : View> View.bindViews(vararg ids: Int): ReadOnlyProperty<View, List<V>> = required(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Activity.bindViews(vararg ids: Int) - : ReadOnlyProperty<Activity, List<V>> = required(ids, viewFinder) +fun <V : View> Activity.bindViews(vararg ids: Int): ReadOnlyProperty<Activity, List<V>> = required(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Dialog.bindViews(vararg ids: Int) - : ReadOnlyProperty<Dialog, List<V>> = required(ids, viewFinder) +fun <V : View> Dialog.bindViews(vararg ids: Int): ReadOnlyProperty<Dialog, List<V>> = required(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> DialogFragment.bindViews(vararg ids: Int) - : ReadOnlyProperty<DialogFragment, List<V>> = required(ids, viewFinder) +fun <V : View> DialogFragment.bindViews(vararg ids: Int): ReadOnlyProperty<DialogFragment, List<V>> = required(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportDialogFragment.bindViews(vararg ids: Int) - : ReadOnlyProperty<android.support.v4.app.DialogFragment, List<V>> = required(ids, viewFinder) +fun <V : View> SupportDialogFragment.bindViews(vararg ids: Int): ReadOnlyProperty<SupportDialogFragment, List<V>> = required(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Fragment.bindViews(vararg ids: Int) - : ReadOnlyProperty<Fragment, List<V>> = required(ids, viewFinder) +fun <V : View> Fragment.bindViews(vararg ids: Int): ReadOnlyProperty<Fragment, List<V>> = required(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportFragment.bindViews(vararg ids: Int) - : ReadOnlyProperty<android.support.v4.app.Fragment, List<V>> = required(ids, viewFinder) +fun <V : View> SupportFragment.bindViews(vararg ids: Int): ReadOnlyProperty<SupportFragment, List<V>> = required(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> ViewHolder.bindViews(vararg ids: Int) - : ReadOnlyProperty<ViewHolder, List<V>> = required(ids, viewFinder) +fun <V : View> ViewHolder.bindViews(vararg ids: Int): ReadOnlyProperty<ViewHolder, List<V>> = required(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> View.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty<View, List<V>> = optional(ids, viewFinder) +fun <V : View> View.bindOptionalViews(vararg ids: Int): ReadOnlyProperty<View, List<V>> = optional(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Activity.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty<Activity, List<V>> = optional(ids, viewFinder) +fun <V : View> Activity.bindOptionalViews(vararg ids: Int): ReadOnlyProperty<Activity, List<V>> = optional(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Dialog.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty<Dialog, List<V>> = optional(ids, viewFinder) +fun <V : View> Dialog.bindOptionalViews(vararg ids: Int): ReadOnlyProperty<Dialog, List<V>> = optional(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> DialogFragment.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty<DialogFragment, List<V>> = optional(ids, viewFinder) +fun <V : View> DialogFragment.bindOptionalViews(vararg ids: Int): ReadOnlyProperty<DialogFragment, List<V>> = optional(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportDialogFragment.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty<android.support.v4.app.DialogFragment, List<V>> = optional(ids, viewFinder) +fun <V : View> SupportDialogFragment.bindOptionalViews(vararg ids: Int): ReadOnlyProperty<SupportDialogFragment, List<V>> = optional(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Fragment.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty<Fragment, List<V>> = optional(ids, viewFinder) +fun <V : View> Fragment.bindOptionalViews(vararg ids: Int): ReadOnlyProperty<Fragment, List<V>> = optional(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportFragment.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty<android.support.v4.app.Fragment, List<V>> = optional(ids, viewFinder) +fun <V : View> SupportFragment.bindOptionalViews(vararg ids: Int): ReadOnlyProperty<SupportFragment, List<V>> = optional(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> ViewHolder.bindOptionalViews(vararg ids: Int) - : ReadOnlyProperty<ViewHolder, List<V>> = optional(ids, viewFinder) +fun <V : View> ViewHolder.bindOptionalViews(vararg ids: Int): ReadOnlyProperty<ViewHolder, List<V>> = optional(ids, viewFinder) private inline val View.viewFinder: View.(Int) -> View? get() = { findViewById(it) } @@ -162,14 +118,14 @@ private inline val DialogFragment.viewFinder: DialogFragment.(Int) -> View? private inline val SupportDialogFragment.viewFinder: SupportDialogFragment.(Int) -> View? get() = { dialog.findViewById(it) } private inline val Fragment.viewFinder: Fragment.(Int) -> View? - get() = { view.findViewById(it) } + get() = { view!!.findViewById(it) } private inline val SupportFragment.viewFinder: SupportFragment.(Int) -> View? get() = { view!!.findViewById(it) } 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 <T, V : View> required(id: Int, finder: T.(Int) -> View?) = Lazy { t: T, desc -> (t.finder(id) as V?)?.apply { } ?: viewNotFound(id, desc) @@ -183,7 +139,8 @@ private fun <T, V : View> required(ids: IntArray, finder: T.(Int) -> View?) = La } } -private fun <T, V : View> optional(ids: IntArray, finder: T.(Int) -> View?) = Lazy { t: T, _ -> ids.map { t.finder(it) as V? }.filterNotNull() } +private fun <T, V : View> 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<in T, out V>(private val initializer: (T, KProperty<*>) -> V) : ReadOnlyProperty<T, V> { @@ -209,139 +166,76 @@ private open class Lazy<in T, out V>(private val initializer: (T, KProperty<*>) * Credits to <a href="https://github.com/MichaelRocks">MichaelRocks</a> */ -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> View.bindViewResettable(id: Int) - : ReadOnlyProperty<View, V> = requiredResettable(id, viewFinder) +fun <V : View> View.bindViewResettable(id: Int): ReadOnlyProperty<View, V> = requiredResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Activity.bindViewResettable(id: Int) - : ReadOnlyProperty<Activity, V> = requiredResettable(id, viewFinder) +fun <V : View> Activity.bindViewResettable(id: Int): ReadOnlyProperty<Activity, V> = requiredResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Dialog.bindViewResettable(id: Int) - : ReadOnlyProperty<Dialog, V> = requiredResettable(id, viewFinder) +fun <V : View> Dialog.bindViewResettable(id: Int): ReadOnlyProperty<Dialog, V> = requiredResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> DialogFragment.bindViewResettable(id: Int) - : ReadOnlyProperty<DialogFragment, V> = requiredResettable(id, viewFinder) +fun <V : View> DialogFragment.bindViewResettable(id: Int): ReadOnlyProperty<DialogFragment, V> = requiredResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportDialogFragment.bindViewResettable(id: Int) - : ReadOnlyProperty<android.support.v4.app.DialogFragment, V> = requiredResettable(id, viewFinder) +fun <V : View> SupportDialogFragment.bindViewResettable(id: Int): ReadOnlyProperty<SupportDialogFragment, V> = requiredResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Fragment.bindViewResettable(id: Int) - : ReadOnlyProperty<Fragment, V> = requiredResettable(id, viewFinder) +fun <V : View> Fragment.bindViewResettable(id: Int): ReadOnlyProperty<Fragment, V> = requiredResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportFragment.bindViewResettable(id: Int) - : ReadOnlyProperty<android.support.v4.app.Fragment, V> = requiredResettable(id, viewFinder) +fun <V : View> SupportFragment.bindViewResettable(id: Int): ReadOnlyProperty<SupportFragment, V> = requiredResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> ViewHolder.bindViewResettable(id: Int) - : ReadOnlyProperty<ViewHolder, V> = requiredResettable(id, viewFinder) +fun <V : View> ViewHolder.bindViewResettable(id: Int): ReadOnlyProperty<ViewHolder, V> = requiredResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> View.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty<View, V?> = optionalResettable(id, viewFinder) +fun <V : View> View.bindOptionalViewResettable(id: Int): ReadOnlyProperty<View, V?> = optionalResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Activity.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty<Activity, V?> = optionalResettable(id, viewFinder) +fun <V : View> Activity.bindOptionalViewResettable(id: Int): ReadOnlyProperty<Activity, V?> = optionalResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Dialog.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty<Dialog, V?> = optionalResettable(id, viewFinder) +fun <V : View> Dialog.bindOptionalViewResettable(id: Int): ReadOnlyProperty<Dialog, V?> = optionalResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> DialogFragment.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty<DialogFragment, V?> = optionalResettable(id, viewFinder) +fun <V : View> DialogFragment.bindOptionalViewResettable(id: Int): ReadOnlyProperty<DialogFragment, V?> = optionalResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportDialogFragment.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty<android.support.v4.app.DialogFragment, V?> = optionalResettable(id, viewFinder) +fun <V : View> SupportDialogFragment.bindOptionalViewResettable(id: Int): ReadOnlyProperty<SupportDialogFragment, V?> = optionalResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Fragment.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty<Fragment, V?> = optionalResettable(id, viewFinder) +fun <V : View> Fragment.bindOptionalViewResettable(id: Int): ReadOnlyProperty<Fragment, V?> = optionalResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportFragment.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty<android.support.v4.app.Fragment, V?> = optionalResettable(id, viewFinder) +fun <V : View> SupportFragment.bindOptionalViewResettable(id: Int): ReadOnlyProperty<SupportFragment, V?> = optionalResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> ViewHolder.bindOptionalViewResettable(id: Int) - : ReadOnlyProperty<ViewHolder, V?> = optionalResettable(id, viewFinder) +fun <V : View> ViewHolder.bindOptionalViewResettable(id: Int): ReadOnlyProperty<ViewHolder, V?> = optionalResettable(id, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> View.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty<View, List<V>> = requiredResettable(ids, viewFinder) +fun <V : View> View.bindViewsResettable(vararg ids: Int): ReadOnlyProperty<View, List<V>> = requiredResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Activity.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty<Activity, List<V>> = requiredResettable(ids, viewFinder) +fun <V : View> Activity.bindViewsResettable(vararg ids: Int): ReadOnlyProperty<Activity, List<V>> = requiredResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Dialog.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty<Dialog, List<V>> = requiredResettable(ids, viewFinder) +fun <V : View> Dialog.bindViewsResettable(vararg ids: Int): ReadOnlyProperty<Dialog, List<V>> = requiredResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> DialogFragment.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty<DialogFragment, List<V>> = requiredResettable(ids, viewFinder) +fun <V : View> DialogFragment.bindViewsResettable(vararg ids: Int): ReadOnlyProperty<DialogFragment, List<V>> = requiredResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportDialogFragment.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty<android.support.v4.app.DialogFragment, List<V>> = requiredResettable(ids, viewFinder) +fun <V : View> SupportDialogFragment.bindViewsResettable(vararg ids: Int): ReadOnlyProperty<SupportDialogFragment, List<V>> = requiredResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Fragment.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty<Fragment, List<V>> = requiredResettable(ids, viewFinder) +fun <V : View> Fragment.bindViewsResettable(vararg ids: Int): ReadOnlyProperty<Fragment, List<V>> = requiredResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportFragment.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty<android.support.v4.app.Fragment, List<V>> = requiredResettable(ids, viewFinder) +fun <V : View> SupportFragment.bindViewsResettable(vararg ids: Int): ReadOnlyProperty<SupportFragment, List<V>> = requiredResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> ViewHolder.bindViewsResettable(vararg ids: Int) - : ReadOnlyProperty<ViewHolder, List<V>> = requiredResettable(ids, viewFinder) +fun <V : View> ViewHolder.bindViewsResettable(vararg ids: Int): ReadOnlyProperty<ViewHolder, List<V>> = requiredResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> View.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty<View, List<V>> = optionalResettable(ids, viewFinder) +fun <V : View> View.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty<View, List<V>> = optionalResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Activity.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty<Activity, List<V>> = optionalResettable(ids, viewFinder) +fun <V : View> Activity.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty<Activity, List<V>> = optionalResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Dialog.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty<Dialog, List<V>> = optionalResettable(ids, viewFinder) +fun <V : View> Dialog.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty<Dialog, List<V>> = optionalResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> DialogFragment.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty<DialogFragment, List<V>> = optionalResettable(ids, viewFinder) +fun <V : View> DialogFragment.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty<DialogFragment, List<V>> = optionalResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportDialogFragment.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty<android.support.v4.app.DialogFragment, List<V>> = optionalResettable(ids, viewFinder) +fun <V : View> SupportDialogFragment.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty<SupportDialogFragment, List<V>> = optionalResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> Fragment.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty<Fragment, List<V>> = optionalResettable(ids, viewFinder) +fun <V : View> Fragment.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty<Fragment, List<V>> = optionalResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> SupportFragment.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty<android.support.v4.app.Fragment, List<V>> = optionalResettable(ids, viewFinder) +fun <V : View> SupportFragment.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty<SupportFragment, List<V>> = optionalResettable(ids, viewFinder) -@Deprecated(DEPRECATION_MESSAGE) -fun <V : View> ViewHolder.bindOptionalViewsResettable(vararg ids: Int) - : ReadOnlyProperty<ViewHolder, List<V>> = optionalResettable(ids, viewFinder) +fun <V : View> ViewHolder.bindOptionalViewsResettable(vararg ids: Int): ReadOnlyProperty<RecyclerView.ViewHolder, List<V>> = optionalResettable(ids, viewFinder) private fun <T, V : View> requiredResettable(id: Int, finder: T.(Int) -> View?) = LazyResettable { t: T, desc -> (t.finder(id) as V?)?.apply { } ?: viewNotFound(id, desc) } -private fun <T, V : View> optionalResettable(id: Int, finder: T.(Int) -> View?) = LazyResettable { t: T, _ -> t.finder(id) as V? } +private fun <T, V : View> optionalResettable(id: Int, finder: T.(Int) -> View?) = + LazyResettable { t: T, _ -> t.finder(id) as V? } private fun <T, V : View> requiredResettable(ids: IntArray, finder: T.(Int) -> View?) = LazyResettable { t: T, desc -> ids.map { @@ -349,7 +243,8 @@ private fun <T, V : View> requiredResettable(ids: IntArray, finder: T.(Int) -> V } } -private fun <T, V : View> optionalResettable(ids: IntArray, finder: T.(Int) -> View?) = LazyResettable { t: T, _ -> ids.map { t.finder(it) as V? }.filterNotNull() } +private fun <T, V : View> 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<in T, out V>(initializer: (T, KProperty<*>) -> V) : Lazy<T, V>(initializer) { @@ -363,7 +258,6 @@ private class LazyResettable<in T, out V>(initializer: (T, KProperty<*>) -> V) : } } -@Deprecated(DEPRECATION_MESSAGE) object Kotterknife { fun reset(target: Any) { KotterknifeRegistry.reset(target) @@ -373,7 +267,8 @@ object Kotterknife { private object KotterknifeRegistry { private val lazyMap = WeakHashMap<Any, MutableCollection<LazyResettable<*, *>>>() - 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 +} 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..32cf084 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 @@ -7,6 +22,7 @@ import android.net.ConnectivityManager /** * Created by Allan Wang on 2017-07-07. */ +@Deprecated("Applications should make use of network callbacks instead of individual queries") inline val Context.isNetworkAvailable: Boolean @SuppressLint("MissingPermission") get() { @@ -15,6 +31,7 @@ inline val Context.isNetworkAvailable: Boolean return activeNetworkInfo?.isConnectedOrConnecting ?: false } +@Deprecated("Applications should make use of network callbacks instead of individual queries") inline val Context.isWifiConnected: Boolean @SuppressLint("MissingPermission") get() { @@ -23,10 +40,11 @@ inline val Context.isWifiConnected: Boolean return (activeNetworkInfo?.type ?: -1) == ConnectivityManager.TYPE_WIFI } +@Deprecated("Applications should make use of network callbacks instead of individual queries") inline val Context.isMobileDataConnected: Boolean @SuppressLint("MissingPermission") get() { 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 1eb0076..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 android.support.v4.app.NotificationManagerCompat - +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 3a34db5..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,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.utils import android.graphics.Rect -import android.support.v7.widget.RecyclerView import android.view.View +import androidx.recyclerview.widget.RecyclerView /** * Created by Allan Wang on 2017-07-11. @@ -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 ec206ee..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,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.utils import android.os.Build -import android.support.annotation.RequiresApi -import android.support.annotation.TransitionRes -import android.support.transition.AutoTransition -import android.support.transition.TransitionInflater -import android.support.transition.TransitionManager import android.transition.Transition import android.view.ViewGroup -import android.support.transition.Transition as SupportTransition +import androidx.annotation.RequiresApi +import androidx.annotation.TransitionRes +import androidx.transition.AutoTransition +import androidx.transition.TransitionInflater +import androidx.transition.TransitionManager +import androidx.transition.Transition as SupportTransition /** * Created by Allan Wang on 2017-06-24. @@ -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) {} @@ -52,9 +68,9 @@ fun ViewGroup.transitionAuto(builder: AutoTransition.() -> Unit = {}) { } @KauUtils -fun ViewGroup.transitionDelayed(@TransitionRes id: Int, builder: android.support.transition.Transition.() -> Unit = {}) { +fun ViewGroup.transitionDelayed(@TransitionRes id: Int, builder: androidx.transition.Transition.() -> Unit = {}) { if (!buildIsLollipopAndUp) return 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 46e29b2..48a2028 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 @@ -8,12 +23,11 @@ import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import android.os.Handler import android.os.Looper -import android.support.annotation.IntRange +import androidx.annotation.IntRange import ca.allanwang.kau.R import java.math.RoundingMode import java.text.DecimalFormat - /** * Created by Allan Wang on 2017-05-28. */ @@ -127,10 +141,10 @@ fun postDelayed(delay: Long, action: () -> Unit) { } inline val kauIsMainThread: Boolean - get() = Looper.myLooper() == Looper.getMainLooper() + get() = Looper.myLooper() == ContextHelper.looper 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 4e020bc..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,15 +22,6 @@ import android.annotation.SuppressLint import android.content.Context import android.graphics.Color import android.os.Build -import android.support.annotation.ColorInt -import android.support.annotation.ColorRes -import android.support.annotation.RequiresApi -import android.support.annotation.StringRes -import android.support.design.widget.FloatingActionButton -import android.support.design.widget.Snackbar -import android.support.design.widget.TextInputEditText -import android.support.v7.widget.LinearLayoutManager -import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.MotionEvent import android.view.View @@ -23,11 +29,19 @@ 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 +import com.google.android.material.floatingactionbutton.FloatingActionButton +import com.google.android.material.snackbar.Snackbar +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 : ImageView> T.fadeScaleTransition(duration: Long = 500L, minScale: Float = 0.7f, crossinline action: T.() -> Unit) { +inline fun <T : ImageView> T.fadeScaleTransition( + duration: Long = 500L, + minScale: Float = 0.7f, + crossinline action: T.() -> Unit +) { if (!isVisible) action() else { var transitioned = false @@ -291,7 +323,7 @@ fun FloatingActionButton.hideOnDownwardsScroll(recycler: RecyclerView) { recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { - if (newState == android.support.v7.widget.RecyclerView.SCROLL_STATE_IDLE && !isShown) show() + if (newState == RecyclerView.SCROLL_STATE_IDLE && !isShown) show() } override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { @@ -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 28d51a4..2e66a97 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt @@ -1,39 +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.xml import android.content.Context import android.content.res.XmlResourceParser -import android.support.annotation.ColorInt -import android.support.annotation.LayoutRes -import android.support.annotation.XmlRes -import android.support.v7.widget.RecyclerView 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.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 com.afollestad.materialdialogs.list.customListAdapter +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.xmlpull.v1.XmlPullParser - /** * Created by Allan Wang on 2017-05-28. * * 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() - } +fun Context.showChangelog(@XmlRes xmlRes: Int, @ColorInt textColor: Int? = null, customize: MaterialDialog.() -> Unit = {}) { + ctxCoroutine.launch { + val items = withContext(Dispatchers.Default) { parse(this@showChangelog, xmlRes) } + materialDialog { + title(R.string.kau_changelog) + positiveButton(R.string.kau_great) + customListAdapter(ChangelogAdapter(items, textColor), null) + customize() } } } @@ -42,10 +57,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<Pair<String, ChangelogType>>, @ColorInt val textColor: Int? = null) : RecyclerView.Adapter<ChangelogAdapter.ChangelogVH>() { +internal class ChangelogAdapter(val items: List<Pair<String, ChangelogType>>, @ColorInt val textColor: Int? = null) : + RecyclerView.Adapter<ChangelogAdapter.ChangelogVH>() { - 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 +116,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 7caf5d6..73d7d6c 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt @@ -1,13 +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.xml import android.content.Context import android.content.res.XmlResourceParser -import android.support.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 import org.xmlpull.v1.XmlPullParser /** @@ -15,51 +28,53 @@ import org.xmlpull.v1.XmlPullParser */ /** - * Parse an xml asynchronously with two tags, <question>Text</question> and <answer>Text</answer>, - * and invoke the [callback] on the ui thread + * Parse an xml asynchronously with two tags, <question>Text</question> and <answer>Text</answer>. + * Note that this should executed in a background thread. */ @Suppress("DEPRECATION") fun Context.kauParseFaq( - @XmlRes xmlRes: Int, - /** - * If \n is used, it will automatically be converted to </br> - */ - parseNewLine: Boolean = true, - callback: (items: List<FaqItem>) -> Unit) { - doAsync { - val items = mutableListOf<FaqItem>() - 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 + @XmlRes xmlRes: Int, + /** + * If \n is used, it will automatically be converted to </br> + */ + parseNewLine: Boolean = true +): List<FaqItem> { + val items = mutableListOf<FaqItem>() + 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) "<br/>" else "")) + flag = -1 } - } else if (eventType == XmlPullParser.TEXT) { - when (flag) { - 0 -> { - question = Html.fromHtml(parser.text.replace("\n", if (parseNewLine) "<br/>" 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) "<br/>" else "")))) - question = null - 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) "<br/>" else "")) + ) + ) + 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)
\ No newline at end of file +data class FaqItem(val number: Int, val question: Spanned, val answer: Spanned) diff --git a/core/src/main/res-public/values-da-rDK/strings_commons.xml b/core/src/main/res-public/values-da-rDK/strings_commons.xml index 5be1277..745418a 100644 --- a/core/src/main/res-public/values-da-rDK/strings_commons.xml +++ b/core/src/main/res-public/values-da-rDK/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-de-rDE/strings_commons.xml b/core/src/main/res-public/values-de-rDE/strings_commons.xml index 015b612..e67292c 100644 --- a/core/src/main/res-public/values-de-rDE/strings_commons.xml +++ b/core/src/main/res-public/values-de-rDE/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-es-rES/strings_commons.xml b/core/src/main/res-public/values-es-rES/strings_commons.xml index 7cab287..34e4aa7 100644 --- a/core/src/main/res-public/values-es-rES/strings_commons.xml +++ b/core/src/main/res-public/values-es-rES/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-fr-rFR/strings_commons.xml b/core/src/main/res-public/values-fr-rFR/strings_commons.xml index 2d681ff..89a9a99 100644 --- a/core/src/main/res-public/values-fr-rFR/strings_commons.xml +++ b/core/src/main/res-public/values-fr-rFR/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-gl-rES/strings_commons.xml b/core/src/main/res-public/values-gl-rES/strings_commons.xml index b9a5564..8b4d1b4 100644 --- a/core/src/main/res-public/values-gl-rES/strings_commons.xml +++ b/core/src/main/res-public/values-gl-rES/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-hu-rHU/strings_commons.xml b/core/src/main/res-public/values-hu-rHU/strings_commons.xml index 5488f1d..bae6c1e 100644 --- a/core/src/main/res-public/values-hu-rHU/strings_commons.xml +++ b/core/src/main/res-public/values-hu-rHU/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-in-rID/strings_commons.xml b/core/src/main/res-public/values-in-rID/strings_commons.xml index b734377..5532b67 100644 --- a/core/src/main/res-public/values-in-rID/strings_commons.xml +++ b/core/src/main/res-public/values-in-rID/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-it-rIT/strings_commons.xml b/core/src/main/res-public/values-it-rIT/strings_commons.xml index 821191e..c2d513a 100644 --- a/core/src/main/res-public/values-it-rIT/strings_commons.xml +++ b/core/src/main/res-public/values-it-rIT/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-ko-rKR/strings_commons.xml b/core/src/main/res-public/values-ko-rKR/strings_commons.xml index 112e8d5..48153cb 100644 --- a/core/src/main/res-public/values-ko-rKR/strings_commons.xml +++ b/core/src/main/res-public/values-ko-rKR/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-nl-rNL/strings_commons.xml b/core/src/main/res-public/values-nl-rNL/strings_commons.xml new file mode 100644 index 0000000..a3967ff --- /dev/null +++ b/core/src/main/res-public/values-nl-rNL/strings_commons.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- +A collection of common string values +Most resources are verbatim and x represents a formatted item +--> +<resources> + <string name="kau_about_app">Over de app</string> + <string name="kau_about_x">Over %s</string> + <string name="kau_add_account">Account toevoegen</string> + <string name="kau_back">Terug</string> + <string name="kau_cancel">Annuleren</string> + <string name="kau_changelog">Veranderingen</string> + <string name="kau_close">Sluiten</string> + <string name="kau_contact_us">Contact opnemen</string> + <string name="kau_copy">Kopiëren</string> + <string name="kau_custom">Aangepast</string> + <string name="kau_dark">Donker</string> + <string name="kau_default">Standaard</string> + <string name="kau_do_not_show_again">Niet opnieuw tonen</string> + <string name="kau_done">Gereed</string> + <string name="kau_error">Fout</string> + <string name="kau_exit">Afsluiten</string> + <string name="kau_exit_confirmation">Afsluiten?</string> + <string name="kau_exit_confirmation_x">%s afsluiten?</string> + <string name="kau_glass">Glas</string> + <string name="kau_got_it">Begrepen</string> + <string name="kau_great">Geweldig</string> + <string name="kau_hide">Verbergen</string> + <string name="kau_light">Licht</string> + <string name="kau_login">Aanmelden</string> + <string name="kau_logout">Afmelden</string> + <string name="kau_logout_confirm_as_x">%s uitloggen?</string> + <string name="kau_manage_account">Account beheren</string> + <string name="kau_maybe">Misschien</string> + <string name="kau_menu">Menu</string> + <string name="kau_no">Nee</string> + <string name="kau_no_results_found">Geen resultaten</string> + <string name="kau_none">Geen</string> + <string name="kau_ok">OK</string> + <string name="kau_play_store">Play Store</string> + <string name="kau_rate">Beoordelen</string> + <string name="kau_report_bug">Een fout melden</string> + <string name="kau_search">Zoeken</string> + <string name="kau_send_feedback">Feedback geven</string> + <string name="kau_send_via">Verzenden via</string> + <string name="kau_settings">Instellingen</string> + <string name="kau_share">Delen</string> + <string name="kau_text_copied">Tekst naar klembord gekopieerd.</string> + <string name="kau_thank_you">Bedankt</string> + <string name="kau_uh_oh">Oeps</string> + <string name="kau_warning">Waarschuwing</string> + <plurals name="kau_x_days"> + <item quantity="one">%d dag</item> + <item quantity="other">%d dagen</item> + </plurals> + <plurals name="kau_x_hours"> + <item quantity="one">%d uur</item> + <item quantity="other">%d uren</item> + </plurals> + <plurals name="kau_x_minutes"> + <item quantity="one">%d minuut</item> + <item quantity="other">%d minuten</item> + </plurals> + <plurals name="kau_x_seconds"> + <item quantity="one">%d seconde</item> + <item quantity="other">%d seconden</item> + </plurals> + <string name="kau_yes">Ja</string> + <string name="kau_permission_denied">Toestemming geweigerd</string> +</resources> diff --git a/core/src/main/res-public/values-no-rNO/strings_commons.xml b/core/src/main/res-public/values-no-rNO/strings_commons.xml index c18b439..e27f20d 100644 --- a/core/src/main/res-public/values-no-rNO/strings_commons.xml +++ b/core/src/main/res-public/values-no-rNO/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-pl-rPL/strings_commons.xml b/core/src/main/res-public/values-pl-rPL/strings_commons.xml index 248e409..323a0ff 100644 --- a/core/src/main/res-public/values-pl-rPL/strings_commons.xml +++ b/core/src/main/res-public/values-pl-rPL/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-pt-rBR/strings_commons.xml b/core/src/main/res-public/values-pt-rBR/strings_commons.xml index 716e373..4eaea6c 100644 --- a/core/src/main/res-public/values-pt-rBR/strings_commons.xml +++ b/core/src/main/res-public/values-pt-rBR/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-pt-rPT/strings_commons.xml b/core/src/main/res-public/values-pt-rPT/strings_commons.xml new file mode 100644 index 0000000..863b8b7 --- /dev/null +++ b/core/src/main/res-public/values-pt-rPT/strings_commons.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- +A collection of common string values +Most resources are verbatim and x represents a formatted item +--> +<resources> + <string name="kau_about_app">Acerca</string> + <string name="kau_about_x">Acerca de %s</string> + <string name="kau_add_account">Adicionar conta</string> + <string name="kau_back">Voltar</string> + <string name="kau_cancel">Cancelar</string> + <string name="kau_changelog">Registo de alterações</string> + <string name="kau_close">Fechar</string> + <string name="kau_contact_us">Contacte-nos</string> + <string name="kau_copy">Copiar</string> + <string name="kau_custom">Personalizada</string> + <string name="kau_dark">Escuro</string> + <string name="kau_default">Padrão</string> + <string name="kau_do_not_show_again">Não mostrar novamente</string> + <string name="kau_done">Feito</string> + <string name="kau_error">Erro</string> + <string name="kau_exit">Sair</string> + <string name="kau_exit_confirmation">Tem a certeza de que deseja sair?</string> + <string name="kau_exit_confirmation_x">Tem a certeza de que deseja sair de %s?</string> + <string name="kau_glass">Vidro</string> + <string name="kau_got_it">Percebi</string> + <string name="kau_great">Excelente</string> + <string name="kau_hide">Ocultar</string> + <string name="kau_light">Claro</string> + <string name="kau_login">Iniciar sessão</string> + <string name="kau_logout">Sair</string> + <string name="kau_logout_confirm_as_x">Tem a certeza de que deseja sair como %s?</string> + <string name="kau_manage_account">Gerir conta</string> + <string name="kau_maybe">Talvez</string> + <string name="kau_menu">Menu</string> + <string name="kau_no">Não</string> + <string name="kau_no_results_found">Não existem resultados</string> + <string name="kau_none">Nenhum</string> + <string name="kau_ok">OK</string> + <string name="kau_play_store">Play Store</string> + <string name="kau_rate">Avaliar</string> + <string name="kau_report_bug">Comunicar um erro</string> + <string name="kau_search">Procurar</string> + <string name="kau_send_feedback">Enviar comentários</string> + <string name="kau_send_via">Enviar via</string> + <string name="kau_settings">Definições</string> + <string name="kau_share">Partilhar</string> + <string name="kau_text_copied">Texto copiado para a área de transferência.</string> + <string name="kau_thank_you">Obrigado</string> + <string name="kau_uh_oh">Bolas</string> + <string name="kau_warning">Aviso</string> + <plurals name="kau_x_days"> + <item quantity="one">%d dia</item> + <item quantity="other">%d dias</item> + </plurals> + <plurals name="kau_x_hours"> + <item quantity="one">%d hora</item> + <item quantity="other">%d horas</item> + </plurals> + <plurals name="kau_x_minutes"> + <item quantity="one">%d minuto</item> + <item quantity="other">%d minutos</item> + </plurals> + <plurals name="kau_x_seconds"> + <item quantity="one">%d segundo</item> + <item quantity="other">%d segundos</item> + </plurals> + <string name="kau_yes">Sim</string> + <string name="kau_permission_denied">Permissão negada</string> +</resources> diff --git a/core/src/main/res-public/values-sr-rSP/strings_commons.xml b/core/src/main/res-public/values-sr-rSP/strings_commons.xml new file mode 100644 index 0000000..213d876 --- /dev/null +++ b/core/src/main/res-public/values-sr-rSP/strings_commons.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- +A collection of common string values +Most resources are verbatim and x represents a formatted item +--> +<resources> + <string name="kau_about_app">О апликацији</string> + <string name="kau_about_x">О %s</string> + <string name="kau_add_account">Додајте налог</string> + <string name="kau_back">Назад</string> + <string name="kau_cancel">Откажи</string> + <string name="kau_changelog">Евиденција измена</string> + <string name="kau_close">Затвори</string> + <string name="kau_contact_us">Контактирајте нас</string> + <string name="kau_copy">Копирај</string> + <string name="kau_custom">Прилагођено</string> + <string name="kau_dark">Тамно</string> + <string name="kau_default">Подразумевано</string> + <string name="kau_do_not_show_again">Не приказуј поново</string> + <string name="kau_done">Готово</string> + <string name="kau_error">Грешка</string> + <string name="kau_exit">Изађи</string> + <string name="kau_exit_confirmation">Да ли сте сигурни да желите да изађете?</string> + <string name="kau_exit_confirmation_x">Да ли сте сигурно желите да напустите %s?</string> + <string name="kau_glass">Стакло</string> + <string name="kau_got_it">Разумем</string> + <string name="kau_great">Одлично</string> + <string name="kau_hide">Сакриј</string> + <string name="kau_light">Светло</string> + <string name="kau_login">Пријава</string> + <string name="kau_logout">Одјави се</string> + <string name="kau_logout_confirm_as_x">Заиста желите да се одјавите са %s?</string> + <string name="kau_manage_account">Управљај налозима</string> + <string name="kau_maybe">Можда</string> + <string name="kau_menu">Мени</string> + <string name="kau_no">Не</string> + <string name="kau_no_results_found">Нема резултата</string> + <string name="kau_none">Ниједно</string> + <string name="kau_ok">ОК</string> + <string name="kau_play_store">Плеј продавница</string> + <string name="kau_rate">Оцени</string> + <string name="kau_report_bug">Пријави грешку</string> + <string name="kau_search">Претражи</string> + <string name="kau_send_feedback">Пошаљите повратне информације</string> + <string name="kau_send_via">Пошаљи преко</string> + <string name="kau_settings">Подешавања</string> + <string name="kau_share">Подели</string> + <string name="kau_text_copied">Текст је копиран у привремену меморију.</string> + <string name="kau_thank_you">Хвала</string> + <string name="kau_uh_oh">Јао не</string> + <string name="kau_warning">Упозорење</string> + <plurals name="kau_x_days"> + <item quantity="one">%d дан</item> + <item quantity="few">%d дана</item> + <item quantity="other">%d дана</item> + </plurals> + <plurals name="kau_x_hours"> + <item quantity="one">%d сат</item> + <item quantity="few">%d сати</item> + <item quantity="other">%d сати</item> + </plurals> + <plurals name="kau_x_minutes"> + <item quantity="one">%d минут</item> + <item quantity="few">%d минута</item> + <item quantity="other">%d минута</item> + </plurals> + <plurals name="kau_x_seconds"> + <item quantity="one">%d секунду</item> + <item quantity="few">%d сек</item> + <item quantity="other">%d секунди</item> + </plurals> + <string name="kau_yes">Да</string> + <string name="kau_permission_denied">Немате овлашћења</string> +</resources> diff --git a/core/src/main/res-public/values-sv-rSE/strings_commons.xml b/core/src/main/res-public/values-sv-rSE/strings_commons.xml index 6cc2bb3..8d4362b 100644 --- a/core/src/main/res-public/values-sv-rSE/strings_commons.xml +++ b/core/src/main/res-public/values-sv-rSE/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-th-rTH/strings_commons.xml b/core/src/main/res-public/values-th-rTH/strings_commons.xml index 2f4bdec..e47273d 100644 --- a/core/src/main/res-public/values-th-rTH/strings_commons.xml +++ b/core/src/main/res-public/values-th-rTH/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-tr-rTR/strings_commons.xml b/core/src/main/res-public/values-tr-rTR/strings_commons.xml index 1e8395e..b36ca43 100644 --- a/core/src/main/res-public/values-tr-rTR/strings_commons.xml +++ b/core/src/main/res-public/values-tr-rTR/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-uk-rUA/strings_commons.xml b/core/src/main/res-public/values-uk-rUA/strings_commons.xml index 60ca520..0f62c6a 100644 --- a/core/src/main/res-public/values-uk-rUA/strings_commons.xml +++ b/core/src/main/res-public/values-uk-rUA/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> @@ -48,6 +50,30 @@ Most resources are verbatim and x represents a formatted item <string name="kau_thank_you">Дякуємо Вам</string> <string name="kau_uh_oh">Ой-ой</string> <string name="kau_warning">Увага</string> + <plurals name="kau_x_days"> + <item quantity="one">%d день</item> + <item quantity="few">%d днів</item> + <item quantity="many">%d днів</item> + <item quantity="other">%d днів</item> + </plurals> + <plurals name="kau_x_hours"> + <item quantity="one">%d годину</item> + <item quantity="few">%d годин</item> + <item quantity="many">%d годин</item> + <item quantity="other">%d годин</item> + </plurals> + <plurals name="kau_x_minutes"> + <item quantity="one">%d хвилини</item> + <item quantity="few">%d хвилин</item> + <item quantity="many">%d хвилин</item> + <item quantity="other">%d хвилин</item> + </plurals> + <plurals name="kau_x_seconds"> + <item quantity="one">%d секунди</item> + <item quantity="few">%d секунд</item> + <item quantity="many">%d секунд</item> + <item quantity="other">%d секунд</item> + </plurals> <string name="kau_yes">Так</string> <string name="kau_permission_denied">У доступі відмовлено</string> </resources> diff --git a/core/src/main/res-public/values-vi-rVN/strings_commons.xml b/core/src/main/res-public/values-vi-rVN/strings_commons.xml index 767e628..a444dc2 100644 --- a/core/src/main/res-public/values-vi-rVN/strings_commons.xml +++ b/core/src/main/res-public/values-vi-rVN/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-zh-rCN/strings_commons.xml b/core/src/main/res-public/values-zh-rCN/strings_commons.xml index 47ddbda..66a7423 100644 --- a/core/src/main/res-public/values-zh-rCN/strings_commons.xml +++ b/core/src/main/res-public/values-zh-rCN/strings_commons.xml @@ -1,4 +1,6 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?><!--Generated by crowdin.com--><!-- +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- A collection of common string values Most resources are verbatim and x represents a formatted item --> diff --git a/core/src/main/res-public/values-zh-rTW/strings_commons.xml b/core/src/main/res-public/values-zh-rTW/strings_commons.xml new file mode 100644 index 0000000..bf9f59b --- /dev/null +++ b/core/src/main/res-public/values-zh-rTW/strings_commons.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!--Generated by crowdin.com--> +<!-- +A collection of common string values +Most resources are verbatim and x represents a formatted item +--> +<resources> + <string name="kau_about_app">關於此程式</string> + <string name="kau_about_x">關於 %s</string> + <string name="kau_add_account">新增帳號</string> + <string name="kau_back">回上頁</string> + <string name="kau_cancel">取消</string> + <string name="kau_changelog">更新資訊</string> + <string name="kau_close">關閉</string> + <string name="kau_contact_us">與我們聯繫</string> + <string name="kau_copy">複製</string> + <string name="kau_custom">自訂</string> + <string name="kau_dark">黑色主題</string> + <string name="kau_default">默認</string> + <string name="kau_do_not_show_again">不要再顯示</string> + <string name="kau_done">完成</string> + <string name="kau_error">錯誤</string> + <string name="kau_exit">結束</string> + <string name="kau_exit_confirmation">您確定要離開嗎?</string> + <string name="kau_exit_confirmation_x">您確定要離開%s嗎?</string> + <string name="kau_glass">玻璃</string> + <string name="kau_got_it">知道了</string> + <string name="kau_great">讚</string> + <string name="kau_hide">隱藏</string> + <string name="kau_light">亮色調</string> + <string name="kau_login">登入</string> + <string name="kau_logout">登出</string> + <string name="kau_logout_confirm_as_x">您確定要登出%s嗎?</string> + <string name="kau_manage_account">帳戶管理</string> + <string name="kau_maybe">可能</string> + <string name="kau_menu">選單</string> + <string name="kau_no">不</string> + <string name="kau_no_results_found">找不到相符的結果</string> + <string name="kau_none">無</string> + <string name="kau_ok">確定</string> + <string name="kau_play_store">Play商店</string> + <string name="kau_rate">評分</string> + <string name="kau_report_bug">回報程式錯誤</string> + <string name="kau_search">搜尋</string> + <string name="kau_send_feedback">回饋意見</string> + <string name="kau_send_via">來發送</string> + <string name="kau_settings">設定</string> + <string name="kau_share">分享</string> + <string name="kau_text_copied">文字已複製到剪貼簿</string> + <string name="kau_thank_you">感謝</string> + <string name="kau_uh_oh">噢!</string> + <string name="kau_warning">警告</string> + <plurals name="kau_x_days"> + <item quantity="other">%d 天</item> + </plurals> + <plurals name="kau_x_hours"> + <item quantity="other">%d 小時</item> + </plurals> + <plurals name="kau_x_minutes"> + <item quantity="other">%d 分鐘</item> + </plurals> + <plurals name="kau_x_seconds"> + <item quantity="other">%d 秒</item> + </plurals> + <string name="kau_yes">是</string> + <string name="kau_permission_denied">權限不足</string> +</resources> diff --git a/core/src/main/res/layout/kau_changelog_content.xml b/core/src/main/res/layout/kau_changelog_content.xml index 5c463aa..ab94956 100644 --- a/core/src/main/res/layout/kau_changelog_content.xml +++ b/core/src/main/res/layout/kau_changelog_content.xml @@ -3,9 +3,9 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" - android:paddingBottom="8.4sp" android:paddingLeft="@dimen/kau_dialog_margin" - android:paddingRight="@dimen/kau_dialog_margin"> + android:paddingRight="@dimen/kau_dialog_margin" + android:paddingBottom="8.4sp"> <!--padding bottom is 14sp * 0.6--> 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..1e86305 --- /dev/null +++ b/core/src/test/kotlin/ca/allanwang/kau/kotlin/CoroutineTest.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2019 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 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") + } + } +} 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 deleted file mode 100644 index 7eeffaf..0000000 --- a/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt +++ /dev/null @@ -1,70 +0,0 @@ -package ca.allanwang.kau.kotlin - -import org.jetbrains.anko.doAsync -import org.junit.Test -import java.util.* -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<Int> -> - 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) - } - -}
\ 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..b9c200a 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 @@ -17,9 +32,27 @@ class UtilsTest { } @Test + fun colorWithAlpha() { + val origColor = 0xFF123456.toInt() + assertEquals(0x00123456, origColor.withAlpha(0), "Failed to convert with alpha 0") + assertEquals(0x50123456, origColor.withAlpha(80), "Failed to convert with alpha 80") + assertEquals(0xFF123456.toInt(), origColor.withAlpha(255), "Failed to convert with alpha 255") + assertEquals(0xFF123456.toInt(), origColor.withAlpha(0xFF), "Failed to convert with alpha 0xFF") + assertEquals(Color.TRANSPARENT, Color.BLACK.withAlpha(0), "Failed to convert black to transparent") + } + + @Test + fun colorWithMinAlpha() { + val origColor = 0x80123456.toInt() + assertEquals(origColor, origColor.withMinAlpha(0), "Failed to convert with min alpha 0") + assertEquals(0xFA123456.toInt(), origColor.withMinAlpha(0xFA), "Failed to convert with min alpha 0xFA") + assertEquals(Color.BLUE, Color.BLUE.withMinAlpha(89), "Failed to convert blue with min alpha 89") + } + + @Test fun rounding() { assertEquals("1.23", 1.23456f.round(2)) assertEquals("22.466", 22.465920439.round(3)) assertEquals("22", 22f.round(3)) } -}
\ No newline at end of file +} diff --git a/crowdin.yaml b/crowdin.yaml deleted file mode 100644 index 9d8a460..0000000 --- a/crowdin.yaml +++ /dev/null @@ -1,21 +0,0 @@ -"project_identifier": "kotlin-android-utils" -"base_path": "/" - -"files": [ - { - "source" : "/about/src/main/res/values/strings_about.xml", - "translation" : "/about/src/main/res/values-%android_code%/strings_about.xml" - }, - { - "source" : "/colorpicker/src/main/res/values/strings_colorpicker.xml", - "translation" : "/colorpicker/src/main/res/values-%android_code%/strings_colorpicker.xml" - }, - { - "source" : "/core/src/main/res-public/values/strings_commons.xml", - "translation" : "/core/src/main/res-public/values-%android_code%/strings_commons.xml" - }, - { - "source" : "/mediapicker/src/main/res/values/strings_mediapicker.xml", - "translation" : "/mediapicker/src/main/res/values-%android_code%/strings_mediapicker.xml" - } -]
\ No newline at end of file diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 0000000..7e610f0 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,9 @@ +files: + - source: /about/src/main/res/values/strings_about.xml + translation: /about/src/main/res/values-%android_code%/strings_about.xml + - source: /colorpicker/src/main/res/values/strings_colorpicker.xml + translation: /colorpicker/src/main/res/values-%android_code%/strings_colorpicker.xml + - source: /core/src/main/res-public/values/strings_commons.xml + translation: /core/src/main/res-public/values-%android_code%/strings_commons.xml + - source: /mediapicker/src/main/res/values/strings_mediapicker.xml + translation: /mediapicker/src/main/res/values-%android_code%/strings_mediapicker.xml diff --git a/docs/Changelog.md b/docs/Changelog.md index a5f24f4..a2c38e1 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -1,5 +1,26 @@ # Changelog +## v4.1.0 +* :core: Deprecate NetworkUtils, as the underlying functions are deprecated +* :core: Permission manager no longer synchronized, as all actions should occur in the main thread +* :kpref-activity: Getter and setter now have action context, with the option to reload self + +## v4.0.0 +* Update translations + +## v4.0.0-alpha02 +* Update translations +* :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 +* :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 +* 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 * Fix new lint issues (see Migration for resource related methods) diff --git a/docs/Migration.md b/docs/Migration.md index ea30c0d..593056e 100644 --- a/docs/Migration.md +++ b/docs/Migration.md @@ -2,12 +2,43 @@ Below are some highlights on major refactoring/breaking changes -# v4.0.0 +# v5.0.0 + +## Material Dialog Update + +Material Dialog is now 3.x. +This leads to a whole new API, but fortunately it is based around kotlin. +Please refer to [MD's documents](https://github.com/afollestad/material-dialogs/tree/3.0.0-rc2/documentation) for the new methods. + +Alongside such changes, `:colorpicker` is no longer as necessary. It exists mainly to provide an internal interface for other submodules. ## Update ProgressAnimator `ProgressAnimator` has been completely rewritten to be an extension of `ValueAnimator`. This for the most part is not a breaking change, apart from the fact that creating an animator will not start it immediately. +Make sure to call `.start()` to begin the animation. + +# 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. +Nothing has been changed internally, but the dependencies are updated. +Notably, Android-Iconics [split their Community Icons](https://github.com/mikepenz/Android-Iconics/blob/develop/MIGRATION.md) into two enums. + +Kotterknife is also no longer deprecated. There are some use cases where `kotlin-android-extensions` isn't the best, such as when multiple layout files are used, or when ids are defined in the id.xml. +It is still recommended to use the extension where applicable. # v3.8.0 diff --git a/favicon/android-chrome-192x192.png b/favicon/android-chrome-192x192.png Binary files differnew file mode 100644 index 0000000..2d2a7fa --- /dev/null +++ b/favicon/android-chrome-192x192.png diff --git a/favicon/android-chrome-512x512.png b/favicon/android-chrome-512x512.png Binary files differnew file mode 100644 index 0000000..6b7cee2 --- /dev/null +++ b/favicon/android-chrome-512x512.png diff --git a/favicon/apple-touch-icon.png b/favicon/apple-touch-icon.png Binary files differnew file mode 100644 index 0000000..a62432c --- /dev/null +++ b/favicon/apple-touch-icon.png diff --git a/favicon/browserconfig.xml b/favicon/browserconfig.xml new file mode 100644 index 0000000..ed5dd79 --- /dev/null +++ b/favicon/browserconfig.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<browserconfig> + <msapplication> + <tile> + <square150x150logo src="favicon/mstile-150x150.png"/> + <TileColor>#da532c</TileColor> + </tile> + </msapplication> +</browserconfig> diff --git a/favicon/favicon-16x16.png b/favicon/favicon-16x16.png Binary files differnew file mode 100644 index 0000000..edd0ca3 --- /dev/null +++ b/favicon/favicon-16x16.png diff --git a/favicon/favicon-32x32.png b/favicon/favicon-32x32.png Binary files differnew file mode 100644 index 0000000..34ab2f4 --- /dev/null +++ b/favicon/favicon-32x32.png diff --git a/favicon/favicon.ico b/favicon/favicon.ico Binary files differnew file mode 100644 index 0000000..f6c4784 --- /dev/null +++ b/favicon/favicon.ico diff --git a/favicon/mstile-150x150.png b/favicon/mstile-150x150.png Binary files differnew file mode 100644 index 0000000..44d2059 --- /dev/null +++ b/favicon/mstile-150x150.png diff --git a/favicon/safari-pinned-tab.svg b/favicon/safari-pinned-tab.svg new file mode 100644 index 0000000..c64d556 --- /dev/null +++ b/favicon/safari-pinned-tab.svg @@ -0,0 +1,17 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" + "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> +<svg version="1.0" xmlns="http://www.w3.org/2000/svg" + width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000" + preserveAspectRatio="xMidYMid meet"> +<metadata> +Created by potrace 1.11, written by Peter Selinger 2001-2013 +</metadata> +<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)" +fill="#000000" stroke="none"> +<path d="M2420 4754 c-495 -44 -915 -214 -1272 -514 l-98 -81 0 -1599 0 -1599 +82 -71 c115 -99 299 -220 441 -292 324 -162 623 -232 987 -232 361 0 669 72 +985 230 200 101 421 261 565 408 l55 56 -753 753 -752 752 750 750 750 750 +-58 58 c-258 264 -662 487 -1042 576 -181 42 -487 69 -640 55z"/> +</g> +</svg> diff --git a/favicon/site.webmanifest b/favicon/site.webmanifest new file mode 100644 index 0000000..1edcfef --- /dev/null +++ b/favicon/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/files/translation_migration.sh b/files/translation_migration.sh index 9adfdc4..d1372d1 100644 --- a/files/translation_migration.sh +++ b/files/translation_migration.sh @@ -6,12 +6,13 @@ cd .. current=${PWD##*/} -if [ "$current" != "$MODULE" ]; then +if [[ "$current" != "$MODULE" ]]; then echo "Not in $MODULE"; else # DANGEROUS! Removes all files matching regex - egrep -lir --include="*.xml" "<resources.*></resources>" "./" | tr '\n' '\0' | xargs -0 -n1 rm + grep -Lir "</string>" --include="strings*.xml" "." | tr '\n' '\0' | xargs -0 -n1 rm # Delete empty directories find . -type d -empty -delete fi +echo "Finished cleanieckng files"
\ No newline at end of file diff --git a/gradle.properties b/gradle.properties index f1c49f3..1e0c1d3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,6 +9,8 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. +android.enableJetifier=true +android.useAndroidX=true org.gradle.jvmargs=-Xmx1536m # When configured, Gradle will run in incubating parallel mode. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9a4163a..9fccf04 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Tue May 21 11:47:57 PDT 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-5.1.1-all.zip diff --git a/kpref-activity/build.gradle b/kpref-activity/build.gradle index 8b2d12d..ef91e2b 100644 --- a/kpref-activity/build.gradle +++ b/kpref-activity/build.gradle @@ -6,8 +6,8 @@ apply from: '../android-lib.gradle' dependencies { implementation project(':core') - implementation project(':adapter') implementation project(':colorpicker') + implementation project(':adapter') } apply from: '../artifacts.gradle' 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<T> { * The item holding the data */ val item: KPrefItemBase<T> -}
\ 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 b9681e9..edaf347 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,42 @@ +/* + * 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.support.annotation.StringRes -import android.support.v7.widget.Toolbar import android.view.View +import androidx.annotation.StringRes +import androidx.appcompat.widget.Toolbar 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 kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.util.Stack abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract { @@ -32,12 +52,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,26 +93,36 @@ 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) - - private fun showNextPrefs(@StringRes toolbarTitleRes: Int, builder: KPrefAdapterBuilder.() -> Unit, first: Boolean) { - doAsync { - val items = KPrefAdapterBuilder(globalOptions) - builder(items) - kprefStack.push(toolbarTitleRes to items.list) - kau_recycler.itemAnimator = if (animate && !first) recyclerAnimatorNext else null - uiThread { - adapter.clear() - adapter.add(items.list.filter { it.core.visible() }) - toolbar.setTitle(toolbarTitleRes) + override fun showNextPrefs(@StringRes toolbarTitleRes: Int, builder: KPrefAdapterBuilder.() -> Unit) = + showNextPrefs(toolbarTitleRes, builder, false) + + private fun showNextPrefs( + @StringRes toolbarTitleRes: Int, + builder: KPrefAdapterBuilder.() -> Unit, + first: Boolean + ) { + launch { + val items = withContext(Dispatchers.Default) { + val items = KPrefAdapterBuilder(globalOptions) + builder(items) + kprefStack.push(toolbarTitleRes to items.list) + items.list } + kau_recycler.itemAnimator = if (animate && !first) recyclerAnimatorNext else null + show(toolbarTitleRes, items) } } + private fun show(@StringRes toolbarTitleRes: Int, items: List<KPrefItemCore>) { + 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 @@ -97,9 +131,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) } /** @@ -162,4 +194,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 2cdeae2..764831e 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 android.support.annotation.StringRes -import ca.allanwang.kau.kpref.activity.items.* +import androidx.annotation.StringRes +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<Boolean>.() -> Unit = {}) = list.add(KPrefCheckbox(KPrefItemBase.BaseBuilder(globalOptions, title, getter, setter) - .apply { builder() })) + fun checkbox( + @StringRes title: Int, + getter: () -> Boolean, + setter: KPrefItemActions.(value: Boolean) -> Unit, + builder: KPrefItemBase.BaseContract<Boolean>.() -> 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: KPrefItemActions.(value: Int) -> Unit, + builder: KPrefColorPicker.KPrefColorContract.() -> Unit = {} + ) = list.add( + KPrefColorPicker(KPrefColorPicker.KPrefColorBuilder(globalOptions, title, getter, setter) + .apply { builder() }) + ) @KPrefMarker - fun <T> text(@StringRes title: Int, - getter: (() -> T), - setter: ((value: T) -> Unit), - builder: KPrefText.KPrefTextContract<T>.() -> Unit = {}) = list.add(KPrefText(KPrefText.KPrefTextBuilder(globalOptions, title, getter, setter) - .apply { builder() })) + fun <T> text( + @StringRes title: Int, + getter: () -> T, + setter: KPrefItemActions.(value: T) -> Unit, + builder: KPrefText.KPrefTextContract<T>.() -> 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>.() -> Unit = {}) = list.add(KPrefPlainText(KPrefPlainText.KPrefPlainTextBuilder(globalOptions, title) - .apply { builder() })) + fun plainText( + @StringRes title: Int, + builder: KPrefItemBase.BaseContract<Unit>.() -> 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: KPrefItemActions.(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: KPrefItemActions.(value: Int) -> Unit, + builder: KPrefTimePicker.KPrefTimeContract.() -> Unit = {} + ) = list.add( + KPrefTimePicker(KPrefTimePicker.KPrefTimeBuilder(globalOptions, title, getter, setter) + .apply { builder() }) + ) @KPrefMarker val list: MutableList<KPrefItemCore> = mutableListOf() -}
\ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefItemActions.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefItemActions.kt new file mode 100644 index 0000000..e28bac6 --- /dev/null +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefItemActions.kt @@ -0,0 +1,11 @@ +package ca.allanwang.kau.kpref.activity + +/** + * Applicable actions + */ +interface KPrefItemActions { + /** + * Attempts to reload current item by identifying it with its titleId + */ + fun reloadSelf() +}
\ 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 f391747..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 android.support.v7.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<Boolean>) : KPrefItemBase<Boolean } override fun getType(): Int = R.id.kau_item_pref_checkbox - -}
\ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefColorPicker.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefColorPicker.kt index 3201fbd..8b051c5 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefColorPicker.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefColorPicker.kt @@ -1,12 +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.kpref.activity.items import ca.allanwang.kau.colorpicker.CircleView import ca.allanwang.kau.colorpicker.ColorBuilder import ca.allanwang.kau.colorpicker.ColorContract -import ca.allanwang.kau.colorpicker.colorPickerDialog +import ca.allanwang.kau.colorpicker.kauColorChooser import ca.allanwang.kau.kpref.activity.GlobalOptions import ca.allanwang.kau.kpref.activity.KClick +import ca.allanwang.kau.kpref.activity.KPrefItemActions import ca.allanwang.kau.kpref.activity.R +import com.afollestad.materialdialogs.MaterialDialog /** * Created by Allan Wang on 2017-06-07. @@ -18,50 +35,52 @@ open class KPrefColorPicker(open val builder: KPrefColorContract) : KPrefItemBas override fun bindView(holder: ViewHolder, payloads: List<Any>) { super.bindView(holder, payloads) - builder.apply { - titleRes = core.titleFun() - colorCallback = { pref = it } - } if (builder.showPreview) { val preview = holder.bindInnerView<CircleView>(R.layout.kau_pref_color) preview.setBackgroundColor(pref) preview.withBorder = true - builder.apply { - colorCallback = { - pref = it - if (builder.showPreview) - preview.setBackgroundColor(it) - holder.updateTitle() - holder.updateDesc() - } + builder.callback = { _, color -> + pref = color + if (builder.showPreview) + preview.setBackgroundColor(color) + holder.updateTitle() + holder.updateDesc() } + } else { + builder.callback = { _, color -> pref = color } } } override fun KClick<Int>.defaultOnClick() { builder.defaultColor = pref - context.colorPickerDialog(builder).show() + MaterialDialog(context).show { + kauColorChooser(builder) + builder.dialogBuilder(this) + title(core.titleFun()) + } } /** * Extension of the base contract and [ColorContract] along with a showPreview option */ - interface KPrefColorContract : BaseContract<Int>, ColorContract { + interface KPrefColorContract : KPrefItemBase.BaseContract<Int>, ColorContract { var showPreview: Boolean + var dialogBuilder: MaterialDialog.() -> Unit } /** * Default implementation of [KPrefColorContract] */ - class KPrefColorBuilder(globalOptions: GlobalOptions, - titleId: Int, - getter: () -> Int, - setter: (value: Int) -> Unit - ) : KPrefColorContract, BaseContract<Int> by BaseBuilder(globalOptions, titleId, getter, setter), - ColorContract by ColorBuilder() { + class KPrefColorBuilder( + globalOptions: GlobalOptions, + titleId: Int, + getter: () -> Int, + setter: KPrefItemActions.(value: Int) -> Unit + ) : KPrefColorContract, KPrefItemBase.BaseContract<Int> by BaseBuilder(globalOptions, titleId, getter, setter), + ColorContract by ColorBuilder() { override var showPreview: Boolean = true + override var dialogBuilder: MaterialDialog.() -> Unit = {} } 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 5081f50..c597b63 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,9 +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.kpref.activity.items -import android.support.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.KPrefItemActions import ca.allanwang.kau.kpref.activity.R import ca.allanwang.kau.utils.resolveDrawable @@ -17,7 +33,7 @@ abstract class KPrefItemBase<T>(protected val base: BaseContract<T>) : KPrefItem open var pref: T get() = base.getter() set(value) { - base.setter(value) + base.setter(this, value) } private var _enabled: Boolean = true @@ -78,20 +94,20 @@ abstract class KPrefItemBase<T>(protected val base: BaseContract<T>) : KPrefItem var onClick: (KClick<T>.() -> Unit)? var onDisabledClick: (KClick<T>.() -> Unit)? val getter: () -> T - val setter: (value: T) -> Unit + val setter: KPrefItemActions.(value: T) -> Unit } /** * Default implementation of [BaseContract] */ - class BaseBuilder<T>(globalOptions: GlobalOptions, - titleId: Int, - override val getter: () -> T, - override val setter: (value: T) -> Unit + class BaseBuilder<T>( + globalOptions: GlobalOptions, + titleId: Int, + override val getter: () -> T, + override val setter: KPrefItemActions.(value: T) -> Unit ) : CoreContract by CoreBuilder(globalOptions, titleId), BaseContract<T> { override var enabler: () -> Boolean = { true } override var onClick: (KClick<T>.() -> Unit)? = null override var onDisabledClick: (KClick<T>.() -> 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 fcc13ba..36bf670 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,44 @@ +/* + * 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 android.support.annotation.CallSuper -import android.support.annotation.IdRes -import android.support.annotation.LayoutRes -import android.support.annotation.StringRes -import android.support.v7.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.KPrefItemActions 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 @@ -27,8 +48,8 @@ import com.mikepenz.iconics.typeface.IIcon * Core class containing nothing but the view items */ -abstract class KPrefItemCore(val core: CoreContract) : AbstractItem<KPrefItemCore, KPrefItemCore.ViewHolder>(), - ThemableIItem by ThemableIItemDelegate() { +abstract class KPrefItemCore(val core: CoreContract) : AbstractItem<KPrefItemCore, KPrefItemCore.ViewHolder>(), KPrefItemActions by core, + ThemableIItem by ThemableIItemDelegate() { final override fun getViewHolder(v: View) = ViewHolder(v) @@ -69,13 +90,15 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem<KPrefItemCor } protected inline fun withAccentColor(action: (color: Int) -> 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) } @@ -97,7 +120,7 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem<KPrefItemCor * Core values for all kpref items */ @KPrefMarker - interface CoreContract { + interface CoreContract : KPrefItemActions { val globalOptions: GlobalOptions val titleId: Int var titleFun: () -> Int @@ -106,18 +129,15 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem<KPrefItemCor var descFun: () -> Int var iicon: IIcon? var visible: () -> Boolean - - /** - * Attempts to reload current item by identifying it with its [id] - */ - fun reloadSelf() } /** * Default implementation of [CoreContract] */ - class CoreBuilder(override val globalOptions: GlobalOptions, - override val titleId: Int) : CoreContract { + class CoreBuilder( + override val globalOptions: GlobalOptions, + override val titleId: Int + ) : CoreContract { override var descRes: Int = INVALID_ID set(value) { field = value @@ -149,7 +169,7 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem<KPrefItemCor inline fun <reified T : View> 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 +182,7 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem<KPrefItemCor inline fun <reified T : View> 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 +193,4 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem<KPrefItemCor operator fun get(@IdRes id: Int): View = itemView.findViewById(id) } -}
\ No newline at end of file +} diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefPlainText.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefPlainText.kt index 40bf284..6a0aaf5 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefPlainText.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefPlainText.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.GlobalOptions @@ -17,10 +32,9 @@ open class KPrefPlainText(open val builder: KPrefPlainTextBuilder) : KPrefItemBa override fun KClick<Unit>.defaultOnClick() = Unit class KPrefPlainTextBuilder( - globalOptions: GlobalOptions, - titleId: Int + globalOptions: GlobalOptions, + titleId: Int ) : BaseContract<Unit> 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..a582ec4 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,9 +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.kpref.activity.items import android.widget.SeekBar import android.widget.TextView import ca.allanwang.kau.kpref.activity.GlobalOptions import ca.allanwang.kau.kpref.activity.KClick +import ca.allanwang.kau.kpref.activity.KPrefItemActions import ca.allanwang.kau.kpref.activity.R import ca.allanwang.kau.utils.tint @@ -67,10 +83,10 @@ open class KPrefSeekbar(val builder: KPrefSeekbarContract) : KPrefItemBase<Int>( * Default implementation of [KPrefSeekbarContract] */ class KPrefSeekbarBuilder( - globalOptions: GlobalOptions, - titleId: Int, - getter: () -> Int, - setter: (value: Int) -> Unit + globalOptions: GlobalOptions, + titleId: Int, + getter: () -> Int, + setter: KPrefItemActions.(value: Int) -> Unit ) : KPrefSeekbarContract, BaseContract<Int> by BaseBuilder(globalOptions, titleId, getter, setter) { override var min: Int = 0 @@ -103,5 +119,4 @@ open class KPrefSeekbar(val builder: KPrefSeekbarContract) : KPrefItemBase<Int>( 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..76c9e20 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,8 +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.kpref.activity.items import android.widget.TextView import ca.allanwang.kau.kpref.activity.GlobalOptions import ca.allanwang.kau.kpref.activity.KClick +import ca.allanwang.kau.kpref.activity.KPrefItemActions import ca.allanwang.kau.kpref.activity.R import ca.allanwang.kau.utils.toast @@ -22,7 +38,7 @@ open class KPrefText<T>(open val builder: KPrefTextContract<T>) : KPrefItemBase< override var pref: T get() = base.getter() set(value) { - base.setter(value) + base.setter(this, value) builder.reloadSelf() } @@ -48,14 +64,13 @@ open class KPrefText<T>(open val builder: KPrefTextContract<T>) : KPrefItemBase< * Default implementation of [KPrefTextContract] */ class KPrefTextBuilder<T>( - globalOptions: GlobalOptions, - titleId: Int, - getter: () -> T, - setter: (value: T) -> Unit + globalOptions: GlobalOptions, + titleId: Int, + getter: () -> T, + setter: KPrefItemActions.(value: T) -> Unit ) : KPrefTextContract<T>, BaseContract<T> by BaseBuilder<T>(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..f50397c 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,11 +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.kpref.activity.items import android.app.TimePickerDialog import android.widget.TimePicker import ca.allanwang.kau.kpref.activity.GlobalOptions import ca.allanwang.kau.kpref.activity.KClick +import ca.allanwang.kau.kpref.activity.KPrefItemActions import ca.allanwang.kau.kpref.activity.R -import java.util.* +import java.util.Locale /** * Created by Allan Wang on 2017-06-14. @@ -30,11 +46,11 @@ open class KPrefTimePicker(override val builder: KPrefTimeContract) : KPrefText< * Default implementation of [KPrefTimeContract] */ class KPrefTimeBuilder( - globalOptions: GlobalOptions, - titleId: Int, - getter: () -> Int, - setter: (value: Int) -> Unit - ) : KPrefTimeContract, BaseContract<Int> by BaseBuilder<Int>(globalOptions, titleId, getter, setter) { + globalOptions: GlobalOptions, + titleId: Int, + getter: () -> Int, + setter: KPrefItemActions.(value: Int) -> Unit + ) : KPrefTimeContract, BaseContract<Int> by BaseBuilder(globalOptions, titleId, getter, setter) { override var use24HourFormat: Boolean = false @@ -50,15 +66,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<Int, Int> get() = Pair(this / 100, this % 100) private val Pair<Int, Int>.mergeTime: Int - get() = first * 100 + second
\ No newline at end of file + get() = first * 100 + second diff --git a/kpref-activity/src/main/res/layout/kau_pref_activity.xml b/kpref-activity/src/main/res/layout/kau_pref_activity.xml index 7651e5a..d6ea6e6 100644 --- a/kpref-activity/src/main/res/layout/kau_pref_activity.xml +++ b/kpref-activity/src/main/res/layout/kau_pref_activity.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> @@ -13,7 +13,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - <android.support.v7.widget.Toolbar + <androidx.appcompat.widget.Toolbar android:id="@id/kau_toolbar" android:layout_width="0dp" android:layout_height="?attr/actionBarSize" @@ -32,7 +32,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/kau_toolbar" /> - <android.support.v7.widget.RecyclerView + <androidx.recyclerview.widget.RecyclerView android:id="@+id/kau_recycler" android:layout_width="0dp" android:layout_height="0dp" @@ -41,4 +41,4 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/kau_toolbar" /> -</android.support.constraint.ConstraintLayout> +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/kpref-activity/src/main/res/layout/kau_pref_checkbox.xml b/kpref-activity/src/main/res/layout/kau_pref_checkbox.xml index 1fecb4d..6c52b52 100644 --- a/kpref-activity/src/main/res/layout/kau_pref_checkbox.xml +++ b/kpref-activity/src/main/res/layout/kau_pref_checkbox.xml @@ -1,4 +1,4 @@ -<android.support.v7.widget.AppCompatCheckBox xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.appcompat.widget.AppCompatCheckBox xmlns:android="http://schemas.android.com/apk/res/android" android:id="@id/kau_pref_inner_content" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/kpref-activity/src/main/res/layout/kau_pref_core.xml b/kpref-activity/src/main/res/layout/kau_pref_core.xml index 72f26d9..2571dd3 100644 --- a/kpref-activity/src/main/res/layout/kau_pref_core.xml +++ b/kpref-activity/src/main/res/layout/kau_pref_core.xml @@ -12,7 +12,7 @@ android:minHeight="?android:attr/listPreferredItemHeightSmall" android:orientation="horizontal"> - <android.support.constraint.ConstraintLayout + <androidx.constraintlayout.widget.ConstraintLayout android:id="@id/kau_pref_container" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -22,7 +22,7 @@ <!--As per Android N, icons (24dp) are aligned to the left rather than centered--> - <android.support.v7.widget.AppCompatImageView + <androidx.appcompat.widget.AppCompatImageView android:id="@id/kau_pref_icon" android:layout_width="56dp" android:layout_height="56dp" @@ -37,7 +37,7 @@ tools:ignore="RtlSymmetry" tools:layout_editor_absoluteX="0dp" /> - <android.support.v7.widget.AppCompatTextView + <androidx.appcompat.widget.AppCompatTextView android:id="@id/kau_pref_title" android:layout_width="0dp" android:layout_height="wrap_content" @@ -52,7 +52,7 @@ app:layout_constraintTop_toTopOf="parent" tools:layout_editor_absoluteX="-175dp" /> - <android.support.v7.widget.AppCompatTextView + <androidx.appcompat.widget.AppCompatTextView android:id="@id/kau_pref_desc" android:layout_width="0dp" android:layout_height="wrap_content" @@ -80,7 +80,7 @@ app:layout_constraintTop_toBottomOf="@id/kau_pref_desc" tools:layout_editor_absoluteX="-175dp" /> - <android.support.constraint.Barrier + <androidx.constraintlayout.widget.Barrier android:id="@id/kau_pref_barrier" android:layout_width="0dp" android:layout_height="0dp" @@ -105,6 +105,6 @@ app:layout_constraintVertical_bias="0.5" tools:layout_editor_absoluteX="1dp" /> - </android.support.constraint.ConstraintLayout> + </androidx.constraintlayout.widget.ConstraintLayout> </LinearLayout>
\ No newline at end of file diff --git a/kpref-activity/src/main/res/layout/kau_pref_header.xml b/kpref-activity/src/main/res/layout/kau_pref_header.xml index d802a14..65504a3 100644 --- a/kpref-activity/src/main/res/layout/kau_pref_header.xml +++ b/kpref-activity/src/main/res/layout/kau_pref_header.xml @@ -1,4 +1,4 @@ -<android.support.v7.widget.AppCompatTextView xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.appcompat.widget.AppCompatTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/kau_pref_title" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/kpref-activity/src/main/res/layout/kau_pref_seekbar.xml b/kpref-activity/src/main/res/layout/kau_pref_seekbar.xml index 0b07e1c..5ff6351 100644 --- a/kpref-activity/src/main/res/layout/kau_pref_seekbar.xml +++ b/kpref-activity/src/main/res/layout/kau_pref_seekbar.xml @@ -1,4 +1,4 @@ -<android.support.v7.widget.AppCompatSeekBar xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.appcompat.widget.AppCompatSeekBar xmlns:android="http://schemas.android.com/apk/res/android" android:id="@id/kau_pref_lower_content" android:layout_width="match_parent" android:paddingTop="@dimen/kau_padding_normal" diff --git a/kpref-activity/src/main/res/layout/kau_pref_seekbar_text.xml b/kpref-activity/src/main/res/layout/kau_pref_seekbar_text.xml index dc11d2a..5834820 100644 --- a/kpref-activity/src/main/res/layout/kau_pref_seekbar_text.xml +++ b/kpref-activity/src/main/res/layout/kau_pref_seekbar_text.xml @@ -1,6 +1,6 @@ <!--TextView that aligns to the bottom--> -<android.support.v7.widget.AppCompatTextView xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.appcompat.widget.AppCompatTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@id/kau_pref_inner_content" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/kpref-activity/src/main/res/layout/kau_pref_text.xml b/kpref-activity/src/main/res/layout/kau_pref_text.xml index 40fed2a..b873eaf 100644 --- a/kpref-activity/src/main/res/layout/kau_pref_text.xml +++ b/kpref-activity/src/main/res/layout/kau_pref_text.xml @@ -1,4 +1,4 @@ -<android.support.v7.widget.AppCompatTextView xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.appcompat.widget.AppCompatTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@id/kau_pref_inner_content" android:layout_width="wrap_content" android:layout_height="wrap_content" 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..1941ec0 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<MediaActionItem, MediaItemBasic.ViewHolder>(R.layout.kau_iitem_image_basic, { MediaItemBasic.ViewHolder(it) }, R.id.kau_item_media_action) { + val action: MediaAction, + val mediaType: MediaType +) : KauIItem<MediaActionItem, MediaItemBasic.ViewHolder>( + 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 @@ -78,7 +96,7 @@ abstract class MediaActionCamera( if (intent.resolveActivity(c.packageManager) == null) { c.materialDialog { title(R.string.kau_no_camera_found) - content(R.string.kau_no_camera_found_content) + message(R.string.kau_no_camera_found_content) } return@kauRequestPermissions } @@ -88,7 +106,7 @@ abstract class MediaActionCamera( } catch (e: java.io.IOException) { c.materialDialog { title(R.string.kau_error) - content(R.string.kau_temp_file_creation_failed) + message(R.string.kau_temp_file_creation_failed) } return@kauRequestPermissions } @@ -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) { @@ -113,7 +131,7 @@ class MediaActionCameraVideo( if (intent.resolveActivity(c.packageManager) == null) { c.materialDialog { title(R.string.kau_no_camera_found) - content(R.string.kau_no_camera_found_content) + message(R.string.kau_no_camera_found_content) } return } @@ -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 c0b7e2d..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 android.support.v7.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<MediaItem, MediaItem.ViewHolder>(R.layout.kau_iitem_image, { ViewHolder(it) }), GlideContract by GlideDelegate() { +class MediaItem(val data: MediaModel) : + KauIItem<MediaItem, MediaItem.ViewHolder>(R.layout.kau_iitem_image, { ViewHolder(it) }), + GlideContract by GlideDelegate() { private var failedToLoad = false companion object { fun bindEvents(fastAdapter: FastAdapter<MediaItem>) { 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<Any>) { super.bindView(holder, payloads) glide(holder.itemView) - .load(data.data) - .applyMediaOptions(holder.itemView.context) - .listener(object : RequestListener<Drawable> { - override fun onLoadFailed(e: GlideException?, model: Any, target: Target<Drawable>, 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<Drawable> { + override fun onLoadFailed( + e: GlideException?, + model: Any, + target: Target<Drawable>, + 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<Drawable>, 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<Drawable>, + 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 59202c0..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 android.support.v7.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<MediaItem, MediaItemBasic.ViewHolder>(R.layout.kau_iitem_image_basic, { ViewHolder(it) }), GlideContract by GlideDelegate() { +class MediaItemBasic(val data: MediaModel) : + KauIItem<MediaItem, MediaItemBasic.ViewHolder>(R.layout.kau_iitem_image_basic, { ViewHolder(it) }), + GlideContract by GlideDelegate() { companion object { @SuppressLint("NewApi") fun bindEvents(activity: Activity, fastAdapter: FastAdapter<MediaItemBasic>) { 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<Any>) { super.bindView(holder, payloads) glide(holder.itemView) - .load(data.data) - .applyMediaOptions(holder.itemView.context) - .listener(object : RequestListener<Drawable> { - override fun onLoadFailed(e: GlideException?, model: Any, target: Target<Drawable>, isFirstResource: Boolean): Boolean { - holder.image.setImageDrawable(MediaPickerCore.getErrorDrawable(holder.itemView.context)) - return true - } - - override fun onResourceReady(resource: Drawable, model: Any, target: Target<Drawable>, dataSource: DataSource, isFirstResource: Boolean): Boolean { - return false - } - }) - .into(holder.image) + .load(data.data) + .applyMediaOptions(holder.itemView.context) + .listener(object : RequestListener<Drawable> { + override fun onLoadFailed( + e: GlideException?, + model: Any, + target: Target<Drawable>, + isFirstResource: Boolean + ): Boolean { + holder.image.setImageDrawable(MediaPickerCore.getErrorDrawable(holder.itemView.context)) + return true + } + + override fun onResourceReady( + resource: Drawable, + model: Any, + target: Target<Drawable>, + 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 26736d4..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 @@ -6,41 +21,45 @@ import android.net.Uri import android.os.Parcel import android.os.Parcelable import android.provider.MediaStore -import android.support.annotation.NonNull +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<MediaModel> { 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 37f2373..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,16 +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.mediapicker import android.database.Cursor import android.os.Bundle -import android.support.design.widget.AppBarLayout -import android.support.v4.content.Loader -import android.support.v7.widget.LinearLayoutManager +import androidx.loader.content.Loader +import androidx.recyclerview.widget.LinearLayoutManager import ca.allanwang.kau.adapters.selectedItems import ca.allanwang.kau.adapters.selectionSize import ca.allanwang.kau.utils.hideOnDownwardsScroll import ca.allanwang.kau.utils.setIcon import ca.allanwang.kau.utils.toDrawable import ca.allanwang.kau.utils.toast +import com.google.android.material.appbar.AppBarLayout import com.mikepenz.google_material_typeface_library.GoogleMaterial import kotlinx.android.synthetic.main.kau_activity_image_picker.* @@ -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<MediaAction> = emptyList() + mediaType: MediaType, + mediaActions: List<MediaAction> = emptyList() ) : MediaPickerCore<MediaItem>(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<Cursor>, 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 122838b..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,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.os.Build import android.os.Bundle -import android.support.annotation.RequiresApi +import androidx.annotation.RequiresApi import ca.allanwang.kau.utils.toast import kotlinx.android.synthetic.main.kau_activity_image_picker_overlay.* @@ -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<MediaAction> = emptyList() + mediaType: MediaType, + mediaActions: List<MediaAction> = emptyList() ) : MediaPickerCore<MediaItemBasic>(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 <reified T : MediaPickerCore<*>> 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 <T> RequestBuilder<T>.applyMediaOptions(context: Context) = apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.RESOURCE).centerCrop().override(MediaPickerCore.viewSize(context))) - +internal fun <T> RequestBuilder<T>.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 6e38d14..e6556ab 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 @@ -13,11 +28,11 @@ import android.os.Bundle import android.provider.BaseColumns import android.provider.DocumentsContract import android.provider.MediaStore -import android.support.v4.app.LoaderManager -import android.support.v4.content.CursorLoader -import android.support.v4.content.Loader -import android.support.v7.widget.GridLayoutManager -import android.support.v7.widget.RecyclerView +import androidx.loader.app.LoaderManager +import androidx.loader.content.CursorLoader +import androidx.loader.content.Loader +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView import ca.allanwang.kau.adapters.fastAdapter import ca.allanwang.kau.animators.FadeScaleAnimatorAdd import ca.allanwang.kau.animators.KauAnimator @@ -34,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. @@ -45,8 +58,8 @@ import java.util.concurrent.Future * Container for the main logic behind the both pickers */ abstract class MediaPickerCore<T : IItem<*, *>>( - val mediaType: MediaType, - val mediaActions: List<MediaAction> + val mediaType: MediaType, + val mediaActions: List<MediaAction> ) : KauBaseActivity(), LoaderManager.LoaderCallbacks<Cursor> { companion object { @@ -79,10 +92,10 @@ abstract class MediaPickerCore<T : IItem<*, *>>( 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() @@ -106,7 +119,6 @@ abstract class MediaPickerCore<T : IItem<*, *>>( lateinit var glide: RequestManager private var hasPreloaded = false - private var prefetcher: Future<*>? = null val adapter = ItemAdapter<T>() @@ -122,7 +134,7 @@ abstract class MediaPickerCore<T : IItem<*, *>>( fun initializeRecycler(recycler: RecyclerView) { val adapterHeader = ItemAdapter<MediaActionItem>() - val fulladapter = fastAdapter(adapterHeader, adapter) + val fulladapter = fastAdapter<IItem<*, *>>(adapterHeader, adapter) adapterHeader.add(mediaActions.map { MediaActionItem(it, mediaType) }) recycler.apply { val manager = object : GridLayoutManager(context, computeColumnCount(context)) { @@ -131,7 +143,6 @@ abstract class MediaPickerCore<T : IItem<*, *>>( } } setItemViewCacheSize(CACHE_SIZE) - isDrawingCacheEnabled = true layoutManager = manager adapter = fulladapter setHasFixedSize(true) @@ -155,7 +166,7 @@ abstract class MediaPickerCore<T : IItem<*, *>>( open fun loadItems() { kauRequestPermissions(Manifest.permission.READ_EXTERNAL_STORAGE) { granted, _ -> if (granted) { - supportLoaderManager.initLoader(LOADER_ID, null, this) + LoaderManager.getInstance(this).initLoader(LOADER_ID, null, this) onStatusChange(true) } else { toast(R.string.kau_permission_denied) @@ -180,18 +191,14 @@ abstract class MediaPickerCore<T : IItem<*, *>>( 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) } } } @@ -227,11 +234,6 @@ abstract class MediaPickerCore<T : IItem<*, *>>( open fun onStatusChange(loaded: Boolean) {} - override fun onDestroy() { - prefetcher?.cancel(true) - super.onDestroy() - } - /** * Method used to retrieve uri data for API 19+ * See <a href="http://hmkcode.com/android-display-selected-image-and-its-real-path/"></a> @@ -274,7 +276,7 @@ abstract class MediaPickerCore<T : IItem<*, *>>( f = File(tempPath) tempPath = null } else if (data?.data != null) { - f = File(data.data.path) + f = File(data.data!!.path) } else { KL.d { "Media camera no file found" } return @@ -291,8 +293,8 @@ abstract class MediaPickerCore<T : IItem<*, *>>( private fun onPickerResult(data: Intent?) { val items = mutableListOf<Uri>() if (data?.data != null) { - KL.v { "Media picker data uri: ${data.data.path}" } - items.add(data.data) + KL.v { "Media picker data uri: ${data.data!!.path}" } + items.add(data.data!!) } else if (data != null) { val clip = data.clipData if (clip != null) { @@ -314,4 +316,4 @@ abstract class MediaPickerCore<T : IItem<*, *>>( } } } -}
\ 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 f37be75..ff6784b 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 @@ -6,13 +21,14 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.os.Environment -import android.support.v7.app.AppCompatActivity +import androidx.appcompat.app.AppCompatActivity 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. @@ -26,14 +42,17 @@ internal fun Activity.finish(data: ArrayList<MediaModel>) { else finish() } +/** + * Creates a folder named [prefix] as well as a new file with the prefix, current time, and extension. + */ @Throws(IOException::class) fun createMediaFile(prefix: String, extension: String): File { val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date()) val imageFileName = "${prefix}_${timeStamp}_" val storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) - val frostDir = File(storageDir, prefix) - if (!frostDir.exists()) frostDir.mkdirs() - return File.createTempFile(imageFileName, extension, frostDir) + val prefixDir = File(storageDir, prefix) + if (!prefixDir.exists()) prefixDir.mkdirs() + return File.createTempFile(imageFileName, extension, prefixDir) } @Throws(IOException::class) @@ -55,4 +74,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/mediapicker/src/main/res/layout-v21/kau_activity_image_picker_overlay.xml b/mediapicker/src/main/res/layout-v21/kau_activity_image_picker_overlay.xml index a0ce301..d7447b0 100644 --- a/mediapicker/src/main/res/layout-v21/kau_activity_image_picker_overlay.xml +++ b/mediapicker/src/main/res/layout-v21/kau_activity_image_picker_overlay.xml @@ -7,7 +7,7 @@ app:dragDismissDistance="@dimen/kau_drag_dismiss_distance_large" app:dragDismissScale="0.95"> - <android.support.v7.widget.RecyclerView + <androidx.recyclerview.widget.RecyclerView android:id="@+id/kau_recyclerview" android:layout_width="match_parent" android:layout_height="match_parent" diff --git a/mediapicker/src/main/res/layout/kau_activity_image_picker.xml b/mediapicker/src/main/res/layout/kau_activity_image_picker.xml index 1b46097..c3458cf 100644 --- a/mediapicker/src/main/res/layout/kau_activity_image_picker.xml +++ b/mediapicker/src/main/res/layout/kau_activity_image_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/kau_coordinator" android:layout_width="match_parent" @@ -7,13 +7,13 @@ android:background="?android:colorBackground" android:fitsSystemWindows="true"> - <android.support.design.widget.AppBarLayout + <com.google.android.material.appbar.AppBarLayout android:id="@+id/kau_appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> - <android.support.v7.widget.Toolbar + <androidx.appcompat.widget.Toolbar android:id="@+id/kau_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" @@ -31,17 +31,17 @@ android:paddingStart="@dimen/kau_padding_normal" android:text="@string/kau_0" /> - </android.support.v7.widget.Toolbar> + </androidx.appcompat.widget.Toolbar> - </android.support.design.widget.AppBarLayout> + </com.google.android.material.appbar.AppBarLayout> - <android.support.v7.widget.RecyclerView + <androidx.recyclerview.widget.RecyclerView android:id="@+id/kau_recyclerview" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> - <android.support.design.widget.FloatingActionButton + <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/kau_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -53,4 +53,4 @@ app:layout_anchorGravity="bottom|right|end" /> -</android.support.design.widget.CoordinatorLayout>
\ No newline at end of file +</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file diff --git a/mediapicker/src/main/res/values-da-rDK/strings_mediapicker.xml b/mediapicker/src/main/res/values-da-rDK/strings_mediapicker.xml index d3636d3..6f37f28 100644 --- a/mediapicker/src/main/res/values-da-rDK/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-da-rDK/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Ingen elementer fundet</string> <string name="kau_no_items_selected">Ingen elementer er valgt</string> diff --git a/mediapicker/src/main/res/values-de-rDE/strings_mediapicker.xml b/mediapicker/src/main/res/values-de-rDE/strings_mediapicker.xml index ae441cc..ff49433 100644 --- a/mediapicker/src/main/res/values-de-rDE/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-de-rDE/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Keine Elemente gefunden</string> <string name="kau_no_items_selected">Keine Datei ausgewählt</string> diff --git a/mediapicker/src/main/res/values-es-rES/strings_mediapicker.xml b/mediapicker/src/main/res/values-es-rES/strings_mediapicker.xml index 21da558..72b8903 100644 --- a/mediapicker/src/main/res/values-es-rES/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-es-rES/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">No se encontraron elementos</string> <string name="kau_no_items_selected">No se han seleccionado elementos</string> diff --git a/mediapicker/src/main/res/values-fr-rFR/strings_mediapicker.xml b/mediapicker/src/main/res/values-fr-rFR/strings_mediapicker.xml index 1705e9e..99a68d4 100644 --- a/mediapicker/src/main/res/values-fr-rFR/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-fr-rFR/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Aucun élément trouvé</string> <string name="kau_no_items_selected">Aucun élément n\'a été sélectionné</string> diff --git a/mediapicker/src/main/res/values-gl-rES/strings_mediapicker.xml b/mediapicker/src/main/res/values-gl-rES/strings_mediapicker.xml index 1ad6650..831c96b 100644 --- a/mediapicker/src/main/res/values-gl-rES/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-gl-rES/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Ningún elemento atopado</string> <string name="kau_no_items_selected">Ningún elemento seleccionado</string> diff --git a/mediapicker/src/main/res/values-hu-rHU/strings_mediapicker.xml b/mediapicker/src/main/res/values-hu-rHU/strings_mediapicker.xml index b191d61..30b6a1b 100644 --- a/mediapicker/src/main/res/values-hu-rHU/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-hu-rHU/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Nem található elem</string> <string name="kau_no_items_selected">Nincs kijelölt elem</string> diff --git a/mediapicker/src/main/res/values-in-rID/strings_mediapicker.xml b/mediapicker/src/main/res/values-in-rID/strings_mediapicker.xml index 8f64d74..3980589 100644 --- a/mediapicker/src/main/res/values-in-rID/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-in-rID/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Item tidak ditemukan</string> <string name="kau_no_items_selected">Tidak ada item yang dipilih</string> diff --git a/mediapicker/src/main/res/values-it-rIT/strings_mediapicker.xml b/mediapicker/src/main/res/values-it-rIT/strings_mediapicker.xml index 4b795b1..f712b12 100644 --- a/mediapicker/src/main/res/values-it-rIT/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-it-rIT/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Nessun elemento trovato</string> <string name="kau_no_items_selected">Non è stato selezionato alcun elemento</string> diff --git a/mediapicker/src/main/res/values-ko-rKR/strings_mediapicker.xml b/mediapicker/src/main/res/values-ko-rKR/strings_mediapicker.xml index aab5e63..26793bc 100644 --- a/mediapicker/src/main/res/values-ko-rKR/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-ko-rKR/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">항목이 없습니다.</string> <string name="kau_no_items_selected">선택된 항목이 없습니다.</string> diff --git a/mediapicker/src/main/res/values-nl-rNL/strings_mediapicker.xml b/mediapicker/src/main/res/values-nl-rNL/strings_mediapicker.xml new file mode 100644 index 0000000..daaad70 --- /dev/null +++ b/mediapicker/src/main/res/values-nl-rNL/strings_mediapicker.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> +<resources> + <string name="kau_no_items_found">Geen items gevonden</string> + <string name="kau_no_items_selected">Er zijn geen items geselecteerd</string> + <string name="kau_no_items_loaded">Er zijn geen items ingeladen</string> + <string name="kau_no_camera_found">Geen camera gevonden</string> + <string name="kau_no_camera_found_content">Installeer een camera-app en probeer het opnieuw.</string> + <string name="kau_temp_file_creation_failed">Kan tijdelijk bestand niet aanmaken.</string> + <string name="kau_select_media">Kies een afbeelding of video</string> +</resources> diff --git a/mediapicker/src/main/res/values-no-rNO/strings_mediapicker.xml b/mediapicker/src/main/res/values-no-rNO/strings_mediapicker.xml index 7b251bc..9ee6501 100644 --- a/mediapicker/src/main/res/values-no-rNO/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-no-rNO/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Ingen elementer funnet</string> <string name="kau_no_items_selected">Ingen elementer har blitt valgt</string> diff --git a/mediapicker/src/main/res/values-pl-rPL/strings_mediapicker.xml b/mediapicker/src/main/res/values-pl-rPL/strings_mediapicker.xml index 5aaaae1..7db61f8 100644 --- a/mediapicker/src/main/res/values-pl-rPL/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-pl-rPL/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Brak pozycji</string> <string name="kau_no_items_selected">Brak wybranych pozycji</string> diff --git a/mediapicker/src/main/res/values-pt-rBR/strings_mediapicker.xml b/mediapicker/src/main/res/values-pt-rBR/strings_mediapicker.xml index bac9913..62abec1 100644 --- a/mediapicker/src/main/res/values-pt-rBR/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-pt-rBR/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Nenhum item encontrado</string> <string name="kau_no_items_selected">Nenhum item foi selecionado</string> diff --git a/mediapicker/src/main/res/values-pt-rPT/strings_mediapicker.xml b/mediapicker/src/main/res/values-pt-rPT/strings_mediapicker.xml new file mode 100644 index 0000000..25b8c46 --- /dev/null +++ b/mediapicker/src/main/res/values-pt-rPT/strings_mediapicker.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> +<resources> + <string name="kau_no_items_found">Nenhum item encontrado</string> + <string name="kau_no_items_selected">Não foi selecionado nenhum item</string> + <string name="kau_no_items_loaded">Nenhum item carregado</string> + <string name="kau_no_camera_found">Nenhuma câmara encontrada</string> + <string name="kau_no_camera_found_content">Por favor instale um aplicação de câmara e tente novamente.</string> + <string name="kau_temp_file_creation_failed">Falha ao criar um ficheiro temporário.</string> + <string name="kau_select_media">Selecionar multimédia</string> +</resources> diff --git a/mediapicker/src/main/res/values-sr-rSP/strings_mediapicker.xml b/mediapicker/src/main/res/values-sr-rSP/strings_mediapicker.xml new file mode 100644 index 0000000..abc3933 --- /dev/null +++ b/mediapicker/src/main/res/values-sr-rSP/strings_mediapicker.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> +<resources> + <string name="kau_no_items_found">Није пронађена ниједна ставка</string> + <string name="kau_no_items_selected">Ниједна ставка није одабрана</string> + <string name="kau_no_items_loaded">Нема учитаних ставки</string> + <string name="kau_no_camera_found">Камера није пронађена</string> + <string name="kau_no_camera_found_content">Инсталирајте апликацију за камеру и покушајте поново.</string> + <string name="kau_temp_file_creation_failed">Креирање привремене датотеке није успело.</string> + <string name="kau_select_media">Одаберите мултимедију</string> +</resources> diff --git a/mediapicker/src/main/res/values-sv-rSE/strings_mediapicker.xml b/mediapicker/src/main/res/values-sv-rSE/strings_mediapicker.xml index 15f991f..0909d2f 100644 --- a/mediapicker/src/main/res/values-sv-rSE/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-sv-rSE/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Inga objekt hittades</string> <string name="kau_no_items_selected">Inga objekt har valts</string> diff --git a/mediapicker/src/main/res/values-th-rTH/strings_mediapicker.xml b/mediapicker/src/main/res/values-th-rTH/strings_mediapicker.xml index 3e97c66..83bd30c 100644 --- a/mediapicker/src/main/res/values-th-rTH/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-th-rTH/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">ไม่พบรายการ</string> <string name="kau_no_items_selected">ยังไม่ได้เลือกรายการ</string> diff --git a/mediapicker/src/main/res/values-tr-rTR/strings_mediapicker.xml b/mediapicker/src/main/res/values-tr-rTR/strings_mediapicker.xml index 55e90b4..601432f 100644 --- a/mediapicker/src/main/res/values-tr-rTR/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-tr-rTR/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Hiç bir öge bulunamadı</string> <string name="kau_no_items_selected">Hiç bir öge seçilmemişti</string> diff --git a/mediapicker/src/main/res/values-uk-rUA/strings_mediapicker.xml b/mediapicker/src/main/res/values-uk-rUA/strings_mediapicker.xml index 6dc767e..f8a9725 100644 --- a/mediapicker/src/main/res/values-uk-rUA/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-uk-rUA/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Нічого не знайдено</string> <string name="kau_no_items_selected">Жодного елементу не обрано</string> diff --git a/mediapicker/src/main/res/values-vi-rVN/strings_mediapicker.xml b/mediapicker/src/main/res/values-vi-rVN/strings_mediapicker.xml index dae9f41..9d5fe5d 100644 --- a/mediapicker/src/main/res/values-vi-rVN/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-vi-rVN/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">Không tìm thấy mục nào</string> <string name="kau_no_items_selected">Chưa chọn mục nào</string> diff --git a/mediapicker/src/main/res/values-zh-rCN/strings_mediapicker.xml b/mediapicker/src/main/res/values-zh-rCN/strings_mediapicker.xml index 2be3fc0..b05f922 100644 --- a/mediapicker/src/main/res/values-zh-rCN/strings_mediapicker.xml +++ b/mediapicker/src/main/res/values-zh-rCN/strings_mediapicker.xml @@ -1,4 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?><!--Generated by crowdin.com--> +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> <resources> <string name="kau_no_items_found">未找到项目</string> <string name="kau_no_items_selected">没有选择任何项目</string> diff --git a/mediapicker/src/main/res/values-zh-rTW/strings_mediapicker.xml b/mediapicker/src/main/res/values-zh-rTW/strings_mediapicker.xml new file mode 100644 index 0000000..1ecb9e0 --- /dev/null +++ b/mediapicker/src/main/res/values-zh-rTW/strings_mediapicker.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.com--> +<resources> + <string name="kau_no_items_found">什麼也沒有</string> + <string name="kau_no_items_selected">什麼也沒選到</string> + <string name="kau_no_items_loaded">什麼也沒載入</string> + <string name="kau_no_camera_found">找不到相機</string> + <string name="kau_no_camera_found_content">請安裝相機應用程式然後重試</string> + <string name="kau_temp_file_creation_failed">無法建立暫存檔</string> + <string name="kau_select_media">選取媒體</string> +</resources> diff --git a/sample/build.gradle b/sample/build.gradle index d7199a3..bb7cab0 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 { @@ -27,7 +24,7 @@ android { versionName androidGitVersion.name() versionCode androidGitVersion.code() multiDexEnabled true - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } def releaseSigning = file("../files/kau.properties") @@ -101,6 +98,18 @@ android { } } } + + // See https://github.com/facebook/flipper/issues/146 + configurations.all { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + def requested = details.requested + if (requested.group == "com.android.support") { + if (!requested.name.startsWith("multidex")) { + details.useVersion "26.+" + } + } + } + } } dependencies { @@ -113,17 +122,15 @@ dependencies { implementation project(':searchview') implementation project(':mediapicker') -// androidTestImplementation("com.android.support.test.espresso:espresso-core:${kau.espresso}") { -// exclude group: 'com.android.support', module: 'support-annotations' -// } -// androidTestImplementation("com.android.support.test:runner:${kau.testRunner}") { -// exclude group: 'com.android.support', module: 'support-annotations' -// } -// androidTestImplementation kauDependency.kotlinTest + implementation "com.afollestad.material-dialogs:input:${kau.materialDialog}" + testImplementation kauDependency.kotlinTest testImplementation kauDependency.junit androidTestImplementation kauDependency.kotlinTest androidTestImplementation kauDependency.espresso + androidTestImplementation "androidx.test.espresso:espresso-intents:${kau.espresso}" + androidTestImplementation "androidx.test.espresso:espresso-contrib:${kau.espresso}" + androidTestImplementation kauDependency.testRules androidTestImplementation kauDependency.testRunner } 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 39aee93..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,16 +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.sample -import android.support.test.espresso.DataInteraction -import android.support.test.espresso.Espresso.onData -import android.support.test.espresso.Espresso.onView -import android.support.test.espresso.ViewAssertion -import android.support.test.espresso.action.ViewActions.click -import android.support.test.espresso.matcher.ViewMatchers.withId -import android.support.test.espresso.matcher.ViewMatchers.withText -import android.support.test.filters.MediumTest -import android.support.test.rule.ActivityTestRule -import android.support.test.runner.AndroidJUnit4 import android.view.View +import androidx.test.espresso.DataInteraction +import androidx.test.espresso.Espresso.onData +import androidx.test.espresso.Espresso.onView +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 ca.allanwang.kau.colorpicker.CircleView import org.hamcrest.Matchers.anything import org.junit.Rule @@ -19,9 +34,10 @@ import org.junit.runner.RunWith import kotlin.test.assertEquals import kotlin.test.fail - /** * Created by Allan Wang on 22/02/2018. + * + * Tests related to the :colorpicker module */ @RunWith(AndroidJUnit4::class) @MediumTest @@ -31,11 +47,15 @@ class ColorPickerTest { val activity: ActivityTestRule<MainActivity> = 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) } @@ -43,7 +63,7 @@ class ColorPickerTest { private val colorNotSelected = ViewAssertion { view, _ -> view.colorSelected(false) } @Test - fun test() { + fun colorClick() { onView(withText(R.string.accent_color)).perform(click()) val colors = onData(anything()).inAdapterView(withId(R.id.md_grid)) @@ -51,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 new file mode 100644 index 0000000..72199cf --- /dev/null +++ b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/KPrefViewTest.kt @@ -0,0 +1,129 @@ +/* + * 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 android.widget.CheckBox +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.ViewInteraction +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.BoundedMatcher +import androidx.test.espresso.matcher.ViewMatchers.withChild +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 org.hamcrest.BaseMatcher +import org.hamcrest.Description +import org.hamcrest.Matcher +import org.hamcrest.Matchers.allOf +import org.hamcrest.Matchers.instanceOf +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Created by Allan Wang on 21/12/2018. + * + * Tests related to the :kpref-activity module + */ +@RunWith(AndroidJUnit4::class) +@MediumTest +class KPrefViewTest { + + @get:Rule + val activity: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java) + + fun verifyCheck(checked: Boolean): Matcher<View> { + return object : BoundedMatcher<View, View>(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<CheckBox>(R.id.kau_pref_inner_content).isChecked == checked + } + } + + inline fun <reified T : View> ViewInteraction.checkInnerContent( + desc: String, + crossinline matcher: (T) -> Boolean + ): ViewInteraction { + val viewMatcher = object : BaseMatcher<View>() { + override fun describeTo(description: Description) { + description.appendText(desc) + } + + override fun matches(item: Any?): Boolean { + val view = item as? View ?: return false + val inner = view.findViewById<View>(R.id.kau_pref_inner_content) as? T + ?: return false + return matcher(inner) + } + } + return check(matches(viewMatcher)) + } + + fun ViewInteraction.verifyCheck(tag: String, checked: Boolean, enabled: Boolean = true) = + checkInnerContent<CheckBox>("$tag should be ${if (checked) "checked" else "not checked"}") { + it.isChecked == checked + }.check { view, _ -> + ((view.alpha == 1f) == enabled) + } + + fun onCheckboxView(vararg matchers: Matcher<View>) = + onView(allOf(*matchers, withChild(withChild(instanceOf(CheckBox::class.java))))) + + @Test + fun basicCheckboxToggle() { + val checkbox1 = onCheckboxView(withChild(withText(R.string.checkbox_1))) + + val initiallyChecked = KPrefSample.check1 + + checkbox1.verifyCheck("checkbox1 init", initiallyChecked) + checkbox1.perform(click()) + checkbox1.verifyCheck("checkbox1 after click", !initiallyChecked) + } + + /** + * Note that checkbox3 depends on checkbox2 + */ + @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))) + + // normalize so that both are checked + if (!KPrefSample.check2) + checkbox2.perform(click()) + if (!KPrefSample.check3) + checkbox3.perform(click()) + + checkbox3.verifyCheck("checkbox3 init", true, true) + checkbox3.perform(click()) + checkbox3.verifyCheck("checkbox3 after click", false, true) + + checkbox2.perform(click()) + checkbox2.verifyCheck("checkbox2 after click", false, true) + checkbox3.verifyCheck("checkbox3 after checkbox2 click", false, false) + + 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 new file mode 100644 index 0000000..09ad00a --- /dev/null +++ b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/utils/EspressoUtils.kt @@ -0,0 +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.sample.utils + +import org.hamcrest.BaseMatcher +import org.hamcrest.Description +import org.hamcrest.Matcher + +fun <T> index(index: Int, matcher: Matcher<T>): Matcher<T> = + object : BaseMatcher<T>() { + + var current = 0 + + 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 + } + } + +fun <T> first(matcher: Matcher<T>): Matcher<T> = index(0, matcher) diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index d8bbe51..5846c6b 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -49,7 +49,7 @@ android:theme="@style/Kau.Translucent.SlideBottom" /> <provider - android:name="android.support.v4.content.FileProvider" + android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> 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<IItem<*, *>>() 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..d9586c4 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt @@ -1,11 +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.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 @@ -17,11 +31,16 @@ 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.afollestad.materialdialogs.input.input 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<String> 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: @@ -139,11 +163,11 @@ class MainActivity : KPrefActivity() { descRes = R.string.text_desc onClick = { itemView.context.materialDialog { - title("Type Text") - input("Type here", item.pref, { _, input -> item.pref = input.toString() }) - inputRange(0, 20) + title(text = "Type Text") + input("Type here", prefill = item.pref, maxLength = 20, allowEmpty = true) { _, input -> + item.pref = input.toString() + } } - } } @@ -189,7 +213,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 +235,6 @@ class MainActivity : KPrefActivity() { descRes = R.string.time_desc_24 use24HourFormat = true } - } fun subPrefs(): KPrefAdapterBuilder.() -> Unit = { @@ -216,12 +242,11 @@ class MainActivity : KPrefActivity() { descRes = R.string.text_desc onClick = { itemView.context.materialDialog { - title("Type Text") - input("Type here", item.pref, { _, input -> + title(text = "Type Text") + input("Type here", prefill = item.pref, maxLength = 20, allowEmpty = true) { _, input -> item.pref = input.toString() reloadSelf() - }) - inputRange(0, 20) + } } } } @@ -236,9 +261,10 @@ class MainActivity : KPrefActivity() { KPrefSample.version = BuildConfig.VERSION_CODE if (!BuildConfig.DEBUG) showChangelog(R.xml.kau_changelog, KPrefSample.textColor) { - titleColor(KPrefSample.textColor) - backgroundColor(KPrefSample.bgColor) - positiveColor(KPrefSample.accentColor) + // TODO MD Color +// titleColor(KPrefSample.textColor) +// backgroundColor(KPrefSample.bgColor) +// positiveColor(KPrefSample.accentColor) } } supportActionBar?.apply { @@ -273,9 +299,10 @@ class MainActivity : KPrefActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.action_changelog -> showChangelog(R.xml.kau_changelog, KPrefSample.textColor) { - titleColor(KPrefSample.textColor) - backgroundColor(KPrefSample.bgColor) - positiveColor(KPrefSample.accentColor) + // TODO MD Color +// titleColor(KPrefSample.textColor) +// backgroundColor(KPrefSample.bgColor) +// positiveColor(KPrefSample.accentColor) } R.id.action_settings -> startActivity<AnimActivity>() R.id.action_email -> sendEmail(R.string.your_email, R.string.your_subject) @@ -295,8 +322,3 @@ class MainActivity : KPrefActivity() { } } } - -inline fun <reified T : AboutActivityBase> Context.kauLaunchAbout() = - startActivity<T>(bundleBuilder = { - withSceneTransitionAnimation(this@kauLaunchAbout) - })
\ No newline at end of file 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 42de62c..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 android.support.v4.content.FileProvider -import ca.allanwang.kau.mediapicker.* +import androidx.core.content.FileProvider +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 beb1a29..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 android.support.v7.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<PermissionCheckbox, PermissionCheckbox.ViewHolder>( - R.layout.permission_checkbox, { ViewHolder(it) }) { + R.layout.permission_checkbox, { ViewHolder(it) }) { override fun bindView(holder: ViewHolder, payloads: MutableList<Any>) { super.bindView(holder, payloads) @@ -25,4 +40,4 @@ class PermissionCheckbox(val permission: String) : KauIItem<PermissionCheckbox, val text: TextView = v.findViewById(R.id.perm_text) val checkbox: CheckBox = v.findViewById(R.id.perm_checkbox) } -}
\ No newline at end of file +} diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/SampleApp.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/SampleApp.kt index 6060245..6e6d718 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/SampleApp.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/SampleApp.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.app.Application @@ -10,4 +25,4 @@ class SampleApp : Application() { super.onCreate() KPrefSample.initialize(this, "pref_sample") } -}
\ No newline at end of file +} diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/SwipeActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/SwipeActivity.kt index 4197b6d..5107e18 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/SwipeActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/SwipeActivity.kt @@ -1,10 +1,35 @@ +/* + * 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.app.Activity import android.os.Bundle import ca.allanwang.kau.internal.KauBaseActivity -import ca.allanwang.kau.swipe.* -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.swipe.SWIPE_EDGE_BOTTOM +import ca.allanwang.kau.swipe.SWIPE_EDGE_LEFT +import ca.allanwang.kau.swipe.SWIPE_EDGE_RIGHT +import ca.allanwang.kau.swipe.SWIPE_EDGE_TOP +import ca.allanwang.kau.swipe.kauSwipeFinish +import ca.allanwang.kau.swipe.kauSwipeOnCreate +import ca.allanwang.kau.swipe.kauSwipeOnDestroy +import ca.allanwang.kau.utils.darken +import ca.allanwang.kau.utils.navigationBarColor +import ca.allanwang.kau.utils.rndColor +import ca.allanwang.kau.utils.startActivity +import ca.allanwang.kau.utils.statusBarColor import kotlinx.android.synthetic.main.activity_swipe.* /** @@ -24,8 +49,8 @@ class SwipeActivity : KauBaseActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_swipe) listOf(swipe_from_left, swipe_from_right, swipe_from_top, swipe_from_bottom) - .zip(listOf(SWIPE_EDGE_LEFT, SWIPE_EDGE_RIGHT, SWIPE_EDGE_TOP, SWIPE_EDGE_BOTTOM)) - .forEach { (button, edge) -> 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/sample/src/main/res/layout/activity_swipe.xml b/sample/src/main/res/layout/activity_swipe.xml index c65bebc..dd52325 100644 --- a/sample/src/main/res/layout/activity_swipe.xml +++ b/sample/src/main/res/layout/activity_swipe.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/swipe_container" @@ -8,7 +8,7 @@ tools:context=".SwipeActivity" tools:ignore="HardcodedText"> - <android.support.v7.widget.Toolbar + <androidx.appcompat.widget.Toolbar android:id="@+id/swipe_toolbar" android:layout_width="0dp" android:layout_height="?attr/actionBarSize" @@ -71,4 +71,4 @@ app:layout_constraintVertical_bias="0.75" /> -</android.support.constraint.ConstraintLayout>
\ No newline at end of file +</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file diff --git a/sample/src/main/res/xml/kau_changelog.xml b/sample/src/main/res/xml/kau_changelog.xml index f6ec799..53265d0 100644 --- a/sample/src/main/res/xml/kau_changelog.xml +++ b/sample/src/main/res/xml/kau_changelog.xml @@ -6,6 +6,36 @@ <item text="" /> --> + <version title="v5.0.0" /> + <item text=":core: Update Material Dialogs to 3.x" /> + <item text=":colorpicker: Strip down to just the interface; unless you require the accent palette, it may be fine to just use MD's color extension" /> + <item text="" /> + <item text="" /> + <item text="" /> + <item text="" /> + + <version title="v4.1.0" /> + <item text=":core: Deprecate NetworkUtils, as the underlying functions are deprecated" /> + <item text=":core: Permission manager no longer synchronized, as all actions should occur in the main thread" /> + <item text=":kpref-activity: Getter and setter now have action context, with the option to reload self" /> + <item text="" /> + + <version title="v4.0.0" /> + <item text="Update translations" /> + + <version title="v4.0.0-alpha02" /> + <item text="Update translations" /> + <item text=":core: Remove anko dependency. Methods that used it now use coroutines; see the migration doc for minor changes" /> + <item text=":core: Add default CoroutineScope implementation to KauBaseActivity" /> + <item text=":core: Remove zip class. Coroutines and join can be used as an alternative" /> + <item text=":core: Delete flyweight implementation. Kotlin already has getOrPut" /> + <item text=":core: Introduce ContextHelper, where you can get the default looper, handler, and dispatcher for Android" /> + <item text=":mediapicker: Use video preloading instead of full async loading" /> + + <version title="v4.0.0-alpha01" /> + <item text="Migrate to androidx. See migration for external dependency changes." /> + <item text=":core: Remove deprecation warning for Kotterknife" /> + <version title="v3.8.0" /> <item text="Update everything to Android Studio 3.1" /> <item text="Fix new lint issues (see Migration for resource related methods)" /> @@ -13,7 +43,6 @@ <item text=":core: Deprecate Kotterknife; use kotlin_android_extensions" /> <item text=":kpref-activity: Fix seekbar increment" /> <item text=":core: Make KPref use Set<String> vs StringSet" /> - <item text="" /> <version title="v3.7.1" /> <item text="Update appcompat to 27.1.0" /> diff --git a/searchview/README.md b/searchview/README.md index 37d059a..4d6f010 100644 --- a/searchview/README.md +++ b/searchview/README.md @@ -9,4 +9,4 @@ The searchview is: * Fully themable - set the foreground or background color to style every portion, from text colors to backgrounds to ripples * Complete - binding the search view to a menu id will set the menu icon (if not previously set) and attach all the necessary listeners * Configurable - modify any portion of the inner Config class when binding the search view -* Debouncable - specify a time interval to throttle your queries; see [debouncing](/core#debounce)
\ No newline at end of file +* Debouncable - specify a time interval to throttle your queries; see [debouncing](../core#debounce) 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 0ae856a..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,17 +1,36 @@ +/* + * 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 android.support.constraint.ConstraintLayout -import android.support.v7.widget.RecyclerView import android.text.Spannable import android.text.SpannableStringBuilder import android.text.style.StyleSpan 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<SearchItem, SearchItem.ViewHolder>( - 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<Any>) { @@ -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 d223ec4..169e914 100644 --- a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt +++ b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt @@ -1,33 +1,71 @@ +/* + * 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 android.support.annotation.ColorInt -import android.support.annotation.IdRes -import android.support.transition.ChangeBounds -import android.support.transition.TransitionManager -import android.support.transition.TransitionSet -import android.support.v7.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.runOnUiThread +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<String, SearchView> = debounce(0) { query, _ -> KL.d { "Search query $query found; set your own textCallback" } } + private var textCallback: Debouncer2<String, SearchView> = + debounce(0) { query, _ -> KL.d { "Search query $query found; set your own textCallback" } } private val adapter = FastItemAdapter<SearchItem>() 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<ViewGroup>(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<ViewGroup>(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/searchview/src/main/res/layout/kau_search_iitem.xml b/searchview/src/main/res/layout/kau_search_iitem.xml index 16df945..53e33ef 100644 --- a/searchview/src/main/res/layout/kau_search_iitem.xml +++ b/searchview/src/main/res/layout/kau_search_iitem.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@id/kau_search_item_frame" android:layout_width="match_parent" @@ -58,4 +58,4 @@ app:layout_constraintStart_toEndOf="@id/kau_search_icon" app:layout_constraintTop_toBottomOf="@id/kau_search_title" /> -</android.support.constraint.ConstraintLayout>
\ No newline at end of file +</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file diff --git a/searchview/src/main/res/layout/kau_search_view.xml b/searchview/src/main/res/layout/kau_search_view.xml index c975dad..cfcb2ed 100644 --- a/searchview/src/main/res/layout/kau_search_view.xml +++ b/searchview/src/main/res/layout/kau_search_view.xml @@ -43,7 +43,7 @@ android:focusable="true" android:scaleType="centerInside" /> - <android.support.v7.widget.AppCompatEditText + <androidx.appcompat.widget.AppCompatEditText android:id="@id/kau_search_edit_text" android:layout_width="0dp" android:layout_height="match_parent" @@ -98,7 +98,7 @@ android:layout_height="@dimen/kau_search_divider" android:background="?android:attr/listDivider" /> - <android.support.v7.widget.RecyclerView + <androidx.recyclerview.widget.RecyclerView android:id="@id/kau_search_recycler" android:layout_width="match_parent" android:layout_height="wrap_content" 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 |