From 53382b44bb7ab7ccb559e96fd1f93c47020878ee Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Wed, 2 Aug 2017 16:21:49 -0700 Subject: Improve video prefetching (#17) * Create base activity and add thumbnails to media picker * Add checker to see if requested permission is inside the manifest * Add faq parser with tests * Add kpref testers and expose sp * Test jitpack sample exclusion * Test caching * Improve glide caching --- core/README.md | 15 ++++ .../kotlin/ca/allanwang/kau/kpref/KPrefTest.kt | 85 ++++++++++++++++++++++ .../ca/allanwang/kau/utils/KotterknifeTest.kt | 4 +- .../kotlin/ca/allanwang/kau/xml/ChangelogTest.kt | 4 +- .../kotlin/ca/allanwang/kau/xml/FaqTest.kt | 38 ++++++++++ core/src/androidTest/res/xml/test_changelog.xml | 12 +++ core/src/androidTest/res/xml/test_faq.xml | 9 +++ core/src/androidTest/res/xml/text_changelog.xml | 11 --- .../ca/allanwang/kau/internal/KauBaseActivity.kt | 21 ++++++ .../ca/allanwang/kau/kotlin/LazyResettable.kt | 2 +- .../main/kotlin/ca/allanwang/kau/kpref/KPref.kt | 3 +- .../allanwang/kau/permissions/PermissionManager.kt | 22 ++++++ .../allanwang/kau/ui/views/MeasureSpecDelegate.kt | 12 +++ core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt | 28 +++++-- 14 files changed, 242 insertions(+), 24 deletions(-) create mode 100644 core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt create mode 100644 core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt create mode 100644 core/src/androidTest/res/xml/test_changelog.xml create mode 100644 core/src/androidTest/res/xml/test_faq.xml delete mode 100644 core/src/androidTest/res/xml/text_changelog.xml create mode 100644 core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt (limited to 'core') diff --git a/core/README.md b/core/README.md index c26836e..b952797 100644 --- a/core/README.md +++ b/core/README.md @@ -6,6 +6,7 @@ * [KPrefs](#kprefs) * [Changelog XML](#changelog) +* [FAQ XML](#faq-xml) * [Kotterknife](#kotterknife) * [Ripple Canvas](#ripple-canvas) * [MeasureSpecDelegate](#measure-spec-delegate) @@ -106,6 +107,20 @@ Here is a template xml changelog file: ``` + +## FAQ XML + +There is another parser for a FAQ list with the following format: + +```xml +This is a question +This is an answer +``` + +Calling `kauParseFaq` will give you a `List` that you can work with. +By default, the questions are numbered, and the content is formatted with HTML. +You may still need to add your own methods to allow interaction with certain elements such as links. + ## Kotterknife diff --git a/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt new file mode 100644 index 0000000..e806a3f --- /dev/null +++ b/core/src/androidTest/kotlin/ca/allanwang/kau/kpref/KPrefTest.kt @@ -0,0 +1,85 @@ +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 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. + */ +@RunWith(AndroidJUnit4::class) +@MediumTest +class ChangelogTest { + + lateinit var pref: TestPref + + class TestPref : KPref() { + init { + initialize(InstrumentationRegistry.getTargetContext(), "kpref_test_${System.currentTimeMillis()}") + } + + var one: Int by kpref("one", 1) + + var `true`: Boolean by kpref("true", true) + + var hello: String by kpref("hello", "hello") + + var set: StringSet by kpref("set", setOf("po", "ta", "to")) + + val oneShot: Boolean by kprefSingle("asdf") + } + + @Before + fun init() { + pref = TestPref() + } + + @Test + fun getDefaults() { + assertEquals(1, pref.one) + 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")) + } + + @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")) + } + + @SuppressLint("CommitPrefEdits") + @Test + fun reset() { + pref.one = 2 + assertEquals(2, pref.one) + pref.reset() //only invalidates our lazy delegate; doesn't change the actual pref + assertEquals(2, pref.one) + pref.sp.edit().putInt("one", -1).commit() + assertEquals(2, pref.one) //our lazy delegate still retains the old value + pref.reset() + assertEquals(-1, pref.one) //back in sync with sp + } + + + @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 3282911..1dac92f 100644 --- a/core/src/androidTest/kotlin/ca/allanwang/kau/utils/KotterknifeTest.kt +++ b/core/src/androidTest/kotlin/ca/allanwang/kau/utils/KotterknifeTest.kt @@ -7,10 +7,12 @@ import android.support.test.runner.AndroidJUnit4 import android.view.View import android.widget.FrameLayout import android.widget.TextView -import org.junit.Assert.* import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertNull /** * Created by Allan Wang on 2017-07-30. diff --git a/core/src/androidTest/kotlin/ca/allanwang/kau/xml/ChangelogTest.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/xml/ChangelogTest.kt index dcff70e..a3c9ff1 100644 --- a/core/src/androidTest/kotlin/ca/allanwang/kau/xml/ChangelogTest.kt +++ b/core/src/androidTest/kotlin/ca/allanwang/kau/xml/ChangelogTest.kt @@ -14,9 +14,9 @@ import org.junit.runner.RunWith @MediumTest class ChangelogTest { - @Test +// @Test //todo internal function sharing is only available on gradle 3.0.0+ fun simpleTest() { - val data = parse(InstrumentationRegistry.getTargetContext(), R.xml.text_changelog) +// val data = parse(InstrumentationRegistry.getTargetContext(), R.xml.test_changelog) } } \ No newline at end of file diff --git a/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt new file mode 100644 index 0000000..94d1330 --- /dev/null +++ b/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt @@ -0,0 +1,38 @@ +package ca.allanwang.kau.xml + +import android.support.test.InstrumentationRegistry +import android.support.test.filters.MediumTest +import android.support.test.runner.AndroidJUnit4 +import ca.allanwang.kau.test.R +import org.junit.Test +import org.junit.runner.RunWith +import kotlin.test.assertEquals + +/** + * Created by Allan Wang on 2017-08-01. + */ +@RunWith(AndroidJUnit4::class) +@MediumTest +class FaqTest { + + @Test + fun simpleTest() { + val data = InstrumentationRegistry.getTargetContext().kauParseFaq(R.xml.test_faq) + assertEquals(2, data.size, "FAQ size is incorrect") + assertEquals("1. This is a question", data.first().first.toString(), "First question does not match") + assertEquals("This is an answer", data.first().second.toString(), "First answer does not match") + assertEquals("2. This is another question", data.last().first.toString(), "Second question does not match") + assertEquals("This is another answer", data.last().second.toString(), "Second answer does not match") + } + + @Test + fun withoutNumbering() { + val data = InstrumentationRegistry.getTargetContext().kauParseFaq(R.xml.test_faq, false) + assertEquals(2, data.size, "FAQ size is incorrect") + assertEquals("This is a question", data.first().first.toString(), "First question does not match") + assertEquals("This is an answer", data.first().second.toString(), "First answer does not match") + assertEquals("This is another question", data.last().first.toString(), "Second question does not match") + assertEquals("This is another answer", data.last().second.toString(), "Second answer does not match") + } + +} \ No newline at end of file diff --git a/core/src/androidTest/res/xml/test_changelog.xml b/core/src/androidTest/res/xml/test_changelog.xml new file mode 100644 index 0000000..2e90561 --- /dev/null +++ b/core/src/androidTest/res/xml/test_changelog.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/core/src/androidTest/res/xml/test_faq.xml b/core/src/androidTest/res/xml/test_faq.xml new file mode 100644 index 0000000..4905df3 --- /dev/null +++ b/core/src/androidTest/res/xml/test_faq.xml @@ -0,0 +1,9 @@ + + + + This is a question + This is an answer + This is another question + This is another answer + + \ No newline at end of file diff --git a/core/src/androidTest/res/xml/text_changelog.xml b/core/src/androidTest/res/xml/text_changelog.xml deleted file mode 100644 index 6294144..0000000 --- a/core/src/androidTest/res/xml/text_changelog.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ 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 new file mode 100644 index 0000000..87d94ce --- /dev/null +++ b/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt @@ -0,0 +1,21 @@ +package ca.allanwang.kau.internal + +import android.support.v7.app.AppCompatActivity +import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult + +/** + * Created by Allan Wang on 2017-08-01. + * + * Base activity for any activity that would have extended [AppCompatActivity] + * + * Ensures that some singleton methods are called. + * This is simply a convenience class; + * you can always copy and paste this to your own class. + */ +abstract class KauBaseActivity : AppCompatActivity() { + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + kauOnRequestPermissionsResult(permissions, grantResults) + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyResettable.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyResettable.kt index 701cb07..2ac5d2f 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyResettable.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyResettable.kt @@ -50,7 +50,7 @@ open class LazyResettable(private val initializer: () -> T, lock: Any? } } -interface ILazyResettable : Lazy { +interface ILazyResettable : Lazy { fun invalidate() } 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 c1ce282..be16c7c 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/kpref/KPref.kt @@ -39,7 +39,8 @@ open class KPref { } } - internal val sp: SharedPreferences by lazy { + //todo hide this + val sp: SharedPreferences by lazy { if (!initialized) throw KPrefException("KPref object has not yet been initialized; please initialize it with a context and preference name") c.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE) } 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 d6e17db..0c42574 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/permissions/PermissionManager.kt @@ -2,13 +2,17 @@ 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 ca.allanwang.kau.kotlin.lazyContext import ca.allanwang.kau.logging.KL import ca.allanwang.kau.utils.KauException import ca.allanwang.kau.utils.buildIsMarshmallowAndUp 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. */ @@ -17,6 +21,17 @@ internal object PermissionManager { var requestInProgress = false val pendingResults: MutableList> by lazy { mutableListOf>() } + /** + * Retrieve permissions requested in our manifest + */ + val manifestPermission = lazyContext> { + try { + it.packageManager.getPackageInfo(it.packageName, PackageManager.GET_PERMISSIONS)?.requestedPermissions ?: emptyArray() + } catch (e: Exception) { + emptyArray() + } + } + operator fun invoke(context: Context, permissions: Array, callback: (granted: Boolean, deniedPerm: String?) -> Unit) { KL.d("Permission manager for: ${permissions.contentToString()}") if (!buildIsMarshmallowAndUp) return callback(true, null) @@ -30,6 +45,13 @@ internal object PermissionManager { } @Synchronized internal fun requestPermissions(context: Context, permissions: Array) { + permissions.forEach { + if (!manifestPermission(context).contains(it)) { + KL.e("Requested permission $it is not stated in the manifest") + context.toast("$it is not in the manifest") + //we'll let the request pass through so it can be denied and so the callback can be triggered + } + } val activity = (context as? Activity) ?: throw KauException("Context is not an instance of an activity; cannot request permissions") KL.d("Requesting permissions ${permissions.contentToString()}") ActivityCompat.requestPermissions(activity, permissions, 1) 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 edc1536..716fd71 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 @@ -11,6 +11,8 @@ import ca.allanwang.kau.utils.parentViewGroup * Created by Allan Wang on 2017-07-14. * * Handles relative sizes for any view + * You may delegate all methods to [MeasureSpecDelegate] + * and call the two methods: [initAttrs] and [onMeasure] */ interface MeasureSpecContract { @@ -53,6 +55,16 @@ interface MeasureSpecContract { * Calculates the final measure specs * Call this from [View.onMeasure] and send the Pair result as the specs * The pair is of the format (width, height) + * + * Example: + *
+     * {@code
+     * override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+     *     val result = onMeasure(this, widthMeasureSpec, heightMeasureSpec)
+     *     super.onMeasure(result.first, result.second)
+     * }
+     * }
+     * 
*/ fun onMeasure(view: View, widthMeasureSpec: Int, heightMeasureSpec: Int): Pair } 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 dedfbbf..b39540c 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt @@ -22,16 +22,28 @@ fun Context.kauParseFaq(@XmlRes xmlRes: Int, withNumbering: Boolean = true): Lis 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) { - if (parser.name == "question") { - var q = parser.text.replace("\n", "
") - if (withNumbering) q = "${items.size + 1}. $q" - question = Html.fromHtml(q) - } else if (parser.name == "answer") { - items.add(Pair(question ?: throw IllegalArgumentException("KAU FAQ answer found without a question"), - Html.fromHtml(parser.text.replace("\n", "
")))) - question = null + flag = when (parser.name) { + "question" -> 0 + "answer" -> 1 + else -> -1 + } + } else if (eventType == XmlPullParser.TEXT) { + when (flag) { + 0 -> { + var q = parser.text.replace("\n", "
") + if (withNumbering) q = "${items.size + 1}. $q" + question = Html.fromHtml(q) + flag = -1 + } + 1 -> { + items.add(Pair(question ?: throw IllegalArgumentException("KAU FAQ answer found without a question"), + Html.fromHtml(parser.text.replace("\n", "
")))) + question = null + flag = -1 + } } } -- cgit v1.2.3