Skip to content

Commit

Permalink
Release 3.3.0 (#32)
Browse files Browse the repository at this point in the history
* 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 -
  • Loading branch information
AllanWang authored Aug 8, 2017
1 parent 187d8e6 commit 02e1dbc
Show file tree
Hide file tree
Showing 25 changed files with 338 additions and 165 deletions.
Empty file added KPref
Empty file.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -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>

Expand Down Expand Up @@ -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)
Expand All @@ -81,20 +83,19 @@ 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)
* Collection of complex views and widgets
* 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)

Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ public void changeAnimation(ViewHolder oldHolder, ViewHolder newHolder, int from
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
*/
Expand Down
3 changes: 1 addition & 2 deletions android-lib.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ android {

lintOptions {
warningsAsErrors true
disable 'LogNotTimber',
'UnusedResources',
disable 'UnusedResources',
'ContentDescription',
'RtlSymmetry',
'RtlHardcoded',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
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;

Expand Down Expand Up @@ -642,7 +641,7 @@ public void onAnimationEnd(Animator animation) {
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();
Expand Down
15 changes: 9 additions & 6 deletions core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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

Expand Down
4 changes: 1 addition & 3 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
}

Expand Down
90 changes: 90 additions & 0 deletions core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt
Original file line number Diff line number Diff line change
@@ -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)
}
2 changes: 1 addition & 1 deletion core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ package ca.allanwang.kau.logging
/**
* Created by Allan Wang on 2017-06-19.
*/
object KL : TimberLogger("KAU")
object KL : KauLogger("KAU")
74 changes: 61 additions & 13 deletions core/src/main/kotlin/ca/allanwang/kau/logging/TimberLogger.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
}
8 changes: 0 additions & 8 deletions core/src/main/kotlin/ca/allanwang/kau/utils/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,6 @@ annotation class KauUtils
@KauUtils inline val Int.pxToDp: Int
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
Expand Down
20 changes: 13 additions & 7 deletions core/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

/**
Expand Down
Loading

0 comments on commit 02e1dbc

Please sign in to comment.