Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
db454bc
Add Japanese translations
daedaevibin Jun 24, 2026
7e927c0
Add MultiLangRomanizer functions for Thai, Arabic, Greek, Hebrew, and…
daedaevibin Jun 24, 2026
f53d857
Add romanization and language detection for Cyrillic and Vietnamese
daedaevibin Jun 24, 2026
d74f593
Fix 21 pre-existing lint errors
daedaevibin Jun 24, 2026
2580e86
Add new app languages and update locale configuration
daedaevibin Jun 24, 2026
5a90005
Add LYRICS settings category and restructure settings screens
daedaevibin Jun 24, 2026
a88c9a1
Update CI workflows and build config
daedaevibin Jun 24, 2026
4940904
Misc fixes: AI max tokens and lyrics loading priority
daedaevibin Jun 24, 2026
0f4045b
Add ServerUrlUtils, Vietnamese/Traditional Chinese translations, and …
daedaevibin Jun 24, 2026
54dca07
Merge remote-tracking branch 'upstream/master'
daedaevibin Jun 24, 2026
b98c567
chore(deps): bump the github-actions group with 2 updates
dependabot[bot] Jun 24, 2026
dce462d
chore(deps): bump the gradle-dependencies group with 2 updates
dependabot[bot] Jun 24, 2026
2bfbd3b
Merge pull request #45 from Veridian-Zenith/dependabot/github_actions…
daedaevibin Jun 25, 2026
b6b2096
Merge pull request #46 from Veridian-Zenith/dependabot/gradle/gradle-…
daedaevibin Jun 25, 2026
8607ca0
File cleanup
daedaevibin Jun 25, 2026
ea72d88
chore(deps): bump the gradle-dependencies group across 1 directory wi…
dependabot[bot] Jun 26, 2026
8eac816
Merge pull request #48 from Veridian-Zenith/dependabot/gradle/gradle-…
daedaevibin Jun 28, 2026
86422df
fix(wear): add error_prone_annotations dependency for Dagger 2.60 gen…
daedaevibin Jun 28, 2026
a10cfe5
chore(deps): bump the gradle-dependencies group with 6 updates
dependabot[bot] Jun 29, 2026
a44b927
Merge pull request #50 from Veridian-Zenith/dependabot/gradle/gradle-…
daedaevibin Jun 30, 2026
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
19 changes: 8 additions & 11 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,32 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Set up JDK 21
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '21'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6
with:
cache-provider: 'enhanced'

- name: Pin Kotlin version for CodeQL compatibility
run: |
# More robust sed pattern that handles various formats
sed -i 's/kotlin = "[^"]*"/kotlin = "2.3.20"/g' gradle/libs.versions.toml

# Verify the change was made
grep 'kotlin = "2.3.20"' gradle/libs.versions.toml


- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6
with:
cache-provider: 'enhanced'

- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: java-kotlin
build-mode: manual

- name: Build with Gradle
run: ${{ github.workspace }}/gradlew :app:assembleDebug :wear:assembleDebug --no-daemon
run: ${{ github.workspace }}/gradlew :app:assembleDebug :wear:assembleDebug --no-daemon --no-build-cache

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/nightly-apk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Set up JDK 21
uses: actions/setup-java@v5
Expand All @@ -98,7 +98,7 @@ jobs:

- name: Cache nightly keystore
id: cache-keystore
uses: actions/cache@v5
uses: actions/cache@v6
with:
path: vz-pixelplay.jks
key: ${{ runner.os }}-nightly-keystore-vz-pixelplay
Expand All @@ -117,7 +117,7 @@ jobs:
echo "keyPassword=994273" >> keystore.properties

- name: Build Phone nightly release APKs
run: gradle :app:assembleRelease -Ppixelplay.enableAbiSplits=true
run: gradle :app:assembleRelease -Ppixelplay.enableAbiSplits=true --no-build-cache

- name: Verify Phone nightly split APKs
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/phone-debug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Set up JDK 21
uses: actions/setup-java@v5
Expand All @@ -30,7 +30,7 @@ jobs:
uses: gradle/actions/setup-gradle@v6

- name: Build Phone debug APK
run: gradle :app:assembleDebug -Ppixelplay.enableAbiSplits=true
run: gradle :app:assembleDebug -Ppixelplay.enableAbiSplits=true --no-build-cache

- name: Verify Phone split APKs
run: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/phone-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Set up JDK 21
uses: actions/setup-java@v5
Expand All @@ -31,7 +31,7 @@ jobs:

- name: Cache keystore
id: cache-keystore
uses: actions/cache@v5
uses: actions/cache@v6
with:
path: vz-pixelplay.jks
key: ${{ runner.os }}-keystore-vz-pixelplay
Expand All @@ -52,7 +52,7 @@ jobs:
echo "keyPassword=994273" >> keystore.properties

