CourseDetailsScreen improvements
This commit is contained in:
@@ -4,11 +4,9 @@ import android.content.res.Configuration
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material.Card
|
import androidx.compose.material.Card
|
||||||
@@ -22,6 +20,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@@ -29,13 +28,14 @@ import androidx.compose.ui.res.dimensionResource
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
|
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
|
||||||
import de.sebse.fuplanner2.MenuItem
|
import de.sebse.fuplanner2.MenuItem
|
||||||
import de.sebse.fuplanner2.R
|
import de.sebse.fuplanner2.R
|
||||||
import de.sebse.fuplanner2.Tools
|
import de.sebse.fuplanner2.Tools
|
||||||
import de.sebse.fuplanner2.database.Course
|
import de.sebse.fuplanner2.database.Course
|
||||||
import de.sebse.fuplanner2.ui.theme.AppTheme
|
import de.sebse.fuplanner2.ui.theme.*
|
||||||
import de.sebse.fuplanner2.ui.tools.previews.CoursePreviewProvider
|
import de.sebse.fuplanner2.ui.tools.previews.CoursePreviewProvider
|
||||||
import de.sebse.fuplanner2.ui.tools.viewmodels.CoursesViewModel
|
import de.sebse.fuplanner2.ui.tools.viewmodels.CoursesViewModel
|
||||||
import de.sebse.fuplanner2.utils.color.getColor
|
import de.sebse.fuplanner2.utils.color.getColor
|
||||||
@@ -67,10 +67,23 @@ fun CoursesScreen(tools: Tools) {
|
|||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun GroupedCourseList(groups: Map<String, List<Course>>, onclick: (course: Course) -> Unit) {
|
fun GroupedCourseList(groups: Map<String, List<Course>>, onclick: (course: Course) -> Unit) {
|
||||||
|
val headerBg =
|
||||||
|
if (MaterialTheme.colors.isLight) md_theme_light_secondaryContainer
|
||||||
|
else md_theme_dark_secondaryContainer
|
||||||
|
val headerColor =
|
||||||
|
if (MaterialTheme.colors.isLight) md_theme_light_onSecondaryContainer
|
||||||
|
else md_theme_dark_onSecondaryContainer
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
for ((key, value) in groups.entries) {
|
for ((key, value) in groups.entries) {
|
||||||
stickyHeader(key = key) {
|
stickyHeader(key = key) {
|
||||||
Text(text = key)
|
Text(
|
||||||
|
text = key,
|
||||||
|
color = headerColor,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(headerBg)
|
||||||
|
.padding()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
items(value) { course ->
|
items(value) { course ->
|
||||||
CourseItem(course) { onclick(course) }
|
CourseItem(course) { onclick(course) }
|
||||||
@@ -109,6 +122,7 @@ fun CourseItem(course: Course, onclick: () -> Unit) {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CourseItem(id: Long?, title: String, lecturers: String, type: String, onclick: () -> Unit) {
|
fun CourseItem(id: Long?, title: String, lecturers: String, type: String, onclick: () -> Unit) {
|
||||||
|
val color = Color(getColor(LocalContext.current, id ?: 0, highContrast = true))
|
||||||
Card(
|
Card(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -116,6 +130,13 @@ fun CourseItem(id: Long?, title: String, lecturers: String, type: String, onclic
|
|||||||
.padding(dimensionResource(R.dimen.card_view_margin)),
|
.padding(dimensionResource(R.dimen.card_view_margin)),
|
||||||
elevation = dimensionResource(R.dimen.card_view_elevation)
|
elevation = dimensionResource(R.dimen.card_view_elevation)
|
||||||
) {
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.height(1.5.dp)
|
||||||
|
.background(Brush.horizontalGradient(
|
||||||
|
colors = listOf(color, MaterialTheme.colors.surface)
|
||||||
|
))
|
||||||
|
) {}
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -123,7 +144,7 @@ fun CourseItem(id: Long?, title: String, lecturers: String, type: String, onclic
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
color = Color(getColor(LocalContext.current, id ?: 0, highContrast = true)),
|
color = MaterialTheme.colors.primaryVariant,
|
||||||
style = MaterialTheme.typography.h6
|
style = MaterialTheme.typography.h6
|
||||||
)
|
)
|
||||||
CourseItemHint(
|
CourseItemHint(
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package de.sebse.fuplanner2.ui.details
|
package de.sebse.fuplanner2.ui.details
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
@@ -15,7 +16,6 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
|||||||
import de.sebse.fuplanner2.R
|
import de.sebse.fuplanner2.R
|
||||||
import de.sebse.fuplanner2.Tools
|
import de.sebse.fuplanner2.Tools
|
||||||
import de.sebse.fuplanner2.database.Announcement
|
import de.sebse.fuplanner2.database.Announcement
|
||||||
import de.sebse.fuplanner2.database.AppDatabase
|
|
||||||
import de.sebse.fuplanner2.database.Course
|
import de.sebse.fuplanner2.database.Course
|
||||||
import de.sebse.fuplanner2.ui.details.components.AnnouncementItem
|
import de.sebse.fuplanner2.ui.details.components.AnnouncementItem
|
||||||
import de.sebse.fuplanner2.ui.details.components.LecturerItem
|
import de.sebse.fuplanner2.ui.details.components.LecturerItem
|
||||||
@@ -25,40 +25,46 @@ import de.sebse.fuplanner2.ui.tools.previews.AnnouncementPreviewProvider
|
|||||||
import de.sebse.fuplanner2.ui.tools.previews.CoursePreviewProvider
|
import de.sebse.fuplanner2.ui.tools.previews.CoursePreviewProvider
|
||||||
import de.sebse.fuplanner2.ui.tools.viewmodels.DetailsViewModel
|
import de.sebse.fuplanner2.ui.tools.viewmodels.DetailsViewModel
|
||||||
import de.sebse.fuplanner2.ui.tools.viewmodels.DetailsViewModelFactory
|
import de.sebse.fuplanner2.ui.tools.viewmodels.DetailsViewModelFactory
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CourseDetailsScreen(tools: Tools, id: Long) {
|
fun CourseDetailsScreen(tools: Tools, id: Long) {
|
||||||
val coursesViewModel: DetailsViewModel = viewModel(factory = DetailsViewModelFactory(id))
|
val coursesViewModel: DetailsViewModel = viewModel(factory = DetailsViewModelFactory(id))
|
||||||
val state = coursesViewModel.course.observeAsState()
|
val course by coursesViewModel.course.observeAsState()
|
||||||
val announce = AppDatabase.getInstance().announcementDao().getAll3(id).observeAsState()
|
val announcements by coursesViewModel.announcements.observeAsState()
|
||||||
val title = state.value?.title
|
val title = course?.title
|
||||||
|
val context = LocalContext.current
|
||||||
LaunchedEffect(title) {
|
LaunchedEffect(title) {
|
||||||
title?.let { tools.setTitle(it) }
|
title?.let { tools.setTitle(it) }
|
||||||
}
|
}
|
||||||
CourseDetailsScreen(state.value, announce.value, id)
|
LaunchedEffect(true) {
|
||||||
|
coursesViewModel.refresh(context)
|
||||||
|
}
|
||||||
|
CourseDetailsScreen(course, announcements, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CourseDetailsScreen(course: Course?, announcement: List<Announcement>?, id: Long) {
|
fun CourseDetailsScreen(course: Course?, announcement: List<Announcement>?, id: Long) {
|
||||||
Column {
|
val announcements = announcement?.subList(0, min(announcement.size, 3)) ?: listOf()
|
||||||
|
LazyColumn {
|
||||||
|
item {
|
||||||
QuickLinks(courseId = id)
|
QuickLinks(courseId = id)
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.lecturers),
|
text = stringResource(R.string.lecturers),
|
||||||
style = MaterialTheme.typography.h5
|
style = MaterialTheme.typography.h5
|
||||||
)
|
)
|
||||||
LazyColumn {
|
}
|
||||||
items(course?.lecturers ?: listOf()) {
|
items(course?.lecturers ?: listOf()) {
|
||||||
LecturerItem(lecturer = it, courseTitle = course?.title ?: "")
|
LecturerItem(lecturer = it, courseTitle = course?.title ?: "")
|
||||||
}
|
}
|
||||||
}
|
item {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.announcements),
|
text = stringResource(R.string.announcements),
|
||||||
style = MaterialTheme.typography.h5
|
style = MaterialTheme.typography.h5
|
||||||
)
|
)
|
||||||
LazyColumn {
|
|
||||||
items(announcement ?: listOf()) {
|
|
||||||
AnnouncementItem(it)
|
|
||||||
}
|
}
|
||||||
|
items(items = announcements) {
|
||||||
|
AnnouncementItem(it)
|
||||||
}
|
}
|
||||||
// TODO: Add latest announcements, current assignments, upcoming events
|
// TODO: Add latest announcements, current assignments, upcoming events
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,9 @@ package de.sebse.fuplanner2.ui.details.components
|
|||||||
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.GridCells
|
import androidx.compose.foundation.lazy.GridCells
|
||||||
import androidx.compose.foundation.lazy.LazyVerticalGrid
|
|
||||||
import androidx.compose.material.Card
|
import androidx.compose.material.Card
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
@@ -18,6 +16,7 @@ import androidx.compose.ui.text.style.TextAlign
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import de.sebse.fuplanner2.R
|
import de.sebse.fuplanner2.R
|
||||||
|
import de.sebse.fuplanner2.ui.shared.VerticalGrid
|
||||||
import de.sebse.fuplanner2.ui.theme.AppTheme
|
import de.sebse.fuplanner2.ui.theme.AppTheme
|
||||||
|
|
||||||
|
|
||||||
@@ -33,14 +32,10 @@ fun QuickLinks(courseId: Long) {
|
|||||||
QuickLinkProps(R.string.announcements, "courses/$courseId/announcements"),
|
QuickLinkProps(R.string.announcements, "courses/$courseId/announcements"),
|
||||||
QuickLinkProps(R.string.events, "courses/$courseId/events")
|
QuickLinkProps(R.string.events, "courses/$courseId/events")
|
||||||
)
|
)
|
||||||
LazyVerticalGrid(
|
VerticalGrid(
|
||||||
cells = GridCells.Adaptive(150.dp),
|
cells = GridCells.Adaptive(150.dp)
|
||||||
contentPadding = PaddingValues(
|
|
||||||
horizontal = 12.dp,
|
|
||||||
vertical = 16.dp
|
|
||||||
),
|
|
||||||
) {
|
) {
|
||||||
items(list.size) { index ->
|
list.forEach {
|
||||||
Card(
|
Card(
|
||||||
backgroundColor = MaterialTheme.colors.secondary,
|
backgroundColor = MaterialTheme.colors.secondary,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -49,7 +44,7 @@ fun QuickLinks(courseId: Long) {
|
|||||||
elevation = dimensionResource(R.dimen.card_view_elevation),
|
elevation = dimensionResource(R.dimen.card_view_elevation),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(list[index].name),
|
text = stringResource(it.name),
|
||||||
color = MaterialTheme.colors.onSecondary,
|
color = MaterialTheme.colors.onSecondary,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
style = MaterialTheme.typography.h6,
|
style = MaterialTheme.typography.h6,
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
package de.sebse.fuplanner2.ui.details_announcements
|
package de.sebse.fuplanner2.ui.details_announcements
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.paging.LivePagedListBuilder
|
import androidx.paging.LivePagedListBuilder
|
||||||
import androidx.paging.PagedList
|
import androidx.paging.PagedList
|
||||||
import androidx.work.workDataOf
|
|
||||||
import de.sebse.fuplanner2.auth.AppAccounts
|
|
||||||
import de.sebse.fuplanner2.database.Announcement
|
import de.sebse.fuplanner2.database.Announcement
|
||||||
import de.sebse.fuplanner2.database.AppDatabase
|
import de.sebse.fuplanner2.database.AppDatabase
|
||||||
import de.sebse.fuplanner2.utils.enqueueOneTimeWork
|
|
||||||
import de.sebse.fuplanner2.worker.AbstractAccountWorker
|
|
||||||
import de.sebse.fuplanner2.worker.AnnouncementWorker
|
|
||||||
|
|
||||||
class AnnouncementsViewModelFactory(private val courseId: Long): ViewModelProvider.NewInstanceFactory() {
|
class AnnouncementsViewModelFactory(private val courseId: Long): ViewModelProvider.NewInstanceFactory() {
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T = AnnouncementsViewModel(courseId) as T
|
override fun <T : ViewModel> create(modelClass: Class<T>): T = AnnouncementsViewModel(courseId) as T
|
||||||
@@ -21,14 +15,5 @@ class AnnouncementsViewModelFactory(private val courseId: Long): ViewModelProvid
|
|||||||
class AnnouncementsViewModel(private val courseId: Long) : ViewModel() {
|
class AnnouncementsViewModel(private val courseId: Long) : ViewModel() {
|
||||||
private val factory = AppDatabase.getInstance().announcementDao().getAll1(courseId)
|
private val factory = AppDatabase.getInstance().announcementDao().getAll1(courseId)
|
||||||
|
|
||||||
fun refresh(ctx: Context) {
|
|
||||||
enqueueOneTimeWork<AnnouncementWorker>(ctx) {
|
|
||||||
it.setInputData(workDataOf(
|
|
||||||
AbstractAccountWorker.KEY_ACCOUNT_NAME to AppAccounts.getInstance().selectedAccount?.name,
|
|
||||||
AbstractAccountWorker.KEY_COURSE_ID to courseId
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val events: LiveData<PagedList<Announcement>> = LivePagedListBuilder(factory, 50).build()
|
val events: LiveData<PagedList<Announcement>> = LivePagedListBuilder(factory, 50).build()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package de.sebse.fuplanner2.ui.shared
|
||||||
|
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.lazy.GridCells
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.layout.Layout
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
fun VerticalGrid(
|
||||||
|
cells: GridCells,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
content: @Composable () -> Unit
|
||||||
|
) {
|
||||||
|
val columns: Int = when (cells) {
|
||||||
|
is GridCells.Fixed -> {
|
||||||
|
cells.count
|
||||||
|
}
|
||||||
|
is GridCells.Adaptive -> {
|
||||||
|
val width = LocalContext.current.resources.displayMetrics.widthPixels
|
||||||
|
val columnWidthPx = with(LocalDensity.current) { cells.minSize.toPx() }
|
||||||
|
((width / columnWidthPx).toInt()).coerceAtLeast(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Layout(
|
||||||
|
content = content,
|
||||||
|
modifier = modifier
|
||||||
|
) { measurables, constraints ->
|
||||||
|
val itemWidth = constraints.maxWidth / columns
|
||||||
|
// Keep given height constraints, but set an exact width
|
||||||
|
val itemConstraints = constraints.copy(
|
||||||
|
minWidth = itemWidth,
|
||||||
|
maxWidth = itemWidth
|
||||||
|
)
|
||||||
|
// Measure each item with these constraints
|
||||||
|
val placeables = measurables.map { measurable ->
|
||||||
|
measurable.measure(itemConstraints)
|
||||||
|
}
|
||||||
|
// Track each columns height so we can calculate the overall height
|
||||||
|
val columnHeights = Array(columns) { 0 }
|
||||||
|
placeables.forEachIndexed { index, placeable ->
|
||||||
|
val column = index % columns
|
||||||
|
columnHeights[column] += placeable.height
|
||||||
|
}
|
||||||
|
val height = (columnHeights.maxOrNull() ?: constraints.minHeight)
|
||||||
|
.coerceAtMost(constraints.maxHeight)
|
||||||
|
layout(constraints.maxWidth, height) {
|
||||||
|
// Track the Y co-ord per column we have placed up to
|
||||||
|
val columnY = Array(columns) { 0 }
|
||||||
|
placeables.forEachIndexed { index, placeable ->
|
||||||
|
val column = index % columns
|
||||||
|
placeable.place(
|
||||||
|
x = column * itemWidth,
|
||||||
|
y = columnY[column]
|
||||||
|
)
|
||||||
|
columnY[column] += placeable.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,40 @@
|
|||||||
package de.sebse.fuplanner2.ui.tools.viewmodels
|
package de.sebse.fuplanner2.ui.tools.viewmodels
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.paging.LivePagedListBuilder
|
||||||
|
import androidx.paging.PagedList
|
||||||
|
import androidx.work.workDataOf
|
||||||
|
import de.sebse.fuplanner2.auth.AppAccounts
|
||||||
|
import de.sebse.fuplanner2.database.Announcement
|
||||||
import de.sebse.fuplanner2.database.AppDatabase
|
import de.sebse.fuplanner2.database.AppDatabase
|
||||||
import de.sebse.fuplanner2.database.Course
|
import de.sebse.fuplanner2.database.Course
|
||||||
|
import de.sebse.fuplanner2.utils.enqueueOneTimeWork
|
||||||
|
import de.sebse.fuplanner2.worker.AbstractAccountWorker
|
||||||
|
import de.sebse.fuplanner2.worker.CourseWorker
|
||||||
|
|
||||||
|
|
||||||
class DetailsViewModelFactory(private val courseId: Long): ViewModelProvider.NewInstanceFactory() {
|
class DetailsViewModelFactory(private val courseId: Long): ViewModelProvider.NewInstanceFactory() {
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T = DetailsViewModel(courseId) as T
|
override fun <T : ViewModel> create(modelClass: Class<T>): T = DetailsViewModel(courseId) as T
|
||||||
}
|
}
|
||||||
|
|
||||||
class DetailsViewModel(courseId: Long) : ViewModel() {
|
class DetailsViewModel(private val courseId: Long) : ViewModel() {
|
||||||
val course: LiveData<Course> = AppDatabase.getInstance().courseDao().getCourseById(courseId)
|
fun refresh(ctx: Context) {
|
||||||
|
enqueueOneTimeWork<CourseWorker>(ctx) {
|
||||||
|
it.setInputData(workDataOf(
|
||||||
|
AbstractAccountWorker.KEY_ACCOUNT_NAME to AppAccounts.getInstance().selectedAccount?.name,
|
||||||
|
AbstractAccountWorker.KEY_COURSE_ID to courseId,
|
||||||
|
AbstractAccountWorker.KEY_FORCE_FETCH to true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val course: LiveData<Course> = AppDatabase.getInstance().courseDao().getCourseById(courseId)
|
||||||
|
val announcements: LiveData<PagedList<Announcement>> = LivePagedListBuilder(
|
||||||
|
AppDatabase.getInstance().announcementDao().getAll1(courseId),
|
||||||
|
50
|
||||||
|
).build()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ abstract class AbstractAccountWorker(context: Context, params: WorkerParameters)
|
|||||||
companion object {
|
companion object {
|
||||||
const val KEY_ACCOUNT_NAME = AccountManager.KEY_ACCOUNT_NAME
|
const val KEY_ACCOUNT_NAME = AccountManager.KEY_ACCOUNT_NAME
|
||||||
const val KEY_COURSE_ID = "KEY_COURSE_ID"
|
const val KEY_COURSE_ID = "KEY_COURSE_ID"
|
||||||
const val OUT_ERROR_CODE = "OUT_CODE"
|
const val OUT_ERROR_CODE = "OUT_ERROR_CODE"
|
||||||
|
const val KEY_FORCE_FETCH = "KEY_FORCE_FETCH"
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class ErrorCodes {
|
enum class ErrorCodes {
|
||||||
|
|||||||
@@ -33,10 +33,17 @@ class CourseWorker(context: Context, params: WorkerParameters) : AbstractAccount
|
|||||||
override suspend fun doActualWork(database: AppDatabase, account: Account, user: User): Data {
|
override suspend fun doActualWork(database: AppDatabase, account: Account, user: User): Data {
|
||||||
val courseId = inputData.getLong(KEY_COURSE_ID, -1)
|
val courseId = inputData.getLong(KEY_COURSE_ID, -1)
|
||||||
.let { if (it == -1L) null else it }
|
.let { if (it == -1L) null else it }
|
||||||
|
val isForceFetch = inputData.getBoolean(KEY_FORCE_FETCH, false)
|
||||||
|
|
||||||
val updates = work(applicationContext, database, user, courseId)
|
val updates = work(applicationContext, database, user, courseId)
|
||||||
val latestSemester = database.courseDao().getLatestSemesterName()
|
val latestSemester = database.courseDao().getLatestSemesterName()
|
||||||
updates.added.forEach {
|
|
||||||
if (it.isSummerSemester == latestSemester.semester && it.year == latestSemester.year) {
|
val detailsToFetch =
|
||||||
|
if (isForceFetch) updates.added + updates.updated
|
||||||
|
else updates.added
|
||||||
|
detailsToFetch.forEach {
|
||||||
|
val isLatestSemester = it.isSummerSemester == latestSemester.semester && it.year == latestSemester.year
|
||||||
|
if (isForceFetch || isLatestSemester) {
|
||||||
EventWorker.work(applicationContext, database, user, it)
|
EventWorker.work(applicationContext, database, user, it)
|
||||||
AnnouncementWorker.work(applicationContext, database, user, it)
|
AnnouncementWorker.work(applicationContext, database, user, it)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user