forked from github/wulkanowy-mirror
Add conferences (#1004)
This commit is contained in:
parent
c3061e75b5
commit
8830240182
1842
app/schemas/io.github.wulkanowy.data.db.AppDatabase/28.json
Normal file
1842
app/schemas/io.github.wulkanowy.data.db.AppDatabase/28.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -154,4 +154,8 @@ internal class RepositoryModule {
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideConferenceDao(database: AppDatabase) = database.conferenceDao
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import androidx.room.migration.Migration
|
||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
||||
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
||||
import io.github.wulkanowy.data.db.dao.ConferenceDao
|
||||
import io.github.wulkanowy.data.db.dao.ExamDao
|
||||
import io.github.wulkanowy.data.db.dao.GradeDao
|
||||
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
|
||||
@ -32,6 +33,7 @@ import io.github.wulkanowy.data.db.dao.TimetableDao
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||
import io.github.wulkanowy.data.db.entities.Conference
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||
@ -70,6 +72,7 @@ import io.github.wulkanowy.data.db.migrations.Migration24
|
||||
import io.github.wulkanowy.data.db.migrations.Migration25
|
||||
import io.github.wulkanowy.data.db.migrations.Migration26
|
||||
import io.github.wulkanowy.data.db.migrations.Migration27
|
||||
import io.github.wulkanowy.data.db.migrations.Migration28
|
||||
import io.github.wulkanowy.data.db.migrations.Migration3
|
||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||
import io.github.wulkanowy.data.db.migrations.Migration5
|
||||
@ -103,7 +106,8 @@ import javax.inject.Singleton
|
||||
Recipient::class,
|
||||
MobileDevice::class,
|
||||
Teacher::class,
|
||||
School::class
|
||||
School::class,
|
||||
Conference::class,
|
||||
],
|
||||
version = AppDatabase.VERSION_SCHEMA,
|
||||
exportSchema = true
|
||||
@ -112,7 +116,7 @@ import javax.inject.Singleton
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
companion object {
|
||||
const val VERSION_SCHEMA = 27
|
||||
const val VERSION_SCHEMA = 28
|
||||
|
||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
|
||||
return arrayOf(
|
||||
@ -142,6 +146,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration25(),
|
||||
Migration26(),
|
||||
Migration27(),
|
||||
Migration28(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -198,4 +203,6 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
abstract val teacherDao: TeacherDao
|
||||
|
||||
abstract val schoolDao: SchoolDao
|
||||
|
||||
abstract val conferenceDao: ConferenceDao
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package io.github.wulkanowy.data.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Conference
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Dao
|
||||
@Singleton
|
||||
interface ConferenceDao : BaseDao<Conference> {
|
||||
|
||||
@Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId")
|
||||
fun loadAll(diaryId: Int, studentId: Int): Flow<List<Conference>>
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package io.github.wulkanowy.data.db.entities
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Entity(tableName = "Conferences")
|
||||
data class Conference(
|
||||
|
||||
@ColumnInfo(name = "student_id")
|
||||
val studentId: Int,
|
||||
|
||||
@ColumnInfo(name = "diary_id")
|
||||
val diaryId: Int,
|
||||
|
||||
val title: String,
|
||||
|
||||
val subject: String,
|
||||
|
||||
val agenda: String,
|
||||
|
||||
@ColumnInfo(name = "present_on_conference")
|
||||
val presentOnConference: String,
|
||||
|
||||
@ColumnInfo(name = "conference_id")
|
||||
val conferenceId: Int,
|
||||
|
||||
val date: LocalDateTime
|
||||
) : Serializable {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration28 : Migration(27, 28) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("""
|
||||
CREATE TABLE IF NOT EXISTS Conferences (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
student_id INTEGER NOT NULL,
|
||||
diary_id INTEGER NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
agenda TEXT NOT NULL,
|
||||
present_on_conference TEXT NOT NULL,
|
||||
conference_id INTEGER NOT NULL,
|
||||
date INTEGER NOT NULL
|
||||
)
|
||||
""")
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package io.github.wulkanowy.data.repositories.conference
|
||||
|
||||
import io.github.wulkanowy.data.db.dao.ConferenceDao
|
||||
import io.github.wulkanowy.data.db.entities.Conference
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ConferenceLocal @Inject constructor(private val conferenceDb: ConferenceDao) {
|
||||
|
||||
fun getConferences(student: Student, semester: Semester): Flow<List<Conference>> {
|
||||
return conferenceDb.loadAll(semester.diaryId, student.studentId)
|
||||
}
|
||||
|
||||
suspend fun saveConferences(items: List<Conference>) {
|
||||
conferenceDb.insertAll(items)
|
||||
}
|
||||
|
||||
suspend fun deleteConferences(items: List<Conference>) {
|
||||
conferenceDb.deleteAll(items)
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package io.github.wulkanowy.data.repositories.conference
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Conference
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.init
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ConferenceRemote @Inject constructor(private val sdk: Sdk) {
|
||||
|
||||
suspend fun getConferences(student: Student, semester: Semester): List<Conference> {
|
||||
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
.getConferences()
|
||||
.map {
|
||||
it.agenda
|
||||
Conference(
|
||||
studentId = student.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
agenda = it.agenda,
|
||||
conferenceId = it.id,
|
||||
date = it.date,
|
||||
presentOnConference = it.presentOnConference,
|
||||
subject = it.subject,
|
||||
title = it.title
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package io.github.wulkanowy.data.repositories.conference
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ConferenceRepository @Inject constructor(
|
||||
private val local: ConferenceLocal,
|
||||
private val remote: ConferenceRemote
|
||||
) {
|
||||
|
||||
fun getConferences(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getConferences(student, semester) },
|
||||
fetch = { remote.getConferences(student, semester) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteConferences(old uniqueSubtract new)
|
||||
local.saveConferences(new uniqueSubtract old)
|
||||
}
|
||||
)
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package io.github.wulkanowy.ui.modules.conference
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.data.db.entities.Conference
|
||||
import io.github.wulkanowy.databinding.ItemConferenceBinding
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import javax.inject.Inject
|
||||
|
||||
class ConferenceAdapter @Inject constructor() :
|
||||
RecyclerView.Adapter<ConferenceAdapter.ItemViewHolder>() {
|
||||
|
||||
var items = emptyList<Conference>()
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
|
||||
ItemConferenceBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
)
|
||||
|
||||
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
with(holder.binding) {
|
||||
conferenceItemDate.text = item.date.toFormattedString("dd.MM.yyyy HH:mm")
|
||||
conferenceItemName.text = item.presentOnConference
|
||||
conferenceItemTitle.text = item.title
|
||||
conferenceItemSubject.text = item.subject
|
||||
conferenceItemContent.text = item.agenda
|
||||
conferenceItemContent.visibility = if (item.agenda.isBlank()) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
class ItemViewHolder(val binding: ItemConferenceBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
package io.github.wulkanowy.ui.modules.conference
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Conference
|
||||
import io.github.wulkanowy.databinding.FragmentConferenceBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.ui.widgets.DividerItemDecoration
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class ConferenceFragment : BaseFragment<FragmentConferenceBinding>(R.layout.fragment_conference),
|
||||
ConferenceView, MainView.TitledView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: ConferencePresenter
|
||||
|
||||
@Inject
|
||||
lateinit var conferencesAdapter: ConferenceAdapter
|
||||
|
||||
companion object {
|
||||
fun newInstance() = ConferenceFragment()
|
||||
}
|
||||
|
||||
override val isViewEmpty: Boolean
|
||||
get() = conferencesAdapter.items.isEmpty()
|
||||
|
||||
override val titleStringId: Int
|
||||
get() = R.string.conferences_title
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding = FragmentConferenceBinding.bind(view)
|
||||
messageContainer = binding.conferenceRecycler
|
||||
presenter.onAttachView(this)
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
with(binding.conferenceRecycler) {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = conferencesAdapter
|
||||
addItemDecoration(DividerItemDecoration(context))
|
||||
}
|
||||
|
||||
with(binding) {
|
||||
conferenceSwipe.setOnRefreshListener { presenter.onSwipeRefresh() }
|
||||
conferenceErrorRetry.setOnClickListener { presenter.onRetry() }
|
||||
conferenceErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateData(data: List<Conference>) {
|
||||
with(conferencesAdapter) {
|
||||
items = data
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearData() {
|
||||
with(conferencesAdapter) {
|
||||
items = emptyList()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
override fun hideRefresh() {
|
||||
binding.conferenceSwipe.isRefreshing = false
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
binding.conferenceProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
override fun showEmpty(show: Boolean) {
|
||||
binding.conferenceEmpty.visibility = if (show) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
override fun showErrorView(show: Boolean) {
|
||||
binding.conferenceError.visibility = if (show) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
override fun setErrorDetails(message: String) {
|
||||
binding.conferenceErrorMessage.text = message
|
||||
}
|
||||
|
||||
override fun enableSwipe(enable: Boolean) {
|
||||
binding.conferenceSwipe.isEnabled = enable
|
||||
}
|
||||
|
||||
override fun showContent(show: Boolean) {
|
||||
binding.conferenceRecycler.visibility = if (show) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
presenter.onDetachView()
|
||||
super.onDestroyView()
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package io.github.wulkanowy.ui.modules.conference
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.repositories.conference.ConferenceRepository
|
||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
import io.github.wulkanowy.utils.afterLoading
|
||||
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class ConferencePresenter @Inject constructor(
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val conferenceRepository: ConferenceRepository,
|
||||
private val analytics: AnalyticsHelper
|
||||
) : BasePresenter<ConferenceView>(errorHandler, studentRepository) {
|
||||
|
||||
private lateinit var lastError: Throwable
|
||||
|
||||
override fun onAttachView(view: ConferenceView) {
|
||||
super.onAttachView(view)
|
||||
view.initView()
|
||||
Timber.i("Conferences view was initialized")
|
||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onRetry() {
|
||||
view?.run {
|
||||
showErrorView(false)
|
||||
showProgress(true)
|
||||
}
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onDetailsClick() {
|
||||
view?.showErrorDetailsDialog(lastError)
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
view?.run {
|
||||
if (isViewEmpty) {
|
||||
lastError = error
|
||||
setErrorDetails(message)
|
||||
showErrorView(true)
|
||||
showEmpty(false)
|
||||
} else showError(message, error)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadData(forceRefresh: Boolean = false) {
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
conferenceRepository.getConferences(student, semester, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading conference data started")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading conference result: Success")
|
||||
view?.run {
|
||||
updateData(it.data!!.sortedByDescending { conference -> conference.date })
|
||||
showContent(it.data.isNotEmpty())
|
||||
showEmpty(it.data.isEmpty())
|
||||
showErrorView(false)
|
||||
}
|
||||
analytics.logEvent(
|
||||
"load_data",
|
||||
"type" to "conferences",
|
||||
"items" to it.data!!.size
|
||||
)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading conference result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package io.github.wulkanowy.ui.modules.conference
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Conference
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface ConferenceView : BaseView {
|
||||
|
||||
val isViewEmpty: Boolean
|
||||
|
||||
fun initView()
|
||||
|
||||
fun updateData(data: List<Conference>)
|
||||
|
||||
fun clearData()
|
||||
|
||||
fun hideRefresh()
|
||||
|
||||
fun showEmpty(show: Boolean)
|
||||
|
||||
fun showErrorView(show: Boolean)
|
||||
|
||||
fun setErrorDetails(message: String)
|
||||
|
||||
fun showProgress(show: Boolean)
|
||||
|
||||
fun enableSwipe(enable: Boolean)
|
||||
|
||||
fun showContent(show: Boolean)
|
||||
}
|
@ -9,6 +9,7 @@ import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.databinding.FragmentMoreBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.about.AboutFragment
|
||||
import io.github.wulkanowy.ui.modules.conference.ConferenceFragment
|
||||
import io.github.wulkanowy.ui.modules.homework.HomeworkFragment
|
||||
import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
@ -53,6 +54,9 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
|
||||
override val mobileDevicesRes: Pair<String, Drawable?>?
|
||||
get() = context?.run { getString(R.string.mobile_devices_title) to getCompatDrawable(R.drawable.ic_more_mobile_devices) }
|
||||
|
||||
override val conferencesRes: Pair<String, Drawable?>?
|
||||
get() = context?.run { getString(R.string.conferences_title) to getCompatDrawable(R.drawable.ic_more_conferences) }
|
||||
|
||||
override val schoolAndTeachersRes: Pair<String, Drawable?>?
|
||||
get() = context?.run { getString(R.string.schoolandteachers_title) to getCompatDrawable((R.drawable.ic_more_schoolandteachers)) }
|
||||
|
||||
@ -108,6 +112,10 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
|
||||
(activity as? MainActivity)?.pushView(MobileDeviceFragment.newInstance())
|
||||
}
|
||||
|
||||
override fun openConferencesView() {
|
||||
(activity as? MainActivity)?.pushView(ConferenceFragment.newInstance())
|
||||
}
|
||||
|
||||
override fun openSchoolAndTeachersView() {
|
||||
(activity as? MainActivity)?.pushView(SchoolAndTeachersFragment.newInstance())
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ class MorePresenter @Inject constructor(
|
||||
noteRes?.first -> openNoteView()
|
||||
luckyNumberRes?.first -> openLuckyNumberView()
|
||||
mobileDevicesRes?.first -> openMobileDevicesView()
|
||||
conferencesRes?.first -> openConferencesView()
|
||||
schoolAndTeachersRes?.first -> openSchoolAndTeachersView()
|
||||
settingsRes?.first -> openSettingsView()
|
||||
aboutRes?.first -> openAboutView()
|
||||
@ -48,6 +49,7 @@ class MorePresenter @Inject constructor(
|
||||
noteRes,
|
||||
luckyNumberRes,
|
||||
mobileDevicesRes,
|
||||
conferencesRes,
|
||||
schoolAndTeachersRes,
|
||||
settingsRes,
|
||||
aboutRes
|
||||
|
@ -15,6 +15,8 @@ interface MoreView : BaseView {
|
||||
|
||||
val mobileDevicesRes: Pair<String, Drawable?>?
|
||||
|
||||
val conferencesRes: Pair<String, Drawable?>?
|
||||
|
||||
val schoolAndTeachersRes: Pair<String, Drawable?>?
|
||||
|
||||
val settingsRes: Pair<String, Drawable?>?
|
||||
@ -41,5 +43,7 @@ interface MoreView : BaseView {
|
||||
|
||||
fun openMobileDevicesView()
|
||||
|
||||
fun openConferencesView()
|
||||
|
||||
fun openSchoolAndTeachersView()
|
||||
}
|
||||
|
9
app/src/main/res/drawable/ic_more_conferences.xml
Normal file
9
app/src/main/res/drawable/ic_more_conferences.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M9,13.75c-2.34,0 -7,1.17 -7,3.5L2,19h14v-1.75c0,-2.33 -4.66,-3.5 -7,-3.5zM4.34,17c0.84,-0.58 2.87,-1.25 4.66,-1.25s3.82,0.67 4.66,1.25L4.34,17zM9,12c1.93,0 3.5,-1.57 3.5,-3.5S10.93,5 9,5 5.5,6.57 5.5,8.5 7.07,12 9,12zM9,7c0.83,0 1.5,0.67 1.5,1.5S9.83,10 9,10s-1.5,-0.67 -1.5,-1.5S8.17,7 9,7zM16.04,13.81c1.16,0.84 1.96,1.96 1.96,3.44L18,19h4v-1.75c0,-2.02 -3.5,-3.17 -5.96,-3.44zM15,12c1.93,0 3.5,-1.57 3.5,-3.5S16.93,5 15,5c-0.54,0 -1.04,0.13 -1.5,0.35 0.63,0.89 1,1.98 1,3.15s-0.37,2.26 -1,3.15c0.46,0.22 0.96,0.35 1.5,0.35z" />
|
||||
</vector>
|
104
app/src/main/res/layout/fragment_conference.xml
Normal file
104
app/src/main/res/layout/fragment_conference.xml
Normal file
@ -0,0 +1,104 @@
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.modules.conference.ConferenceFragment">
|
||||
|
||||
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
|
||||
android:id="@+id/conferenceProgress"
|
||||
style="@style/Widget.MaterialProgressBar.ProgressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true" />
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/conferenceSwipe"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/conferenceRecycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/item_conference" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conferenceEmpty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="10dp"
|
||||
android:visibility="gone"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
app:srcCompat="@drawable/ic_more_conferences"
|
||||
app:tint="?colorOnBackground"
|
||||
tools:ignore="contentDescription" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/conference_no_items"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conferenceError"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="invisible"
|
||||
tools:ignore="UseCompoundDrawables"
|
||||
tools:visibility="invisible">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
app:srcCompat="@drawable/ic_error"
|
||||
app:tint="?colorOnBackground"
|
||||
tools:ignore="contentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conferenceErrorMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="@string/error_unknown"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/conferenceErrorDetails"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:text="@string/all_details" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/conferenceErrorRetry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/all_retry" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
87
app/src/main/res/layout/item_conference.xml
Normal file
87
app/src/main/res/layout/item_conference.xml
Normal file
@ -0,0 +1,87 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/conference_item_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
tools:context=".ui.modules.conference.ConferenceAdapter">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conferenceItemDate"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="15sp"
|
||||
app:layout_constraintRight_toLeftOf="@+id/conferenceItemName"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@tools:sample/date/ddmmyy" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conferenceItemName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="end"
|
||||
android:singleLine="true"
|
||||
android:textSize="13sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/conferenceItemDate"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@tools:sample/full_names" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conferenceItemTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="@id/conferenceItemName"
|
||||
app:layout_constraintStart_toStartOf="@id/conferenceItemDate"
|
||||
app:layout_constraintTop_toBottomOf="@id/conferenceItemDate"
|
||||
app:layout_goneMarginEnd="0dp"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conferenceItemSubject"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/conferenceItemContent"
|
||||
app:layout_constraintEnd_toEndOf="@id/conferenceItemTitle"
|
||||
app:layout_constraintStart_toStartOf="@id/conferenceItemTitle"
|
||||
app:layout_constraintTop_toBottomOf="@id/conferenceItemTitle"
|
||||
app:layout_goneMarginBottom="15dp"
|
||||
app:layout_goneMarginEnd="0dp"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conferenceItemContent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:ellipsize="end"
|
||||
android:lineSpacingMultiplier="1.2"
|
||||
android:maxLines="2"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/conferenceItemName"
|
||||
app:layout_constraintStart_toStartOf="@id/conferenceItemDate"
|
||||
app:layout_constraintTop_toBottomOf="@id/conferenceItemSubject"
|
||||
tools:text="@tools:sample/lorem/random"
|
||||
tools:visibility="visible" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -325,6 +325,11 @@
|
||||
<string name="teacher_no_subject">No subject</string>
|
||||
|
||||
|
||||
<!--Conference-->
|
||||
<string name="conferences_title">Conferences</string>
|
||||
<string name="conference_no_items">No info about conferences</string>
|
||||
|
||||
|
||||
<!--Account-->
|
||||
<string name="account_add_new">Add account</string>
|
||||
<string name="account_logout">Logout</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user