Skip to content
This repository has been archived by the owner on Nov 12, 2024. It is now read-only.

Hopefully fix string formatting on iOS #1525

Merged
merged 1 commit into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2023, Christopher Banes and the Tivi project contributors
// SPDX-License-Identifier: Apache-2.0

package app.tivi.util

import app.tivi.common.ui.resources.EnTiviStrings
import assertk.assertThat
import assertk.assertions.isEqualTo
import kotlin.test.Test

class StringFormattingTest {
private val strings = EnTiviStrings

@Test
fun rating() {
assertThat(strings.traktRatingText(76.74f)).isEqualTo("77%")
assertThat(strings.traktRatingText(40.00f)).isEqualTo("40%")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,31 @@ package app.tivi.common.ui.resources
import platform.Foundation.NSString
import platform.Foundation.stringWithFormat

private val PATTERNS_REGEX = "%[\\d|.]*[sdf]".toRegex()

/**
* https://github.com/icerockdev/moko-resources/blob/c7e3ec78838308aaf9079496a080a12a1adff938/resources/src/appleMain/kotlin/dev/icerock/moko/resources/desc/Utils.kt#L137
* Yes, this is gross, but it's the only way I could get it to work.
* Related: https://youtrack.jetbrains.com/issue/KT-25506
*/
@Suppress("USELESS_CAST")
actual fun String.fmt(vararg args: Any?): String {
// NSString format works with NSObjects via %@, we should change standard format to %@
val fixed = replace(Regex("%((?:\\.|\\d|\\$)*)[abcdefs]"), "%$1@")

return when (args.size) {
0 -> NSString.stringWithFormat(fixed)
1 -> NSString.stringWithFormat(fixed, args[0])
2 -> NSString.stringWithFormat(fixed, args[0], args[1])
3 -> NSString.stringWithFormat(fixed, args[0], args[1], args[2])
4 -> NSString.stringWithFormat(fixed, args[0], args[1], args[2], args[3])
5 -> NSString.stringWithFormat(fixed, args[0], args[1], args[2], args[3], args[4])
6 -> NSString.stringWithFormat(fixed, args[0], args[1], args[2], args[3], args[4], args[5])
7 -> NSString.stringWithFormat(fixed, args[0], args[1], args[2], args[3], args[4], args[5], args[6])
8 -> NSString.stringWithFormat(fixed, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7])
9 -> NSString.stringWithFormat(fixed, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8])
10 -> NSString.stringWithFormat(fixed, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9])
else -> error("String.fmt() can only accept up to 10 arguments")
val formats = PATTERNS_REGEX.findAll(this).map { it.groupValues.first() }.toList()

var result = this

formats.forEachIndexed { i, format ->
val arg = args[i]

val formatted = when (arg) {
is Double -> NSString.stringWithFormat(format, arg as Double)
is Float -> NSString.stringWithFormat(format, arg as Float)
is Int -> NSString.stringWithFormat(format, arg as Int)
is Long -> NSString.stringWithFormat(format, arg as Long)
else -> NSString.stringWithFormat("%@", arg)
}
result = result.replaceFirst(format, formatted)
}

// We put the string through stringWithFormat again, to remove any escaped characters
return NSString.stringWithFormat(result, Any())
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package app.tivi.util

import app.tivi.inject.ActivityScope
import kotlin.time.Duration.Companion.days
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.convert
import kotlinx.datetime.DayOfWeek
import kotlinx.datetime.Instant
Expand All @@ -30,6 +31,7 @@ import platform.Foundation.NSLocale
import platform.Foundation.NSRelativeDateTimeFormatter
import platform.Foundation.NSRelativeDateTimeFormatterStyleNamed

@OptIn(ExperimentalForeignApi::class)
@ActivityScope
@Inject
actual class TiviDateFormatter(
Expand Down Expand Up @@ -149,6 +151,7 @@ actual class TiviDateFormatter(
}
}

@OptIn(ExperimentalForeignApi::class)
private fun LocalTime.toNSDateComponents(): NSDateComponents {
val components = NSDateComponents()
components.hour = hour.convert()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package app.tivi.util
import app.tivi.common.ui.resources.TiviStrings
import app.tivi.data.models.TiviShow
import app.tivi.inject.ActivityScope
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.convert
import kotlinx.datetime.DayOfWeek
import kotlinx.datetime.TimeZone
Expand All @@ -17,6 +18,7 @@ import platform.Foundation.NSCalendarMatchNextTime
import platform.Foundation.NSDate
import platform.Foundation.NSDateComponents

@OptIn(ExperimentalForeignApi::class)
@ActivityScope
@Inject
actual class TiviTextCreator(
Expand Down