Commit 5137c6cf by Aleksandr

pass messages between modules while rendering and sending pages to server

parent 716c048f
......@@ -2,8 +2,12 @@ package com.isidroid.c23.domain.use_case
import android.content.Context
import com.isidroid.c23.data.mapper.createListItem
import com.isidroid.c23.domain.dto.PrintJobListItem
import com.isidroid.c23.ext.getPrintJobStatus
import com.isidroid.c23.ext.getPrintJobStatusColor
import com.isidroid.core.FlowResult
import com.isidroid.job.repository.JobRepository
import com.isidroid.job_sender.domain.dto.JobSenderResult
import com.isidroid.spot.repository.SpotRepository
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.flow
......@@ -20,9 +24,11 @@ class PrintJobsUseCase @Inject constructor(
emit(FlowResult.Loading)
val jobList = jobRepository.readLocalList()
val spots = jobList
.asSequence()
.sortedByDescending { it.createdAt }
.map { it.spotId }
.distinct()
.let { spotRepository.findLocalRichSpots(it) }
.let { spotRepository.findLocalRichSpots(it.toList()) }
?.associateBy({ it.spot.id }, { it })
val result = jobList.map { job -> job.createListItem(context = context, richSpot = spots?.get(job.spotId)) }
......@@ -34,4 +40,19 @@ class PrintJobsUseCase @Inject constructor(
val result = spotRepository.findRichSpot(spotCode)?.spot
emit(FlowResult.Success(result))
}
fun updateStatuses(jobs: Collection<PrintJobListItem>?, info: JobSenderResult.Statuses): List<PrintJobListItem>? {
val list = jobs?.toMutableList() ?: return null
for (index in list.indices) {
val job = list[index]
if (job.id in info.jobIds)
list[index] = job.copy(
statusName = context.getString(getPrintJobStatus(info.status)),
statusColor = getPrintJobStatusColor(info.status)
)
}
return list
}
}
\ No newline at end of file
......@@ -21,6 +21,10 @@ fun getPrintJobStatus(@JobStatus status: Int) = when (status) {
JobStatus.RENDER_UPLOAD -> R.string.print_job_status_render_upload
JobStatus.READY_TO_PRINT -> R.string.print_job_status_ready_to_print
JobStatus.UPLOAD_ERROR -> R.string.print_job_status_upload_error
JobStatus.RENDERED -> R.string.print_job_status_rendered
JobStatus.SENDING -> R.string.print_job_status_sending
else -> R.string.empty
}
......@@ -39,5 +43,7 @@ fun getPrintJobStatusColor(@JobStatus status: Int) = when (status) {
JobStatus.RENDER_UPLOAD -> ColorBlue
JobStatus.READY_TO_PRINT -> ColorBlue
JobStatus.UPLOAD_ERROR -> ColorRed
JobStatus.RENDERED -> ColorOrange
JobStatus.SENDING -> ColorOrange
else -> Color.Transparent
}
\ No newline at end of file
package com.isidroid.sync_service.ext
package com.isidroid.c23.ext
import androidx.work.ListenableWorker
import androidx.work.WorkInfo
......
......@@ -4,6 +4,7 @@ import com.isidroid.c23.domain.dto.PrintJobListItem
import com.isidroid.core.vm.ViewEvent
import com.isidroid.core.vm.ViewSideEffect
import com.isidroid.core.vm.ViewState
import com.isidroid.job_sender.domain.dto.JobSenderResult
class PrintJobsContract {
sealed interface Event : ViewEvent {
......@@ -22,6 +23,6 @@ class PrintJobsContract {
data class State(
val loading: Boolean = false,
val jobs: List<PrintJobListItem>? = null
val jobs: List<PrintJobListItem>? = null,
) : ViewState
}
\ No newline at end of file
......@@ -5,20 +5,25 @@ import com.isidroid.c23.domain.use_case.PrintJobsUseCase
import com.isidroid.c23.ext.isDebug
import com.isidroid.core.FlowResult
import com.isidroid.core.vm.BaseViewModel
import com.isidroid.job_sender.SendJobEventCollectorFlow
import com.isidroid.job_sender.domain.dto.JobSenderResult
import com.isidroid.spot.model.Spot
import com.isidroid.utils.catchTimber
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class PrintJobsViewModel @Inject constructor(
private val useCase: PrintJobsUseCase
private val useCase: PrintJobsUseCase,
private val sendJobEventCollectorFlow: SendJobEventCollectorFlow
) : BaseViewModel<PrintJobsContract.Event, PrintJobsContract.State, PrintJobsContract.Effect>() {
init {
viewModelScope.launch { load() }
viewModelScope.launch { listenSendJobEvents() }
}
override val isDebug: Boolean = isDebug()
......@@ -58,6 +63,17 @@ class PrintJobsViewModel @Inject constructor(
}
}
private suspend fun listenSendJobEvents() {
sendJobEventCollectorFlow.eventsFlow
.filterIsInstance<JobSenderResult.Statuses>()
.collect { st -> updateStatuses(st) }
}
private fun updateStatuses(statuses: JobSenderResult.Statuses) {
val listItems = useCase.updateStatuses(jobs = viewState.value.jobs, info = statuses) ?: return
setState { copy(jobs = listItems) }
}
// handle callbacks
private fun openSpotOnMap(spot: Spot?) {
spot ?: return
......
......@@ -40,4 +40,6 @@
<string name="empty" />
<string name="print_job_details">Job details</string>
<string name="app_navigation_explanation">To navigate to this location, please use an external navigation app. Tap the button below to open your preferred navigation app and plan your route.</string>
<string name="print_job_status_rendered">Render complete</string>
<string name="print_job_status_sending">Sending</string>
</resources>
\ No newline at end of file
......@@ -19,6 +19,9 @@ annotation class JobStatus {
const val RENDER_UPLOAD = 9
const val READY_TO_PRINT = 10
const val UPLOAD_ERROR = 11
const val RENDERED = 12
const val SENDING = 13
const val RENDER_STARTED = 14
}
}
......@@ -38,5 +41,8 @@ val Int.jobStatusName
JobStatus.RENDER_UPLOAD -> "RENDER_UPLOAD"
JobStatus.READY_TO_PRINT -> "READY_TO_PRINT"
JobStatus.UPLOAD_ERROR -> "UPLOAD_ERROR"
JobStatus.RENDERED -> "RENDERED"
JobStatus.SENDING -> "SENDING"
JobStatus.RENDER_STARTED -> "RENDER_STARTED"
else -> "Unknown"
}
\ No newline at end of file
package com.isidroid.job_sender
import com.isidroid.job.constant.JobStatus
import com.isidroid.job.model.PrintJob
import com.isidroid.job_sender.domain.dto.JobSenderResult
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
......@@ -20,9 +19,6 @@ class SendJobEventCollectorFlow @Inject constructor() {
suspend fun renderProgress(index: Int, total: Int) = emit(JobSenderResult.RenderProgress(index, total))
suspend fun updateProgress(index: Int, total: Int) = emit(JobSenderResult.UploadProgress(index, total))
suspend fun jobError(jobId: String, t: Throwable) = emit(JobSenderResult.Error(jobId, t))
suspend fun updateStatus(@JobStatus status: Int, vararg job: PrintJob?) {
val jobList = job.toList().filterNotNull()
if (jobList.isNotEmpty())
emit(JobSenderResult.Statuses(status = status, jobs = jobList))
}
suspend fun updateStatus(@JobStatus status: Int, vararg jobIds: String?) = emit(JobSenderResult.Statuses(status = status, jobIds = jobIds.toSet()))
}
\ No newline at end of file
......@@ -7,5 +7,5 @@ sealed interface JobSenderResult {
data class RenderProgress(val position: Int, val total: Int) : JobSenderResult
data class UploadProgress(val position: Int, val total: Int) : JobSenderResult
data class Error(val jobId: String, val t: Throwable) : JobSenderResult
data class Statuses(@JobStatus val status: Int, val jobs: Collection<PrintJob>): JobSenderResult
data class Statuses(@JobStatus val status: Int, val jobIds: Collection<String?>): JobSenderResult
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package com.isidroid.job_sender.ext
import android.content.Context
import android.graphics.BitmapFactory
import com.isidroid.job.constant.JobStatus
import com.isidroid.job.constant.SendJobStatus
import com.isidroid.job.model.PrintJob
import com.isidroid.job_sender.RenderBitmapProfileException
......
......@@ -3,7 +3,6 @@ package com.isidroid.job_sender.repository
import android.content.Context
import com.isidroid.job.constant.JobStatus
import com.isidroid.job.constant.SendJobStatus
import com.isidroid.job.constant.jobStatusName
import com.isidroid.job.model.PrintJob
import com.isidroid.job.repository.JobRepository
import com.isidroid.job_sender.SendJobEventCollectorFlow
......@@ -27,7 +26,6 @@ internal class JobSendRepositoryImpl(
private val eventCollector: SendJobEventCollectorFlow,
) : JobSendRepository {
override suspend fun completeUpload(jobId: String, token: String): PrintJob? {
val printJob = printJobRepository.readLocalList(ids = listOf(jobId)).firstOrNull()
val uploadResult = sendJobNetworkSource.complete(jobId = jobId, token = token)
......@@ -41,6 +39,8 @@ internal class JobSendRepositoryImpl(
// let's check whether there is not rendered print jobs
override suspend fun checkNotRenderedPrintJobs(items: Collection<PrintJob>): Collection<PrintJobSender>? {
if (items.isNotEmpty()) {
eventCollector.updateStatus(JobStatus.RENDER_STARTED, *items.map { it.id }.toTypedArray())
val renderItems = createRenderItems(context, spotRepository, renderRepository, eventCollector, items)
val jobIds = renderItems.map { it.printJobId }.distinct()
......@@ -61,24 +61,27 @@ internal class JobSendRepositoryImpl(
for ((index, item) in items.withIndex()) {
eventCollector.updateProgress(index, total)
try {
sendJobLocalSource.updateStatus(item, SendJobStatus.SENDING)
updateStatus(item, SendJobStatus.SENDING)
val uploadResult = sendJobNetworkSource.uploadPage(
jobId = item.printJobId,
token = item.accessToken,
filePath = item.sourceFile
)
val uploadResult = sendJobNetworkSource.uploadPage(jobId = item.printJobId, token = item.accessToken, filePath = item.sourceFile)
if (!uploadResult)
throw UploadPageException()
sendJobResults.decreaseCounter(item.printJobId)
sendJobLocalSource.updateStatus(item, SendJobStatus.COMPLETE)
updateStatus(item, SendJobStatus.COMPLETE)
} catch (t: Throwable) {
sendJobLocalSource.updateStatus(item, SendJobStatus.RENDERED)
updateStatus(item, SendJobStatus.RENDERED)
Timber.e(t)
eventCollector.jobError(jobId = item.printJobId, t = t)
}
}
// Timber.i("===> readFilesAndSend sendJobResults=${sendJobResults}")
eventCollector.updateProgress(total, total)
// update jobs
......@@ -93,10 +96,10 @@ internal class JobSendRepositoryImpl(
// notify event emitters
if (successJobs.isNotEmpty())
eventCollector.updateStatus(status = JobStatus.RENDER_UPLOAD, *successJobs.toTypedArray())
eventCollector.updateStatus(status = JobStatus.RENDER_UPLOAD, *successJobs.map { it.id }.toTypedArray())
if (failedJobs.isNotEmpty())
eventCollector.updateStatus(status = JobStatus.UPLOAD_ERROR, *failedJobs.toTypedArray())
eventCollector.updateStatus(status = JobStatus.UPLOAD_ERROR, *failedJobs.map { it.id }.toTypedArray())
return successJobs
}
......@@ -107,9 +110,22 @@ internal class JobSendRepositoryImpl(
val updateJob = completeUpload(jobId = job.id, token = job.accessToken.orEmpty())
// notify event emitters
eventCollector.updateStatus(status = JobStatus.READY_TO_PRINT, updateJob)
eventCollector.updateStatus(status = JobStatus.READY_TO_PRINT, updateJob?.id)
updateJob
}
}
private suspend fun updateStatus(item: PrintJobSender, @SendJobStatus status: Int) {
sendJobLocalSource.updateStatus(item, status)
val jobStatus = when (status) {
SendJobStatus.RENDERED -> JobStatus.READY
SendJobStatus.SENDING -> JobStatus.SENDING
SendJobStatus.COMPLETE -> JobStatus.READY_TO_PRINT
else -> return
}
eventCollector.updateStatus(jobStatus, item.printJobId)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment