From 8b3e7b6d5de3ce99be14e0ce36909c1a365a5a47 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Tue, 28 Jul 2026 23:35:54 +0800 Subject: [PATCH 01/20] Modify MP3 extractor flags to disable ID3 metadata --- .../pixelplay/data/service/player/DualPlayerEngine.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/theveloper/pixelplay/data/service/player/DualPlayerEngine.kt b/app/src/main/java/com/theveloper/pixelplay/data/service/player/DualPlayerEngine.kt index c8f05dc0a2..1721655fdf 100644 --- a/app/src/main/java/com/theveloper/pixelplay/data/service/player/DualPlayerEngine.kt +++ b/app/src/main/java/com/theveloper/pixelplay/data/service/player/DualPlayerEngine.kt @@ -1121,7 +1121,7 @@ class DualPlayerEngine @Inject constructor( // FLAG_ENABLE_CONSTANT_BITRATE_SEEKING (not _ALWAYS): fallback-only CBR seeking // so VBR MP3s with proper Xing/VBRI headers still use their seek table and land // on the exact frame instead of jumping ±30 s on a VBR file. - .setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING) + .setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING or Mp3Extractor.FLAG_DISABLE_ID3_METADATA) .setFlacExtractorFlags(FlacExtractor.FLAG_DISABLE_ID3_METADATA) val loadControl = buildAdaptiveLoadControl() From ac281594c9ceb09680bf7bfc4099dbc4a225bac6 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Tue, 28 Jul 2026 23:38:00 +0800 Subject: [PATCH 02/20] Increase SHUFFLE_SAMPLE_LIMIT to 10000 --- .../pixelplay/presentation/viewmodel/QueueStateHolder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/QueueStateHolder.kt b/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/QueueStateHolder.kt index d69d9f52f3..38aafaf1df 100644 --- a/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/QueueStateHolder.kt +++ b/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/QueueStateHolder.kt @@ -55,7 +55,7 @@ class QueueStateHolder @Inject constructor( ) { companion object { - private const val SHUFFLE_SAMPLE_LIMIT = 500 + private const val SHUFFLE_SAMPLE_LIMIT = 10000 private const val ALL_SONGS_SHUFFLED_QUEUE = "All Songs (Shuffled)" private const val FAVORITES_SHUFFLED_QUEUE = "Liked Songs (Shuffled)" } From bd84527334815d9b12136523cd9f8197e98a4a6c Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Tue, 28 Jul 2026 23:40:04 +0800 Subject: [PATCH 03/20] Increase limit for random songs retrieval to 10000 --- .../presentation/viewmodel/PlaybackDispatchStateHolder.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/PlaybackDispatchStateHolder.kt b/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/PlaybackDispatchStateHolder.kt index 8e346ebc43..d32229c3ec 100644 --- a/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/PlaybackDispatchStateHolder.kt +++ b/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/PlaybackDispatchStateHolder.kt @@ -654,7 +654,7 @@ class PlaybackDispatchStateHolder @Inject constructor( val action: () -> Unit = { Timber.d("[TileDebug] action() invoked") cb.scope.launch { - var songs = musicRepository.getRandomSongs(limit = 500) + var songs = musicRepository.getRandomSongs(limit = 10000) Timber.d("[TileDebug] Repository returned ${songs.size} random songs immediately") if (songs.isEmpty()) { @@ -664,7 +664,7 @@ class PlaybackDispatchStateHolder @Inject constructor( songs = withTimeoutOrNull(30_000L) { var refreshedSongs = emptyList() while (refreshedSongs.isEmpty()) { - refreshedSongs = musicRepository.getRandomSongs(limit = 500) + refreshedSongs = musicRepository.getRandomSongs(limit = 10000) if (refreshedSongs.isEmpty()) { delay(500L) } From eaba30476cdcd42fecee7153942576302d50514a Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 09:18:32 +0800 Subject: [PATCH 04/20] Remove armeabi-v7a from ABI splits inclusion --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9f2583065f..80cf70ff36 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -178,7 +178,7 @@ android { isEnable = enableAbiSplits reset() if (enableAbiSplits) { - include("arm64-v8a", "armeabi-v7a") + include("arm64-v8a") isUniversalApk = false } } From 5bce15e8e090c72e39570c2e58b1309a41b2f712 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 09:29:31 +0800 Subject: [PATCH 05/20] Modify phone-release workflow for APK handling Updated permissions to allow write access and modified APK verification and release steps. --- .github/workflows/phone-release.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/phone-release.yml b/.github/workflows/phone-release.yml index 1c33965a3e..27c316561a 100644 --- a/.github/workflows/phone-release.yml +++ b/.github/workflows/phone-release.yml @@ -9,7 +9,7 @@ on: workflow_dispatch: permissions: - contents: read + contents: write jobs: build-phone: @@ -58,8 +58,8 @@ jobs: run: | BUILD_TOOLS_VERSION="$(ls "$ANDROID_HOME/build-tools" | sort -V | tail -n 1)" for apk in \ - app/build/outputs/apk/release/app-arm64-v8a-release.apk \ - app/build/outputs/apk/release/app-armeabi-v7a-release.apk + app/build/outputs/apk/release/app-arm64-v8a-release.apk + do "$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION/aapt2" dump badging "$apk" >/dev/null "$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION/apksigner" verify --verbose "$apk" @@ -71,6 +71,14 @@ jobs: name: PixelPlay-phone-release-split-apks path: | app/build/outputs/apk/release/app-arm64-v8a-release.apk - app/build/outputs/apk/release/app-armeabi-v7a-release.apk + if-no-files-found: error compression-level: 0 + + - name: Publish direct-download release + uses: softprops/action-gh-release@v2 + with: + tag_name: latest-release + name: "Latest build" + prerelease: true + files: app/build/outputs/apk/release/app-arm64-v8a-release.apk From d1f754d4e4c13caf3b63ee6b301873c87dada534 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 09:34:40 +0800 Subject: [PATCH 06/20] Refactor phone-release workflow for APK verification --- .github/workflows/phone-release.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/phone-release.yml b/.github/workflows/phone-release.yml index 27c316561a..525ea2dbfd 100644 --- a/.github/workflows/phone-release.yml +++ b/.github/workflows/phone-release.yml @@ -58,8 +58,7 @@ jobs: run: | BUILD_TOOLS_VERSION="$(ls "$ANDROID_HOME/build-tools" | sort -V | tail -n 1)" for apk in \ - app/build/outputs/apk/release/app-arm64-v8a-release.apk - + app/build/outputs/apk/release/app-arm64-v8a-release.apk do "$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION/aapt2" dump badging "$apk" >/dev/null "$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION/apksigner" verify --verbose "$apk" @@ -71,11 +70,10 @@ jobs: name: PixelPlay-phone-release-split-apks path: | app/build/outputs/apk/release/app-arm64-v8a-release.apk - if-no-files-found: error compression-level: 0 - - name: Publish direct-download release + - name: Publish direct-download release uses: softprops/action-gh-release@v2 with: tag_name: latest-release From 4803622c247af48a4d0a07107aed8efc87ad2a06 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 10:34:11 +0800 Subject: [PATCH 07/20] Add Your Mix settings category strings --- app/src/main/res/values/strings_settings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values/strings_settings.xml b/app/src/main/res/values/strings_settings.xml index 1c6ae4e284..b335980b79 100644 --- a/app/src/main/res/values/strings_settings.xml +++ b/app/src/main/res/values/strings_settings.xml @@ -1,6 +1,8 @@ + Your Mix + Tune the size and randomness of your home screen mix Music Management Manage folders, refresh library, parsing options Appearance From 0e9c3fa1730be012d49be71abe7ac14b22a4aada Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 10:49:33 +0800 Subject: [PATCH 08/20] Update SettingsCategory.kt --- .../pixelplay/presentation/model/SettingsCategory.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/com/theveloper/pixelplay/presentation/model/SettingsCategory.kt b/app/src/main/java/com/theveloper/pixelplay/presentation/model/SettingsCategory.kt index e59c3d7a8c..d11fa64e51 100644 --- a/app/src/main/java/com/theveloper/pixelplay/presentation/model/SettingsCategory.kt +++ b/app/src/main/java/com/theveloper/pixelplay/presentation/model/SettingsCategory.kt @@ -19,6 +19,12 @@ enum class SettingsCategory( val icon: ImageVector? = null, val iconRes: Int? = null ) { + YOUR_MIX( + id = "your_mix", + titleRes = R.string.settings_category_yourmix_title, + subtitleRes = R.string.settings_category_yourmix_subtitle, + iconRes = R.drawable.rounded_instant_mix_24 + ), LIBRARY( id = "library", titleRes = R.string.settings_category_music_management_title, From c6777d577eee36d6b307a3ddb36de5b7272d9149 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 11:03:29 +0800 Subject: [PATCH 09/20] Update color mappings for YOUR_MIX category --- .../theveloper/pixelplay/presentation/screens/SettingsScreen.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/theveloper/pixelplay/presentation/screens/SettingsScreen.kt b/app/src/main/java/com/theveloper/pixelplay/presentation/screens/SettingsScreen.kt index fa40ecb265..db70a6d436 100644 --- a/app/src/main/java/com/theveloper/pixelplay/presentation/screens/SettingsScreen.kt +++ b/app/src/main/java/com/theveloper/pixelplay/presentation/screens/SettingsScreen.kt @@ -478,6 +478,7 @@ fun ExpressiveSettingsGroup(content: @Composable () -> Unit) { private fun getCategoryColors(category: SettingsCategory, isDark: Boolean): Pair { return if (isDark) { when (category) { + SettingsCategory.YOUR_MIX -> Color(0xFF4A3B77) to Color(0xFFE2D6FF) SettingsCategory.LIBRARY -> Color(0xFF004A77) to Color(0xFFC2E7FF) SettingsCategory.APPEARANCE -> Color(0xFF7D5260) to Color(0xFFFFD8E4) SettingsCategory.PLAYBACK -> Color(0xFF633B48) to Color(0xFFFFD8EC) @@ -491,6 +492,7 @@ private fun getCategoryColors(category: SettingsCategory, isDark: Boolean): Pair } } else { when (category) { + SettingsCategory.YOUR_MIX -> Color(0xFFE2D6FF) to Color(0xFF2C1B5B) SettingsCategory.LIBRARY -> Color(0xFFD7E3FF) to Color(0xFF005AC1) SettingsCategory.APPEARANCE -> Color(0xFFFFD8E4) to Color(0xFF631835) SettingsCategory.PLAYBACK -> Color(0xFFFFD8EC) to Color(0xFF631B4B) From ab221f29fe889a4abc66032c8ce328c8fbcc6bfc Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 11:12:14 +0800 Subject: [PATCH 10/20] Add user mix preferences to UserPreferencesRepository Added preferences for mix size, favorite percent, and core percent with corresponding flows and setters. --- .../preferences/UserPreferencesRepository.kt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/app/src/main/java/com/theveloper/pixelplay/data/preferences/UserPreferencesRepository.kt b/app/src/main/java/com/theveloper/pixelplay/data/preferences/UserPreferencesRepository.kt index 4598f1a86f..e6766ce968 100644 --- a/app/src/main/java/com/theveloper/pixelplay/data/preferences/UserPreferencesRepository.kt +++ b/app/src/main/java/com/theveloper/pixelplay/data/preferences/UserPreferencesRepository.kt @@ -119,6 +119,9 @@ class UserPreferencesRepository @Inject constructor( val LAST_DAILY_MIX_UPDATE = longPreferencesKey("last_daily_mix_update") val DAILY_MIX_SONG_IDS = stringPreferencesKey("daily_mix_song_ids") val YOUR_MIX_SONG_IDS = stringPreferencesKey("your_mix_song_ids") + val YOUR_MIX_SIZE = intPreferencesKey("your_mix_size") + val YOUR_MIX_FAVORITE_PERCENT = intPreferencesKey("your_mix_favorite_percent") + val YOUR_MIX_CORE_PERCENT = intPreferencesKey("your_mix_core_percent") val NAV_BAR_CORNER_RADIUS = intPreferencesKey("nav_bar_corner_radius") val NAV_BAR_STYLE = stringPreferencesKey("nav_bar_style") val NAV_BAR_COMPACT_MODE = booleanPreferencesKey("nav_bar_compact_mode") @@ -665,6 +668,27 @@ suspend fun markDirectoryRulesVersionApplied(version: Int) { } } + val yourMixSizeFlow: Flow = + dataStore.data.map { preferences -> preferences[PreferencesKeys.YOUR_MIX_SIZE] ?: 60 } + + suspend fun setYourMixSize(size: Int) { + dataStore.edit { preferences -> preferences[PreferencesKeys.YOUR_MIX_SIZE] = size.coerceIn(20, 300) } + } + + val yourMixFavoritePercentFlow: Flow = + dataStore.data.map { preferences -> preferences[PreferencesKeys.YOUR_MIX_FAVORITE_PERCENT] ?: 30 } + + suspend fun setYourMixFavoritePercent(percent: Int) { + dataStore.edit { preferences -> preferences[PreferencesKeys.YOUR_MIX_FAVORITE_PERCENT] = percent.coerceIn(0, 100) } + } + + val yourMixCorePercentFlow: Flow = + dataStore.data.map { preferences -> preferences[PreferencesKeys.YOUR_MIX_CORE_PERCENT] ?: 45 } + + suspend fun setYourMixCorePercent(percent: Int) { + dataStore.edit { preferences -> preferences[PreferencesKeys.YOUR_MIX_CORE_PERCENT] = percent.coerceIn(0, 100) } + } + val isGenreGridViewFlow: Flow = dataStore.data.map { preferences -> preferences[PreferencesKeys.IS_GENRE_GRID_VIEW] ?: true From 8d1caa0866242fbecf9cc916277264f257d0fa68 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 11:15:26 +0800 Subject: [PATCH 11/20] Update DailyMixManager.kt --- .../java/com/theveloper/pixelplay/data/DailyMixManager.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/theveloper/pixelplay/data/DailyMixManager.kt b/app/src/main/java/com/theveloper/pixelplay/data/DailyMixManager.kt index 1d00e69ab5..d940d5d21e 100644 --- a/app/src/main/java/com/theveloper/pixelplay/data/DailyMixManager.kt +++ b/app/src/main/java/com/theveloper/pixelplay/data/DailyMixManager.kt @@ -423,8 +423,8 @@ class DailyMixManager @Inject constructor( return allSongs.shuffled(random).take(limit.coerceAtMost(allSongs.size)) } - val favoriteSectionSize = (limit * 0.3).toInt().coerceAtLeast(5).coerceAtMost(limit) - val coreSectionSize = (limit * 0.45).toInt().coerceAtLeast(10).coerceAtMost(limit) + val favoriteSectionSize = (limit * (favoriteWeightPercent / 100.0)).toInt().coerceAtLeast(0).coerceAtMost(limit) + val coreSectionSize = (limit * (coreWeightPercent / 100.0)).toInt().coerceAtLeast(0).coerceAtMost(limit - favoriteSectionSize) val discoverySectionSize = (limit - favoriteSectionSize - coreSectionSize).coerceAtLeast(0) val diversityState = DiversityState() From ae08754a64cbdb5f625c2ea9eed265d5a82bfeb4 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 11:24:47 +0800 Subject: [PATCH 12/20] Enhance daily mix generation with user preferences Refactor daily mix generation to include user-defined limits and weights. --- .../presentation/viewmodel/DailyMixStateHolder.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/DailyMixStateHolder.kt b/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/DailyMixStateHolder.kt index 92dbee60bd..bbd316bd62 100644 --- a/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/DailyMixStateHolder.kt +++ b/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/DailyMixStateHolder.kt @@ -80,7 +80,16 @@ class DailyMixStateHolder @Inject constructor( userPreferencesRepository.saveDailyMixSongIds(mix.map { it.id }) // Generate your mix - val yourMix = dailyMixManager.generateYourMix(allSongs, favoriteIds) + val yourMixSize = userPreferencesRepository.yourMixSizeFlow.first() + val yourMixFavoritePercent = userPreferencesRepository.yourMixFavoritePercentFlow.first() + val yourMixCorePercent = userPreferencesRepository.yourMixCorePercentFlow.first() + val yourMix = dailyMixManager.generateYourMix( + allSongs, + favoriteIds, + limit = yourMixSize, + favoriteWeightPercent = yourMixFavoritePercent, + coreWeightPercent = yourMixCorePercent + ) _yourMixSongs.value = yourMix.toImmutableList() userPreferencesRepository.saveYourMixSongIds(yourMix.map { it.id }) } else { From 4a4698c4582d827db8ddd304d46dca363f9c2122 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 11:28:19 +0800 Subject: [PATCH 13/20] Update SettingsViewModel.kt --- .../viewmodel/SettingsViewModel.kt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/SettingsViewModel.kt b/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/SettingsViewModel.kt index abba7eaceb..cdfaeae06a 100644 --- a/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/SettingsViewModel.kt +++ b/app/src/main/java/com/theveloper/pixelplay/presentation/viewmodel/SettingsViewModel.kt @@ -60,6 +60,9 @@ data class SettingsUiState( val albumArtPaletteStyle: AlbumArtPaletteStyle = AlbumArtPaletteStyle.default, val albumArtColorAccuracy: Int = AlbumArtColorAccuracy.DEFAULT, val mockGenresEnabled: Boolean = false, + val yourMixSize: Int = 60, + val yourMixFavoritePercent: Int = 30, + val yourMixCorePercent: Int = 45, val navBarCornerRadius: Int = 32, val navBarStyle: String = NavBarStyle.DEFAULT, val navBarCompactMode: Boolean = false, @@ -579,6 +582,24 @@ class SettingsViewModel @Inject constructor( } } + viewModelScope.launch { + userPreferencesRepository.yourMixSizeFlow.collect { size -> + _uiState.update { it.copy(yourMixSize = size) } + } + } + + viewModelScope.launch { + userPreferencesRepository.yourMixFavoritePercentFlow.collect { percent -> + _uiState.update { it.copy(yourMixFavoritePercent = percent) } + } + } + + viewModelScope.launch { + userPreferencesRepository.yourMixCorePercentFlow.collect { percent -> + _uiState.update { it.copy(yourMixCorePercent = percent) } + } + } + // One-time device capability check — result is cached inside HiFiCapabilityChecker _uiState.update { it.copy( @@ -1314,6 +1335,18 @@ class SettingsViewModel @Inject constructor( fun setNavBarCornerRadius(radius: Int) { viewModelScope.launch { userPreferencesRepository.setNavBarCornerRadius(radius) } } + + fun setYourMixSize(size: Int) { + viewModelScope.launch { userPreferencesRepository.setYourMixSize(size) } + } + + fun setYourMixFavoritePercent(percent: Int) { + viewModelScope.launch { userPreferencesRepository.setYourMixFavoritePercent(percent) } + } + + fun setYourMixCorePercent(percent: Int) { + viewModelScope.launch { userPreferencesRepository.setYourMixCorePercent(percent) } + } /** * Triggers a test crash to verify the crash handler is working correctly. * This should only be used for testing in Developer Options. From fa592929ef2c7c38eb3f79251e97b42adc61a12b Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 11:34:50 +0800 Subject: [PATCH 14/20] Update SettingsCategoryScreen.kt --- .../screens/SettingsCategoryScreen.kt | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/app/src/main/java/com/theveloper/pixelplay/presentation/screens/SettingsCategoryScreen.kt b/app/src/main/java/com/theveloper/pixelplay/presentation/screens/SettingsCategoryScreen.kt index dd1672dbc6..2acbd94316 100644 --- a/app/src/main/java/com/theveloper/pixelplay/presentation/screens/SettingsCategoryScreen.kt +++ b/app/src/main/java/com/theveloper/pixelplay/presentation/screens/SettingsCategoryScreen.kt @@ -415,6 +415,52 @@ fun SettingsCategoryScreen( modifier = Modifier.background(Color.Transparent) ) { when (category) { + SettingsCategory.YOUR_MIX -> { + SettingsSubsection(title = "Mix size") { + SliderSettingsItem( + label = "Number of songs", + value = uiState.yourMixSize.toFloat(), + valueRange = 20f..300f, + steps = 27, + onValueChange = { settingsViewModel.setYourMixSize(it.toInt()) }, + valueText = { value -> "${value.toInt()} songs" } + ) + } + SettingsSubsection(title = "Composition") { + SliderSettingsItem( + label = "Favorites", + value = uiState.yourMixFavoritePercent.toFloat(), + valueRange = 0f..100f, + steps = 19, + onValueChange = { settingsViewModel.setYourMixFavoritePercent(it.toInt()) }, + valueText = { value -> "${value.toInt()}%" } + ) + SliderSettingsItem( + label = "Core (most played)", + value = uiState.yourMixCorePercent.toFloat(), + valueRange = 0f..100f, + steps = 19, + onValueChange = { settingsViewModel.setYourMixCorePercent(it.toInt()) }, + valueText = { value -> "${value.toInt()}%" } + ) + val discoveryPercent = (100 - uiState.yourMixFavoritePercent - uiState.yourMixCorePercent).coerceAtLeast(0) + Text( + text = "Discovery (rarely played): $discoveryPercent% — fills whatever's left over", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 8.dp) + ) + } + SettingsSubsection(title = "Apply changes", addBottomSpace = false) { + ActionSettingsItem( + title = "Regenerate Your Mix now", + subtitle = "Rebuild your home screen mix using the settings above", + icon = { Icon(painterResource(R.drawable.rounded_instant_mix_24), null, tint = MaterialTheme.colorScheme.secondary) }, + primaryActionLabel = "Regenerate", + onPrimaryAction = { showRegenerateDailyMixDialog = true } + ) + } + } SettingsCategory.LIBRARY -> { SettingsSubsection(title = stringResource(R.string.settings_library_structure_section)) { SettingsItem( From 2e4d88536a3067220031eaae71c7919f3e2fafd8 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 11:49:49 +0800 Subject: [PATCH 15/20] Add weight parameters to generateYourMix function Added parameters for favorite and core weight percentages in generateYourMix function. --- .../java/com/theveloper/pixelplay/data/DailyMixManager.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/theveloper/pixelplay/data/DailyMixManager.kt b/app/src/main/java/com/theveloper/pixelplay/data/DailyMixManager.kt index d940d5d21e..7bed49928c 100644 --- a/app/src/main/java/com/theveloper/pixelplay/data/DailyMixManager.kt +++ b/app/src/main/java/com/theveloper/pixelplay/data/DailyMixManager.kt @@ -408,7 +408,9 @@ class DailyMixManager @Inject constructor( suspend fun generateYourMix( allSongs: List, favoriteSongIds: Set = emptySet(), - limit: Int = 60 + limit: Int = 60, + favoriteWeightPercent: Int = 30, + coreWeightPercent: Int = 45 ): List { if (allSongs.isEmpty()) { return emptyList() From 5a1eae9b6e7b40f3ec3dda31cb1226859e7dac02 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 12:48:09 +0800 Subject: [PATCH 16/20] Rename project from PixelPlayer to PixelPlayerX --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca3d9e1ecb..025c6de905 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# PixelPlayer 🎵 +# PixelPlayerX 🎵

App Icon From f830f3f3a1f911351fd1de1caff7fd34fef0159a Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 13:13:09 +0800 Subject: [PATCH 17/20] Rename project from PixelPlayerX to PixelPlayer --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 025c6de905..ca3d9e1ecb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# PixelPlayerX 🎵 +# PixelPlayer 🎵

App Icon From 1e63f93c8e5691844da5e6e199bff69cbe8332d4 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 13:31:55 +0800 Subject: [PATCH 18/20] Add armeabi-v7a APK to release artifacts --- .github/workflows/phone-release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/phone-release.yml b/.github/workflows/phone-release.yml index 525ea2dbfd..c1194e0fa0 100644 --- a/.github/workflows/phone-release.yml +++ b/.github/workflows/phone-release.yml @@ -69,7 +69,8 @@ jobs: with: name: PixelPlay-phone-release-split-apks path: | - app/build/outputs/apk/release/app-arm64-v8a-release.apk + app/build/outputs/apk/release/app-arm64-v8a-release.apk \ + app/build/outputs/apk/release/app-armeabi-v7a-release.apk if-no-files-found: error compression-level: 0 From 014d53539d3caf216849c1a51997253e38299f93 Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 13:43:31 +0800 Subject: [PATCH 19/20] Update phone-release.yml --- .github/workflows/phone-release.yml | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/.github/workflows/phone-release.yml b/.github/workflows/phone-release.yml index c1194e0fa0..1c33965a3e 100644 --- a/.github/workflows/phone-release.yml +++ b/.github/workflows/phone-release.yml @@ -9,7 +9,7 @@ on: workflow_dispatch: permissions: - contents: write + contents: read jobs: build-phone: @@ -58,7 +58,8 @@ jobs: run: | BUILD_TOOLS_VERSION="$(ls "$ANDROID_HOME/build-tools" | sort -V | tail -n 1)" for apk in \ - app/build/outputs/apk/release/app-arm64-v8a-release.apk + app/build/outputs/apk/release/app-arm64-v8a-release.apk \ + app/build/outputs/apk/release/app-armeabi-v7a-release.apk do "$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION/aapt2" dump badging "$apk" >/dev/null "$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION/apksigner" verify --verbose "$apk" @@ -69,15 +70,7 @@ jobs: with: name: PixelPlay-phone-release-split-apks path: | - app/build/outputs/apk/release/app-arm64-v8a-release.apk \ + app/build/outputs/apk/release/app-arm64-v8a-release.apk app/build/outputs/apk/release/app-armeabi-v7a-release.apk if-no-files-found: error compression-level: 0 - - - name: Publish direct-download release - uses: softprops/action-gh-release@v2 - with: - tag_name: latest-release - name: "Latest build" - prerelease: true - files: app/build/outputs/apk/release/app-arm64-v8a-release.apk From 9ddc670a62e7dfc8eae4dae05b68758920f5a33c Mon Sep 17 00:00:00 2001 From: tehrzky <61300808+tehrzky@users.noreply.github.com> Date: Wed, 29 Jul 2026 13:59:25 +0800 Subject: [PATCH 20/20] Add armeabi-v7a to ABI splits configuration --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 80cf70ff36..9f2583065f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -178,7 +178,7 @@ android { isEnable = enableAbiSplits reset() if (enableAbiSplits) { - include("arm64-v8a") + include("arm64-v8a", "armeabi-v7a") isUniversalApk = false } }