aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2017-08-07 22:20:57 -0700
committerGitHub <noreply@github.com>2017-08-07 22:20:57 -0700
commit02e1dbc84425b0ac7f771c82f70444f742397452 (patch)
tree05e978e7588e30ce653428671f3d9f5df5397385
parent187d8e64dc7189f63707d154166867084662dbe3 (diff)
downloadkau-02e1dbc84425b0ac7f771c82f70444f742397452.tar.gz
kau-02e1dbc84425b0ac7f771c82f70444f742397452.tar.bz2
kau-02e1dbc84425b0ac7f771c82f70444f742397452.zip
Release 3.3.0 (#32)3.3.0
* Rewrite Logger (#29) * Remove dependency on timber * Update logger * Reorder throwabl * Fix lint * Update readme * Blank target * Create Zip (#30) * Finish zips with tests * Finalize * Update changelog * Add log hooks * Open most logging functions * Remap kpref items (#31) * Update readme * Generate files and prepare release * Kpref -
-rw-r--r--KPref0
-rw-r--r--README.md13
-rw-r--r--adapter/src/main/kotlin/ca/allanwang/kau/adapters/ChainedAdapters.kt4
-rw-r--r--adapter/src/main/kotlin/ca/allanwang/kau/animators/BaseItemAnimator.java2
-rw-r--r--android-lib.gradle3
-rw-r--r--core-ui/src/main/kotlin/ca/allanwang/kau/ui/widgets/InkPageIndicator.java3
-rw-r--r--core/README.md15
-rw-r--r--core/build.gradle4
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt90
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt2
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/logging/TimberLogger.kt74
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt8
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt20
-rw-r--r--core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt72
-rw-r--r--docs/Changelog.md5
-rw-r--r--gradle.properties7
-rw-r--r--kpref-activity/README.md16
-rw-r--r--kpref-activity/build.gradle1
-rw-r--r--kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt98
-rw-r--r--kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefBinder.kt29
-rw-r--r--kpref-activity/src/main/res/layout/kau_pref_activity.xml16
-rw-r--r--sample/src/main/kotlin/ca/allanwang/kau/sample/SL.kt8
-rw-r--r--sample/src/main/kotlin/ca/allanwang/kau/sample/SampleApp.kt4
-rw-r--r--sample/src/main/res/xml/kau_changelog.xml6
-rw-r--r--searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt3
25 files changed, 338 insertions, 165 deletions
diff --git a/KPref b/KPref
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/KPref
diff --git a/README.md b/README.md
index 5092d77..f895eb6 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
+<a href="https://allanwang.github.io/KAU/" target="_blank">
<img src="https://cdn.rawgit.com/AllanWang/KAU/master/files/images/logo.svg" alt="KAU" width="30%"/>
+</a>
An extensive collection of <b>Kotlin Android Utils</b>
@@ -72,7 +74,7 @@ dependencies {
* [CollapsibleViewDelegate](core#collapsible-view-delegate)
* [Swipe](core#swipe)
* [Debounce](core#debounce)
- * [Timber Logger](core#timber-logger)
+ * [KAU Logger](core#kau-logger)
* [Email Builder](core#email-builder)
* [Extension Functions](core#extension-functions)
* [Lazy Resettable](core#lazy-resettable)
@@ -81,7 +83,6 @@ dependencies {
[`Material Dialogs (core)`](https://github.com/afollestad/material-dialogs),
[`Iconics`](https://github.com/mikepenz/Android-Iconics),
[`Anko`](https://github.com/Kotlin/anko),
-[`Timber`](https://github.com/JakeWharton/timber),
[`Kotlin stdlib`](https://kotlinlang.org/api/latest/jvm/stdlib/)
## [Core UI](core-ui#readme)
@@ -89,12 +90,12 @@ dependencies {
* Includes `:core`, `:adapter`
## [About](about#readme)
-* Implementation of an overlaying about section, along with automatic lib detection; also includes the lib strings for KAU
+* Modularized overlaying about section. Comes with a main panel, automatic lib detection, and a FAQ parser; also includes the lib strings for KAU.
* Includes `:core-ui`, `:adapter`,
[`About Libraries`](https://github.com/mikepenz/AboutLibraries)
## [Adapter](adapter#readme)
-* Kotlin bindings for the fast adapter, as well as RecyclerView animations
+* Kotlin bindings for the fast adapter, as well as modularized RecyclerView animations
* Includes `:core`,
[`Fast Adapter`](https://github.com/mikepenz/FastAdapter)
@@ -104,8 +105,8 @@ dependencies {
([`Material Dialogs (commons)`](https://github.com/afollestad/material-dialogs))
## [KPref Activity](kpref-activity#readme)
-* Fully programmatic implementation of a Preference Activity, backed by RecyclerViews
-* Includes `:core-ui`, `:adapter`, `colorpicker`
+* Fully programmatic implementation of a Preference Activity, backed by a RecyclerView
+* Includes `:core`, `:adapter`, `:colorpicker`
## [Media Picker](mediapicker#readme)
* Fully functional image and video pickers, both as an overlay and as a requested activity.
diff --git a/adapter/src/main/kotlin/ca/allanwang/kau/adapters/ChainedAdapters.kt b/adapter/src/main/kotlin/ca/allanwang/kau/adapters/ChainedAdapters.kt
index e1c5c18..2da0cac 100644
--- a/adapter/src/main/kotlin/ca/allanwang/kau/adapters/ChainedAdapters.kt
+++ b/adapter/src/main/kotlin/ca/allanwang/kau/adapters/ChainedAdapters.kt
@@ -2,6 +2,7 @@ package ca.allanwang.kau.adapters
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
+import ca.allanwang.kau.utils.withLinearAdapter
import com.mikepenz.fastadapter.IItem
import com.mikepenz.fastadapter.adapters.HeaderAdapter
import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter
@@ -55,8 +56,7 @@ class ChainedAdapters<T>(vararg items: Pair<T, SectionAdapter<*>>) {
recycler = recyclerView
indexStack.push(0)
with(recyclerView) {
- layoutManager = LinearLayoutManager(context)
- adapter = chain.first().second
+ withLinearAdapter(chain.first().second)
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(rv: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(rv, dx, dy)
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 69c2cf3..06b8df6 100644
--- a/adapter/src/main/kotlin/ca/allanwang/kau/animators/BaseItemAnimator.java
+++ b/adapter/src/main/kotlin/ca/allanwang/kau/animators/BaseItemAnimator.java
@@ -485,7 +485,7 @@ public abstract class BaseItemAnimator extends SimpleItemAnimator {
public abstract ViewPropertyAnimator changeNewAnimation(ViewHolder holder);
/**
- * the cleanup method if the animation needs to be stopped. and tro prepare for the next view
+ * the cleanup method if the animation needs to be stopped. and to prepare for the next view
*
* @param holder
*/
diff --git a/android-lib.gradle b/android-lib.gradle
index 46b74a8..a8417c0 100644
--- a/android-lib.gradle
+++ b/android-lib.gradle
@@ -36,8 +36,7 @@ android {
lintOptions {
warningsAsErrors true
- disable 'LogNotTimber',
- 'UnusedResources',
+ disable 'UnusedResources',
'ContentDescription',
'RtlSymmetry',
'RtlHardcoded',
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 65eb5b7..d56c85e 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
@@ -30,7 +30,6 @@ import android.graphics.RectF;
import android.support.annotation.ColorInt;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
import android.view.animation.Interpolator;
@@ -642,7 +641,7 @@ public class InkPageIndicator extends View implements ViewPager.OnPageChangeList
private void setJoiningFraction(int leftDot, float fraction) {
if (leftDot < joiningFractions.length) {
- if (leftDot == 1) KL.INSTANCE.v("PageIndicator dot 1 fraction:\t$fraction");
+ if (leftDot == 1) KL.INSTANCE.v("PageIndicator dot 1 fraction:\t" + fraction, null);
joiningFractions[leftDot] = fraction;
postInvalidateOnAnimation();
diff --git a/core/README.md b/core/README.md
index 6796082..4cb68d0 100644
--- a/core/README.md
+++ b/core/README.md
@@ -13,7 +13,7 @@
* [CollapsibleViewDelegate](#collapsible-view-delegate)
* [Swipe](#swipe)
* [Debounce](#debounce)
-* [Timber Logger](#timber-logger)
+* [KAU Logger](#kau-logger)
* [Email Builder](#email-builder)
* [Extension Functions](#extension-functions)
* [Lazy Resettable](#lazy-resettable)
@@ -58,7 +58,7 @@ The object inherits the initializer method `fun initialize(c: Context, preferenc
There is also a `reset()` method to clear the local values and have them retrieve from the SharedPreference again.
In shared preferences, we often require a boolean that returns true once, so we can use it to showcase views or display prompts on the first load.
-Kpref supports special preferences like these through the `KPrefSingleDelgate`
+KPref supports special preferences like these through the `KPrefSingleDelgate`
It can be used in a KPref like so:
@@ -193,11 +193,14 @@ KAU offers extensions to easily convert or create functions into debouncables.
Simply call `debounce` and specify your interval on an existing function, or with a new function.
-## Timber Logger
+## KAU Logger
-[Timber](https://github.com/JakeWharton/timber)'s DebugTree uses the tag to specify the current class that is being logged.
-To add the tag directly in the message, create an object that extends the TimberLogger class with the tag name as the argument.
-Along with the timber methods (`v`, `i`, `d`, `e`), Timber Logger also supports `eThrow` to wrap a String in a throwable
+`KauLogger` can be extended by an object to implement a logger with a permanent tag.
+It's methods are the same as the main logger, along with the following:
+* Logging methods have two inputs, the main text and private text.
+If private text is disabled (default), it will not be logged.
+* The loggers have toggles to enable logging as a whole and to filter out priorities that we wish to ignore.
+* Has some other functions, like logging the current thread.
## Email Builder
diff --git a/core/build.gradle b/core/build.gradle
index 0960d59..cdd7859 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -16,9 +16,7 @@ dependencies {
compile "com.mikepenz:google-material-typeface:${IICON_GOOGLE}.original@aar"
compile "com.afollestad.material-dialogs:core:${MATERIAL_DIALOG}"
-
- compile "com.jakewharton.timber:timber:${TIMBER}"
-
+
compile "org.jetbrains.anko:anko-commons:${ANKO}"
}
diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt
new file mode 100644
index 0000000..cff520f
--- /dev/null
+++ b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt
@@ -0,0 +1,90 @@
+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<T> {
+ result[index] = it
+ if (countDown.decrementAndGet() <= 0)
+ onFinished(result)
+ })
+ }
+}
+
+/**
+ * Simplified zip method with no finished callback arguments
+ */
+inline fun Collection<(ZipEmptyCallback) -> Unit>.zip(crossinline onFinished: () -> Unit) {
+ val countDown = AtomicInteger(size)
+ forEach { asyncFun ->
+ asyncFun(ZipEmptyCallback {
+ if (countDown.decrementAndGet() <= 0)
+ onFinished()
+ })
+ }
+}
+
+/**
+ * Converts a collection of synchronous tasks to asynchronous tasks with a common callback
+ */
+inline fun Collection<() -> Unit>.zipAsync(crossinline onFinished: () -> Unit) {
+ map { synchronousFun ->
+ {
+ callback: ZipEmptyCallback ->
+ doAsync {
+ synchronousFun()
+ callback()
+ }; Unit
+ }
+ }.zip(onFinished)
+}
diff --git a/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt b/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt
index 4fa3360..24146b0 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt
@@ -3,4 +3,4 @@ package ca.allanwang.kau.logging
/**
* Created by Allan Wang on 2017-06-19.
*/
-object KL : TimberLogger("KAU") \ No newline at end of file
+object KL : KauLogger("KAU") \ No newline at end of file
diff --git a/core/src/main/kotlin/ca/allanwang/kau/logging/TimberLogger.kt b/core/src/main/kotlin/ca/allanwang/kau/logging/TimberLogger.kt
index 4cf566a..2fbecf5 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/logging/TimberLogger.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/logging/TimberLogger.kt
@@ -2,23 +2,71 @@
package ca.allanwang.kau.logging
-import timber.log.Timber
+import android.os.Looper
+import android.util.Log
/**
* Created by Allan Wang on 2017-05-28.
*
- * Timber extension that will embed the tag as part of the message for each log item
+ * Base logger class with a predefined tag
+ * This may be extended by an object to effectively replace [Log]
*/
-open class TimberLogger(tag: String) {
- val TAG = "$tag: %s"
- inline fun e(s: String) = Timber.e(TAG, s)
- inline fun e(t: Throwable?, s: String = "error") = if (t == null) e(s) else Timber.e(t, TAG, s)
- inline fun d(s: String) = Timber.d(TAG, s)
- inline fun i(s: String) = Timber.i(TAG, s)
- inline fun v(s: String) = Timber.v(TAG, s)
- inline fun eThrow(s: String) = e(Throwable(s))
-// fun plant() {
-// Timber.plant(Timber.Tree())
-// }
+open class KauLogger(val tag: String) {
+
+ open var enabled = true
+ open var showPrivateText = false
+
+ /**
+ * Filter pass-through to decide what we wish to log
+ * By default, we will ignore verbose and debug logs
+ * @returns {@code true} to log the message, {@code false} to ignore
+ */
+ open var filter: (Int) -> Boolean = { it != Log.VERBOSE && it != Log.DEBUG }
+
+ open fun disable(disable: Boolean = true): KauLogger {
+ enabled = !disable
+ return this
+ }
+
+ open fun debug(enable: Boolean) {
+ filter = if (enable) { _ -> true } else { i -> i != Log.VERBOSE && i != Log.DEBUG }
+ showPrivateText = enable
+ }
+
+ open fun log(priority: Int, message: String?, privateMessage: String?, t: Throwable? = null) {
+ if (!shouldLog(priority, message, privateMessage, t)) return
+ logImpl(priority, message, privateMessage, t)
+ }
+
+ protected open fun shouldLog(priority: Int, message: String?, privateMessage: String?, t: Throwable?): Boolean
+ = enabled && filter(priority)
+
+ protected open fun logImpl(priority: Int, message: String?, privateMessage: String?, t: Throwable?) {
+ var text = message ?: ""
+ if (showPrivateText && privateMessage != null)
+ text += "\n-\t$privateMessage"
+ if (t != null) Log.e(tag, text, t)
+ else if (text.isNotBlank()) Log.println(priority, tag, text)
+ }
+
+ open fun v(text: String?, privateText: String? = null) = log(Log.VERBOSE, text, privateText)
+ open fun d(text: String?, privateText: String? = null) = log(Log.DEBUG, text, privateText)
+ open fun i(text: String?, privateText: String? = null) = log(Log.INFO, text, privateText)
+ open fun e(text: String?, privateText: String? = null) = log(Log.ERROR, text, privateText)
+ open fun a(text: String?, privateText: String? = null) = log(Log.ASSERT, text, privateText)
+ open fun e(t: Throwable?, text: String?, privateText: String? = null) = log(Log.ERROR, text, privateText, t)
+ open fun eThrow(text: String?) {
+ if (text != null)
+ e(Throwable(text), text)
+ }
+
+ /**
+ * Log the looper
+ */
+ open fun checkThread(id: Int) {
+ val name = Thread.currentThread().name
+ val status = if (Looper.myLooper() == Looper.getMainLooper()) "is" else "is not"
+ d("$id $status in the main thread - thread name: $name")
+ }
} \ 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 e8f385a..2f3e9a5 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt
@@ -39,14 +39,6 @@ annotation class KauUtils
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
/**
- * Log whether current state is in the main thread
- */
-@KauUtils fun checkThread(id: Int) {
- val status = if (Looper.myLooper() == Looper.getMainLooper()) "is" else "is not"
- KL.d("$id $status in the main thread")
-}
-
-/**
* Converts minute value to string
* Whole hours and days will be converted as such, otherwise it will default to x minutes
*/
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 53d711d..3620a4a 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
@@ -211,13 +211,19 @@ 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 {
- return 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
+ */
+fun RecyclerView.withLinearAdapter(rvAdapter: RecyclerView.Adapter<*>) = apply {
+ layoutManager = LinearLayoutManager(context)
+ adapter = rvAdapter
}
/**
diff --git a/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt b/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt
new file mode 100644
index 0000000..4a04142
--- /dev/null
+++ b/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt
@@ -0,0 +1,72 @@
+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/docs/Changelog.md b/docs/Changelog.md
index 3c61dd3..0fe867a 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -2,6 +2,11 @@
## v3.3.0
* :core: Create debounce methods
+* :core: Create zip methods
+* :core: [Breaking] Logging base has been renamed to KauLogger and no longer depends on timber
+* :kpref-activity: Rewrote binding logic to use only one recyclerview
+* :kpref-activity: [Breaking] Removed sliding toolbar and use normal toolbar title
+* :kpref-activity: Remove :core-ui: dependency
* :searchview: [Breaking] remove reactive dependencies and stick with basic callbacks
## v3.2.5
diff --git a/gradle.properties b/gradle.properties
index a778a66..b738642 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -23,7 +23,7 @@ TARGET_SDK=26
BUILD_TOOLS=26.0.1
ANDROID_SUPPORT_LIBS=26.0.0
-VERSION_NAME=3.2.6
+VERSION_NAME=3.3.0
KOTLIN=1.1.3-2
ABOUT_LIBRARIES=5.9.7
@@ -36,11 +36,6 @@ GLIDE=4.0.0
ICONICS=2.9.1
IICON_GOOGLE=3.0.1.1
MATERIAL_DIALOG=0.9.4.5
-RX_ANDROID=2.0.1
-RX_BINDING=2.0.0
-RX_JAVA=2.1.2
-RX_KOTLIN=2.1.0
-TIMBER=4.5.1
ESPRESSO=3.0.0
JUNIT=4.12
diff --git a/kpref-activity/README.md b/kpref-activity/README.md
index 5ec94a6..015d0d8 100644
--- a/kpref-activity/README.md
+++ b/kpref-activity/README.md
@@ -39,9 +39,6 @@ An example of the adapter builder:
```kotlin
override fun onCreateKPrefs(savedInstanceState: android.os.Bundle?): KPrefAdapterBuilder.() -> Unit = {
-
- textColor = { KPrefSample.textColor } // getter function so the new text color will be retrieved for every reload
- accentColor = { KPrefSample.accentColor }
header(R.string.header)
@@ -66,4 +63,17 @@ override fun onCreateKPrefs(savedInstanceState: android.os.Bundle?): KPrefAdapte
}
}
}
+```
+
+On top of per item configurations, `KPrefActivity` has some core attributes that you can define on creation.
+It is done through the abstract function:
+
+```kotlin
+
+ override fun kPrefCoreAttributes(): CoreAttributeContract.() -> Unit = {
+ textColor = { Prefs.textColor } // text color getter; refreshes automatically on reload
+ accentColor = { Prefs.accentColor } // accent color getter
+ // background color does not exist as it is done through the ripple canvas
+ }
+
``` \ No newline at end of file
diff --git a/kpref-activity/build.gradle b/kpref-activity/build.gradle
index ab2a7de..e0849d4 100644
--- a/kpref-activity/build.gradle
+++ b/kpref-activity/build.gradle
@@ -5,7 +5,6 @@ ext.kauSubModuleResourcePrefix = "kau_pref_"
apply from: '../android-lib.gradle'
dependencies {
- compile project(':core-ui')
compile project(':adapter')
compile project(':colorpicker')
}
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 3e1596f..900b004 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
@@ -3,49 +3,43 @@ package ca.allanwang.kau.kpref.activity
import android.annotation.SuppressLint
import android.os.Bundle
import android.support.annotation.StringRes
-import android.support.constraint.ConstraintLayout
-import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.Toolbar
import android.view.View
-import android.view.animation.Animation
-import android.view.animation.AnimationUtils
-import android.widget.FrameLayout
-import android.widget.ViewAnimator
+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.ui.widgets.TextSlider
-import ca.allanwang.kau.utils.bindView
-import ca.allanwang.kau.utils.resolveColor
-import ca.allanwang.kau.utils.statusBarColor
-import ca.allanwang.kau.utils.string
+import ca.allanwang.kau.utils.*
import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter
+import org.jetbrains.anko.doAsync
+import org.jetbrains.anko.uiThread
+import java.util.*
abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract {
- val adapter: FastItemAdapter<KPrefItemCore>
- @Suppress("UNCHECKED_CAST")
- get() = recycler.adapter as FastItemAdapter<KPrefItemCore>
- val recycler: RecyclerView
- get() = prefHolder.currentView as RecyclerView
- val container: ConstraintLayout by bindView(R.id.kau_container)
+ private val adapter: FastItemAdapter<KPrefItemCore> = FastItemAdapter()
+ private val recycler: RecyclerView by bindView(R.id.kau_recycler)
val bgCanvas: RippleCanvas by bindView(R.id.kau_ripple)
val toolbarCanvas: RippleCanvas by bindView(R.id.kau_toolbar_ripple)
val toolbar: Toolbar by bindView(R.id.kau_toolbar)
- val toolbarTitle: TextSlider by bindView(R.id.kau_toolbar_text)
- val prefHolder: ViewAnimator by bindView(R.id.kau_holder)
private lateinit var globalOptions: GlobalOptions
+ private val kprefStack = Stack<Pair<Int, List<KPrefItemCore>>>()
+ /**
+ * Toggle sliding animations for the kpref items
+ */
var animate: Boolean = true
- set(value) {
- field = value
- toolbarTitle.animationType = if (value) TextSlider.ANIMATION_SLIDE_HORIZONTAL else TextSlider.ANIMATION_NONE
- }
- private val SLIDE_IN_LEFT_ITEMS: Animation by lazy { AnimationUtils.loadAnimation(this, R.anim.kau_slide_in_left) }
- private val SLIDE_IN_RIGHT_ITEMS: Animation by lazy { AnimationUtils.loadAnimation(this, R.anim.kau_slide_in_right) }
- private val SLIDE_OUT_LEFT_ITEMS: Animation by lazy { AnimationUtils.loadAnimation(this, R.anim.kau_slide_out_left) }
- private val SLIDE_OUT_RIGHT_ITEMS: Animation by lazy { AnimationUtils.loadAnimation(this, R.anim.kau_slide_out_right) }
+ private val recyclerAnimatorNext: KauAnimator by lazy {
+ 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))
+ }
/**
* Core attribute builder that is consistent throughout all items
@@ -69,43 +63,41 @@ abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract {
statusBarColor = 0x30000000
toolbarCanvas.set(resolveColor(R.attr.colorPrimary))
bgCanvas.set(resolveColor(android.R.attr.colorBackground))
- prefHolder.animateFirstView = false
//setup prefs
val core = CoreAttributeBuilder()
val builder = kPrefCoreAttributes()
core.builder()
globalOptions = GlobalOptions(core, this)
- showNextPrefs(R.string.kau_settings, onCreateKPrefs(savedInstanceState))
+ recycler.withLinearAdapter(adapter)
+ adapter.withSelectable(false)
+ .withOnClickListener { v, _, item, _ -> item.onClick(v, v.findViewById(R.id.kau_pref_inner_content)) }
+ showNextPrefs(R.string.kau_settings, onCreateKPrefs(savedInstanceState), true)
}
- override fun onPostCreate(savedInstanceState: Bundle?) {
- super.onPostCreate(savedInstanceState)
- }
+ override fun showNextPrefs(@StringRes toolbarTitleRes: Int, builder: KPrefAdapterBuilder.() -> Unit)
+ = showNextPrefs(toolbarTitleRes, builder, false)
- override fun showNextPrefs(@StringRes toolbarTitleRes: Int, builder: KPrefAdapterBuilder.() -> Unit) {
- val rv = RecyclerView(this).apply {
- layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)
- setKPrefAdapter(globalOptions, builder)
+ private fun showNextPrefs(@StringRes toolbarTitleRes: Int, builder: KPrefAdapterBuilder.() -> Unit, first: Boolean) {
+ doAsync {
+ val items = KPrefAdapterBuilder(globalOptions)
+ builder(items)
+ kprefStack.push(toolbarTitleRes to items.list)
+ recycler.itemAnimator = if (animate && !first) recyclerAnimatorNext else null
+ uiThread {
+ adapter.clear()
+ adapter.add(items.list)
+ toolbar.setTitle(toolbarTitleRes)
+ }
}
- with(prefHolder) {
- inAnimation = if (animate) SLIDE_IN_RIGHT_ITEMS else null
- outAnimation = if (animate) SLIDE_OUT_LEFT_ITEMS else null
- addView(rv)
- showNext()
- }
- toolbarTitle.setNextText(string(toolbarTitleRes))
}
override fun showPrevPrefs() {
- val current = prefHolder.currentView
- with(prefHolder) {
- inAnimation = if (animate) SLIDE_IN_LEFT_ITEMS else null
- outAnimation = if (animate) SLIDE_OUT_RIGHT_ITEMS else null
- showPrevious()
- removeView(current)
- adapter.notifyAdapterDataSetChanged()
- }
- toolbarTitle.setPrevText()
+ kprefStack.pop()
+ val (title, list) = kprefStack.peek()
+ recycler.itemAnimator = if (animate) recyclerAnimatorPrev else null
+ adapter.clear()
+ adapter.add(list)
+ toolbar.setTitle(title)
}
fun reload(vararg index: Int) {
@@ -128,7 +120,7 @@ abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract {
}
fun backPress(): Boolean {
- if (!toolbarTitle.isRoot) {
+ if (kprefStack.size > 1) {
showPrevPrefs()
return true
}
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 6048c1a..b45e406 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,39 +1,13 @@
package ca.allanwang.kau.kpref.activity
import android.support.annotation.StringRes
-import android.support.v7.widget.LinearLayoutManager
-import android.support.v7.widget.RecyclerView
-import ca.allanwang.kau.R
import ca.allanwang.kau.kpref.activity.items.*
-import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter
-import org.jetbrains.anko.doAsync
-import org.jetbrains.anko.uiThread
/**
* Created by Allan Wang on 2017-06-08.
*
* Houses all the components that can be called externally to setup the kpref mainAdapter
*/
-
-/**
- * Base extension that will register the layout manager and mainAdapter with the given items
- * Returns FastAdapter
- */
-fun RecyclerView.setKPrefAdapter(globalOptions: GlobalOptions, builder: KPrefAdapterBuilder.() -> Unit): FastItemAdapter<KPrefItemCore> {
- layoutManager = LinearLayoutManager(context)
- val adapter = FastItemAdapter<KPrefItemCore>()
- adapter.withOnClickListener { v, _, item, _ -> item.onClick(v, v.findViewById(R.id.kau_pref_inner_content)) }
- this.adapter = adapter
- doAsync {
- val items = KPrefAdapterBuilder(globalOptions)
- builder.invoke(items)
- uiThread {
- adapter.add(items.list)
- }
- }
- return adapter
-}
-
@DslMarker
annotation class KPrefMarker
@@ -70,6 +44,9 @@ class GlobalOptions(core: CoreAttributeContract, activity: KPrefActivityContract
* Contains DSLs for every possible item
* The arguments are all the mandatory values plus an optional builder housing all the possible configurations
* The mandatory values are final so they cannot be edited in the builder
+ *
+ * This function will be called asynchronously, so don't worry about blocking the thread
+ * The recycler will only animate once this is completed though
*/
@KPrefMarker
class KPrefAdapterBuilder(val globalOptions: GlobalOptions) {
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 19320b8..7651e5a 100644
--- a/kpref-activity/src/main/res/layout/kau_pref_activity.xml
+++ b/kpref-activity/src/main/res/layout/kau_pref_activity.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">
@@ -22,16 +21,7 @@
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent">
-
- <ca.allanwang.kau.ui.widgets.TextSlider
- android:id="@+id/kau_toolbar_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- app:animation_type="slide_horizontal" />
-
- </android.support.v7.widget.Toolbar>
+ app:layout_constraintTop_toTopOf="parent" />
<ca.allanwang.kau.ui.views.RippleCanvas
android:id="@+id/kau_ripple"
@@ -42,8 +32,8 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/kau_toolbar" />
- <ViewAnimator
- android:id="@+id/kau_holder"
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/kau_recycler"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/SL.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/SL.kt
deleted file mode 100644
index a77ffe8..0000000
--- a/sample/src/main/kotlin/ca/allanwang/kau/sample/SL.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package ca.allanwang.kau.sample
-
-import ca.allanwang.kau.logging.TimberLogger
-
-/**
- * Created by Allan Wang on 2017-06-08.
- */
-object SL: TimberLogger("KAU Sample") \ 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 7fdc83d..541eaec 100644
--- a/sample/src/main/kotlin/ca/allanwang/kau/sample/SampleApp.kt
+++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/SampleApp.kt
@@ -1,7 +1,7 @@
package ca.allanwang.kau.sample
import android.app.Application
-import timber.log.Timber
+import ca.allanwang.kau.logging.KL
/**
* Created by Allan Wang on 2017-06-08.
@@ -9,7 +9,7 @@ import timber.log.Timber
class SampleApp : Application() {
override fun onCreate() {
super.onCreate()
- Timber.plant(Timber.DebugTree())
+ KL.debug(BuildConfig.DEBUG)
KPrefSample.initialize(this, "pref_sample")
}
} \ 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 96ae965..6008ae1 100644
--- a/sample/src/main/res/xml/kau_changelog.xml
+++ b/sample/src/main/res/xml/kau_changelog.xml
@@ -8,9 +8,15 @@
<version title="v3.3.0"/>
<item text=":core: Create debounce methods" />
+ <item text=":core: Create zip methods" />
+ <item text=":core: [Breaking] Logging base has been renamed to KauLogger and no longer depends on timber" />
+ <item text=":kpref-activity: Rewrote binding logic to use only one recyclerview" />
+ <item text=":kpref-activity: [Breaking] Removed sliding toolbar and use normal toolbar title" />
+ <item text=":kpref-activity: Remove :core-ui: dependency" />
<item text=":searchview: [Breaking] remove reactive dependencies and stick with basic callbacks" />
<item text="" />
<item text="" />
+ <item text="" />
<version title="v3.2.5"/>
<item text=":core: Fix FAQ background" />
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 a98b2f6..cc56289 100644
--- a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
+++ b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
@@ -229,14 +229,13 @@ class SearchView @JvmOverloads constructor(
tintBackground(configs.backgroundColor)
with(recycler) {
isNestedScrollingEnabled = false
- layoutManager = LinearLayoutManager(context)
+ withLinearAdapter(this@SearchView.adapter)
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) hideKeyboard()
}
})
- adapter = this@SearchView.adapter
itemAnimator = null
}
with(adapter) {