2 Commits
8 changed files with 19 additions and 54 deletions

No files matched your search

+1 -1
View File
@@ -10,7 +10,7 @@ The gear icon opens **Car**. A new install already has the server address filled
`http://sync.sleepingliongames.com:27017`
**Sync on its own** sends a save right away, checks about every 30 seconds while the app is open, and about every 15 minutes while it is closed. **Sync now** sends every car on the phone.
**Sync on its own** sends a save right away and checks about every 30 seconds while the app is open. It stays quiet while the app is closed. **Sync now** sends every car on the phone.
Each car has its own token, shown on the **Car** screen. **Share token** sends that string to another phone. On the other phone, paste it under **Add a car from a token**. That phone then syncs that car. A different car gets a different token.
-1
View File
@@ -70,7 +70,6 @@ dependencies {
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.room.ktx)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.androidx.work)
ksp(libs.androidx.room.compiler)
debugImplementation(libs.androidx.compose.ui.tooling)
testImplementation(libs.junit)
@@ -18,8 +18,7 @@ open class RacingApp : Application() {
val dao = AppDatabase.create(this).raceDao()
val preferences = SyncPreferences(this)
runBlocking(Dispatchers.IO) { ensureCars(dao, preferences) }
val sync = PitSync(this, dao, preferences)
val sync = PitSync(dao, preferences)
repository = Repository(dao, sync, preferences)
sync.schedule()
}
}
@@ -1,17 +1,10 @@
package com.racingapp.pitlog.data
import android.content.Context
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.NetworkType
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import java.net.HttpURLConnection
import java.net.URL
import java.time.LocalTime
import java.time.format.DateTimeFormatter
import java.util.UUID
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
@@ -23,10 +16,7 @@ import org.json.JSONObject
class SyncException(message: String) : Exception(message)
private const val WORK_NAME = "pitlog-sync"
class PitSync(
private val appContext: Context,
private val dao: RaceDao,
private val preferences: SyncPreferences,
) {
@@ -39,30 +29,10 @@ class PitSync(
fun saveAddress(address: String) {
preferences.address = address.trim().trimEnd('/')
schedule()
}
fun setAutomatic(enabled: Boolean) {
preferences.automatic = enabled
schedule()
}
fun schedule() {
try {
val manager = WorkManager.getInstance(appContext)
if (!preferences.automatic || preferences.address.isBlank()) {
manager.cancelUniqueWork(WORK_NAME)
return
}
val request = PeriodicWorkRequestBuilder<SyncWorker>(15, TimeUnit.MINUTES)
.setConstraints(
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build(),
)
.build()
manager.enqueueUniquePeriodicWork(WORK_NAME, ExistingPeriodicWorkPolicy.UPDATE, request)
} catch (_: Exception) {
// Unit tests do not start WorkManager.
}
}
fun launchAutomatic() {
@@ -1,17 +0,0 @@
package com.racingapp.pitlog.data
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.racingapp.pitlog.RacingApp
class SyncWorker(
context: Context,
params: WorkerParameters,
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val app = applicationContext as? RacingApp ?: return Result.success()
app.repository.syncAutomatic()
return Result.success()
}
}
@@ -286,7 +286,7 @@ fun SettingsScreen(onBack: () -> Unit) {
}
SectionLabel("Server")
Text(
"This is the Pelican address. Every car on this phone uses it. Sync on its own sends each save right away, checks every half minute while the app is open, and about every 15 minutes while it is closed.",
"This is the Pelican address. Every car on this phone uses it. Sync on its own sends each save right away and checks every half minute while the app is open.",
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
Row(
-2
View File
@@ -9,7 +9,6 @@ lifecycle = "2.11.0"
activity = "1.12.4"
core = "1.19.1"
coroutines = "1.10.1"
work = "2.10.1"
junit = "4.13.2"
robolectric = "4.16"
androidxTestCore = "1.6.1"
@@ -32,7 +31,6 @@ androidx-room-runtime = { group = "androidx.room", name = "room-runtime", versio
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" }
androidx-work = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-test-core = { group = "androidx.test", name = "core", version.ref = "androidxTestCore" }
+16
View File
@@ -355,6 +355,22 @@ def sync_body(payload, db=None):
class Handler(BaseHTTPRequestHandler):
protocol_version = "HTTP/1.1"
def handle(self):
try:
super().handle()
except (ConnectionError, TimeoutError):
return
def send_error(self, code, message=None, explain=None):
try:
self.close_connection = True
self.send_response_only(code)
self.send_header("Content-Length", "0")
self.send_header("Connection", "close")
self.end_headers()
except (ConnectionError, TimeoutError):
self.close_connection = True
def log_message(self, fmt, *args):
sys.stdout.write("%s - %s\n" % (self.address_string(), fmt % args))