- name: Build Phone release APK
run: gradle :app:assembleRelease -Ppixelplay.enableAbiSplits=true
run: gradle :app:assembleRelease -Ppixelplay.enableAbiSplits=true --no-build-cache

- name: Verify Phone split APKs
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/wearos-apk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Set up JDK 21
uses: actions/setup-java@v5
Expand All @@ -30,7 +30,7 @@ jobs:
uses: gradle/actions/setup-gradle@v6

- name: Build Wear OS debug APK
run: gradle :wear:assembleDebug
run: gradle :wear:assembleDebug --no-build-cache

- name: Upload Wear OS APK artifact
uses: actions/upload-artifact@v7.0.1
Expand Down
1 change: 0 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,6 @@ dependencies {

// UI Utilities & Extra
implementation(libs.timber)
implementation(libs.generativeai)
implementation(libs.smooth.corner.rect.android.compose)
implementation(libs.reorderables)
implementation(libs.codeview)
Expand Down
20 changes: 20 additions & 0 deletions app/lint.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<!-- Translation completeness cannot be enforced without native speakers -->
<issue id="MissingTranslation" severity="warning" />
<issue id="ExtraTranslation" severity="warning" />
<issue id="MissingQuantity" severity="warning" />
<issue id="ImpliedQuantity" severity="warning" />

<!-- Intentional use of Material Design 3 internal color APIs for dynamic theme -->
<issue id="RestrictedApi" severity="warning" />

<!-- Media3 APIs marked @UnstableApi are used intentionally throughout -->
<issue id="UnsafeOptInUsageError" severity="warning" />

<!-- Compose resource access via LocalContext.current is accepted pattern -->
<issue id="LocalContextGetResourceValueCall" severity="warning" />

<!-- Missing default resource -- resolved by adding declarations to base values/ -->
<issue id="MissingDefaultResource" severity="error" />
</lint>
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@
<action android:name="com.theveloper.pixelplay.action.OPEN_PLAYER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class ExternalPlayerActivity : ComponentActivity() {
return intent.data
}

