aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/README.md8
-rw-r--r--core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt87
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt10
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt75
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt96
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefSingleDelegate.kt58
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefTransaction.kt2
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/swipe/ViewDragHelper.java2
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt12
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt32
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt2
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/CoroutineUtils.kt5
-rw-r--r--core/src/main/res-public/values-ar-rSA/strings_commons.xml55
-rw-r--r--core/src/main/res-public/values/public.xml52
-rw-r--r--core/src/test/kotlin/ca/allanwang/kau/ui/ProgressAnimatorTest.kt18
15 files changed, 364 insertions, 150 deletions
diff --git a/core/README.md b/core/README.md
index b9a10f5..b1140bf 100644
--- a/core/README.md
+++ b/core/README.md
@@ -71,6 +71,14 @@ object MyPrefs : KPref() {
Notice that it is a `val` and takes no default. It will return true the first time and false for all subsequent calls.
+### KPref Testing
+
+If your android components can be tested without an emulator, you can also modify KPref to operate without shared preferences.
+To do so, call `KPref(KPrefBuilderInMemory)` when creating your preferences.
+This variant does not pass updates to the shared preferences.
+To set the builder, you may wish to use dependency injection or service locators to supply the builder and the KPref.
+In that case, your preferences would be a class instead of an object.
+
## Changelog XML
Create an xml resource with the following structure:
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 29f5af1..143b83f 100644
--- a/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt
+++ b/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt
@@ -24,8 +24,6 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
-import kotlin.test.assertFalse
-import kotlin.test.assertTrue
/**
* Created by Allan Wang on 2017-08-01.
@@ -34,19 +32,24 @@ import kotlin.test.assertTrue
@MediumTest
class KPrefTest {
- lateinit var pref: TestPref
+ lateinit var androidPref: TestPref
+ lateinit var memPref: TestPref
- class TestPref : KPref() {
+ class TestPref(builder: KPrefBuilder) : KPref(builder) {
init {
initialize(ApplicationProvider.getApplicationContext<Context>(), "kpref_test_${System.currentTimeMillis()}")
}
+ var postSetterCount: Int = 0
+
var one by kpref("one", 1)
var two by kpref("two", 2f)
- var `true` by kpref("true", true)
+ var `true` by kpref("true", true, postSetter = {
+ postSetterCount++
+ })
var hello by kpref("hello", "hello")
@@ -57,51 +60,67 @@ class KPrefTest {
@Before
fun init() {
- pref = TestPref()
- pref.sp.edit().clear().commit()
+ androidPref = TestPref(KPrefBuilderAndroid)
+ androidPref.sp.edit().clear().commit()
+ memPref = TestPref(KPrefBuilderInMemory)
+ }
+
+ private fun pref(action: TestPref.() -> Unit) {
+ androidPref.action()
+ memPref.action()
+ }
+
+ private fun <T> assertPrefEquals(expected: T, actual: TestPref.() -> T, message: String? = null) {
+ assertEquals(expected, androidPref.actual(), "Android KPrefs: $message")
+ assertEquals(expected, memPref.actual(), "In Mem KPrefs: $message")
}
@Test
fun getDefaults() {
- assertEquals(1, pref.one)
- assertEquals(2f, pref.two)
- assertEquals(true, pref.`true`)
- assertEquals("hello", pref.hello)
- assertEquals(3, pref.set.size)
- assertTrue(pref.set.contains("po"))
- assertTrue(pref.set.contains("ta"))
- assertTrue(pref.set.contains("to"))
- assertEquals(0, pref.sp.all.size, "Defaults should not be set automatically")
+ assertPrefEquals(1, { one })
+ assertPrefEquals(2f, { two })
+ assertPrefEquals(true, { `true` })
+ assertPrefEquals("hello", { hello })
+ assertPrefEquals(3, { set.size })
+ assertPrefEquals(setOf("po", "ta", "to"), { set })
+ assertEquals(0, androidPref.sp.all.size, "Defaults should not be set automatically")
}
@Test
fun setter() {
- assertEquals(1, pref.one)
- pref.one = 2
- assertEquals(2, pref.one)
- pref.hello = "goodbye"
- assertEquals("goodbye", pref.hello)
- assertEquals(pref.hello, pref.sp.getString("hello", "hello"))
- assertEquals(2, pref.sp.all.size)
+ assertPrefEquals(1, { one })
+ pref { one = 2 }
+ assertPrefEquals(2, { one })
+ pref { hello = "goodbye" }
+ assertPrefEquals("goodbye", { hello })
+ assertEquals(androidPref.hello, androidPref.sp.getString("hello", "badfallback"))
+ assertEquals(2, androidPref.sp.all.size)
}
@SuppressLint("CommitPrefEdits")
@Test
fun reset() {
- pref.one = 2
- assertEquals(2, pref.one)
- assertEquals(6, pref.prefMap.size, "Prefmap does not have all elements")
- pref.reset() //only invalidates our lazy delegate; doesn't change the actual pref
- assertEquals(2, pref.one, "Kpref did not properly fetch from shared prefs")
- pref.sp.edit().putInt("one", -1).commit()
- assertEquals(2, pref.one, "Lazy kpref should still retain old value")
- pref.reset()
- assertEquals(-1, pref.one, "Kpref did not refetch from shared prefs upon reset")
+ pref { one = 2 }
+ assertPrefEquals(2, { one })
+ assertPrefEquals(6, { prefMap.size }, "Prefmap does not have all elements")
+ pref { reset() } //only invalidates our lazy delegate; doesn't change the actual pref
+ assertPrefEquals(2, { one }, "Kpref did not properly fetch from shared prefs")
+ // Android pref only
+ androidPref.sp.edit().putInt("one", -1).commit()
+ assertEquals(2, androidPref.one, "Lazy kpref should still retain old value")
+ androidPref.reset()
+ assertEquals(-1, androidPref.one, "Kpref did not refetch from shared prefs upon reset")
}
@Test
fun single() {
- assertTrue(pref.oneShot)
- assertFalse(pref.oneShot)
+ assertPrefEquals(true, { oneShot })
+ assertPrefEquals(false, { androidPref.oneShot })
+ }
+
+ @Test
+ fun postSetter() {
+ pref { `true` = true }
+ assertPrefEquals(1, { postSetterCount }, "Post setter was not called")
}
}
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 7a6330f..fc7a76a 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt
@@ -36,14 +36,18 @@ import ca.allanwang.kau.logging.KL
* You may optionally override [deleteKeys]. This will be called on initialization
* And delete all keys returned from that method
*/
-open class KPref {
+open class KPref(builder: KPrefBuilder = KPrefBuilderAndroid) : KPrefBuilder by builder {
lateinit var PREFERENCE_NAME: String
lateinit var sp: SharedPreferences
- fun initialize(c: Context, preferenceName: String) {
+ fun initialize(
+ c: Context,
+ preferenceName: String,
+ sharedPrefs: SharedPreferences = c.applicationContext.getSharedPreferences(preferenceName, Context.MODE_PRIVATE)
+ ) {
PREFERENCE_NAME = preferenceName
- sp = c.applicationContext.getSharedPreferences(preferenceName, Context.MODE_PRIVATE)
+ sp = sharedPrefs
KL.d { "Shared Preference $preferenceName has been initialized" }
val toDelete = deleteKeys()
if (toDelete.isNotEmpty()) {
diff --git a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt
new file mode 100644
index 0000000..4dd3012
--- /dev/null
+++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBuilder.kt
@@ -0,0 +1,75 @@
+package ca.allanwang.kau.kpref
+
+interface KPrefBuilder {
+ fun KPref.kpref(key: String, fallback: Boolean, postSetter: (value: Boolean) -> Unit = {}): KPrefDelegate<Boolean>
+
+ fun KPref.kpref(key: String, fallback: Float, postSetter: (value: Float) -> Unit = {}): KPrefDelegate<Float>
+
+ @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 = {}): KPrefDelegate<Float> =
+ kpref(key, fallback.toFloat(), postSetter)
+
+ fun KPref.kpref(key: String, fallback: Int, postSetter: (value: Int) -> Unit = {}): KPrefDelegate<Int>
+
+ fun KPref.kpref(key: String, fallback: Long, postSetter: (value: Long) -> Unit = {}): KPrefDelegate<Long>
+
+ fun KPref.kpref(
+ key: String,
+ fallback: Set<String>,
+ postSetter: (value: Set<String>) -> Unit = {}
+ ): KPrefDelegate<Set<String>>
+
+ fun KPref.kpref(key: String, fallback: String, postSetter: (value: String) -> Unit = {}): KPrefDelegate<String>
+
+ fun KPref.kprefSingle(key: String): KPrefSingleDelegate
+}
+
+object KPrefBuilderAndroid : KPrefBuilder {
+
+ override fun KPref.kpref(key: String, fallback: Boolean, postSetter: (value: Boolean) -> Unit) =
+ KPrefDelegateAndroid(key, fallback, this, KPrefBooleanTransaction, postSetter)
+
+ override fun KPref.kpref(key: String, fallback: Float, postSetter: (value: Float) -> Unit) =
+ KPrefDelegateAndroid(key, fallback, this, KPrefFloatTransaction, postSetter)
+
+ override fun KPref.kpref(key: String, fallback: Int, postSetter: (value: Int) -> Unit) =
+ KPrefDelegateAndroid(key, fallback, this, KPrefIntTransaction, postSetter)
+
+ override fun KPref.kpref(key: String, fallback: Long, postSetter: (value: Long) -> Unit) =
+ KPrefDelegateAndroid(key, fallback, this, KPrefLongTransaction, postSetter)
+
+ override fun KPref.kpref(key: String, fallback: Set<String>, postSetter: (value: Set<String>) -> Unit) =
+ KPrefDelegateAndroid(key, fallback, this, KPrefSetTransaction, postSetter)
+
+ override fun KPref.kpref(key: String, fallback: String, postSetter: (value: String) -> Unit) =
+ KPrefDelegateAndroid(key, fallback, this, KPrefStringTransaction, postSetter)
+
+ override fun KPref.kprefSingle(key: String) = KPrefSingleDelegateAndroid(key, this)
+}
+
+object KPrefBuilderInMemory : KPrefBuilder {
+
+ override fun KPref.kpref(key: String, fallback: Boolean, postSetter: (value: Boolean) -> Unit) =
+ KPrefDelegateInMemory(key, fallback, this, postSetter)
+
+ override fun KPref.kpref(key: String, fallback: Float, postSetter: (value: Float) -> Unit) =
+ KPrefDelegateInMemory(key, fallback, this, postSetter)
+
+ override fun KPref.kpref(key: String, fallback: Int, postSetter: (value: Int) -> Unit) =
+ KPrefDelegateInMemory(key, fallback, this, postSetter)
+
+ override fun KPref.kpref(key: String, fallback: Long, postSetter: (value: Long) -> Unit) =
+ KPrefDelegateInMemory(key, fallback, this, postSetter)
+
+ override fun KPref.kpref(key: String, fallback: Set<String>, postSetter: (value: Set<String>) -> Unit) =
+ KPrefDelegateInMemory(key, fallback, this, postSetter)
+
+ override fun KPref.kpref(key: String, fallback: String, postSetter: (value: String) -> Unit) =
+ KPrefDelegateInMemory(key, fallback, this, postSetter)
+
+ override fun KPref.kprefSingle(key: String) = KPrefSingleDelegateInMemory(key, this)
+} \ 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 9813f24..684b139 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefDelegate.kt
@@ -17,32 +17,6 @@ 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)
-
-fun KPref.kpref(key: String, fallback: Float, postSetter: (value: Float) -> Unit = {}) =
- 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
-)
-fun KPref.kpref(key: String, fallback: Double, postSetter: (value: Float) -> Unit = {}) =
- kpref(key, fallback.toFloat(), postSetter)
-
-fun KPref.kpref(key: String, fallback: Int, postSetter: (value: Int) -> Unit = {}) =
- KPrefDelegate(key, fallback, this, KPrefIntTransaction, postSetter)
-
-fun KPref.kpref(key: String, fallback: Long, postSetter: (value: Long) -> Unit = {}) =
- 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)
-
-fun KPref.kpref(key: String, fallback: String, postSetter: (value: String) -> Unit = {}) =
- KPrefDelegate(key, fallback, this, KPrefStringTransaction, postSetter)
-
/**
* Created by Allan Wang on 2017-06-07.
*
@@ -50,13 +24,20 @@ fun KPref.kpref(key: String, fallback: String, postSetter: (value: String) -> Un
* Contains a unique key for the shared preference as well as a nonnull fallback item
* Also contains an optional mutable postSetter that will be called every time a new value is given
*/
-class KPrefDelegate<T> internal constructor(
+
+interface KPrefDelegate<T> : ILazyResettable<T> {
+ operator fun setValue(any: Any, property: kotlin.reflect.KProperty<*>, t: T)
+}
+
+class KPrefException(message: String) : IllegalAccessException(message)
+
+class KPrefDelegateAndroid<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 = {}
-) : ILazyResettable<T> {
+) : KPrefDelegate<T> {
private object UNINITIALIZED
@@ -67,28 +48,26 @@ class KPrefDelegate<T> internal constructor(
init {
if (pref.prefMap.containsKey(key))
throw KPrefException("$key is already used elsewhere in preference ${pref.PREFERENCE_NAME}")
- pref.prefMap[key] = this@KPrefDelegate
+ pref.prefMap[key] = this@KPrefDelegateAndroid
}
override fun invalidate() {
_value = UNINITIALIZED
}
+ @Suppress("UNCHECKED_CAST")
override val value: T
get() {
val _v1 = _value
if (_v1 !== UNINITIALIZED)
- @Suppress("UNCHECKED_CAST")
return _v1 as T
return synchronized(lock) {
val _v2 = _value
if (_v2 !== UNINITIALIZED) {
- @Suppress("UNCHECKED_CAST")
_v2 as T
} else {
_value = transaction.get(pref.sp, key, fallback)
- @Suppress("UNCHECKED_CAST")
_value as T
}
}
@@ -98,7 +77,7 @@ class KPrefDelegate<T> internal constructor(
override fun toString(): String = if (isInitialized()) value.toString() else "Lazy kPref $key not initialized yet."
- operator fun setValue(any: Any, property: kotlin.reflect.KProperty<*>, t: T) {
+ override operator fun setValue(any: Any, property: kotlin.reflect.KProperty<*>, t: T) {
_value = t
val editor = pref.sp.edit()
transaction.set(editor, key, t)
@@ -107,4 +86,53 @@ class KPrefDelegate<T> internal constructor(
}
}
-class KPrefException(message: String) : IllegalAccessException(message)
+class KPrefDelegateInMemory<T> internal constructor(
+ private val key: String,
+ private val fallback: T,
+ private val pref: KPref,
+ private var postSetter: (value: T) -> Unit = {}
+) : KPrefDelegate<T> {
+
+ private object UNINITIALIZED
+
+ @Volatile
+ private var _value: Any? = UNINITIALIZED
+ private val lock = this
+
+ init {
+ if (pref.prefMap.containsKey(key))
+ throw KPrefException("$key is already used elsewhere in preference ${pref.PREFERENCE_NAME}")
+ pref.prefMap[key] = this
+ }
+
+ override fun invalidate() {
+ // No op
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ override val value: T
+ get() {
+ val _v1 = _value
+ if (_v1 !== UNINITIALIZED)
+ return _v1 as T
+
+ return synchronized(lock) {
+ val _v2 = _value
+ if (_v2 !== UNINITIALIZED) {
+ _v2 as T
+ } else {
+ _value = fallback
+ _value as T
+ }
+ }
+ }
+
+ override fun isInitialized(): Boolean = _value !== UNINITIALIZED
+
+ override fun toString(): String = if (isInitialized()) value.toString() else "Lazy kPref $key not initialized yet."
+
+ override operator fun setValue(any: Any, property: kotlin.reflect.KProperty<*>, t: T) {
+ _value = t
+ postSetter(t)
+ }
+}
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 204e07e..ef59e78 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefSingleDelegate.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefSingleDelegate.kt
@@ -17,8 +17,6 @@ package ca.allanwang.kau.kpref
import ca.allanwang.kau.kotlin.ILazyResettable
-fun KPref.kprefSingle(key: String) = KPrefSingleDelegate(key, this)
-
/**
* Created by Allan Wang on 2017-06-07.
*
@@ -27,17 +25,21 @@ 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> {
+interface KPrefSingleDelegate : ILazyResettable<Boolean>
+
+class KPrefSingleDelegateAndroid internal constructor(
+ private val key: String,
+ private val pref: KPref
+) : KPrefSingleDelegate {
@Volatile
private var _value: Boolean? = null
- private val lock = lock ?: this
+ private val lock = this
init {
if (pref.prefMap.containsKey(key))
throw KPrefException("$key is already used elsewhere in preference ${pref.PREFERENCE_NAME}")
- pref.prefMap.put(key, this@KPrefSingleDelegate)
+ pref.prefMap[key] = this
}
override fun invalidate() {
@@ -47,9 +49,9 @@ class KPrefSingleDelegate internal constructor(private val key: String, private
override val value: Boolean
get() {
val _v1 = _value
- if (_v1 != null)
+ if (_v1 != null) {
return _v1
-
+ }
return synchronized(lock) {
val _v2 = _value
if (_v2 != null) {
@@ -69,3 +71,43 @@ class KPrefSingleDelegate internal constructor(private val key: String, private
override fun toString(): String = if (isInitialized()) value.toString() else "Lazy kPref $key not initialized yet."
}
+
+class KPrefSingleDelegateInMemory internal constructor(
+ private val key: String,
+ private val pref: KPref
+) : KPrefSingleDelegate {
+ @Volatile
+ private var _value: Boolean? = null
+ private val lock = this
+
+ init {
+ if (pref.prefMap.containsKey(key))
+ throw KPrefException("$key is already used elsewhere in preference ${pref.PREFERENCE_NAME}")
+ pref.prefMap[key] = this
+ }
+
+ override fun invalidate() {
+ // No op
+ }
+
+ override val value: Boolean
+ get() {
+ val _v1 = _value
+ if (_v1 != null) {
+ return _v1
+ }
+ return synchronized(lock) {
+ val _v2 = _value
+ if (_v2 != null) {
+ _v2
+ } else {
+ _value = false
+ true
+ }
+ }
+ }
+
+ 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 1070e11..3f8fe28 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefTransaction.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPrefTransaction.kt
@@ -60,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)
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 ac7fb7e..f6e907a 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/swipe/ViewDragHelper.java
+++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/ViewDragHelper.java
@@ -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 androidx.core.widget.ViewDragHelper}
+ * This is an extension of {@link androidx.customview.widget.ViewDragHelper}
* Along with additional methods defined in {@link ViewDragHelperExtras}
*/
class ViewDragHelper implements ViewDragHelperExtras {
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 40c1c72..b857eb0 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt
@@ -89,16 +89,6 @@ fun bundleOf(vararg params: kotlin.Pair<String, Any?>): Bundle {
}
/**
- * Adds transition bundle if context is activity and build is lollipop+
- */
-@SuppressLint("NewApi")
-fun Bundle.withSceneTransitionAnimation(context: Context) {
- if (context !is Activity || !buildIsLollipopAndUp) return
- val options = ActivityOptions.makeSceneTransitionAnimation(context)
- putAll(options.toBundle())
-}
-
-/**
* Given the parent view and map of view ids to tags,
* create a scene transition animation
*/
@@ -112,7 +102,7 @@ fun Bundle.withSceneTransitionAnimation(parent: View, data: Map<Int, String>) =
* create a scene transition animation
*/
@SuppressLint("NewApi")
-fun Bundle.withSceneTransitionAnimation(context: Context, data: Map<out View, String>) {
+fun Bundle.withSceneTransitionAnimation(context: Context, data: Map<out View, String> = emptyMap()) {
if (context !is Activity || !buildIsLollipopAndUp) return
val options = ActivityOptions.makeSceneTransitionAnimation(
context,
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 bbb8953..3de0297 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt
@@ -20,7 +20,6 @@ import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.PorterDuff
-import android.graphics.drawable.Drawable
import android.os.Build
import android.widget.CheckBox
import android.widget.EditText
@@ -28,13 +27,13 @@ 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 androidx.core.view.ViewCompat
import com.afollestad.materialdialogs.R
import java.util.Random
@@ -248,37 +247,16 @@ fun Context.textColorStateList(@ColorInt color: Int): ColorStateList {
return ColorStateList(states, colors)
}
-@SuppressLint("RestrictedApi")
+/**
+ * Note that this does not tint the cursor, as there is no public api to do so.
+ */
fun EditText.tint(@ColorInt color: Int) {
val editTextColorStateList = context.textColorStateList(color)
if (this is AppCompatEditText) {
- supportBackgroundTintList = editTextColorStateList
+ ViewCompat.setBackgroundTintList(this, editTextColorStateList)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
backgroundTintList = editTextColorStateList
}
- tintCursor(color)
-}
-
-fun EditText.tintCursor(@ColorInt color: Int) {
- try {
- val fCursorDrawableRes = TextView::class.java.getDeclaredField("mCursorDrawableRes")
- fCursorDrawableRes.isAccessible = true
- val mCursorDrawableRes = fCursorDrawableRes.getInt(this)
- val fEditor = TextView::class.java.getDeclaredField("mEditor")
- fEditor.isAccessible = true
- val editor = fEditor.get(this)
- val clazz = editor.javaClass
- val fCursorDrawable = clazz.getDeclaredField("mCursorDrawable")
- fCursorDrawable.isAccessible = true
- val drawables: Array<Drawable> = Array(2, {
- val drawable = context.drawable(mCursorDrawableRes)
- drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN)
- drawable
- })
- fCursorDrawable.set(editor, drawables)
- } catch (e: Exception) {
- e.printStackTrace()
- }
}
fun Toolbar.tint(@ColorInt color: Int, tintTitle: Boolean = true) {
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 e8680dc..d002fb8 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt
@@ -239,7 +239,7 @@ fun Context.hasPermission(permissions: String) = !buildIsMarshmallowAndUp || Con
fun Context.copyToClipboard(text: String?, label: String = "Copied Text", showToast: Boolean = true) {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
- clipboard.primaryClip = ClipData.newPlainText(label, text ?: "")
+ clipboard.setPrimaryClip(ClipData.newPlainText(label, text ?: ""))
if (showToast) toast(R.string.kau_text_copied)
}
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/CoroutineUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/CoroutineUtils.kt
index 57a9921..4d6ee54 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/CoroutineUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/CoroutineUtils.kt
@@ -18,6 +18,7 @@ package ca.allanwang.kau.utils
import android.content.Context
import android.os.Handler
import android.os.Looper
+import ca.allanwang.kau.internal.KauBaseActivity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.android.asCoroutineDispatcher
@@ -43,11 +44,11 @@ object ContextHelper : CoroutineScope {
}
/**
- * Most context items implement [CoroutineScope] by default.
+ * Most context items implement [CoroutineScope] by default (through [KauBaseActivity]).
* 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
+inline val Context.ctxCoroutine: CoroutineScope
get() = this as? CoroutineScope ?: ContextHelper
/**
diff --git a/core/src/main/res-public/values-ar-rSA/strings_commons.xml b/core/src/main/res-public/values-ar-rSA/strings_commons.xml
new file mode 100644
index 0000000..efaa623
--- /dev/null
+++ b/core/src/main/res-public/values-ar-rSA/strings_commons.xml
@@ -0,0 +1,55 @@
+<?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">Google 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>
+ <string name="kau_yes">نعم</string>
+ <string name="kau_permission_denied">الإذن مرفوض</string>
+</resources>
diff --git a/core/src/main/res-public/values/public.xml b/core/src/main/res-public/values/public.xml
index 9761199..0b050dc 100644
--- a/core/src/main/res-public/values/public.xml
+++ b/core/src/main/res-public/values/public.xml
@@ -1,20 +1,27 @@
-<resources xmlns:tools='http://schemas.android.com/tools' tools:ignore='ResourceName'>
+<resources xmlns:tools='http://schemas.android.com/tools' tools:ignore='ResourceName'>
<!-- AUTO-GENERATED FILE. DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task -->
+ <public name='kau_enter_slide_left' type='transition' />
+ <public name='kau_exit_slide_right' type='transition' />
+ <public name='kau_exit_slide_bottom' type='transition' />
+ <public name='kau_enter_slide_bottom' type='transition' />
+ <public name='kau_enter_slide_right' type='transition' />
+ <public name='kau_exit_slide_top' type='transition' />
+ <public name='kau_enter_slide_top' type='transition' />
+ <public name='kau_exit_slide_left' type='transition' />
+ <public name='kau_selectable_white' type='drawable' />
+ <public name='kau_transparent' type='drawable' />
+ <public name='kau_slide_out_left_top' type='anim' />
+ <public name='kau_slide_in_right' type='anim' />
+ <public name='kau_slide_out_right_top' type='anim' />
<public name='kau_slide_in_top' type='anim' />
- <public name='kau_slide_in_left' type='anim' />
+ <public name='kau_slide_out_left' type='anim' />
<public name='kau_slide_out_right' type='anim' />
- <public name='kau_slide_out_right_top' type='anim' />
<public name='kau_fade_in' type='anim' />
- <public name='kau_slide_out_top' type='anim' />
<public name='kau_slide_out_bottom' type='anim' />
- <public name='kau_fade_out' type='anim' />
- <public name='kau_slide_out_left' type='anim' />
- <public name='kau_slide_out_left_top' type='anim' />
<public name='kau_slide_in_bottom' type='anim' />
- <public name='kau_slide_in_right' type='anim' />
- <public name='kau_transparent' type='drawable' />
- <public name='kau_selectable_white' type='drawable' />
- <public name='kau_shadow_overlay' type='color' />
+ <public name='kau_slide_out_top' type='anim' />
+ <public name='kau_fade_out' type='anim' />
+ <public name='kau_slide_in_left' type='anim' />
<public name='kau_activity_horizontal_margin' type='dimen' />
<public name='kau_activity_vertical_margin' type='dimen' />
<public name='kau_dialog_margin' type='dimen' />
@@ -43,6 +50,13 @@
<public name='kau_avatar_padding' type='dimen' />
<public name='kau_avatar_margin' type='dimen' />
<public name='kau_avatar_ripple_radius' type='dimen' />
+ <public name='KauFadeIn' type='style' />
+ <public name='KauFadeInFadeOut' type='style' />
+ <public name='KauSlideInRight' type='style' />
+ <public name='KauSlideInBottom' type='style' />
+ <public name='KauSlideInFadeOut' type='style' />
+ <public name='KauSlideInSlideOutRight' type='style' />
+ <public name='KauSlideInSlideOutBottom' type='style' />
<public name='kau_about_app' type='string' />
<public name='kau_about_x' type='string' />
<public name='kau_add_account' type='string' />
@@ -98,21 +112,7 @@
<public name='kau_permission_denied' type='string' />
<public name='kau_0' type='string' />
<public name='kau_bullet_point' type='string' />
+ <public name='kau_shadow_overlay' type='color' />
<public name='Kau' type='style' />
<public name='Kau.Translucent' type='style' />
- <public name='KauFadeIn' type='style' />
- <public name='KauFadeInFadeOut' type='style' />
- <public name='KauSlideInRight' type='style' />
- <public name='KauSlideInBottom' type='style' />
- <public name='KauSlideInFadeOut' type='style' />
- <public name='KauSlideInSlideOutRight' type='style' />
- <public name='KauSlideInSlideOutBottom' type='style' />
- <public name='kau_enter_slide_bottom' type='transition' />
- <public name='kau_enter_slide_top' type='transition' />
- <public name='kau_exit_slide_bottom' type='transition' />
- <public name='kau_exit_slide_top' type='transition' />
- <public name='kau_enter_slide_right' type='transition' />
- <public name='kau_exit_slide_right' type='transition' />
- <public name='kau_exit_slide_left' type='transition' />
- <public name='kau_enter_slide_left' type='transition' />
</resources> \ No newline at end of file
diff --git a/core/src/test/kotlin/ca/allanwang/kau/ui/ProgressAnimatorTest.kt b/core/src/test/kotlin/ca/allanwang/kau/ui/ProgressAnimatorTest.kt
index 60f8680..6b99b14 100644
--- a/core/src/test/kotlin/ca/allanwang/kau/ui/ProgressAnimatorTest.kt
+++ b/core/src/test/kotlin/ca/allanwang/kau/ui/ProgressAnimatorTest.kt
@@ -1,3 +1,18 @@
+/*
+ * 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.ui
import org.junit.Test
@@ -71,5 +86,4 @@ class ProgressAnimatorTest {
assertTrue(called)
assertTrue(i > 0.5f)
}
-
-} \ No newline at end of file
+}