v1.0.63: live sync progress counters, pause/resume, .gitignore fix
Build & Release APK / build (push) Has been cancelled
Build & Release APK / build (push) Has been cancelled
- SyncEngine: accepts onProgress callback — emits uploaded/downloaded/ deleted/bytes counts atomically as each file completes - SyncWorker: streams progress to WorkManager data so the UI can poll it live; reports per-run counters in the completion notification; adds pause/resume support - HomeViewModel/PairDetailViewModel: subscribe to live WorkManager progress and surface it via SyncProgress state - SyncPairEntity/SyncPairDao/SyncDatabase: persist last-run counters (uploaded, downloaded, deleted, bytesTransferred) in the DB with a Room migration (v3→v4) - AppModule: provides WorkManager as an injectable singleton - .gitignore: add .kotlin/ to exclude compiler session files Security: no new issues — all logging via Timber (debug-only), DB queries use Room parameterized API, file sharing via FileProvider. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package com.syncflow.ui.pairdetail
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import com.syncflow.data.db.SyncConflictDao
|
||||
import com.syncflow.data.db.SyncEventDao
|
||||
@@ -10,7 +11,9 @@ import com.syncflow.data.db.SyncPairDao
|
||||
import com.syncflow.domain.model.SyncStatus
|
||||
import com.syncflow.worker.SyncWorker
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import com.syncflow.ui.shared.SyncProgress
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
@@ -35,6 +38,19 @@ class PairDetailViewModel @Inject constructor(
|
||||
val unresolvedConflicts = conflictDao.observeUnresolvedCount(pairId)
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), 0)
|
||||
|
||||
val syncProgress = workManager.getWorkInfosByTagFlow("sync_$pairId")
|
||||
.map { infos ->
|
||||
infos.firstOrNull { it.state == WorkInfo.State.RUNNING }?.progress?.let { data ->
|
||||
SyncProgress(
|
||||
uploaded = data.getInt(SyncWorker.KEY_PROGRESS_UPLOADED, 0),
|
||||
downloaded = data.getInt(SyncWorker.KEY_PROGRESS_DOWNLOADED, 0),
|
||||
deleted = data.getInt(SyncWorker.KEY_PROGRESS_DELETED, 0),
|
||||
bytesTransferred = data.getLong(SyncWorker.KEY_PROGRESS_BYTES, 0L),
|
||||
).takeIf { it.uploaded > 0 || it.downloaded > 0 || it.deleted > 0 }
|
||||
}
|
||||
}
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), null)
|
||||
|
||||
fun syncNow() {
|
||||
val p = pair.value ?: return
|
||||
workManager.enqueue(SyncWorker.buildOneTimeRequest(p.id, wifiOnly = false, chargingOnly = false))
|
||||
|
||||
Reference in New Issue
Block a user