08dc4f5bd4
- FilesScreen: per-file context menu (Open, Share, Rename, Delete), rename dialog, delete confirmation, FileProvider-based open/share intents, Snackbar error feedback - FilesViewModel: FileAction sealed class + SharedFlow; openFile, shareFile, deleteFile, renameFile with DB cleanup; resolveFile handles SAF primary: URIs - FileWatchService: stopWithTask=false keeps watcher alive after app swipe-away; catchupScan on startup detects changes missed while service was not running; SyncFileStateDao injected; FileObserver used for real-path SAF URIs - BootReceiver: handles MY_PACKAGE_REPLACED to restart service after app update - file_paths.xml: added external-path so FileProvider can serve /storage/emulated/0 files - ic_launcher_foreground: three curved stroke-based arrows (quadratic bezier, round caps) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
51 lines
1.9 KiB
Kotlin
51 lines
1.9 KiB
Kotlin
package com.syncflow.worker
|
|
|
|
import android.content.BroadcastReceiver
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import androidx.work.ExistingPeriodicWorkPolicy
|
|
import androidx.work.WorkManager
|
|
import dagger.hilt.android.AndroidEntryPoint
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.launch
|
|
import com.syncflow.data.db.SyncPairDao
|
|
import com.syncflow.domain.model.ScheduleType
|
|
import javax.inject.Inject
|
|
|
|
@AndroidEntryPoint
|
|
class BootReceiver : BroadcastReceiver() {
|
|
@Inject lateinit var syncPairDao: SyncPairDao
|
|
|
|
override fun onReceive(context: Context, intent: Intent) {
|
|
val validActions = setOf(Intent.ACTION_BOOT_COMPLETED, Intent.ACTION_MY_PACKAGE_REPLACED)
|
|
if (intent.action !in validActions) return
|
|
val wm = WorkManager.getInstance(context)
|
|
val pending = goAsync()
|
|
CoroutineScope(Dispatchers.IO).launch {
|
|
try {
|
|
val pairs = syncPairDao.getEnabled()
|
|
var hasOnChange = false
|
|
pairs.forEach { pair ->
|
|
when (pair.scheduleType) {
|
|
ScheduleType.ON_CHANGE -> hasOnChange = true
|
|
ScheduleType.MANUAL -> { /* nothing */ }
|
|
else -> {
|
|
val req = SyncWorker.buildPeriodicRequest(
|
|
pair.id,
|
|
pair.scheduleIntervalMinutes.toLong().coerceAtLeast(15),
|
|
pair.wifiOnly,
|
|
pair.chargingOnly,
|
|
)
|
|
wm.enqueueUniquePeriodicWork("periodic_${pair.id}", ExistingPeriodicWorkPolicy.UPDATE, req)
|
|
}
|
|
}
|
|
}
|
|
if (hasOnChange) FileWatchService.start(context)
|
|
} finally {
|
|
pending.finish()
|
|
}
|
|
}
|
|
}
|
|
}
|