Skip to content

Commit

Permalink
Merge pull request #3 from ridebus-by/feature/schedule
Browse files Browse the repository at this point in the history
Update schedule view
  • Loading branch information
ztimms73 committed May 18, 2023
2 parents 36b4367 + a8b4dcd commit f18a845
Show file tree
Hide file tree
Showing 19 changed files with 311 additions and 256 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ package org.xtimms.ridebus.data.database.dao

import androidx.room.Dao
import androidx.room.Query
import androidx.room.Transaction
import kotlinx.coroutines.flow.Flow

@Dao
interface ScheduleDao {

@Query("SELECT schedule._id AS id, schedule.route_id AS routeId, schedule.type_day AS typeDay, strftime('%H:%M', 'now', 'localtime', 'start of day', schedule.hour || ' hours', schedule.minute || ' minutes', routeStops.shift_hour || ' hours', routeStops.shift_minute || ' minutes') AS arrivalTime FROM schedule, routeStops WHERE (routeStops.route_id = :routeId AND schedule.route_id = :routeId AND routeStops.stop_id = :stopId AND schedule.type_day = :typeDay) ORDER BY schedule.hour, schedule.minute")
fun getArrivalTime(typeDay: Int, routeId: Int, stopId: Int): List<Timetable>

@Transaction
@Query("SELECT schedule._id AS id, schedule.route_id AS routeId, schedule.type_day AS typeDay, strftime('%H:%M', 'now', 'localtime', 'start of day', schedule.hour || ' hours', schedule.minute || ' minutes', routeStops.shift_hour || ' hours', routeStops.shift_minute || ' minutes') AS arrivalTime FROM schedule, routeStops WHERE (routeStops.route_id = :routeId AND schedule.route_id = :routeId AND routeStops.stop_id = :stopId AND schedule.type_day = :typeDay) ORDER BY schedule.hour, schedule.minute")
fun observeArrivalTime(typeDay: Int, routeId: Int, stopId: Int): Flow<List<Timetable>>

@Query("SELECT DISTINCT hour FROM schedule where route_id = :routeId and type_day = :typeDay")
fun getHours(typeDay: Int, routeId: Int): List<Int>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ data class Route(
@ColumnInfo(name = "following") val following: String,
@ColumnInfo(name = "carrier_company") val carrierCompany: String,
@ColumnInfo(name = "tech_info") val techInfo: String,
@ColumnInfo(name = "cash") val cash: Int,
@ColumnInfo(name = "qr_code") val qrCode: Int,
@ColumnInfo(name = "is_small") val isSmall: Int,
@ColumnInfo(name = "is_big") val isBig: Int,
@ColumnInfo(name = "is_very_big") val isVeryBig: Int,
@ColumnInfo(name = "eco") val isEco: Int,
@ColumnInfo(name = "wifi") val wifi: Int,
@ColumnInfo(name = "low_floor") val isLowFloor: Int
@ColumnInfo(name = "cash") val cash: Boolean,
@ColumnInfo(name = "qr_code") val qrCode: Boolean,
@ColumnInfo(name = "is_small") val isSmall: Boolean,
@ColumnInfo(name = "is_big") val isBig: Boolean,
@ColumnInfo(name = "is_very_big") val isVeryBig: Boolean,
@ColumnInfo(name = "eco") val isEco: Boolean,
@ColumnInfo(name = "wifi") val wifi: Boolean,
@ColumnInfo(name = "low_floor") val isLowFloor: Boolean
)
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ import com.yandex.mapkit.directions.driving.DrivingRoute
import com.yandex.mapkit.directions.driving.DrivingRouter
import com.yandex.mapkit.directions.driving.DrivingSession
import com.yandex.mapkit.directions.driving.VehicleOptions
import com.yandex.mapkit.geometry.BoundingBox
import com.yandex.mapkit.geometry.BoundingBoxHelper
import com.yandex.mapkit.geometry.Point
import com.yandex.mapkit.geometry.Polyline
import com.yandex.mapkit.map.CameraPosition
import com.yandex.mapkit.map.MapObjectCollection
import com.yandex.runtime.Error
Expand Down Expand Up @@ -77,12 +78,9 @@ class RouteInfoHeaderAdapter(
)
}

