conventionschedule-android/app/src/main/java/com/adlerosn/brasilfurfest/schedule/fragments/ConventionSummaryFragment.kt

387 lines
19 KiB
Kotlin
Raw Normal View History

2018-12-13 02:04:29 +00:00
package com.adlerosn.brasilfurfest.schedule.fragments
2018-07-13 21:09:43 +00:00
import android.app.AlertDialog
2018-07-18 05:51:07 +00:00
import android.content.Context
2018-07-13 21:09:43 +00:00
import android.content.DialogInterface
2018-07-14 19:43:24 +00:00
import android.content.Intent
import android.net.Uri
2018-07-13 21:09:43 +00:00
import android.os.Bundle
import androidx.fragment.app.Fragment
2018-07-18 15:01:16 +00:00
import android.util.Log
2018-07-13 21:09:43 +00:00
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Space
2018-07-13 21:09:43 +00:00
import android.widget.TextView
2018-07-14 19:43:24 +00:00
import com.adlerosn.brasilfurfest.AssetImageViewerActivity
2018-07-27 03:39:36 +00:00
import com.adlerosn.brasilfurfest.CountdownActivity
2018-07-13 21:09:43 +00:00
import com.adlerosn.brasilfurfest.R
2018-07-18 05:51:07 +00:00
import com.adlerosn.brasilfurfest.helper.*
import com.adlerosn.brasilfurfest.helper.observables.Observable
import com.adlerosn.brasilfurfest.helper.observables.Observer
2018-07-16 23:15:20 +00:00
import com.adlerosn.brasilfurfest.schedule.EventActivity
2018-12-12 04:30:34 +00:00
import com.adlerosn.brasilfurfest.schedule.abstractDataTypes.dataholder.PeekableEvent
2018-07-16 23:15:20 +00:00
import com.adlerosn.brasilfurfest.schedule.abstractDataTypes.managed.Actions
import com.adlerosn.brasilfurfest.schedule.abstractDataTypes.managed.AttendeeConFavorite
2018-12-13 02:04:29 +00:00
import com.adlerosn.brasilfurfest.schedule.managers.ScheduleManagerGetter
import kotlinx.android.synthetic.main.activity_schedule.*
2018-07-13 21:09:43 +00:00
import kotlinx.android.synthetic.main.dialogview_schedule_registration_tier.view.*
import kotlinx.android.synthetic.main.dialogview_schedule_registration_tiers.view.*
import kotlinx.android.synthetic.main.fragment_schedule_summary.view.*
2018-07-26 02:29:15 +00:00
import kotlinx.android.synthetic.main.fragment_schedule_summary_countdown.view.*
2018-07-16 23:15:20 +00:00
import kotlinx.android.synthetic.main.fragment_schedule_summary_eventitem.view.*
import kotlinx.android.synthetic.main.fragment_schedule_summary_r621violation.view.*
2018-07-14 19:43:24 +00:00
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
2018-07-18 15:01:16 +00:00
import java.io.PrintWriter
import java.io.StringWriter
2018-07-16 23:15:20 +00:00
import java.text.SimpleDateFormat
2018-07-13 21:09:43 +00:00
import java.util.*
2018-07-16 23:15:20 +00:00
import kotlin.math.floor
import kotlin.math.roundToInt
2018-07-13 21:09:43 +00:00
class ConventionSummaryFragment : Fragment(), Observer<Observable<Any?>, Any?> {
2018-07-13 21:09:43 +00:00
companion object {
2018-12-13 02:04:29 +00:00
fun newInstance(): Fragment {
2018-07-13 21:09:43 +00:00
return ConventionSummaryFragment().apply {
2018-12-13 02:04:29 +00:00
arguments = Bundle()
2018-07-13 21:09:43 +00:00
}
}
}
override fun update(observable: Observable<Any?>, args: Any?) {
2018-07-13 21:09:43 +00:00
try {
2018-12-12 04:30:34 +00:00
safeActivity.runOnUiThread {
updateView()
2018-07-16 23:15:20 +00:00
}
} catch (e: Throwable) {
2018-07-18 15:01:16 +00:00
val writer = StringWriter()
e.printStackTrace(PrintWriter(writer))
val s = writer.toString()
Log.e(ConventionSummaryFragment::class.java.simpleName, s)
2018-07-16 23:15:20 +00:00
}
2018-07-13 21:09:43 +00:00
}
2018-12-13 02:04:29 +00:00
val safeActivity = ActivitiesForFragments["ScheduleActivity"]!!
val scheduleManager = ScheduleManagerGetter[safeActivity]
2018-07-13 21:09:43 +00:00
lateinit var rootView: View
2018-07-14 19:43:24 +00:00
lateinit var timer: Timer
2018-07-13 21:09:43 +00:00
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
rootView = inflater.inflate(R.layout.fragment_schedule_summary, container, false)
updateView()
2018-07-14 19:43:24 +00:00
timer = Timer()
2018-12-12 04:30:34 +00:00
timer.scheduleAtFixedRate(object : TimerTask() {
override fun run() { safeActivity.runOnUiThread {
try {
rootView.let {
this@ConventionSummaryFragment.updateView()
2018-07-14 19:43:24 +00:00
}
2018-12-12 04:30:34 +00:00
} catch (e: Throwable){
val writer = StringWriter()
e.printStackTrace(PrintWriter(writer))
val s = writer.toString()
Log.e(ConventionSummaryFragment::class.java.simpleName, s)
2018-07-14 19:43:24 +00:00
}
2018-12-12 04:30:34 +00:00
} }
}, 3000, 30*1000)
2018-07-13 21:09:43 +00:00
scheduleManager.addObserver(this)
return rootView
}
2018-12-12 04:30:34 +00:00
private fun updateView() {
safeActivity.runOnUiThread {
val conventionTime = scheduleManager.conventionTime
val context = rootView.context
val inflater = context.layoutInflater
2018-12-28 00:28:48 +00:00
rootView.textRegistrationTier.text = scheduleManager.attendeeFavorites.registrationTier.names.solved
rootView.textRegistrationBenefits.text = scheduleManager.attendeeFavorites.registrationTier.benefits.size.run { pluralize(
R.string.schedule_tierbenefit_none.getString(),
R.string.schedule_tierbenefit_singular.getString().format(this),
R.string.schedule_tierbenefit_plural.getString().format(this)
) }
2018-12-12 04:30:34 +00:00
rootView.registrationTierSection.setOnClickListener {
val dialog = AlertDialog.Builder(safeActivity).create()
dialog.setTitle(R.string.schedule_registrationtier_question.getString())
2018-12-12 04:30:34 +00:00
val scroller = inflater.inflate(R.layout.dialogview_schedule_registration_tiers)
scheduleManager.convention.registrationTiers.sortedBy { it.level }.forEach {
scroller.container.addView(inflater.inflate(R.layout.dialogview_schedule_registration_tier).apply {
2018-12-28 00:28:48 +00:00
tier.text = it.names.solved
2018-12-12 04:30:34 +00:00
it.benefits.forEach {
benefitsList.addView(TextView(context).apply {
2018-12-28 00:28:48 +00:00
this.text = it.solved
this.setTextColor(scroller.context.getColorCompat(R.color.colorBase05))
2018-12-12 04:30:34 +00:00
})
}
if (it.benefits.isEmpty()) ticket.visibility = View.GONE
setOnClickListener { _ ->
dialog.dismiss()
scheduleManager.attendeeFavorites.registrationTier = it
}
})
}
dialog.setView(scroller)
2018-12-28 00:28:48 +00:00
dialog.setButton(AlertDialog.BUTTON_NEUTRAL, R.string.dialog_cancel.getString()) { dialogInterface: DialogInterface, _: Int -> dialogInterface.dismiss() }
val callbacks =
(scheduleManager.convention.registrationLinks.filter { scheduleManager.conventionTime in it.lifetime } + listOf(null, null))
.subList(0, 2).let {
Pair(it.getOrNull(0), it.getOrNull(1))
}.let {
listOf(
Pair(it.first, AlertDialog.BUTTON_POSITIVE),
Pair(it.second, AlertDialog.BUTTON_NEGATIVE)
)
}.map {
it.first?.run {
dialog.setButton(it.second, name.solved) { dialogInterface: DialogInterface, _: Int ->
val i = Intent(Intent.ACTION_VIEW)
i.data = Uri.parse(url.solved)
dialog.context.startActivity(i)
dialogInterface.dismiss()
}
fun(){
this.color?.let { color -> dialog.getButton(it.second).setTextColor(color) }
}
}
}
dialog.setOnShowListener { callbacks.filterNotNull().forEach { it() } }
2018-12-12 04:30:34 +00:00
dialog.show()
2018-07-13 21:09:43 +00:00
}
2018-12-12 04:30:34 +00:00
if (!scheduleManager.attendeeFavorites.registrationTierSelectorShown) {
rootView.registrationTierSection.performClick()
scheduleManager.attendeeFavorites.registrationTierSelectorShown = true
2018-07-14 19:43:24 +00:00
}
val mapButtons = rootView.mapButtons
mapButtons.removeAllViews()
val maps = scheduleManager.convention.maps
maps.withIndex().forEach {
val isLast = it.index+1 >= maps.size
Button(rootView.context).apply {
2018-12-28 00:28:48 +00:00
text = it.value.name.solved
setOnClickListener {view ->
Intent(view.context, AssetImageViewerActivity::class.java).apply {
2018-12-28 00:28:48 +00:00
putExtra("asset", it.value.image.solved)
startActivity(this)
}
}
2018-12-28 00:28:48 +00:00
setTextColor(mapButtons.context.getColorCompat(R.color.colorBase04).asColorStateList)
backgroundTintList = mapButtons.context.getColorCompat(R.color.colorBase18).asColorStateList
mapButtons.addView(this)
2018-12-12 04:30:34 +00:00
}
if(!isLast){
Space(rootView.context).apply {
2018-12-28 00:28:48 +00:00
minimumWidth = 4.asDpToPx.roundToInt()
minimumHeight = 0
mapButtons.addView(this)
}
2018-12-12 04:30:34 +00:00
}
2018-07-14 19:43:24 +00:00
}
2018-07-16 23:15:20 +00:00
2018-12-12 04:30:34 +00:00
val eventCountdown = scheduleManager.nextEditionStartCountdown
if (eventCountdown == null)
rootView.countdown.visibility = View.GONE
else {
rootView.countdown.visibility = View.VISIBLE
rootView.countdownTitle.text = context
.getString(R.string.thingsLacking_to)
.format(
eventCountdown.let { (f, s, t) ->
"%dd %dh %dm".format(f, s, t)
}
)
2018-07-27 03:39:36 +00:00
}
2018-12-12 04:30:34 +00:00
rootView.countdown.setOnClickListener {
Intent(safeActivity, CountdownActivity::class.java).let {
it.putExtra("label", scheduleManager.convention.genericName)
it.putExtra("counter", scheduleManager.nextEditionStartTime)
startActivity(it)
2018-07-16 23:15:20 +00:00
}
2018-12-12 04:30:34 +00:00
}
val allHappening = scheduleManager.convention.events
.filterNot {
it.isCustom
}.map {
2018-12-28 00:28:48 +00:00
AttendeeConFavorite(scheduleManager.convention, it)
2018-12-12 04:30:34 +00:00
} +
scheduleManager.attendeeFavorites.toList().filter {
it.isCustom
}
val happeningNow = allHappening
.filter { conventionTime in it.timeRange }
.sortedBy { -it.timeRange.start.timeInMillis }
val nextDayPart = allHappening
.sortedBy {
it.timeRange.start.timeInMillis
}
.firstOrNull {
it.timeRange.start.timeInMillis > conventionTime.timeInMillis
}
?.timeRange
?.start
?.dayRange
?.split(scheduleManager.convention.splitDayIn)
?.dropWhile {
it.start.timeInMillis <= conventionTime.timeInMillis
}
?.getOrNull(0)
val happeningNext = nextDayPart?.let { part ->
allHappening.filter {
2018-12-28 00:28:48 +00:00
it.timeRange.start in part
2018-07-16 23:15:20 +00:00
}
2018-12-12 04:30:34 +00:00
} ?: listOf()
2018-12-28 00:28:48 +00:00
rootView.eventsNowDescription.text = happeningNow.size.run { pluralize(
R.string.schedule_now_no_event.getString(),
R.string.schedule_now_n_event.getString().format(this),
R.string.schedule_now_n_events.getString().format(this)
) }
rootView.eventsComingDescription.text = happeningNext.size.run { pluralize(
R.string.schedule_coming_no_event.getString(),
R.string.schedule_coming_n_event.getString().format(this),
R.string.schedule_coming_n_events.getString().format(this)
) }
2018-12-12 04:30:34 +00:00
rootView.eventsNowContainer.removeAllViews()
rootView.eventsComingContainer.removeAllViews()
happeningNow.forEach { rootView.eventsNowContainer.addView(renderEventCard(context, it)) }
happeningNext.forEach { rootView.eventsComingContainer.addView(renderEventCard(context, it)) }
2018-07-16 23:15:20 +00:00
2018-12-12 04:30:34 +00:00
rootView.r621watcher.removeAllViews()
if (scheduleManager.convention.r621checker) {
val favorites = scheduleManager.attendeeFavorites.toList()
val r621watchedDays =
scheduleManager.convention.days.map {
it.dayRange
}.filter {
it.start.timeInMillis > scheduleManager.convention.startCalendarOn.timeInMillis
}
r621watchedDays.forEach { dayRange ->
2018-12-28 00:28:48 +00:00
val todayFavorites = favorites.filter { it.timeRange.start in dayRange }
2018-12-12 04:30:34 +00:00
val sleepFavorites = todayFavorites.filter { it.kind == Actions.Intention.SLEEP }.filterNot { sleep ->
2018-12-28 00:28:48 +00:00
todayFavorites.filter { sleep.timeRange in it.timeRange }.size > 1
2018-12-12 04:30:34 +00:00
}
val eatFavorites = todayFavorites.filter { it.kind == Actions.Intention.EAT }
val showerFavorites = todayFavorites.filter { it.kind == Actions.Intention.SHOWER }
val daySegment = 24.0 / scheduleManager.convention.splitDayIn
if (
((sleepFavorites.size * daySegment) < 6)
or
((eatFavorites.size * daySegment) < 2)
or
((showerFavorites.size * daySegment) < 1)
) {
rootView.r621watcher.addView(
rule621renderer(
context,
dayRange.start,
sleepFavorites.size * daySegment,
eatFavorites.size * daySegment,
showerFavorites.size * daySegment
)
)
2018-07-16 23:47:27 +00:00
}
}
}
2018-07-18 19:46:28 +00:00
2018-12-12 04:30:34 +00:00
val hashtag = scheduleManager.convention.hashtagReminder
if (hashtag == null) {
rootView.shareReminder.visibility = View.GONE
} else {
rootView.shareReminderTitle.text = hashtag
}
2018-12-13 02:04:29 +00:00
rootView.readTheRules.setOnClickListener {
safeActivity.container.currentItem = scheduleManager.convention.days.size+1
2018-12-13 02:04:29 +00:00
}
2018-07-18 19:46:28 +00:00
}
2018-07-13 21:09:43 +00:00
}
2018-07-16 23:15:20 +00:00
2018-07-18 05:51:07 +00:00
private fun dowFormatter(context: Context) = SimpleDateFormat("E", context.runtimeLanguage.locale)
private fun hourMinuteFormatter(context: Context) = SimpleDateFormat("HH:mm", context.runtimeLanguage.locale)
2018-07-16 23:15:20 +00:00
2018-07-18 05:51:07 +00:00
private fun renderEventCard(context: Context, attendeeConFavorite: AttendeeConFavorite): View{
val view = context.layoutInflater.inflate(R.layout.fragment_schedule_summary_eventitem)
2018-07-16 23:15:20 +00:00
val event = attendeeConFavorite.findInConvention(scheduleManager.convention)
2018-07-18 05:51:07 +00:00
view.startDay.text = dowFormatter(context).format(attendeeConFavorite.timeRange.start.timeInMillis).capitalize()
view.startText.text = hourMinuteFormatter(context).format(attendeeConFavorite.timeRange.start.timeInMillis)
view.finishText.text = hourMinuteFormatter(context).format(attendeeConFavorite.timeRange.finish.timeInMillis)
2018-12-28 00:28:48 +00:00
view.eventTitle.text = attendeeConFavorite.getString()
view.eventSubtitle.text = attendeeConFavorite.getSecondaryString()
2018-07-16 23:15:20 +00:00
if(attendeeConFavorite in scheduleManager.attendeeFavorites) {
view.starButton.setOnClickListener {
2018-12-12 04:30:34 +00:00
val dialog = AlertDialog.Builder(safeActivity).create()
2018-07-16 23:15:20 +00:00
dialog.setTitle(context.getString(R.string.schedule_action_interest_remove))
dialog.setButton(AlertDialog.BUTTON_NEUTRAL, context.getString(R.string.dialog_cancel)) { dialogInterface, _ ->
dialogInterface.dismiss()
}
dialog.setButton(AlertDialog.BUTTON_NEGATIVE, context.getString(R.string.list_action_remove)) { dialogInterface, _ ->
dialogInterface.dismiss()
scheduleManager.attendeeFavorites.remove(attendeeConFavorite)
updateView()
}
dialog.show()
}
} else {
view.star.setImageResource(R.drawable.ic_star_border_black_24dp)
view.starButton.setOnClickListener {
view.star.setImageResource(R.drawable.ic_star_half_black_24dp)
scheduleManager.attendeeFavorites.add(attendeeConFavorite)
updateView()
}
}
if (event != null) {
if (
event.hiddenFromTimeTable
or
(scheduleManager.attendeeFavorites.registrationTier.level !in event.attendableBy.map { it.level })
){
view.star.visibility = View.INVISIBLE
view.starButton.setOnClickListener { }
}
}
if (event?.language == null) {
view.flag.visibility = View.GONE
} else {
view.flag.setImageResource(event.language.drawableId)
}
view.setOnClickListener {
context.startActivity(
2018-12-12 04:30:34 +00:00
Intent(safeActivity, EventActivity::class.java).apply {
2018-07-16 23:15:20 +00:00
putExtra("favorite", attendeeConFavorite)
putExtra("offerStar", true)
}
)
}
2018-12-12 04:30:34 +00:00
bindPeekAndPop(
safeActivity,
view as ViewGroup,
view,
if (view.star.visibility == View.INVISIBLE)
null
else
2018-12-28 00:28:48 +00:00
attendeeConFavorite in scheduleManager.attendeeFavorites,
2018-12-12 04:30:34 +00:00
{ doAsync { uiThread { view.starButton.callOnClick() } } },
{ doAsync { uiThread { view.callOnClick() } } },
scheduleManager.convention.events.firstOrNull {
it.conbookId == attendeeConFavorite.conBookId
}?.let { PeekableEvent(it) }
2018-12-28 00:28:48 +00:00
?: PeekableEvent(attendeeConFavorite)
2018-12-12 04:30:34 +00:00
)
2018-07-16 23:15:20 +00:00
return view
}
2018-07-18 05:51:07 +00:00
private fun rule621renderer(context: Context, day: GregorianCalendar, sleep: Double, meals: Double, showers: Double): View{
val view = context.layoutInflater.inflate(R.layout.fragment_schedule_summary_r621violation)
view.r621Description.text = context.getString(R.string.on_something).format(
SimpleDateFormat("EEEE (d)", context.runtimeLanguage.locale).format(day.timeInMillis)
2018-07-16 23:47:27 +00:00
)
2018-07-18 05:51:07 +00:00
view.r621_sleep_minimum.text = context.getString(R.string.r621_minimum_is_d).format(6)
view.r621_eat_minimum.text = context.getString(R.string.r621_minimum_is_d).format(2)
view.r621_shower_minimum.text = context.getString(R.string.r621_minimum_is_d).format(1)
view.r621_sleep_found.text = context.getString(R.string.r621_found_d).format(floor(sleep).roundToInt())
view.r621_eat_found.text = context.getString(R.string.r621_found_d).format(floor(meals).roundToInt())
view.r621_shower_found.text = context.getString(R.string.r621_found_d).format(floor(showers).roundToInt())
2018-12-28 00:28:48 +00:00
if(sleep<6) view.r621_sleep_found.setTextColor(context.getColorCompat(R.color.colorBase06))
if(meals<2) view.r621_eat_found.setTextColor(context.getColorCompat(R.color.colorBase06))
if(showers<1) view.r621_shower_found.setTextColor(context.getColorCompat(R.color.colorBase06))
2018-07-16 23:47:27 +00:00
return view
}
2018-07-13 21:09:43 +00:00
}