From b3b69dd2b2b9a3bcf11486527cf5ae4522f0ad6e Mon Sep 17 00:00:00 2001 From: Amir Khodak Date: Fri, 22 May 2026 16:10:09 +0000 Subject: [PATCH] =?UTF-8?q?v1.5:=20time-based=20rotation=20angle=20?= =?UTF-8?q?=E2=80=94=20constant=20speed=20regardless=20of=20IPC=20load?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++-- .../khodak/claudeusage/UsageUpdateWorker.kt | 22 ++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 046985d..89c349f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -11,8 +11,8 @@ android { applicationId = "me.khodak.claudeusage" minSdk = 26 targetSdk = 34 - versionCode = 5 - versionName = "1.4" + versionCode = 6 + versionName = "1.5" } signingConfigs { diff --git a/app/src/main/java/me/khodak/claudeusage/UsageUpdateWorker.kt b/app/src/main/java/me/khodak/claudeusage/UsageUpdateWorker.kt index b2d87c9..b0a968f 100644 --- a/app/src/main/java/me/khodak/claudeusage/UsageUpdateWorker.kt +++ b/app/src/main/java/me/khodak/claudeusage/UsageUpdateWorker.kt @@ -33,7 +33,7 @@ class UsageUpdateWorker( prefs.saveUsageData(data) } catch (_: Exception) {} animJob.cancel() - animJob.join() // wait for the minimum-rotation finally block to finish + animJob.join() } pushWidgetUpdate() @@ -43,23 +43,25 @@ class UsageUpdateWorker( private suspend fun rotateRefreshIcon() { val manager = AppWidgetManager.getInstance(context) val ids = manager.getAppWidgetIds(ComponentName(context, ClaudeUsageWidget::class.java)) - var totalDegrees = 0f + val startMs = System.currentTimeMillis() + val msPerRotation = 800L // one full rotation every 0.8 seconds + + fun angleAt(now: Long) = ((now - startMs) % msPerRotation) * 360f / msPerRotation try { while (true) { - ClaudeUsageWidget.currentRotation = (ClaudeUsageWidget.currentRotation + 12f) % 360f - totalDegrees += 12f + ClaudeUsageWidget.currentRotation = angleAt(System.currentTimeMillis()) ids.forEach { id -> ClaudeUsageWidget.updateWidget(context, manager, id) } - delay(33) // 30 fps, one full rotation per second + delay(16) // aim for ~60fps; IPC speed sets the real ceiling } } finally { - // Even if the fetch finishes early, complete at least one full 360° + // Finish the current rotation cleanly — run until at least one full spin withContext(NonCancellable) { - while (totalDegrees < 360f) { - ClaudeUsageWidget.currentRotation = (ClaudeUsageWidget.currentRotation + 6f) % 360f - totalDegrees += 6f + val minEndMs = startMs + msPerRotation + while (System.currentTimeMillis() < minEndMs) { + ClaudeUsageWidget.currentRotation = angleAt(System.currentTimeMillis()) ids.forEach { id -> ClaudeUsageWidget.updateWidget(context, manager, id) } - delay(33) + delay(16) } } }