Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinTCoughlin committed Nov 29, 2024
1 parent d104ccb commit 9fad704
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 31 deletions.
16 changes: 0 additions & 16 deletions .idea/modules.xml

This file was deleted.

108 changes: 104 additions & 4 deletions Smodr/src/main/java/com/kevintcoughlin/smodr/views/TextView.kt
Original file line number Diff line number Diff line change
@@ -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)
}
/**
* 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<Int, String>()

fun Context.getFallbackText(@StringRes resId: Int): String {
return fallbackTextCache.getOrPut(resId) { getString(resId) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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))
}
}

Expand All @@ -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())
}
}
}
}

Expand Down Expand Up @@ -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))
}
}
1 change: 1 addition & 0 deletions Smodr/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
<string name="third_party_notices">Third-party notices</string>
<string name="privacy_policy">Privacy policy</string>
<string name="feedback">Report an issue</string>
<string name="elapsed_time_fallback">--:--</string>
</resources>

0 comments on commit 9fad704

Please sign in to comment.