val boundingBox = BoundingBox(
Point(stopsPoints.first().latitude, stopsPoints.last().longitude),
Point(stopsPoints.last().latitude, stopsPoints.first().longitude)
)
val boundsHelper = BoundingBoxHelper.getBounds(Polyline(stopsPoints))

val cameraPosition = binding.mapView.map.cameraPosition(boundingBox)
val cameraPosition = binding.mapView.map.cameraPosition(boundsHelper)

constraintSet.clone(constraintLayout)
constraintSet.connect(
Expand Down Expand Up @@ -195,9 +193,7 @@ class RouteInfoHeaderAdapter(
* Update the view with route information.
*/
private fun setRouteInfo() {
if (route.transportId == MINIBUS && preferences.isVisibleAttentionNote()
.get()
) {
if (route.transportId == MINIBUS && preferences.isVisibleAttentionNote().get()) {
binding.noteChip.visibility = View.VISIBLE
}

Expand Down Expand Up @@ -268,49 +264,49 @@ class RouteInfoHeaderAdapter(
binding.fare.text = route.fare

val tags = ArrayList<RideBusChipGroup.ChipModel>()
if (route.qrCode == 1) {
if (route.qrCode) {
tags += RideBusChipGroup.ChipModel(
title = view.context.getString(R.string.qr),
icon = R.drawable.ic_qr_code
)
}
if (route.cash == 1) {
if (route.cash) {
tags += RideBusChipGroup.ChipModel(
title = view.context.getString(R.string.in_cash),
icon = R.drawable.ic_account_balance_wallet
)
}
if (route.isSmall == 1) {
if (route.isSmall) {
tags += RideBusChipGroup.ChipModel(
title = view.context.getString(R.string.small_class),
icon = R.drawable.ic_little_class
)
}
if (route.isBig == 1) {
if (route.isBig) {
tags += RideBusChipGroup.ChipModel(
title = view.context.getString(R.string.big_class),
icon = R.drawable.ic_big_class
)
}
if (route.isVeryBig == 1) {
if (route.isVeryBig) {
tags += RideBusChipGroup.ChipModel(
title = view.context.getString(R.string.very_big_class),
icon = R.drawable.ic_very_big_class
)
}
if (route.isEco == 1) {
if (route.isEco) {
tags += RideBusChipGroup.ChipModel(
title = view.context.getString(R.string.ecotransport),
icon = R.drawable.ic_eco
)
}
if (route.wifi == 1) {
if (route.wifi) {
tags += RideBusChipGroup.ChipModel(
title = view.context.getString(R.string.wifi),
icon = R.drawable.ic_wifi
)
}
if (route.isLowFloor == 1) {
if (route.isLowFloor) {
tags += RideBusChipGroup.ChipModel(
title = view.context.getString(R.string.low_floor),
icon = R.drawable.ic_wheelchair
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class ScheduleController :

private var adapter: ScheduleAdapter? = null

private var schedule: List<ScheduleItem> = emptyList()
private var schedule: List<ScheduleRow> = emptyList()

override fun createBinding(inflater: LayoutInflater) = ScheduleControllerBinding.inflate(inflater)

Expand All @@ -77,6 +77,7 @@ class ScheduleController :

adapter = ScheduleAdapter(this)
binding.recycler.layoutManager = LinearLayoutManager(view.context)
binding.recycler.itemAnimator = null
binding.recycler.adapter = adapter
binding.recycler.setHasFixedSize(true)
}
Expand All @@ -94,7 +95,7 @@ class ScheduleController :
}
}

fun setSchedule(schedule: List<ScheduleItem>) {
fun setSchedule(schedule: List<ScheduleRow>) {
this.schedule = schedule
adapter?.updateDataSet(schedule)
}
Expand Down
56 changes: 51 additions & 5 deletions app/src/main/java/org/xtimms/ridebus/ui/schedule/ScheduleHolder.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,62 @@
package org.xtimms.ridebus.ui.schedule

import android.graphics.Color
import android.graphics.Typeface
import android.text.Spannable
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.view.View
import androidx.core.text.buildSpannedString
import eu.davidea.viewholders.FlexibleViewHolder
import org.xtimms.ridebus.databinding.ScheduleItemLegacyBinding
import org.xtimms.ridebus.databinding.ScheduleItemBinding
import org.xtimms.ridebus.util.system.getThemeColor
import com.google.android.material.R as materialR

class ScheduleHolder(view: View, val adapter: ScheduleAdapter) :
FlexibleViewHolder(view, adapter) {

private val binding = ScheduleItemLegacyBinding.bind(view)
private val binding = ScheduleItemBinding.bind(view)
private val highlightColor = view.context.getThemeColor(materialR.attr.colorPrimary)
private val bgHighlightColor =
view.context.getThemeColor(materialR.attr.colorSecondaryContainer)
private val bgTextColor =
view.context.getThemeColor(materialR.attr.colorOnSecondaryContainer)
private val defaultTextColor =
view.context.getThemeColor(materialR.attr.colorOnSurface)

fun bind(item: ScheduleItem) {
val schedule = item.schedule
binding.textTimeExact.text = schedule.arrivalTime
fun bind(item: ScheduleRow) {
binding.textHour.text = item.hour.toString()
binding.textHour.setTextColor(
if (item.isCurrentHour()) bgTextColor else defaultTextColor
)
binding.row.setBackgroundColor(
if (item.isCurrentHour()) bgHighlightColor else Color.TRANSPARENT
)
val closestMinute = item.getClosestMinute()
binding.textMinutes.text = buildSpannedString {
var isFirst = true
for (minute in item.minutes) {
if (isFirst) {
isFirst = false
} else {
append("\t\t\t")
}
append("%02d".format(minute))
if (closestMinute == minute) {
setSpan(
ForegroundColorSpan(highlightColor),
length - 2,
length,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
)
setSpan(
StyleSpan(Typeface.BOLD),
length - 2,
length,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
)
}
}
}
}
}
43 changes: 0 additions & 43 deletions app/src/main/java/org/xtimms/ridebus/ui/schedule/ScheduleItem.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
package org.xtimms.ridebus.ui.schedule

import android.os.Bundle
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.isActive
import org.xtimms.ridebus.data.database.RideBusDatabase
import org.xtimms.ridebus.data.database.entity.Route
import org.xtimms.ridebus.data.database.entity.Stop
import org.xtimms.ridebus.ui.base.presenter.BasePresenter
import org.xtimms.ridebus.util.lang.withUIContext
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.NavigableSet
import java.util.TreeSet
import java.util.concurrent.TimeUnit

class SchedulePresenter(
private val typeDay: Int,
Expand All @@ -19,15 +28,31 @@ class SchedulePresenter(

override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
loadSchedule(typeDay, route, stop)
observeSchedule(typeDay, route, stop)
}

private fun loadSchedule(typeDay: Int, route: Route, stop: Stop) {
presenterScope.launch {
val arrivalTimes = db.scheduleDao().getArrivalTime(typeDay, route.routeId, stop.stopId)
withUIContext {
view?.setSchedule(arrivalTimes.map(::ScheduleItem))
private fun observeSchedule(typeDay: Int, route: Route, stop: Stop) {
combine(
db.scheduleDao().observeArrivalTime(typeDay, route.routeId, stop.stopId),
tickerFlow()
) { schedule, time ->
val rows = HashMap<Int, NavigableSet<Int>>(schedule.size)
for (item in schedule) {
val (hour, minute) = item.arrivalTime?.split(':') ?: continue
rows.getOrPut(hour.toInt()) { TreeSet() }.add(minute.toInt())
}
rows.entries.map {
ScheduleRow(it.key, it.value, time)
}
}.flowOn(Dispatchers.Default)
.onEach { view?.setSchedule(it) }
.launchIn(presenterScope)
}

private fun tickerFlow() = flow {
while (isActive) {
emit(System.currentTimeMillis())
delay(TimeUnit.MINUTES.toMillis(1))
}
}
}
Loading

0 comments on commit f18a845

Please sign in to comment.