Commit 2b0d2c13 authored by Filip Wiesner's avatar Filip Wiesner

EventDetail cleanup with ‘DetailedEvent’ impl

parent 4080a753
......@@ -20,6 +20,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildToolsVersion '28.0.3'
}
kapt {
......@@ -35,8 +36,7 @@ dependencies {
def room_version = "2.0.0-rc01"
def dagger_version = "2.16"
def nav_version = "1.0.0-alpha06"
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation 'com.google.android.material:material:1.0.0'
......@@ -53,14 +53,13 @@ dependencies {
implementation "org.jetbrains.anko:anko-commons:$anko_version"
implementation 'androidx.core:core-ktx:1.0.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.25.3'
implementation "org.jetbrains.kotlin:kotlin-reflect:1.2.71"
implementation 'org.jetbrains.kotlin:kotlin-reflect:1.2.71'
implementation 'com.github.magneticflux:kotlin-livedata-utils:0.3.3'
//Navigation
implementation "android.arch.navigation:navigation-fragment-ktx:$nav_version"
implementation "android.arch.navigation:navigation-ui-ktx:$nav_version"
//Dependency injection
implementation "com.google.dagger:dagger:$dagger_version"
implementation "com.google.dagger:dagger-android:$dagger_version"
......@@ -72,18 +71,18 @@ dependencies {
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.tickaroo.tikxml:retrofit-converter:0.8.13'
// Shared Prefs
// Shared Prefs
implementation 'com.chibatching.kotpref:kotpref:2.6.0'
implementation 'com.chibatching.kotpref:livedata-support:2.6.0'
// Parsing
// Parsing
implementation 'com.google.code.gson:gson:2.8.4'
implementation 'com.tickaroo.tikxml:annotation:0.8.13'
implementation 'com.tickaroo.tikxml:core:0.8.13'
kapt 'com.tickaroo.tikxml:processor:0.8.13'
implementation 'net.danlew:android.joda:2.9.9.4'
// Animation/Trasnition
// Animation/Trasnition
implementation 'bg.devlabs.transitioner:transitioner:1.3'
implementation 'com.github.florent37:kotlinpleaseanimate:1.0.4'
implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'
......@@ -101,7 +100,6 @@ dependencies {
debugImplementation 'com.willowtreeapps.hyperion:hyperion-crash:0.9.24'
debugImplementation 'com.willowtreeapps.hyperion:hyperion-measurement:0.9.24'
debugImplementation 'com.willowtreeapps.hyperion:hyperion-geiger-counter:0.9.24'
}
kotlin {
experimental {
......
{
"formatVersion": 1,
"database": {
"version": 7,
"identityHash": "4accc8019952a9b15793c92e27f562ee",
"entities": [
{
"tableName": "Event",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `sequenceNum` INTEGER NOT NULL, `startsAt` INTEGER NOT NULL, `endsAt` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `capacity` INTEGER NOT NULL, `occupied` INTEGER NOT NULL, `eventTypeRaw` TEXT NOT NULL, `parallel` TEXT NOT NULL, `cs` TEXT, `en` TEXT, `course` TEXT, `room` TEXT, `teachers` TEXT, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sequenceNum",
"columnName": "sequenceNum",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "startsAt",
"columnName": "startsAt",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "endsAt",
"columnName": "endsAt",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "deleted",
"columnName": "deleted",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "capacity",
"columnName": "capacity",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "occupied",
"columnName": "occupied",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "eventTypeRaw",
"columnName": "eventTypeRaw",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "parallel",
"columnName": "parallel",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "note.cs",
"columnName": "cs",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "note.en",
"columnName": "en",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "linked.course",
"columnName": "course",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "linked.room",
"columnName": "room",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "linked.teachers",
"columnName": "teachers",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_Event_eventTypeRaw",
"unique": false,
"columnNames": [
"eventTypeRaw"
],
"createSql": "CREATE INDEX `index_Event_eventTypeRaw` ON `${TABLE_NAME}` (`eventTypeRaw`)"
}
],
"foreignKeys": []
},
{
"tableName": "EventNote",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`noteId` INTEGER NOT NULL, `eventId` INTEGER NOT NULL, `note` TEXT NOT NULL, PRIMARY KEY(`noteId`))",
"fields": [
{
"fieldPath": "noteId",
"columnName": "noteId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "eventId",
"columnName": "eventId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "note",
"columnName": "note",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"noteId"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "Course",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`code` TEXT NOT NULL, `completion` TEXT NOT NULL, `credits` INTEGER NOT NULL, `department` TEXT NOT NULL, `homepage` TEXT, `name` TEXT NOT NULL, `range` TEXT NOT NULL, `season` TEXT NOT NULL, `state` TEXT NOT NULL, `studyForm` TEXT, PRIMARY KEY(`code`))",
"fields": [
{
"fieldPath": "code",
"columnName": "code",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "completion",
"columnName": "completion",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "credits",
"columnName": "credits",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "department",
"columnName": "department",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "homepage",
"columnName": "homepage",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "range",
"columnName": "range",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "season",
"columnName": "season",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "state",
"columnName": "state",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "studyForm",
"columnName": "studyForm",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"code"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "Teacher",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`firstName` TEXT NOT NULL, `lastName` TEXT NOT NULL, `personalNumber` INTEGER NOT NULL, `titlesPost` TEXT, `titlesPre` TEXT, `username` TEXT NOT NULL, `division` TEXT NOT NULL, `email` TEXT NOT NULL, `extern` INTEGER NOT NULL, `phone` TEXT, PRIMARY KEY(`username`))",
"fields": [
{
"fieldPath": "firstName",
"columnName": "firstName",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "lastName",
"columnName": "lastName",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "personalNumber",
"columnName": "personalNumber",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "titlesPost",
"columnName": "titlesPost",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "titlesPre",
"columnName": "titlesPre",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "division",
"columnName": "division",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "extern",
"columnName": "extern",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "phone",
"columnName": "phone",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"username"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"4accc8019952a9b15793c92e27f562ee\")"
]
}
}
\ No newline at end of file
......@@ -58,7 +58,7 @@ class AuthViewModel : ViewModel() {
} else return@fetchUsing user as Failure
val teachers = if (events is Success) {
_userInitState.postValue("Downloading all your teachers")
_userInitState.postValue("Downloading all your teachersSet")
model.loadTeachers()
} else return@fetchUsing events as Failure
......
......@@ -3,7 +3,6 @@ package com.cvut.blackbird.flows.detail
import android.content.res.ColorStateList
import android.os.Bundle
import android.text.InputType
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
......@@ -13,17 +12,13 @@ import androidx.lifecycle.ViewModelProviders
import com.cvut.blackbird.R
import com.cvut.blackbird.extensions.courseAbbr
import com.cvut.blackbird.extensions.getColor
import com.cvut.blackbird.model.Success
import com.cvut.blackbird.model.entities.Course
import com.cvut.blackbird.model.entities.Event
import com.cvut.blackbird.model.entities.EventType
import com.cvut.blackbird.model.entities.Teacher
import com.cvut.blackbird.model.entities.*
import com.cvut.blackbird.support.glue.*
import kotlinx.android.synthetic.main.fragment_timetable_detail.*
class EventDetailFragment : Fragment() {
lateinit var event: Event
lateinit var detailedEvent: DetailedEvent
private lateinit var viewModel: EventDetailViewModel
......@@ -37,36 +32,41 @@ class EventDetailFragment : Fragment() {
= inflater.inflate(R.layout.fragment_timetable_detail, container, false)
private fun setupBinding() {
bind(viewModel.eventDetail) toPassValueTo ::setupEvent
bind(viewModel.eventDetail) toPassValueTo { viewModel
.requestCourse(event.linked?.course ?: "") }
bind(viewModel.eventDetail) toPassValueTo {if (event.linked?.teachers != null) viewModel
.requestTeachers(event.linked!!.teachers!!)}
bind(viewModel.course) toPassValueTo ::setupCourse
bind(viewModel.teacher) toPassValueTo ::setupTeachers
bind(viewModel.detailedEvent) toPassValueTo ::setupEvent
// observe(viewModel.detailedEvent) { viewModel
// .requestCourse(detailedEvent.linked?.course ?: "") }
// observe(viewModel.detailedEvent) {if (detailedEvent.linked?.teachersSet != null) viewModel
// .requestTeachers(detailedEvent.linked!!.teachersSet!!) }
// bind(viewModel.course) toPassValueTo ::setupCourse
// bind(viewModel.teacher) toPassValueTo ::setupTeachers
bind(detail_pin) clickToInvoke ::onPinnedStateChange
bindText(detail_notePersonalContent) changeTo viewModel::changeEventNote
}
private fun setupEvent(event: Event) {
this.event = event
private fun setupEvent(event: DetailedEvent) {
this.detailedEvent = event
detail_abbr.background = when(event.eventType) {
detail_abbr.background = when(event.event.eventType) {
EventType.LECTURE -> context?.resources?.getDrawable(R.drawable.ic_timetable_lecture, context?.theme)
EventType.TUTORIAL -> context?.resources?.getDrawable(R.drawable.ic_timetable_tutorial, context?.theme)
else -> context?.resources?.getDrawable(R.drawable.ic_timetable_info, context?.theme)
}
detail_abbr.text = event.linked?.course?.courseAbbr ?: "-"
detail_codeName.text = event.linked?.course
detail_sequenceNum.text = event.sequenceNum.toString()
detail_lengthTxt.text = "${event.endsAt.minuteOfDay - event.startsAt.minuteOfDay} min"
detail_capacityTxt.text = "${event.occupied}/${event.capacity}"
detail_timeTxt.text = "${event.startsAt.toString("HH:mm")} - ${event.endsAt.toString("HH:mm")}"
detail_teachersContent.text = event.linked?.teachers?.firstOrNull() ?: "None"
detail_parallelContent.text = if (event.parallel.isNotBlank()) event.parallel else "-"
detail_roomContent.text = event.linked?.room ?: "None"
detail_noteContent.setText(event.note?.cs ?: "None")
detail_abbr.text = event.courseEnt?.code?.courseAbbr ?: "-"
detail_codeName.text = event.courseEnt?.code
detail_sequenceNum.text = event.event.sequenceNum.toString()
detail_lengthTxt.text = "${event.event.endsAt.minuteOfDay - event.event.startsAt.minuteOfDay} min"
detail_capacityTxt.text = "${event.event.occupied}/${event.event.capacity}"
detail_timeTxt.text = "${event.event.startsAt.toString("HH:mm")} - ${event.event.endsAt.toString("HH:mm")}"
detail_teachersContent.text = event.event.linked?.teachers?.firstOrNull() ?: "None"
detail_parallelContent.text = if (event.event.parallel.isNotBlank()) event.event.parallel else "-"
detail_roomContent.text = event.event.linked?.room ?: "None"
detail_noteContent.text = event.event.note?.cs ?: "None"
setupCourse(event.courseEnt)
setupTeachers(event.teacherList)
refreshPinTint()
}
......@@ -87,14 +87,14 @@ class EventDetailFragment : Fragment() {
detail_teachersContent.text = teachersText.dropLast(1)
}
private fun onPinnedStateChange() = event.apply {
private fun onPinnedStateChange() = detailedEvent.event.apply {
isPinned = !isPinned
refreshPinTint()
}
private fun refreshPinTint() = detail_pin.apply {
imageTintList =
if (event.isPinned) ColorStateList.valueOf(getColor(R.color.colorTextLight))
if (detailedEvent.event.isPinned) ColorStateList.valueOf(getColor(R.color.colorTextLight))
else ColorStateList.valueOf(getColor(R.color.colorTextDark))
}
}
\ No newline at end of file
package com.cvut.blackbird.flows.detail
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.cvut.blackbird.BlackBirdAC
import com.cvut.blackbird.extensions.withDefault
import com.cvut.blackbird.model.entities.Course
import com.cvut.blackbird.model.entities.DetailedEvent
import com.cvut.blackbird.model.entities.Event
import com.cvut.blackbird.model.entities.Teacher
import com.cvut.blackbird.model.flows.EventDetailModel
import kotlinx.coroutines.experimental.Job
import kotlinx.coroutines.experimental.launch
class EventDetailViewModel: ViewModel() {
......@@ -16,32 +20,24 @@ class EventDetailViewModel: ViewModel() {
/**
* Observables
*/
private val _detailedEvent = MutableLiveData<DetailedEvent>() withDefault DetailedEvent.empty()
private val _course = MutableLiveData<Course?>()
private val _teachers = MutableLiveData<List<Teacher>>() withDefault listOf()
val detailedEvent: LiveData<DetailedEvent> get() = _detailedEvent
val course: LiveData<Course?> get() = _course
val teacher: LiveData<List<Teacher>> get() = _teachers
/**
* Transition data
*/
val eventDetail = MutableLiveData<Event>() withDefault Event.empty
/**
* INPUT
*/
fun requestCourse(code: String) { launch {
_course.postValue(model.getCourse(code))
} }
var job: Job? = null
fun setEvent(event: Event) {
job?.cancel()
job = launch {
_detailedEvent.postValue( model.getDetailedEvent(event.id) )
}
}
fun requestTeachers(usernames: List<String>) { launch {
_teachers.postValue(model.getTeachers(usernames))
} }
fun changeEventNote(note: String) {
fun changeEventNote(eventId: Int, note: String) {
}
}
\ No newline at end of file
......@@ -198,6 +198,7 @@ class NewsViewHolder(view: View, context: Context) : TaskViewHolder(view, contex
.isFullSpan = true
}
@Suppress("DEPRECATION")
fun TextView.setHtmlText(text: String) = setText(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(text, Html.FROM_HTML_MODE_COMPACT)
......
......@@ -24,11 +24,6 @@ import com.cvut.blackbird.support.glue.toPassValueTo
import kotlinx.android.synthetic.main.tasks_fragment.*
class TasksFragment : Fragment() {
companion object {
fun newInstance() = TasksFragment()
}
private lateinit var viewModel: TasksViewModel
private lateinit var eventViewModel: EventDetailViewModel
private lateinit var taskAdapter: TasksListAdapter
......@@ -68,7 +63,7 @@ class TasksFragment : Fragment() {
}
private fun goToEventDetail(event: Event) {
eventViewModel.eventDetail.postValue(event)
eventViewModel.setEvent(event)
findMainNav()?.navigate(R.id.toEventDetail)
}
......
......@@ -107,7 +107,7 @@ class TimetableFragment : Fragment() {
private fun onLectureClick(element: View) {
if (element is TimetableBall) {
eventViewModel.eventDetail.value = element.payload
eventViewMo