aboutsummaryrefslogtreecommitdiff
path: root/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt
blob: b9681e9b581c2cb9d14d6f59347a255aa00429a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package ca.allanwang.kau.kpref.activity

import android.annotation.SuppressLint
import android.os.Bundle
import android.support.annotation.StringRes
import android.support.v7.widget.Toolbar
import android.view.View
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.utils.*
import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter
import kotlinx.android.synthetic.main.kau_pref_activity.*
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
import java.util.*

abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract {

    private val adapter: FastItemAdapter<KPrefItemCore> = FastItemAdapter()
    val bgCanvas: RippleCanvas get() = kau_ripple
    val toolbarCanvas: RippleCanvas get() = kau_toolbar_ripple
    val toolbar: Toolbar get() = kau_toolbar
    private lateinit var globalOptions: GlobalOptions
    private val kprefStack = Stack<Pair<Int, List<KPrefItemCore>>>()
    /**
     * Toggle sliding animations for the kpref items
     */
    var animate: Boolean = true

    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
     * Leave blank to use defaults
     */
    abstract fun kPrefCoreAttributes(): CoreAttributeContract.() -> Unit

    @SuppressLint("NewApi")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //setup layout
        setContentView(R.layout.kau_pref_activity)
        setSupportActionBar(toolbar)
        supportActionBar?.apply {
            setDisplayHomeAsUpEnabled(true)
            setDisplayShowHomeEnabled(true)
            toolbar.setNavigationOnClickListener { onBackPressed() }
            setDisplayShowTitleEnabled(false)
        }
        window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        statusBarColor = 0x30000000
        kau_toolbar_ripple.set(resolveColor(R.attr.colorPrimary))
        kau_ripple.set(resolveColor(android.R.attr.colorBackground))
        //setup prefs
        val core = CoreAttributeBuilder()
        val builder = kPrefCoreAttributes()
        core.builder()
        globalOptions = GlobalOptions(core, this)
        kau_recycler.withLinearAdapter(adapter)
        adapter.withSelectable(false)
                .withOnClickListener { v, _, item, _ -> item.onClick(v!!); true }
        showNextPrefs(R.string.kau_settings, onCreateKPrefs(savedInstanceState), true)
    }

    override fun showNextPrefs(@StringRes toolbarTitleRes: Int, builder: KPrefAdapterBuilder.() -> Unit) = showNextPrefs(toolbarTitleRes, builder, false)

    private fun showNextPrefs(@StringRes toolbarTitleRes: Int, builder: KPrefAdapterBuilder.() -> Unit, first: Boolean) {
        doAsync {
            val items = KPrefAdapterBuilder(globalOptions)
            builder(items)
            kprefStack.push(toolbarTitleRes to items.list)
            kau_recycler.itemAnimator = if (animate && !first) recyclerAnimatorNext else null
            uiThread {
                adapter.clear()
                adapter.add(items.list.filter { it.core.visible() })
                toolbar.setTitle(toolbarTitleRes)
            }
        }
    }

    /**
     * Pops the stack and loads the next kpref list
     * Indices are not checked so ensure that this is possible first
     */
    override fun showPrevPrefs() {
        kprefStack.pop()
        val (title, list) = kprefStack.peek()
        kau_recycler.itemAnimator = if (animate) recyclerAnimatorPrev else null
        adapter.clear()
        adapter.add(list.filter { it.core.visible() })
        toolbar.setTitle(title)
    }

    /**
     * Check if it's possible to go back a stack
     */
    override val hasPrevPrefs
        get() = kprefStack.size > 1

    /**
     * Reload the current pref list from the stack.
     * This will adjust the list of items change in visibility
     */
    fun reloadList() {
        // If for some reason we are calling a reload before fetching our first kpref list, we will ignore it
        if (kprefStack.size < 1) return
        kau_recycler.itemAnimator = null
        val list = kprefStack.peek().second
        adapter.setNewList(list.filter { it.core.visible() })
    }

    /**
     * Selectively reload an item based on its index.
     * Note that this might not behave as expected if certain items are not visible,
     * as those items aren't sent to the adapter.
     *
     * For those cases, consider using [reloadByTitle]
     */
    fun reload(vararg index: Int) {
        if (index.isEmpty()) adapter.notifyAdapterDataSetChanged()
        else index.forEach { adapter.notifyItemChanged(it) }
    }

    /**
     * Iterate through all items and reload if it matches any of the titles
     * If multiple items have the same title, they will all be reloaded
     */
    override fun reloadByTitle(@StringRes vararg title: Int) {
        if (title.isEmpty()) return
        adapter.adapterItems.forEachIndexed { index, item ->
            if (title.any { item.core.titleId == it })
                adapter.notifyItemChanged(index)
        }
    }

    abstract fun onCreateKPrefs(savedInstanceState: Bundle?): KPrefAdapterBuilder.() -> Unit

    override fun onBackPressed() {
        if (!backPress()) super.onBackPressed()
    }

    /**
     * Back press handler with status output
     * Returns [true] if the press has been consumed, [false] otherwise
     */
    fun backPress(): Boolean {
        if (hasPrevPrefs) {
            showPrevPrefs()
            return true
        }
        return false
    }
}