diff options
Diffstat (limited to 'app/src/main')
| -rw-r--r-- | app/src/main/java/invalid/lena/rsend/App.kt | 7 | ||||
| -rw-r--r-- | app/src/main/java/invalid/lena/rsend/MainActivity.kt | 50 |
2 files changed, 44 insertions, 13 deletions
diff --git a/app/src/main/java/invalid/lena/rsend/App.kt b/app/src/main/java/invalid/lena/rsend/App.kt index 0251d7d..443229d 100644 --- a/app/src/main/java/invalid/lena/rsend/App.kt +++ b/app/src/main/java/invalid/lena/rsend/App.kt @@ -3,6 +3,7 @@ package invalid.lena.rsend import android.app.Application import android.app.NotificationChannel import android.app.NotificationManager +import kotlin.concurrent.thread // App creates the notification channel used by the foreground sync service. class App : Application() { @@ -13,8 +14,10 @@ class App : Application() { getSystemService(NotificationManager::class.java).createNotificationChannel(ch) // Apply on every process start, including one launched by an old // WorkManager request after an app upgrade. This retires stale unique - // names without waiting for the dashboard to be opened. - Scheduler.apply(this) + // names without waiting for the dashboard to be opened. Off the main + // thread: it reads the config and opens WorkManager's database, and + // nothing here has to finish before the first screen draws. + thread { Scheduler.apply(this) } } companion object { diff --git a/app/src/main/java/invalid/lena/rsend/MainActivity.kt b/app/src/main/java/invalid/lena/rsend/MainActivity.kt index 875afdf..06270ca 100644 --- a/app/src/main/java/invalid/lena/rsend/MainActivity.kt +++ b/app/src/main/java/invalid/lena/rsend/MainActivity.kt @@ -62,6 +62,10 @@ class MainActivity : AppCompatActivity() { private var jobState: String = "none" private var recoveryShown = false + // Settles overlapping refreshes: a resume and a finishing sync can start + // one each, and only the newest read may draw. + private var generation = 0 + private val notifPerm = registerForActivityResult(ActivityResultContracts.RequestPermission()) { refresh() } @@ -221,15 +225,11 @@ class MainActivity : AppCompatActivity() { override fun onResume() { super.onResume() - Scheduler.apply(this) refresh() - showRecoveryNotice() } - private fun showRecoveryNotice() { - if (recoveryShown) return - val message = Config.recoveryMessage(this).trim() - if (message.isEmpty()) return + private fun showRecoveryNotice(message: String) { + if (recoveryShown || message.isEmpty()) return recoveryShown = true AlertDialog.Builder(this) .setTitle("Configuration recovered") @@ -277,12 +277,40 @@ class MainActivity : AppCompatActivity() { scheduleValue.text = "$sched, job $jobState" } + // One read of everything the dashboard draws. + private data class Dashboard( + val cfg: Config, + val lastSync: String, + val keyExists: Boolean, + val recovery: String, + ) + + // Every field above comes from an app-private file, so read them on a worker + // thread and draw the result. Reading them during layout was the same + // main-thread stall the WorkManager query was moved off. private fun refresh() { - val cfg = Config.load(this) + val current = ++generation + thread { + Scheduler.apply(this) + val d = Dashboard( + cfg = Config.load(this), + lastSync = LastSync.get(this), + keyExists = Keys.exists(this), + recovery = Config.recoveryMessage(this).trim(), + ) + runOnUiThread { + if (isFinishing || isDestroyed || current != generation) return@runOnUiThread + draw(d) + } + } + } - lastSync.text = "Last sync: ${LastSync.get(this)}" + private fun draw(d: Dashboard) { + val cfg = d.cfg - keyValue.text = if (Keys.exists(this)) "Generated, tap to view" else "Not created, tap to create" + lastSync.text = "Last sync: ${d.lastSync}" + + keyValue.text = if (d.keyExists) "Generated, tap to view" else "Not created, tap to create" schedule = cfg.schedule renderSchedule(cfg.schedule) @@ -324,6 +352,8 @@ class MainActivity : AppCompatActivity() { } } } + + showRecoveryNotice(d.recovery) } // addRow inflates one tappable list row: icon, title, subtitle, chip. @@ -451,7 +481,6 @@ class MainActivity : AppCompatActivity() { runOnUiThread { if (isFinishing || isDestroyed) return@runOnUiThread if (error == null) { - Scheduler.apply(this) refresh() Toast.makeText(this, "New key generated.", Toast.LENGTH_SHORT).show() showKey() @@ -497,7 +526,6 @@ class MainActivity : AppCompatActivity() { runOnUiThread { if (isFinishing || isDestroyed) return@runOnUiThread if (error == null) { - Scheduler.apply(this) refresh() Toast.makeText(this, "Key imported.", Toast.LENGTH_SHORT).show() showKey() |