Skip to content

Commit

Permalink
3.2.2 - Create faq parser and update sample (#19)
Browse files Browse the repository at this point in the history
* Test emulator

* Update readme

* Update fastadapter and about listing

* Make faq parser asynchronous

* Modularize about panels

* Add basis for faq

* Test and finalize the faq panel

* Update readme

* Update changelog

* Remove emulator for now

* Update sample
  • Loading branch information
AllanWang authored Aug 3, 2017
1 parent 84b9d3b commit bafc199
Show file tree
Hide file tree
Showing 29 changed files with 733 additions and 259 deletions.
14 changes: 11 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ jdk:
android:
components:
- tools
# - android-21
- platform-tools
- tools
- build-tools-26.0.1
- android-26
- extra-android-support
- extra-android-m2repository
- extra-google-m2repository
licenses:
- ".+"
#before_script:
#- echo no | android create avd --force -n test -t android-21 --abi armeabi-v7a
#- emulator -avd test -no-audio -no-window &
#- android-wait-for-emulator
#- adb shell input keyevent 82 &
script:
- chmod +x gradlew
- ./gradlew --quiet androidGitVersion
- if [[ "$TRAVIS_BRANCH" == "master" ]]; then ./gradlew lintRelease publishRelease; else ./gradlew lintRelease test; fi
branches:
Expand All @@ -25,12 +33,12 @@ notifications:
- pitchedapps:G5OB9U1vsDxy9mxt0Nt6gbFu#kau
on_success: always
on_failure: always
sudo: false
cache:
directories:
- "$HOME/.m2"
before_script:
- chmod +x gradlew
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
- $HOME/.android/build-cache
before_install:
- openssl aes-256-cbc -K $encrypted_12e8842891a3_key -iv $encrypted_12e8842891a3_iv
-in files/kau.tar.enc -out kau.tar -d
Expand Down
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ dependencies {
compile "ca.allanwang.kau:about:$KAU"
compile "ca.allanwang.kau:colorpicker:$KAU"
compile "ca.allanwang.kau:mediapicker:$KAU"
compile "ca.allanwang.kau:kpref-activity:$KAU"
compile "ca.allanwang.kau:mediapicker:$KAU"
compile "ca.allanwang.kau:searchview:$KAU"
}
Expand All @@ -53,9 +53,10 @@ dependencies {
-----------

# Submodules
(linked to their respective Docs)
> linked to their respective Docs
> included dependencies are only those with exposed APIs. See [new dependency configurations](https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#new_configurations)
## [Core](core#readme)****
## [Core](core#readme)
* Collection of extension functions and small helper methods applicable in almost any application.
* Notable features: KPrefs, Changelog XML, Kotterknife, Ripple Canvas, Delegates, Lazy Resettables, Extensions, Email Builder
* Includes
Expand Down Expand Up @@ -89,16 +90,16 @@ dependencies {
* Includes `:core`,
[`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`

## [Media Picker](mediapicker#readme)
* Fully functional image and video pickers, both as an overlay and as a requested activity.
* Includes `:core-ui`,
[`Glide`](https://github.com/bumptech/glide),
[`Blurry`](https://github.com/wasabeef/Blurry)

## [Kpref Activity](kpref-activity#readme)
* Fully programmatic implementation of a Preference Activity, backed by RecyclerViews
* Includes `:core-ui`, `:adapter`, `colorpicker`

## [SearchView](searchview#readme)
* Material searchview with kotlin bindings
* Includes `:core-ui`, `:adapter`
Expand Down
9 changes: 6 additions & 3 deletions about/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ and adds on the power of [About Libraries](https://github.com/mikepenz/AboutLibr

This activity can be easily added by extending `AboutActivityBase`.
Everything is already prepared, but you can modify the theme or other components through the config DSL or through the open functions.
There are also numerous iitem cards already prepared (in this submodule and from `:adapter`)if you wish to add that in your main view.

You may also easily launch the activity through the simple binder:
If you wish to add custom panels, you will need to implement `AboutPanelContract`.
The most common usage is with a recyclerview, so there is a simplified class `AboutPanelRecycler` that you may extend as well.
Note that the viewpager by default will keep all panels in memory, so it's best to not have too many pages with expensive interactions.

You may easily launch the activity through the binder:
```
Activity.kauLaunchAbout(YourClass::class.java)
```
Expand All @@ -22,7 +25,7 @@ Be sure to include the activity in your Manifest and have it extend `Kau.About`,

## Proguard

Without auto detect, KAU about will retain the classes containing the lib strings by default.
Without auto detection, KAU about will retain the classes containing the lib strings by default.
If you use proguard with auto detect, make sure to retain all R classes to make it possible

```
Expand Down
184 changes: 60 additions & 124 deletions about/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,22 @@ import android.graphics.drawable.Drawable
import android.os.Bundle
import android.support.v4.view.PagerAdapter
import android.support.v4.view.ViewPager
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.RecyclerView
import android.transition.TransitionInflater
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import ca.allanwang.kau.adapters.FastItemThemedAdapter
import ca.allanwang.kau.adapters.ThemableIItemColors
import ca.allanwang.kau.adapters.ThemableIItemColorsDelegate
import ca.allanwang.kau.animators.FadeScaleAnimatorAdd
import ca.allanwang.kau.animators.KauAnimator
import ca.allanwang.kau.iitems.HeaderIItem
import ca.allanwang.kau.internal.KauBaseActivity
import ca.allanwang.kau.ui.widgets.ElasticDragDismissFrameLayout
import ca.allanwang.kau.ui.widgets.InkPageIndicator
import ca.allanwang.kau.utils.*
import ca.allanwang.kau.utils.AnimHolder
import ca.allanwang.kau.utils.bindView
import ca.allanwang.kau.utils.dimenPixelSize
import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.entity.Library
import com.mikepenz.fastadapter.IItem
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
import java.security.InvalidParameterException

/**
* Created by Allan Wang on 2017-06-28.
Expand All @@ -38,125 +32,87 @@ import java.security.InvalidParameterException
* Note that for the auto detection to work, the R fields must be excluded from Proguard
* Manual lib listings and other extra modifications can be done so by overriding the open functions
*/
abstract class AboutActivityBase(val rClass: Class<*>?, val configBuilder: Configs.() -> Unit = {}) : KauBaseActivity(), ViewPager.OnPageChangeListener {
abstract class AboutActivityBase(val rClass: Class<*>?, private val configBuilder: Configs.() -> Unit = {}) : KauBaseActivity(), ViewPager.OnPageChangeListener {

private val draggableFrame: ElasticDragDismissFrameLayout by bindView(R.id.about_draggable_frame)
private val pager: ViewPager by bindView(R.id.about_pager)
private val indicator: InkPageIndicator by bindView(R.id.about_indicator)

val currentPage
get() = pager.currentItem

val draggableFrame: ElasticDragDismissFrameLayout by bindView(R.id.about_draggable_frame)
val pager: ViewPager by bindView(R.id.about_pager)
val indicator: InkPageIndicator by bindView(R.id.about_indicator)
/**
* Holds some common configurations that may be added directly from the constructor
* Applied lazily since it needs the context to fetch resources
*/
val configs: Configs by lazy { Configs().apply { configBuilder() } }
/**
* Number of pages in the adapter
* Defaults to just the main view and lib view
*/
open val pageCount: Int = 2
/**
* Page position for the libs
* This is generated automatically if [inflateLibPage] is called
*/
private var libPage: Int = -2

/**
* Holds that status of each page
* 0 means nothing has happened
* 1 means this page has been in view at least once
* The rest is up to you
*/
lateinit var pageStatus: IntArray
/**
* Holds the lib items once they are fetched asynchronously
*/
var libItems: List<LibraryIItem>? = null
/**
* Holds the adapter for the library page; this is generated later because it uses the config colors
*/
lateinit var libAdapter: FastItemThemedAdapter<IItem<*, *>>
/**
* Global reference of the library recycler
* This is set by default through [inflateLibPage] and is used to stop scrolling
* When the draggable frame exits
* It is not required, hence its nullability
*/
private var libRecycler: RecyclerView? = null

val panels: List<AboutPanelContract> by lazy {
val defaultPanels = mutableListOf(AboutPanelMain(), AboutPanelLibs())
if (configs.faqXmlRes != -1) defaultPanels.add(AboutPanelFaqs())
defaultPanels
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.kau_activity_about)
pageStatus = IntArray(pageCount)
libAdapter = FastItemThemedAdapter(configs)
LibraryIItem.bindClickEvents(libAdapter)
pageStatus = IntArray(panels.size)
pageStatus[0] = 2 //the first page is instantly visible
if (configs.textColor != null) indicator.setColour(configs.textColor!!)
with(pager) {
adapter = AboutPagerAdapter()
pageMargin = dimenPixelSize(R.dimen.kau_spacing_normal)
offscreenPageLimit = panels.size - 1
addOnPageChangeListener(this@AboutActivityBase)
}
indicator.setViewPager(pager)
draggableFrame.addListener(object : ElasticDragDismissFrameLayout.SystemChromeFader(this) {
override fun onDragDismissed() {
window.returnTransition = TransitionInflater.from(this@AboutActivityBase)
.inflateTransition(if (draggableFrame.translationY > 0) configs.transitionExitBottom else configs.transitionExitTop)

libRecycler?.stopScroll()
.inflateTransition(if (draggableFrame.translationY > 0) R.transition.kau_exit_slide_bottom else R.transition.kau_exit_slide_top)
panels[currentPage].recycler?.stopScroll()
finishAfterTransition()
}
})
panels.forEachIndexed { index, contract -> contract.loadItems(this, index) }
}

inner class Configs : ThemableIItemColors by ThemableIItemColorsDelegate() {
class Configs : ThemableIItemColors by ThemableIItemColorsDelegate() {
var cutoutTextRes: Int = -1
var cutoutText: String? = null
var cutoutDrawableRes: Int = -1
var cutoutDrawable: Drawable? = null
var cutoutForeground: Int? = null
var libPageTitleRes: Int = -1
var libPageTitle: String? = string(R.string.kau_about_libraries_intro) //This is in the string by default since it's lower priority

var transitionExitTop: Int = R.transition.kau_exit_slide_top
var transitionExitBottom: Int = R.transition.kau_exit_slide_bottom
}

/**
* Method to fetch the library list
* This is fetched asynchronously and you may override it to customize the list
*/
open fun getLibraries(libs: Libs): List<Library> = libs.prepareLibraries(this, null, null, true, true)!!

/**
* Gets the view associated with the given page position
* Keep in mind that when inflating, do NOT add the view to the viewgroup
* Use layoutInflater.inflate(id, parent, false)
*/
open fun getPage(position: Int, layoutInflater: LayoutInflater, parent: ViewGroup): View {
return when (position) {
0 -> inflateMainPage(layoutInflater, parent, position)
pageCount - 1 -> inflateLibPage(layoutInflater, parent, position)
else -> throw InvalidParameterException()
}
}

/**
* Create the main view with the cutout
*/
open fun inflateMainPage(layoutInflater: LayoutInflater, parent: ViewGroup, position: Int): View {
val fastAdapter = FastItemThemedAdapter<IItem<*, *>>(configs)
val recycler = fullLinearRecycler(fastAdapter)
fastAdapter.add(CutoutIItem {
with(configs) {
text = string(cutoutTextRes, cutoutText)
drawable = drawable(cutoutDrawableRes, cutoutDrawable)
if (configs.cutoutForeground != null) foregroundColor = configs.cutoutForeground!!
var libPageTitleRes: Int = R.string.kau_about_libraries_intro
var libPageTitle: String? = null
set(value) {
field = value
libPageTitleRes = -1 //reset res so we don't use our default
}
}.apply {
themeEnabled = configs.cutoutForeground == null
})
postInflateMainPage(fastAdapter)
return recycler
var faqXmlRes: Int = -1
var faqPageTitleRes: Int = R.string.kau_about_faq_intro
var faqPageTitle: String? = null
set(value) {
field = value
faqPageTitleRes = -1 //reset res so we don't use our default
}
/**
* Whether new lines should be included
*/
var faqParseNewLine: Boolean = true
}

/**
* For [mainPanel]
*
* Open hook called just before the main page view is returned
* Feel free to add your own items to the adapter in here
*/
Expand All @@ -165,32 +121,23 @@ abstract class AboutActivityBase(val rClass: Class<*>?, val configBuilder: Confi
}

/**
* Create the lib view with the list of libraries
* For [libPanel]
*
* Method to fetch the library list
* This is fetched asynchronously and you may override it to customize the list
*/
open fun getLibraries(libs: Libs): List<Library> = libs.prepareLibraries(this, null, null, true, true)!!

/*
* -------------------------------------------------------------------
* Page 3: FAQ
* -------------------------------------------------------------------
*/
open fun inflateLibPage(layoutInflater: LayoutInflater, parent: ViewGroup, position: Int): View {
libPage = position
val v = layoutInflater.inflate(R.layout.kau_recycler_detached_background, parent, false)
val recycler = v.findViewById<RecyclerView>(R.id.kau_recycler_detached)
libRecycler = recycler
recycler.withMarginDecoration(16, KAU_BOTTOM)
recycler.adapter = libAdapter
recycler.itemAnimator = KauAnimator(addAnimator = FadeScaleAnimatorAdd(scaleFactor = 0.7f, itemDelayFactor = 0.2f)).apply { addDuration = 300; interpolator = AnimHolder.decelerateInterpolator(this@AboutActivityBase) }
val background = v.findViewById<View>(R.id.kau_recycler_detached_background)
if (configs.backgroundColor != null) background.setBackgroundColor(configs.backgroundColor!!.colorToForeground())
doAsync {
libItems = getLibraries(
if (rClass == null) Libs(this@AboutActivityBase) else Libs(this@AboutActivityBase, Libs.toStringArray(rClass.fields))
).map { LibraryIItem(it) }
if (libPage >= 0 && pageStatus[libPage] == 1)
uiThread { addLibItems() }
}
return v
}

inner class AboutPagerAdapter : PagerAdapter() {
private inner class AboutPagerAdapter : PagerAdapter() {

private val layoutInflater: LayoutInflater = LayoutInflater.from(this@AboutActivityBase)
private val views = Array<View?>(pageCount) { null }
private val views = Array<View?>(panels.size) { null }

override fun instantiateItem(collection: ViewGroup, position: Int): Any {
val layout = getPage(position, collection)
Expand All @@ -203,15 +150,16 @@ abstract class AboutActivityBase(val rClass: Class<*>?, val configBuilder: Confi
views[position] = null
}

override fun getCount(): Int = pageCount
override fun getCount(): Int = panels.size

override fun isViewFromObject(view: View, `object`: Any): Boolean = view === `object`

/**
* Only get page if view does not exist
*/
private fun getPage(position: Int, parent: ViewGroup): View {
if (views[position] == null) views[position] = getPage(position, layoutInflater, parent)
if (views[position] == null) views[position] = panels[position]
.inflatePage(this@AboutActivityBase, parent, position)
return views[position]!!
}
}
Expand All @@ -222,19 +170,7 @@ abstract class AboutActivityBase(val rClass: Class<*>?, val configBuilder: Confi

override fun onPageSelected(position: Int) {
if (pageStatus[position] == 0) pageStatus[position] = 1 // mark as seen if previously null
if (position == libPage && libItems != null && pageStatus[position] == 1) {
pageStatus[position] = 2 //add libs and mark as such
postDelayed(300) { addLibItems() } //delay so that the animations occur once the page is fully switched
}
}

/**
* Function that is called when the view is ready to add the lib items
* Feel free to add your own items here
*/
open fun addLibItems() {
libAdapter.add(HeaderIItem(text = configs.libPageTitle, textRes = configs.libPageTitleRes))
.add(libItems)
if (pageStatus[position] == 1) panels[position].addItems(this, position)
}

override fun onDestroy() {
Expand Down
Loading

0 comments on commit bafc199

Please sign in to comment.