Mercats de Mallorca v1.3: ficha, filtros y calendario
Cuando publiqué Mercats de Mallorca la app ya hacía lo básico: qué mercado toca hoy, la semana entera y un mapa. Desde entonces han caído dos actualizaciones (v1.2 y v1.3) y me apetecía contarlas, porque son justo el tipo de cosas que solo se te ocurren cuando la app la usa gente de verdad.
La ficha: tocar un mercado y verlo todo
Lo más visible de la 1.3 es que ahora cada mercado tiene su ficha. En la lista va solo la primera frase (se lee mucho mejor), y al tocar se abre la pantalla completa: descripción, horario, cuándo es la próxima vez, un mapa para situarte y los botones de cómo llegar, guardar, avisarme y añadir al calendario.
Código molón 1: al calendario sin pedir permisos
El botón de “añadir al calendario” es de mis detalles favoritos, porque es puro Android bien hecho: no pido el permiso de calendario (que asusta y para qué), sino que lanzo un intent y es la app de calendario quien enseña el evento para que lo guardes tú. Si el mercado no tiene hora publicada, va como evento de todo el día.
fun Context.afegeixAlCalendari(mercat: Mercat, data: LocalDate, titol: String) {
val intent = Intent(Intent.ACTION_INSERT)
.setData(CalendarContract.Events.CONTENT_URI)
.putExtra(CalendarContract.Events.TITLE, titol)
.putExtra(CalendarContract.Events.EVENT_LOCATION, adrecaText(mercat))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val rang = horariRang(mercat.horari)
if (rang == null) {
intent.putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, true)
.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, data.milisegons(LocalTime.MIDNIGHT))
} else {
intent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, data.milisegons(rang.first))
.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, data.milisegons(rang.second))
}
startActivity(intent)
}
Un permiso menos que pedir es un permiso menos que explicar.
Filtros de verdad
La 1.2 trajo los filtros, que era lo que más me pedían: buscar un pueblo, elegir días y temática, y que funcione igual en Hoy, en Semana y en el mapa. Parece poca cosa hasta que tienes 150 mercados y quieres solo los artesanales del sábado cerca de ti.
Código molón 2: que lo quincenal no salga cada semana
Este es el que más me gustó resolver. Había mercados quincenales y mensuales saliendo todas las semanas, porque el código solo miraba el día, no qué semana era. La lógica quedó así:
fun Mercat.esCelebraEl(data: LocalDate): Boolean {
if (temporada?.inclou(data) == false) return false
if (frequencia == Frequencia.DIARIA) return true
if (dia.iso != data.dayOfWeek.value) return false
return when (frequencia) {
Frequencia.QUINZENAL -> referencia?.let { ChronoUnit.DAYS.between(it, data).mod(14L) == 0L } ?: true
Frequencia.MENSUAL -> setmanaDelMes?.let { data.esLaSetmana(it) } ?: true
else -> true
}
}
/** ¿Es esta la n-ésima vez que cae este día de la semana dentro del mes? -1 = la última. */
private fun LocalDate.esLaSetmana(n: Int): Boolean =
if (n == -1) plusWeeks(1).monthValue != monthValue else (dayOfMonth - 1) / 7 == n - 1
Me gustan dos cosas de aquí. La primera, el truco de la última semana: en vez de contar
cuántas semanas tiene el mes, miro si sumar siete días ya me cambia de mes; si sí, es la
última. La segunda, los ?: true: si en los datos no sé desde cuándo contar los quince días,
o qué semana del mes toca, el mercado sale igual. Prefiero que salga de más y que alguien
llegue un día que no tocaba, antes que esconderlo y que se pierda uno que sí. Y por eso
mismo, cuando el ayuntamiento no publica la hora, la app lo dice con un “aprox.” en vez de
inventarse una: poner una hora exacta la haría pasar por segura, y no lo es.
Avisar de errores desde dentro
Lo último: en cada ficha hay un “¿hay algo que no cuadra?”. Un horario cambia, un mercado se mueve de plaza, y quien mejor lo sabe es quien está allí. Recoger eso desde dentro de la app vale más que cualquier fuente que consulte yo desde casa.