@Suppress("WrongConstant")
private fun persistUriPermissionIfNeeded(intent: Intent, uri: Uri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val hasPersistablePermission = intent.flags and Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION != 0
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/theveloper/pixelplay/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import android.content.Context
import android.content.ComponentName
import android.content.Intent
import android.os.Build
import androidx.annotation.RequiresApi
import android.graphics.RenderEffect as AndroidRenderEffect
import android.graphics.Shader as AndroidShader
import androidx.compose.ui.graphics.asComposeRenderEffect
Expand Down Expand Up @@ -943,6 +944,7 @@ class MainActivity : ComponentActivity() {
val expansionFractionProvider = remember(playerViewModel.playerContentExpansionFraction) {
{ playerViewModel.playerContentExpansionFraction.value }
}
@Suppress("NewApi")
val blurEffectCache = remember { BlurEffectCache() }

Box(
Expand Down Expand Up @@ -1152,10 +1154,12 @@ class MainActivity : ComponentActivity() {
* blur every animation frame. The radius is quantized at the call site, so this
* only rebuilds ~25 times across the whole expand animation instead of 60+/sec.
*/
@RequiresApi(Build.VERSION_CODES.S)
private class BlurEffectCache {
private var lastRadiusPx: Float = Float.NaN
private var cached: androidx.compose.ui.graphics.RenderEffect? = null

@RequiresApi(Build.VERSION_CODES.S)
fun get(radiusPx: Float): androidx.compose.ui.graphics.RenderEffect? {
if (radiusPx <= 0f) {
lastRadiusPx = 0f
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class AiPreferencesRepository @Inject constructor(
dataStore.data.map { preferences -> preferences[Keys.AI_TOP_K] ?: 64 }

val aiMaxTokens: Flow<Int> =
dataStore.data.map { preferences -> preferences[Keys.AI_MAX_TOKENS] ?: 4096 }
dataStore.data.map { preferences -> preferences[Keys.AI_MAX_TOKENS] ?: 8192 }

val aiPresencePenalty: Flow<Float> =
dataStore.data.map { preferences -> preferences[Keys.AI_PRESENCE_PENALTY] ?: 0.0f }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ enum class AppLanguage(val tag: String, @StringRes val labelRes: Int) {
FRENCH("fr", R.string.settings_language_french),
INDONESIAN("in", R.string.settings_language_indonesian),
ITALIAN("it", R.string.settings_language_italian),
JAPANESE("ja", R.string.settings_language_japanese),
KOREAN("ko", R.string.settings_language_korean),
NORWEGIAN_BOKMAL("nb", R.string.settings_language_norwegian_bokmal),
RUSSIAN("ru", R.string.settings_language_russian),
SIMPLIFIED_CHINESE("zh-CN", R.string.settings_language_chinese),
TURKISH("tr", R.string.settings_language_turkish);
TRADITIONAL_CHINESE("zh-TW", R.string.settings_language_traditional_chinese),
TURKISH("tr", R.string.settings_language_turkish),
VIETNAMESE("vi", R.string.settings_language_vietnamese);

companion object {
val supportedLanguageTags: Set<String> = values().map { it.tag }.toSet()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,14 @@ class LyricsRepositoryImpl @Inject constructor(

val lyricsData = LyricsData(
plainLyrics = lyrics.plain?.joinToString("\n"),
syncedLyrics = lyrics.synced?.joinToString("\n") { "[${formatTimestamp(it.time)}]${it.line}" },
syncedLyrics = lyrics.synced?.joinToString("\n") { line ->
buildString {
append("[${formatTimestamp(line.time)}]${line.line}")
if (!line.translation.isNullOrBlank()) {
append("\n[${formatTimestamp(line.time)}]${line.translation}")
}
}
},
wordByWordLyrics = wordByWordLyrics
)

Expand Down Expand Up @@ -1247,7 +1254,12 @@ class LyricsRepositoryImpl @Inject constructor(
toWordByWordLrc(syncedLyrics)
} else {
syncedLyrics.joinToString("\n") { line ->
"[${formatTimestamp(line.time)}]${line.line}"
buildString {
append("[${formatTimestamp(line.time)}]${line.line}")
if (!line.translation.isNullOrBlank()) {
append("\n[${formatTimestamp(line.time)}]${line.translation}")
}
}
}
}
}
Expand Down Expand Up @@ -1710,6 +1722,8 @@ class LyricsRepositoryImpl @Inject constructor(
MultiLangRomanizer.isJapanese(text) -> MultiLangRomanizer.romanizeJapanese(text) ?: text
MultiLangRomanizer.isChinese(text) -> MultiLangRomanizer.romanizeChinese(text) ?: text
MultiLangRomanizer.isKorean(text) -> MultiLangRomanizer.romanizeKorean(text)
MultiLangRomanizer.isCyrillic(text) -> MultiLangRomanizer.romanizeCyrillic(text) ?: text
MultiLangRomanizer.isVietnamese(text) -> MultiLangRomanizer.romanizeVietnamese(text)
else -> text
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,6 @@ fun FullPlayerContent(
if (showFetchLyricsDialog) {
showFetchLyricsDialog = false
showLyricsSheet = true
playerViewModel.resetLyricsSearchState()
}
}
is LyricsSearchUiState.Error -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.material.icons.rounded.Info
import androidx.compose.material.icons.rounded.LibraryMusic
import androidx.compose.material.icons.rounded.MusicNote
import androidx.compose.material.icons.rounded.Palette
import androidx.compose.material.icons.rounded.QueueMusic
import androidx.compose.ui.graphics.vector.ImageVector
import com.theveloper.pixelplay.R

Expand All @@ -31,11 +32,23 @@ enum class SettingsCategory(
subtitleRes = R.string.settings_category_appearance_subtitle,
icon = Icons.Rounded.Palette
),
LYRICS(
id = "lyrics",
titleRes = R.string.settings_category_lyrics_title,
subtitleRes = R.string.settings_category_lyrics_subtitle,
icon = Icons.Rounded.QueueMusic
),
PLAYBACK(
id = "playback",
titleRes = R.string.settings_category_playback_title,
subtitleRes = R.string.settings_category_playback_subtitle,
icon = Icons.Rounded.MusicNote // Using MusicNote again or maybe PlayCircle if available
icon = Icons.Rounded.MusicNote
),
EQUALIZER(
id = "equalizer",
titleRes = R.string.settings_category_equalizer_title,
subtitleRes = R.string.settings_category_equalizer_subtitle,
icon = Icons.Rounded.GraphicEq
),
BEHAVIOR(
id = "behavior",
Expand All @@ -61,17 +74,11 @@ enum class SettingsCategory(
subtitleRes = R.string.settings_category_developer_subtitle,
icon = Icons.Rounded.DeveloperMode
),
EQUALIZER(
id = "equalizer",
titleRes = R.string.settings_category_equalizer_title,
subtitleRes = R.string.settings_category_equalizer_subtitle,
icon = Icons.Rounded.GraphicEq
),
DEVICE_CAPABILITIES(
id = "device_capabilities",
titleRes = R.string.settings_category_device_capabilities_title,
subtitleRes = R.string.settings_category_device_capabilities_subtitle,
icon = Icons.Rounded.DeveloperBoard // Placeholder, maybe Memory or SettingsInputComponent
icon = Icons.Rounded.DeveloperBoard
),
ABOUT(
id = "about",
Expand All @@ -83,4 +90,6 @@ enum class SettingsCategory(
companion object {
fun fromId(id: String): SettingsCategory? = entries.find { it.id == id }
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ fun AiUsageDateHeader(date: String) {
}

@Composable
@Suppress("NonObservableLocale")
fun AiUsageLogItem(
usage: AiUsageEntity
) {
Expand Down
Loading
Loading