Skip to content

Commit

Permalink
Merge pull request #6172 from Bnyro/master
Browse files Browse the repository at this point in the history
feat: support for duration inputs in submit segment dialog
  • Loading branch information
Bnyro committed Jun 21, 2024
2 parents 007dfba + 3b0ef23 commit c65a2b8
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 6 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ dependencies {
implementation(libs.kotlinx.serialization)
implementation(libs.kotlinx.datetime)
implementation(libs.kotlinx.serialization.retrofit)
testImplementation(libs.testng)

/* Cronet and Coil */
coreLibraryDesugaring(libs.desugaring)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.github.libretube.extensions.TAG
import com.github.libretube.extensions.toastFromMainDispatcher
import com.github.libretube.helpers.PreferenceHelper
import com.github.libretube.util.TextUtils
import com.github.libretube.util.TextUtils.parseDurationString
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -52,7 +53,7 @@ class SubmitSegmentDialog : DialogFragment() {
lifecycleScope.launch { voteForSegment() }
}

binding.startTime.setText((currentPosition.toFloat() / 1000).toString())
binding.startTime.setText(DateUtils.formatElapsedTime(((currentPosition.toFloat() / 1000).toLong())))

binding.segmentCategory.items = resources.getStringArray(R.array.sponsorBlockSegmentNames).toList()

Expand All @@ -72,8 +73,9 @@ class SubmitSegmentDialog : DialogFragment() {

requireDialog().hide()

val startTime = binding.startTime.text.toString().toFloatOrNull()
var endTime = binding.endTime.text.toString().toFloatOrNull()
val startTime = binding.startTime.text.toString().parseDurationString()
var endTime = binding.endTime.text.toString().parseDurationString()

if (endTime == null || startTime == null || startTime > endTime) {
context.toastFromMainDispatcher(R.string.sb_invalid_segment)
return
Expand Down
41 changes: 39 additions & 2 deletions app/src/main/java/com/github/libretube/util/TextUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.os.Build
import android.text.format.DateUtils
import com.github.libretube.BuildConfig
import com.github.libretube.R
import com.google.common.math.IntMath.pow
import kotlinx.datetime.toJavaLocalDate
import java.time.Instant
import java.time.LocalDateTime
Expand Down Expand Up @@ -49,8 +50,44 @@ object TextUtils {
* Get time in seconds from a YouTube video link.
* @return Time in seconds
*/
fun String.toTimeInSeconds(): Long? {
return toLongOrNull() ?: Duration.parseOrNull(this)?.inWholeSeconds
fun String.toTimeInSeconds(): Long? = parseTimeString(this)?.toLong()

fun String.parseDurationString(): Float? = parseTimeString(this)

private fun parseTimeString(timeString: String): Float? {
if (timeString.all { it.isDigit() }) return timeString.toLongOrNull()?.toFloat()

if (timeString.all { it.isDigit() || ",.:".contains(it) }) {
var secondsTotal = 0
var secondsScoped = 0

var milliseconds = 0
var inMillis = false

for (char in timeString) {
if (inMillis) {
if (!char.isDigit()) break

milliseconds *= 10
milliseconds += char.digitToInt()
} else if (char.isDigit()) {
secondsScoped *= 10
secondsScoped += char.digitToInt()
} else if (char == ':') {
secondsTotal += secondsScoped * 60
secondsScoped = 0
} else if (",.".contains(char)) {
secondsTotal += secondsScoped
secondsScoped = 0
inMillis = true
}
}

val millisDecimal = milliseconds.toFloat() / pow(10, milliseconds.toString().length)
return secondsTotal.toFloat() + millisDecimal
}

return Duration.parseOrNull(timeString)?.inWholeMilliseconds?.toFloat()?.div(1000)
}

/**
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/res/layout/dialog_submit_segment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
android:id="@+id/start_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal" />
android:digits="0123456789.:"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
Expand Down
16 changes: 16 additions & 0 deletions app/src/test/java/com/github/libretube/TextParserTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.github.libretube

import com.github.libretube.util.TextUtils.parseDurationString
import com.github.libretube.util.TextUtils.toTimeInSeconds
import org.junit.Test
import org.junit.Assert.assertEquals

class TextParserTest {
@Test
fun testTimeParser() {
assertEquals(15L * 60 + 20, "15m 20s".toTimeInSeconds())
assertEquals(1520L, "1520".toTimeInSeconds())
assertEquals(15L * 60 + 20, "15:20.25".toTimeInSeconds())
assertEquals(15f * 60 + 20 + 0.25f, "15:20.25".parseDurationString())
}
}
4 changes: 4 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
appcompat = "1.7.0"
core = "1.13.1"
gradle = "8.5.0"
junit = "4.13.2"
kotlin = "1.9.24"
ksp = "1.9.24-1.0.20"
lifecycle = "2.8.2"
Expand Down Expand Up @@ -34,6 +35,7 @@ profileinstaller = "1.3.1"
paging = "3.3.0"
collection = "1.4.0"
swiperefreshlayout = "1.1.0"
testng = "6.9.6"

[libraries]
androidx-activity = { group = "androidx.activity", name = "activity-ktx", version.ref = "activity" }
Expand All @@ -42,6 +44,7 @@ androidx-core = { group = "androidx.core", name = "core", version.ref = "core" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
androidx-fragment = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "fragment" }
gradle = { module = "com.android.tools.build:gradle", version.ref = "gradle" }
junit = { module = "junit:junit", version.ref = "junit" }
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlin-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin" }
logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "loggingInterceptor" }
Expand Down Expand Up @@ -81,6 +84,7 @@ androidx-profileinstaller = { group = "androidx.profileinstaller", name = "profi
androidx-paging = { group = "androidx.paging", name = "paging-runtime-ktx", version.ref = "paging" }
androidx-collection = { group = "androidx.collection", name = "collection", version.ref = "collection" }
androidx-swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
testng = { group = "org.testng", name = "testng", version.ref = "testng" }

[plugins]
androidTest = { id = "com.android.test", version.ref = "gradle" }
Expand Down

0 comments on commit c65a2b8

Please sign in to comment.