From 9fad7042586ee2c19706e4cef616276c096fce82 Mon Sep 17 00:00:00 2001
From: "Kevin T. Coughlin" <706967+KevinTCoughlin@users.noreply.github.com>
Date: Thu, 28 Nov 2024 19:20:24 -0800
Subject: [PATCH] Refactor
---
.idea/modules.xml | 16 ---
.../kevintcoughlin/smodr/views/TextView.kt | 108 +++++++++++++++++-
.../smodr/views/activities/MainActivity.kt | 20 ++--
Smodr/src/main/res/values/strings.xml | 1 +
4 files changed, 114 insertions(+), 31 deletions(-)
delete mode 100644 .idea/modules.xml
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 44e8d53f..00000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Smodr/src/main/java/com/kevintcoughlin/smodr/views/TextView.kt b/Smodr/src/main/java/com/kevintcoughlin/smodr/views/TextView.kt
index 91310439..4fbdada3 100644
--- a/Smodr/src/main/java/com/kevintcoughlin/smodr/views/TextView.kt
+++ b/Smodr/src/main/java/com/kevintcoughlin/smodr/views/TextView.kt
@@ -1,8 +1,108 @@
package com.kevintcoughlin.smodr.views
-import android.text.format.DateUtils
+import android.content.Context
+import android.util.Log
import android.widget.TextView
+import androidx.annotation.CheckResult
+import androidx.annotation.StringRes
+import com.kevintcoughlin.smodr.R
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.withContext
+import kotlin.time.Duration
+import kotlin.time.DurationUnit
+import kotlin.time.toDuration
+import java.util.Locale
-fun TextView.setElapsedTime(milliseconds: Int) {
- this.text = DateUtils.formatElapsedTime(milliseconds.toLong() / 1000)
-}
\ No newline at end of file
+/**
+ * Sets the text of the TextView to display elapsed time in the format HH:mm:ss or MM:ss.
+ *
+ * @param milliseconds The elapsed time in milliseconds. Must be non-negative.
+ * @param locale The desired locale for formatting the elapsed time. Defaults to the system's default locale.
+ * @param fallbackTextResId The resource ID for the fallback text if the time is invalid.
+ * @param formatter A custom formatter function for elapsed time.
+ */
+inline fun TextView.setElapsedTime(
+ milliseconds: Long,
+ locale: Locale = Locale.getDefault(),
+ @StringRes fallbackTextResId: Int? = null,
+ formatter: (Duration, Locale) -> String = ::defaultElapsedTimeFormatter
+) {
+ val fallbackText = fallbackTextResId?.let { context.getString(it) }
+ ?: context.getString(R.string.elapsed_time_fallback)
+
+ this.text = if (milliseconds >= 0) {
+ formatter(milliseconds.toDuration(DurationUnit.MILLISECONDS), locale)
+ } else {
+ Log.w("setElapsedTime", "Invalid duration: $milliseconds")
+ fallbackText
+ }
+}
+
+/**
+ * Default formatter for elapsed time.
+ *
+ * Formats elapsed time in the format HH:mm:ss or MM:ss. For durations exceeding 1 day, it includes days.
+ *
+ * @param duration The elapsed time as a [Duration].
+ * @param locale The locale to use for formatting.
+ * @return A formatted elapsed time string.
+ */
+@CheckResult
+fun defaultElapsedTimeFormatter(duration: Duration, locale: Locale): String {
+ val totalSeconds = duration.toLong(DurationUnit.SECONDS)
+ val days = totalSeconds / 86400
+ val hours = (totalSeconds % 86400) / 3600
+ val minutes = (totalSeconds % 3600) / 60
+ val seconds = totalSeconds % 60
+
+ return when {
+ days > 0 -> String.format(locale, "%d days, %d:%02d:%02d", days, hours, minutes, seconds)
+ hours > 0 -> String.format(locale, "%d:%02d:%02d", hours, minutes, seconds)
+ else -> String.format(locale, "%d:%02d", minutes, seconds)
+ }
+}
+
+/**
+ * Coroutine-based extension to update a TextView with elapsed time periodically.
+ *
+ * The update stops when the TextView is detached from the window.
+ *
+ * @param startTimeMillis The starting time in milliseconds since epoch.
+ * @param locale The desired locale for formatting the elapsed time. Defaults to the system's default locale.
+ * @param intervalMillis The interval between updates in milliseconds.
+ */
+suspend fun TextView.updateElapsedTime(
+ startTimeMillis: Long,
+ locale: Locale = Locale.getDefault(),
+ intervalMillis: Long = 1000L
+) = withContext(Dispatchers.Main) {
+ while (isAttachedToWindow) {
+ val elapsedMillis = System.currentTimeMillis() - startTimeMillis
+ setElapsedTime(elapsedMillis, locale)
+ delay(intervalMillis)
+ }
+}
+
+/**
+ * Formats elapsed time as a string without requiring a TextView.
+ *
+ * Useful for non-UI use cases such as logging or notifications.
+ *
+ * @param duration The elapsed time as a [Duration].
+ * @param locale The desired locale for formatting the elapsed time. Defaults to the system's default locale.
+ * @return A formatted elapsed time string.
+ */
+@CheckResult
+fun Duration.formatElapsedTime(locale: Locale = Locale.getDefault()): String {
+ return defaultElapsedTimeFormatter(this, locale)
+}
+
+/**
+ * Utility to retrieve and cache fallback text for a given string resource ID.
+ */
+private val fallbackTextCache = mutableMapOf()
+
+fun Context.getFallbackText(@StringRes resId: Int): String {
+ return fallbackTextCache.getOrPut(resId) { getString(resId) }
+}
diff --git a/Smodr/src/main/java/com/kevintcoughlin/smodr/views/activities/MainActivity.kt b/Smodr/src/main/java/com/kevintcoughlin/smodr/views/activities/MainActivity.kt
index c5afb25e..4356bb4b 100644
--- a/Smodr/src/main/java/com/kevintcoughlin/smodr/views/activities/MainActivity.kt
+++ b/Smodr/src/main/java/com/kevintcoughlin/smodr/views/activities/MainActivity.kt
@@ -14,7 +14,6 @@ import android.view.View
import android.widget.SeekBar
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
-import androidx.fragment.app.Fragment
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.MobileAds
import com.google.android.gms.ads.RequestConfiguration
@@ -115,7 +114,6 @@ class MainActivity : AppCompatActivity(), SeekBar.OnSeekBarChangeListener {
updatePlayButtonState(R.drawable.ic_round_play_arrow_24)
currentItem?.completed = true
currentItem = null
- logEvent("complete_playback", safeGetEventBundle(currentItem))
}
}
@@ -135,9 +133,15 @@ class MainActivity : AppCompatActivity(), SeekBar.OnSeekBarChangeListener {
private fun updateSeekProgress() {
mediaService?.let { service ->
- binding.seekbar.progress = service.currentTime
- binding.currentTime.setElapsedTime(service.currentTime)
- binding.remainingTime.setElapsedTime(service.remainingTime)
+ with(binding) {
+ seekbar.progress = service.currentTime
+ listOf(
+ currentTime to service.currentTime,
+ remainingTime to service.remainingTime
+ ).forEach { (textView, time) ->
+ textView.setElapsedTime(time.toLong())
+ }
+ }
}
}
@@ -206,10 +210,4 @@ class MainActivity : AppCompatActivity(), SeekBar.OnSeekBarChangeListener {
private const val FEEDBACK_URL = "https://github.com/cascadiacollections/SModr/issues/new"
private val DEFAULT_CHANNEL = Channel("Tell 'Em Steve-Dave", "http://feeds.feedburner.com/TellEmSteveDave/")
}
-
- fun onItemSelected(item: Item?) {
- currentItem = item
- mediaService?.startPlayback(item?.uri)
- logEvent("selected_item", safeGetEventBundle(item))
- }
}
\ No newline at end of file
diff --git a/Smodr/src/main/res/values/strings.xml b/Smodr/src/main/res/values/strings.xml
index 2ba21202..687ba88f 100755
--- a/Smodr/src/main/res/values/strings.xml
+++ b/Smodr/src/main/res/values/strings.xml
@@ -7,4 +7,5 @@
Third-party notices
Privacy policy
Report an issue
+ --:--