Skip to content

Commit

Permalink
Add font option, fix non-standard font lyrics
Browse files Browse the repository at this point in the history
Rewrite lyrics display to fix incorrect display with some fonts
Make top bar and main view lyrics display style consistent
Reduce space between main lyrics text and furigana
Fix lack of padding below settings subpages
Add font selection option (closes #69)
  • Loading branch information
toasterofbread committed Aug 18, 2023
1 parent 85683fa commit eee67ad
Show file tree
Hide file tree
Showing 17 changed files with 120 additions and 90 deletions.
3 changes: 1 addition & 2 deletions shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ kotlin {
@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
implementation(compose.components.resources)

implementation("com.github.TeamNewPipe:NewPipeExtractor")
implementation("com.github.TeamNewPipe:NewPipeExtractor") // Submodule

implementation("com.squareup.okhttp3:okhttp:4.10.0")
implementation("com.beust:klaxon:5.5")
Expand All @@ -117,7 +117,6 @@ kotlin {
implementation("com.github.SvenWoltmann:color-thief-java:v1.1.2")
implementation("com.github.catppuccin:java:v1.0.0")
implementation("com.github.paramsen:noise:2.0.0")
// implementation("org.xmlpull:xmlpull:1.1.4.0")
}
kotlin.srcDir(buildConfigDir)
}
Expand Down
44 changes: 12 additions & 32 deletions shared/src/commonMain/kotlin/SpMp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ import com.beust.klaxon.Klaxon
import com.beust.klaxon.KlaxonException
import com.toasterofbread.spmp.api.Api
import com.toasterofbread.spmp.model.Cache
import com.toasterofbread.spmp.model.FontMode
import com.toasterofbread.spmp.model.Settings
import com.toasterofbread.spmp.platform.PlatformContext
import com.toasterofbread.spmp.platform.ProjectPreferences
import com.toasterofbread.spmp.platform.composable.PlatformAlertDialog
import com.toasterofbread.spmp.platform.vibrateShort
import com.toasterofbread.spmp.resources.Languages
import com.toasterofbread.spmp.resources.getString
import com.toasterofbread.spmp.resources.getStringTODO
import com.toasterofbread.spmp.resources.initResources
import com.toasterofbread.spmp.resources.uilocalisation.localised.UILanguages
import com.toasterofbread.spmp.resources.uilocalisation.YoutubeUILocalisation
import com.toasterofbread.spmp.resources.uilocalisation.LocalisedYoutubeString
import com.toasterofbread.spmp.resources.uilocalisation.UnlocalisedStringCollector
import com.toasterofbread.spmp.resources.uilocalisation.YoutubeUILocalisation
import com.toasterofbread.spmp.resources.uilocalisation.localised.UILanguages
import com.toasterofbread.spmp.ui.layout.mainpage.PlayerState
import com.toasterofbread.spmp.ui.layout.mainpage.PlayerStateImpl
import com.toasterofbread.spmp.ui.layout.mainpage.RootView
Expand All @@ -53,7 +53,6 @@ import com.toasterofbread.utils.*
import com.toasterofbread.utils.composable.OnChangedEffect
import com.toasterofbread.utils.composable.ShapedIconButton
import com.toasterofbread.utils.composable.WidthShrinkText
import java.text.DateFormat
import java.util.*
import java.util.concurrent.CancellationException
import java.util.logging.Logger
Expand All @@ -80,18 +79,10 @@ object SpMp {

private val low_memory_listeners: MutableList<() -> Unit> = mutableListOf()

// fun getLanguageCode(index: Int): String = LANGUAGES[index]
// fun getLanguageIndex(language_code: String): Int {
// val language_index = LANGUAGES.indexOf(language_code)
// if (language_index == -1) {
// throw NotImplementedError(language_code)
// }
// return language_index
// }
// fun getLanguageCount(): Int = LANGUAGES.size

val ui_language: String get() = Settings.KEY_LANG_UI.get<String>().ifEmpty { Locale.getDefault().toLanguageTag() }
val data_language: String get() = Settings.KEY_LANG_DATA.get<String>().ifEmpty { Locale.getDefault().toLanguageTag() }
val ui_language: String get() =
Settings.KEY_LANG_UI.get<String>(context.getPrefs()).ifEmpty { Locale.getDefault().toLanguageTag() }
val data_language: String get() =
Settings.KEY_LANG_DATA.get<String>(context.getPrefs()).ifEmpty { Locale.getDefault().toLanguageTag() }

fun init(context: PlatformContext) {
this.context = context
Expand Down Expand Up @@ -123,7 +114,7 @@ object SpMp {

@Composable
fun App(open_uri: String? = null) {
Theme.ApplicationTheme(context, getFontFamily(context)) {
Theme.ApplicationTheme(context, getFontFamily(context) ?: FontFamily.Default) {
Theme.Update(context)

player_state.initComposable(context)
Expand Down Expand Up @@ -172,21 +163,10 @@ object SpMp {
Text(exception.toString())
}

private fun getFontFamily(context: PlatformContext): FontFamily {
val locale = ui_language
val font_dirs = context.listResourceFiles("")!!.filter { it.length > 4 && it.startsWith("font") }

var font_dir: String? = font_dirs.firstOrNull { it.endsWith("-$locale") }
if (font_dir == null) {
val locale_split = locale.indexOf('-')
if (locale_split > 0) {
val sublocale = locale.take(locale_split)
font_dir = font_dirs.firstOrNull { it.endsWith("-$sublocale") }
}
}

val font_name = font_dir ?: "font"
return FontFamily(context.loadFontFromFile("$font_name/regular.ttf"))
private fun getFontFamily(context: PlatformContext): FontFamily? {
val font_mode: FontMode = Settings.KEY_FONT.getEnum(context.getPrefs())
val font_path: String = font_mode.getFontFilePath(ui_language) ?: return null
return FontFamily(context.loadFontFromFile("font/$font_path"))
}

val app_name: String get() = getString("app_name")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ class SettingsInterface(
}

@Composable
fun Interface(height: Dp, modifier: Modifier = Modifier, content_padding: PaddingValues = PaddingValues(0.dp)) {
Crossfade(current_page, modifier = modifier.requiredHeight(height)) { page ->
fun Interface(modifier: Modifier = Modifier, content_padding: PaddingValues = PaddingValues(0.dp)) {
Crossfade(current_page, modifier = modifier) { page ->
var width by remember { mutableStateOf(0) }

Column(
Expand All @@ -88,7 +88,6 @@ class SettingsInterface(
.thenIf(!page.disable_padding, Modifier.padding(top = 18.dp, start = 20.dp, end = 20.dp))
.onSizeChanged { width = it.width }
) {

var go_back by remember { mutableStateOf(false) }
LaunchedEffect(go_back) {
if (go_back) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,35 @@ enum class NowPlayingQueueWaveBorderMode {
TIME, TIME_SYNC, SCROLL, NONE, LINE
}

enum class FontMode {
DEFAULT, SYSTEM, HC_MARU_GOTHIC;

fun getFontFilePath(language: String): String? =
when (this) {
DEFAULT -> getDefaultFont(language).getFontFilePath(language)
SYSTEM -> null
HC_MARU_GOTHIC -> "hc-maru-gothic/font.ttf"
}

fun getReadable(language: String): String =
when (this) {
DEFAULT -> {
val default_font = getDefaultFont(language).getReadable(language)
getString("font_option_default_\$x").replace("\$x", default_font)
}
SYSTEM -> getString("font_option_system")
HC_MARU_GOTHIC -> getString("font_option_hc_maru_gothic")
}

companion object {
fun getDefaultFont(language: String): FontMode =
when (language) {
"ja-JP" -> HC_MARU_GOTHIC
else -> SYSTEM
}
}
}

enum class Settings {
// Language
KEY_LANG_UI,
Expand Down Expand Up @@ -163,6 +192,7 @@ enum class Settings {
KEY_PERSISTENT_QUEUE,
KEY_ADD_SONGS_TO_HISTORY,
KEY_TREAT_SINGLES_AS_SONG,
KEY_FONT,

// Internal
INTERNAL_TOPBAR_MODE_HOME,
Expand All @@ -178,7 +208,7 @@ enum class Settings {
return Settings.get(this, context.getPrefs())
}

inline fun <reified T: Enum<T>> getEnum(): T = Settings.getEnum(this)
inline fun <reified T: Enum<T>> getEnum(preferences: ProjectPreferences = prefs): T = Settings.getEnum(this, preferences)

fun <T> set(value: T?, preferences: ProjectPreferences = prefs) {
Settings.set(this, value, preferences)
Expand Down Expand Up @@ -339,6 +369,7 @@ enum class Settings {
KEY_PERSISTENT_QUEUE -> true
KEY_ADD_SONGS_TO_HISTORY -> false
KEY_TREAT_SINGLES_AS_SONG -> false
KEY_FONT -> FontMode.DEFAULT.ordinal

KEY_SPMS_PORT -> 3973

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,8 @@ fun ArtistPage(
for (artist_layout in item_layouts ?: emptyList()) {
val layout = artist_layout.rememberMediaItemLayout(db)
val is_singles =
Settings.KEY_TREAT_SINGLES_AS_SONG.get() && layout.title?.getID() == YoutubeUILocalisation.StringID.ARTIST_PAGE_SINGLES
Settings.KEY_TREAT_SINGLES_AS_SONG.get()
&& layout.title?.getID() == YoutubeUILocalisation.StringID.ARTIST_PAGE_SINGLES

CompositionLocalProvider(LocalPlayerState provides remember {
if (!is_singles) player
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,11 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Error
import androidx.compose.material.icons.filled.HourglassEmpty
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.outlined.Info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.toasterofbread.composesettings.ui.item.SettingsItem
import com.toasterofbread.composesettings.ui.item.SettingsSliderItem
import com.toasterofbread.composesettings.ui.item.SettingsToggleItem
import com.toasterofbread.composesettings.ui.item.SettingsValueState
import com.toasterofbread.spmp.model.FontMode
import com.toasterofbread.spmp.model.Settings
import com.toasterofbread.spmp.resources.Languages
import com.toasterofbread.spmp.resources.getString
Expand Down Expand Up @@ -67,7 +68,7 @@ fun getLanguageDropdownItem(
}
}

internal fun getGeneralCategory(available_languages: List<Languages.LanguageInfo>): List<SettingsItem> {
internal fun getGeneralCategory(language: String, available_languages: List<Languages.LanguageInfo>): List<SettingsItem> {
return listOf(
SettingsComposableItem {
WidthShrinkText(getString("language_change_restart_notice"))
Expand Down Expand Up @@ -124,6 +125,15 @@ internal fun getGeneralCategory(available_languages: List<Languages.LanguageInfo
getString("s_sub_treat_singles_as_song")
),

SettingsDropdownItem(
SettingsValueState(Settings.KEY_FONT.name),
getString("s_key_font"),
null,
FontMode.values().size,
) { index ->
FontMode.values()[index].getReadable(language)
},

SettingsGroupItem(getString("s_group_long_press_menu")),

SettingsToggleItem(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ fun PrefsPage(
) {
CompositionLocalProvider(LocalContentColor provides Theme.on_background) {
settings_interface.Interface(
SpMp.context.getScreenHeight() - SpMp.context.getStatusBarHeight(),
Modifier.fillMaxSize(),
content_padding = PaddingValues(bottom = bottom_padding)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ internal fun rememberPrefsPageSettingsInterface(
SettingsValueState<String>(Settings.KEY_DISCORD_ACCOUNT_TOKEN.name).init(Settings.prefs, Settings.Companion::provideDefault)

val categories = mapOf(
PrefsPageCategory.GENERAL to lazy { getGeneralCategory(Languages.loadAvailableLanugages(SpMp.context)) },
PrefsPageCategory.GENERAL to lazy { getGeneralCategory(SpMp.ui_language, Languages.loadAvailableLanugages(SpMp.context)) },
PrefsPageCategory.FILTER to lazy { getFilterCategory() },
PrefsPageCategory.FEED to lazy { getFeedCategory() },
PrefsPageCategory.PLAYER to lazy { getPlayerCategory() },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@ package com.toasterofbread.utils

// Originally based on https://github.com/mainrs/android-compose-furigana

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.foundation.text.appendInlineContent
Expand Down Expand Up @@ -98,33 +94,13 @@ fun BasicFuriganaText(

for (term in terms) {
for (subterm in term.subterms) {
if (subterm.furi == null || !show_readings) {
string_builder.append(subterm.text)
}
else {
val furi = subterm.furi!!
string_builder.appendInlineContent(subterm.text, furi)

inline_content.putIfAbsent(subterm.text) {
val text = subterm.text
val width = (text.length.toDouble() + (text.length - 1) * 0.05).em

InlineTextContent(
placeholder = Placeholder(
width = width,
height = (font_size.value + (reading_font_size.value * 2)).sp,
placeholderVerticalAlign = PlaceholderVerticalAlign.Center,
)
) { furi ->
Column(
Modifier.fillMaxHeight().padding(bottom = with(LocalDensity.current) { reading_font_size.toDp() }),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Bottom,
) {
Text(furi, Modifier.wrapContentWidth(unbounded = true), fontSize = reading_font_size, color = text_colour)
Text(text, fontSize = font_size, color = text_colour)
}
}
string_builder.appendInlineContent(subterm.text)

inline_content.putIfAbsent(subterm.text) {
getLyricsInlineTextContent(
subterm.text, subterm.furi, show_readings, font_size, reading_font_size
) { is_reading, text, alternate_text, font_size, modifier ->
Text(text, modifier, fontSize = font_size, color = text_colour)
}
}
}
Expand Down Expand Up @@ -159,31 +135,55 @@ private fun annotateString(

string.appendInlineContent(text, index.toString())

inline_content[text] = InlineTextContent(
inline_content[text] = getLyricsInlineTextContent(
text, reading, show_readings, text_style.fontSize, reading_font_size
) { is_reading, text, alternate_text, font_size, modifier ->
val child_index = alternate_text.toInt()
textElement(is_reading, text, text_style.copy(fontSize = font_size), child_index, modifier) {
getLine(child_index)
}
}
}

private fun getLyricsInlineTextContent(
text: String,
reading: String?,
show_readings: Boolean,
font_size: TextUnit,
reading_font_size: TextUnit,
textElement: @Composable (is_reading: Boolean, text: String, alternate_text: String, font_size: TextUnit, modifier: Modifier) -> Unit
): InlineTextContent {
return InlineTextContent(
placeholder = Placeholder(
width = (text.length.toDouble() + (text.length - 1) * 0.05).em * (
if (text.any { it.isFullWidth() }) 1f
else 0.5f
),
height = 1.97.em,
height = (font_size.value + (reading_font_size.value * 2)).sp,
placeholderVerticalAlign = PlaceholderVerticalAlign.Bottom,
),
children = {
val child_index = it.toInt()
val box_height = with(LocalDensity.current) { reading_font_size.toDp() }

Column(
children = { alternate_text ->
Box(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Bottom,
contentAlignment = Alignment.Center
) {
Box(modifier = Modifier.requiredHeight(box_height + 3.dp)) {
if (show_readings && reading != null) {
textElement(true, reading, text_style.copy(fontSize = reading_font_size), child_index, Modifier.wrapContentWidth(unbounded = true)) { getLine(child_index) }
}
if (show_readings && reading != null) {
textElement(
true,
reading,
alternate_text,
reading_font_size,
Modifier
.wrapContentWidth(unbounded = true)
.offset(
y = with(LocalDensity.current) {
(font_size.toDp() * -0.5f) - reading_font_size.toDp() + 3.dp
}
)
)
}

textElement(false, text, text_style, child_index, Modifier) { getLine(child_index) }
textElement(false, text, alternate_text, font_size, Modifier)
}
}
)
Expand Down
Loading

0 comments on commit eee67ad

Please sign in to comment.