mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2024-11-24 19:04:38 -06:00
[API] Improve Lab fragment. Fix OkHttp crashing on API <21.
This commit is contained in:
parent
fada483d55
commit
9261848369
@ -145,7 +145,11 @@ dependencies {
|
||||
implementation("com.github.ozodrukh:CircularReveal:2.0.1@aar") {transitive = true}
|
||||
implementation "com.heinrichreimersoftware:material-intro:1.5.8" // do not update
|
||||
implementation "com.jaredrummler:colorpicker:1.0.2"
|
||||
implementation "com.squareup.okhttp3:okhttp:3.12.2"
|
||||
implementation("com.squareup.okhttp3:okhttp") {
|
||||
version {
|
||||
strictly "3.12.2"
|
||||
}
|
||||
}
|
||||
implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0" // do not update
|
||||
implementation "com.wdullaer:materialdatetimepicker:4.1.2"
|
||||
implementation "com.yuyh.json:jsonviewer:1.0.6"
|
||||
|
@ -173,6 +173,8 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||
}
|
||||
|
||||
devMode = BuildConfig.DEBUG
|
||||
if (BuildConfig.DEBUG)
|
||||
debugMode = true
|
||||
|
||||
Signing.getCert(this)
|
||||
|
||||
|
@ -19,6 +19,7 @@ import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.task.IApiTask
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
@ -28,6 +29,9 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
companion object {
|
||||
private const val TAG = "EdziennikTask"
|
||||
|
||||
var profile: Profile? = null
|
||||
var loginStore: LoginStore? = null
|
||||
|
||||
fun firstLogin(loginStore: LoginStore) = EdziennikTask(-1, FirstLoginRequest(loginStore))
|
||||
fun sync() = EdziennikTask(-1, SyncRequest())
|
||||
fun syncProfile(profileId: Int, viewIds: List<Pair<Int, Int>>? = null, onlyEndpoints: List<Int>? = null, arguments: JsonObject? = null) = EdziennikTask(profileId, SyncProfileRequest(viewIds, onlyEndpoints, arguments))
|
||||
@ -59,6 +63,8 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
// save the profile ID and name as the current task's
|
||||
taskName = app.getString(R.string.edziennik_notification_api_sync_title_format, profile.name)
|
||||
}
|
||||
EdziennikTask.profile = this.profile
|
||||
EdziennikTask.loginStore = this.loginStore
|
||||
}
|
||||
|
||||
private var edziennikInterface: EdziennikInterface? = null
|
||||
|
@ -26,7 +26,7 @@ class DumbCookieJar(
|
||||
) : CookieJar {
|
||||
|
||||
private val prefs = context.getSharedPreferences("cookies", Context.MODE_PRIVATE)
|
||||
private val sessionCookies = mutableSetOf<DumbCookie>()
|
||||
val sessionCookies = mutableSetOf<DumbCookie>()
|
||||
private val savedCookies = mutableSetOf<DumbCookie>()
|
||||
private fun save(dc: DumbCookie) {
|
||||
sessionCookies.remove(dc)
|
||||
|
@ -9,26 +9,25 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.databinding.LabFragmentBinding
|
||||
import pl.szczodrzynski.edziennik.onClick
|
||||
import pl.szczodrzynski.edziennik.addOnPageSelectedListener
|
||||
import pl.szczodrzynski.edziennik.databinding.TemplateFragmentBinding
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.FragmentLazyPagerAdapter
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class LabFragment : Fragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "LabFragment"
|
||||
var pageSelection = 0
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var activity: MainActivity
|
||||
private lateinit var b: LabFragmentBinding
|
||||
private lateinit var b: TemplateFragmentBinding
|
||||
|
||||
private val job: Job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
@ -40,29 +39,30 @@ class LabFragment : Fragment(), CoroutineScope {
|
||||
activity = (getActivity() as MainActivity?) ?: return null
|
||||
context ?: return null
|
||||
app = activity.application as App
|
||||
b = LabFragmentBinding.inflate(inflater)
|
||||
b = TemplateFragmentBinding.inflate(inflater)
|
||||
b.refreshLayout.setParent(activity.swipeRefreshLayout)
|
||||
return b.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
if (!isAdded) return
|
||||
|
||||
b.last10unseen.onClick {
|
||||
launch(Dispatchers.Default) {
|
||||
val events = app.db.eventDao().getAllNow(App.profileId)
|
||||
val ids = events.sortedBy { it.date }.filter { it.type == Event.TYPE_HOMEWORK }.takeLast(10)
|
||||
ids.forEach {
|
||||
app.db.metadataDao().setSeen(App.profileId, it, false)
|
||||
}
|
||||
val pagerAdapter = FragmentLazyPagerAdapter(
|
||||
fragmentManager ?: return,
|
||||
b.refreshLayout,
|
||||
listOf(
|
||||
LabPageFragment() to "click me",
|
||||
LabProfileFragment() to "JSON"
|
||||
)
|
||||
)
|
||||
b.viewPager.apply {
|
||||
offscreenPageLimit = 1
|
||||
adapter = pagerAdapter
|
||||
currentItem = pageSelection
|
||||
addOnPageSelectedListener {
|
||||
pageSelection = it
|
||||
}
|
||||
}
|
||||
|
||||
b.rodo.onClick {
|
||||
app.db.teacherDao().query(SimpleSQLiteQuery("UPDATE teachers SET teacherSurname = \"\" WHERE profileId = ${App.profileId}"))
|
||||
}
|
||||
|
||||
b.removeHomework.onClick {
|
||||
app.db.eventDao().getRawNow("UPDATE events SET homeworkBody = NULL WHERE profileId = ${App.profileId}")
|
||||
b.tabLayout.setupWithViewPager(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-5-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.debug
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.models.LabJsonArray
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.models.LabJsonElement
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.models.LabJsonObject
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.viewholder.JsonArrayViewHolder
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.viewholder.JsonElementViewHolder
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.viewholder.JsonObjectViewHolder
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class LabJsonAdapter(
|
||||
val activity: AppCompatActivity,
|
||||
var onJsonElementClick: ((item: LabJsonElement) -> Unit)? = null
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "AttendanceAdapter"
|
||||
private const val ITEM_TYPE_OBJECT = 0
|
||||
private const val ITEM_TYPE_ARRAY = 1
|
||||
private const val ITEM_TYPE_ELEMENT = 2
|
||||
const val STATE_CLOSED = 0
|
||||
const val STATE_OPENED = 1
|
||||
|
||||
fun expand(item: Any, level: Int): MutableList<Any> {
|
||||
val json = when (item) {
|
||||
is LabJsonObject -> item.jsonObject
|
||||
is LabJsonArray -> item.jsonArray
|
||||
is JsonObject -> item
|
||||
is JsonArray -> item
|
||||
is JsonPrimitive -> item
|
||||
else -> return mutableListOf()
|
||||
}
|
||||
|
||||
return when (json) {
|
||||
is JsonObject -> json.entrySet().mapNotNull { wrap(it.key, it.value, level) }
|
||||
is JsonArray -> json.mapIndexedNotNull { index, jsonElement -> wrap(index.toString(), jsonElement, level) }
|
||||
else -> listOf(LabJsonElement("?", json, level))
|
||||
}.toMutableList()
|
||||
}
|
||||
fun wrap(key: String, item: JsonElement, level: Int = 0): Any? {
|
||||
return when (item) {
|
||||
is JsonObject -> LabJsonObject(key, item, level + 1)
|
||||
is JsonArray -> LabJsonArray(key, item, level + 1)
|
||||
is JsonElement -> LabJsonElement(key, item, level + 1)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val app = activity.applicationContext as App
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
var items = mutableListOf<Any>()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return when (viewType) {
|
||||
ITEM_TYPE_OBJECT -> JsonObjectViewHolder(inflater, parent)
|
||||
ITEM_TYPE_ARRAY -> JsonArrayViewHolder(inflater, parent)
|
||||
ITEM_TYPE_ELEMENT -> JsonElementViewHolder(inflater, parent)
|
||||
else -> throw IllegalArgumentException("Incorrect viewType")
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when (items[position]) {
|
||||
is LabJsonObject -> ITEM_TYPE_OBJECT
|
||||
is LabJsonArray -> ITEM_TYPE_ARRAY
|
||||
is LabJsonElement -> ITEM_TYPE_ELEMENT
|
||||
else -> throw IllegalArgumentException("Incorrect viewType")
|
||||
}
|
||||
}
|
||||
|
||||
private val onClickListener = View.OnClickListener { view ->
|
||||
val model = view.getTag(R.string.tag_key_model)
|
||||
if (model is LabJsonElement) {
|
||||
onJsonElementClick?.invoke(model)
|
||||
return@OnClickListener
|
||||
}
|
||||
if (model !is ExpandableItemModel<*>)
|
||||
return@OnClickListener
|
||||
expandModel(model, view)
|
||||
}
|
||||
|
||||
fun expandModel(model: ExpandableItemModel<*>?, view: View?, notifyAdapter: Boolean = true) {
|
||||
model ?: return
|
||||
val position = items.indexOf(model)
|
||||
if (position == -1)
|
||||
return
|
||||
|
||||
view?.findViewById<View>(R.id.dropdownIcon)?.let { dropdownIcon ->
|
||||
ObjectAnimator.ofFloat(
|
||||
dropdownIcon,
|
||||
View.ROTATION,
|
||||
if (model.state == STATE_CLOSED) 0f else 180f,
|
||||
if (model.state == STATE_CLOSED) 180f else 0f
|
||||
).setDuration(200).start();
|
||||
}
|
||||
|
||||
// hide the preview, show summary
|
||||
val preview = view?.findViewById<View>(R.id.previewContainer)
|
||||
val summary = view?.findViewById<View>(R.id.summaryContainer)
|
||||
preview?.isInvisible = model.state == STATE_CLOSED
|
||||
summary?.isInvisible = model.state != STATE_CLOSED
|
||||
|
||||
if (model.state == STATE_CLOSED) {
|
||||
|
||||
val subItems = when {
|
||||
//model.items.isEmpty() -> listOf(AttendanceEmpty())
|
||||
else -> expand(model, model.level)
|
||||
}
|
||||
|
||||
model.state = STATE_OPENED
|
||||
items.addAll(position + 1, subItems)
|
||||
if (notifyAdapter) notifyItemRangeInserted(position + 1, subItems.size)
|
||||
}
|
||||
else {
|
||||
val start = position + 1
|
||||
var end: Int = items.size
|
||||
for (i in start until items.size) {
|
||||
val model1 = items[i]
|
||||
val level = (model1 as? ExpandableItemModel<*>)?.level ?: 3
|
||||
if (level <= model.level) {
|
||||
end = i
|
||||
break
|
||||
} else {
|
||||
if (model1 is ExpandableItemModel<*> && model1.state == STATE_OPENED) {
|
||||
model1.state = STATE_CLOSED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (end != -1) {
|
||||
items.subList(start, end).clear()
|
||||
if (notifyAdapter) notifyItemRangeRemoved(start, end - start)
|
||||
}
|
||||
|
||||
model.state = STATE_CLOSED
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
if (holder !is BindableViewHolder<*, *>)
|
||||
return
|
||||
|
||||
val viewType = when (holder) {
|
||||
is JsonObjectViewHolder -> ITEM_TYPE_OBJECT
|
||||
is JsonArrayViewHolder -> ITEM_TYPE_ARRAY
|
||||
is JsonElementViewHolder -> ITEM_TYPE_ELEMENT
|
||||
else -> throw IllegalArgumentException("Incorrect viewType")
|
||||
}
|
||||
holder.itemView.setTag(R.string.tag_key_view_type, viewType)
|
||||
holder.itemView.setTag(R.string.tag_key_position, position)
|
||||
holder.itemView.setTag(R.string.tag_key_model, item)
|
||||
|
||||
when {
|
||||
holder is JsonObjectViewHolder && item is LabJsonObject -> holder.onBind(activity, app, item, position, this)
|
||||
holder is JsonArrayViewHolder && item is LabJsonArray -> holder.onBind(activity, app, item, position, this)
|
||||
holder is JsonElementViewHolder && item is LabJsonElement -> holder.onBind(activity, app, item, position, this)
|
||||
}
|
||||
|
||||
holder.itemView.setOnClickListener(onClickListener)
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-5-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.debug
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.databinding.LabFragmentBinding
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment
|
||||
import pl.szczodrzynski.fslogin.decode
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class LabPageFragment : LazyFragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "LabPageFragment"
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var activity: MainActivity
|
||||
private lateinit var b: LabFragmentBinding
|
||||
|
||||
private val job: Job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
// local/private variables go here
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
activity = (getActivity() as MainActivity?) ?: return null
|
||||
context ?: return null
|
||||
app = activity.application as App
|
||||
b = LabFragmentBinding.inflate(inflater)
|
||||
return b.root
|
||||
}
|
||||
|
||||
override fun onPageCreated(): Boolean {
|
||||
b.last10unseen.onClick {
|
||||
launch(Dispatchers.Default) {
|
||||
val events = app.db.eventDao().getAllNow(App.profileId)
|
||||
val ids = events.sortedBy { it.date }.filter { it.type == Event.TYPE_HOMEWORK }.takeLast(10)
|
||||
ids.forEach {
|
||||
app.db.metadataDao().setSeen(App.profileId, it, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.rodo.onClick {
|
||||
app.db.teacherDao().query(SimpleSQLiteQuery("UPDATE teachers SET teacherSurname = \"\" WHERE profileId = ${App.profileId}"))
|
||||
}
|
||||
|
||||
b.removeHomework.onClick {
|
||||
app.db.eventDao().getRawNow("UPDATE events SET homeworkBody = NULL WHERE profileId = ${App.profileId}")
|
||||
}
|
||||
|
||||
val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity)
|
||||
startCoroutineTimer(500L, 300L) {
|
||||
val text = app.cookieJar.sessionCookies
|
||||
.map { it.cookie }
|
||||
.sortedBy { it.domain() }
|
||||
.groupBy { it.domain() }
|
||||
.map {
|
||||
listOf(
|
||||
it.key.asBoldSpannable(),
|
||||
":\n",
|
||||
it.value
|
||||
.sortedBy { it.name() }
|
||||
.map {
|
||||
listOf(
|
||||
" ",
|
||||
it.name(),
|
||||
"=",
|
||||
it.value().decode().take(40).asItalicSpannable().asColoredSpannable(colorSecondary)
|
||||
).concat("")
|
||||
}.concat("\n")
|
||||
).concat("")
|
||||
}.concat("\n\n")
|
||||
b.cookies.text = text
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-5-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.debug
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||
import pl.szczodrzynski.edziennik.databinding.TemplateListPageFragmentBinding
|
||||
import pl.szczodrzynski.edziennik.startCoroutineTimer
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment
|
||||
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class LabProfileFragment : LazyFragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "LabProfileFragment"
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var activity: MainActivity
|
||||
private lateinit var b: TemplateListPageFragmentBinding
|
||||
|
||||
private val job: Job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
// local/private variables go here
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
activity = (getActivity() as MainActivity?) ?: return null
|
||||
context ?: return null
|
||||
app = activity.application as App
|
||||
b = TemplateListPageFragmentBinding.inflate(inflater)
|
||||
return b.root
|
||||
}
|
||||
|
||||
override fun onPageCreated(): Boolean { startCoroutineTimer(100L) {
|
||||
val adapter = LabJsonAdapter(activity)
|
||||
val json = JsonObject().also { json ->
|
||||
json.add("app.profile", app.profile.studentData)
|
||||
json.add("app.config", JsonParser().parse(app.gson.toJson(app.config.values)))
|
||||
EdziennikTask.profile?.let {
|
||||
json.add("API.profile", it.studentData)
|
||||
} ?: {
|
||||
json.addProperty("API.profile", "null")
|
||||
}()
|
||||
EdziennikTask.loginStore?.let {
|
||||
json.add("API.loginStore", it.data)
|
||||
} ?: {
|
||||
json.addProperty("API.loginStore", "null")
|
||||
}()
|
||||
}
|
||||
adapter.items = LabJsonAdapter.expand(json, 0)
|
||||
|
||||
b.list.adapter = adapter
|
||||
b.list.apply {
|
||||
setHasFixedSize(true)
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
addItemDecoration(SimpleDividerItemDecoration(context))
|
||||
addOnScrollListener(onScrollListener)
|
||||
}
|
||||
|
||||
// show/hide relevant views
|
||||
b.progressBar.isVisible = false
|
||||
b.list.isVisible = true
|
||||
b.noData.isVisible = false
|
||||
|
||||
}; return true }
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-5-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.debug.models
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel
|
||||
|
||||
data class LabJsonArray(
|
||||
val key: String,
|
||||
val jsonArray: JsonArray,
|
||||
override var level: Int
|
||||
) : ExpandableItemModel<JsonElement>(jsonArray.toMutableList())
|
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-5-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.debug.models
|
||||
|
||||
import com.google.gson.JsonElement
|
||||
|
||||
data class LabJsonElement(
|
||||
val key: String,
|
||||
val jsonElement: JsonElement,
|
||||
var level: Int
|
||||
)
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-5-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.debug.models
|
||||
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel
|
||||
|
||||
data class LabJsonObject(
|
||||
val key: String,
|
||||
val jsonObject: JsonObject,
|
||||
override var level: Int
|
||||
) : ExpandableItemModel<JsonElement>(jsonObject.entrySet().map { it.value }.toMutableList())
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-5-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.debug.viewholder
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.databinding.LabItemObjectBinding
|
||||
import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.LabJsonAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.models.LabJsonArray
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
|
||||
import pl.szczodrzynski.edziennik.utils.Themes
|
||||
|
||||
class JsonArrayViewHolder(
|
||||
inflater: LayoutInflater,
|
||||
parent: ViewGroup,
|
||||
val b: LabItemObjectBinding = LabItemObjectBinding.inflate(inflater, parent, false)
|
||||
) : RecyclerView.ViewHolder(b.root), BindableViewHolder<LabJsonArray, LabJsonAdapter> {
|
||||
companion object {
|
||||
private const val TAG = "JsonArrayViewHolder"
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBind(activity: AppCompatActivity, app: App, item: LabJsonArray, position: Int, adapter: LabJsonAdapter) {
|
||||
val contextWrapper = ContextThemeWrapper(activity, Themes.appTheme)
|
||||
|
||||
b.dropdownIcon.rotation = when (item.state) {
|
||||
AttendanceAdapter.STATE_CLOSED -> 0f
|
||||
else -> 180f
|
||||
}
|
||||
b.previewContainer.isInvisible = item.state != AttendanceAdapter.STATE_CLOSED
|
||||
b.summaryContainer.isInvisible = item.state == AttendanceAdapter.STATE_CLOSED
|
||||
|
||||
b.key.text = item.key
|
||||
b.previewContainer.text = item.jsonArray.toString().take(200)
|
||||
b.summaryContainer.text = item.jsonArray.size().toString() + " elements"
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-5-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.debug.viewholder
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.gson.JsonNull
|
||||
import com.google.gson.JsonPrimitive
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.databinding.LabItemElementBinding
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.LabJsonAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.models.LabJsonElement
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
|
||||
import pl.szczodrzynski.edziennik.utils.Themes
|
||||
|
||||
class JsonElementViewHolder(
|
||||
inflater: LayoutInflater,
|
||||
parent: ViewGroup,
|
||||
val b: LabItemElementBinding = LabItemElementBinding.inflate(inflater, parent, false)
|
||||
) : RecyclerView.ViewHolder(b.root), BindableViewHolder<LabJsonElement, LabJsonAdapter> {
|
||||
companion object {
|
||||
private const val TAG = "JsonObjectViewHolder"
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBind(activity: AppCompatActivity, app: App, item: LabJsonElement, position: Int, adapter: LabJsonAdapter) {
|
||||
val contextWrapper = ContextThemeWrapper(activity, Themes.appTheme)
|
||||
|
||||
b.type.text = when (item.jsonElement) {
|
||||
is JsonPrimitive -> when {
|
||||
item.jsonElement.isNumber -> "Number"
|
||||
item.jsonElement.isString -> "String"
|
||||
item.jsonElement.isBoolean -> "Boolean"
|
||||
else -> "Primitive"
|
||||
}
|
||||
is JsonNull -> "null"
|
||||
else -> null
|
||||
}
|
||||
|
||||
val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity)
|
||||
b.key.text = listOf(
|
||||
item.key.asColoredSpannable(colorSecondary),
|
||||
": ",
|
||||
item.jsonElement.toString().asItalicSpannable()
|
||||
).concat("")
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-5-12.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.debug.viewholder
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.databinding.LabItemObjectBinding
|
||||
import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.LabJsonAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.debug.models.LabJsonObject
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
|
||||
import pl.szczodrzynski.edziennik.utils.Themes
|
||||
|
||||
class JsonObjectViewHolder(
|
||||
inflater: LayoutInflater,
|
||||
parent: ViewGroup,
|
||||
val b: LabItemObjectBinding = LabItemObjectBinding.inflate(inflater, parent, false)
|
||||
) : RecyclerView.ViewHolder(b.root), BindableViewHolder<LabJsonObject, LabJsonAdapter> {
|
||||
companion object {
|
||||
private const val TAG = "JsonObjectViewHolder"
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBind(activity: AppCompatActivity, app: App, item: LabJsonObject, position: Int, adapter: LabJsonAdapter) {
|
||||
val contextWrapper = ContextThemeWrapper(activity, Themes.appTheme)
|
||||
|
||||
b.dropdownIcon.rotation = when (item.state) {
|
||||
AttendanceAdapter.STATE_CLOSED -> 0f
|
||||
else -> 180f
|
||||
}
|
||||
b.previewContainer.isInvisible = item.state != AttendanceAdapter.STATE_CLOSED
|
||||
b.summaryContainer.isInvisible = item.state == AttendanceAdapter.STATE_CLOSED
|
||||
|
||||
b.key.text = item.key
|
||||
b.previewContainer.text = item.jsonObject.toString().take(200)
|
||||
b.summaryContainer.text = item.jsonObject.size().toString() + " elements"
|
||||
}
|
||||
}
|
@ -54,6 +54,13 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Remove all homework body (null)"
|
||||
android:textAllCaps="false" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cookies"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="monospace"
|
||||
tools:text="Cookies:\n\nsynergia.librus.pl\n DZIENNIKSID=L01~1234567890abcdef"/>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</layout>
|
||||
|
34
app/src/main/res/layout/lab_item_element.xml
Normal file
34
app/src/main/res/layout/lab_item_element.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2020-5-12.
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/key"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:fontFamily="monospace"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"
|
||||
tools:text="lessonRanges: 8" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="monospace"
|
||||
android:text="Int"
|
||||
android:textAppearance="@style/NavView.TextView.Helper" />
|
||||
</LinearLayout>
|
||||
</layout>
|
75
app/src/main/res/layout/lab_item_object.xml
Normal file
75
app/src/main/res/layout/lab_item_object.xml
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2020-5-12.
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:baselineAligned="false"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/key"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:fontFamily="monospace"
|
||||
android:textAppearance="@style/NavView.TextView.Medium"
|
||||
tools:text="lessonRanges" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:fontFamily="monospace"
|
||||
android:text="JsonObject"
|
||||
android:textAppearance="@style/NavView.TextView.Helper" />
|
||||
|
||||
<com.mikepenz.iconics.view.IconicsImageView
|
||||
android:id="@+id/dropdownIcon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:scaleType="centerInside"
|
||||
app:iiv_color="?android:textColorSecondary"
|
||||
app:iiv_icon="cmd-chevron-down"
|
||||
app:iiv_size="18dp"
|
||||
tools:src="@android:drawable/ic_menu_more" />
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/previewContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="monospace"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
tools:text="{"accountId":8765432,"accountLogin":"2345678u","accountToken":"49azsnNZfxxfdSYb6lKU8NambrMXjeCrw7yA" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/summaryContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
tools:text="8 elements"
|
||||
tools:visibility="gone" />
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
</layout>
|
Loading…
Reference in New Issue
Block a user