Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
13aaad9
Update French changelog strings and translations
rebornlokii Jun 13, 2026
5196043
Revise Italian changelog strings for clarity
rebornlokii Jun 13, 2026
31c9678
Update beta version to 0.7.5 in strings resource
rebornlokii Jun 13, 2026
70c42fc
Update beta version to 0.7.5 in Italian strings
rebornlokii Jun 13, 2026
ddade1d
Update strings_home_screen.xml
rebornlokii Jun 13, 2026
698ae10
Update beta version strings to 0.7.5
rebornlokii Jun 13, 2026
7e346a3
Update beta version strings to 0.7.5
rebornlokii Jun 13, 2026
2c376a8
Update beta version strings to 0.7.5
rebornlokii Jun 13, 2026
df83b66
Update beta version strings to 0.7.5 in russian strings
rebornlokii Jun 13, 2026
f99cb20
Update beta version strings to 0.7.5
rebornlokii Jun 13, 2026
b44ba5d
Update beta version strings to 0.7.5
rebornlokii Jun 13, 2026
3cc47db
Update beta version strings to 0.7.5
rebornlokii Jun 13, 2026
5325ea2
Update strings_home_screen.xml
rebornlokii Jun 13, 2026
c0063e7
feat: add Arabic language support and restructure localized strings f…
adlifarizi Jun 13, 2026
77ca1d8
feat: add version 0.7.5 changelog entries and refine Indonesia transl…
adlifarizi Jun 13, 2026
c581610
refactor: replace language string resources with native names in AppL…
adlifarizi Jun 13, 2026
432796a
Update French lyrics mode strings for consistency
rebornlokii Jun 13, 2026
5bca974
feat(i18n): init pt-BR localization
retrozinndev Jun 14, 2026
a3335e2
Feat: the opt for tablet on StartPage
ZL114514 Jun 14, 2026
9e0d181
fix: clean the unstashed conflict
ZL114514 Jun 14, 2026
919a4f4
Update PlaylistContainer.kt
ZL114514 Jun 14, 2026
5e00b0b
feat: NavigationRail for tablet
ZL114514 Jun 15, 2026
e26ee58
feat: predictive back animation handler
ZL114514 Jun 15, 2026
13fab2a
opt: add padding animation back handler
ZL114514 Jun 15, 2026
402e457
refactor(ai): rename AiOrchestrator to AiHandler
VoidX3D Jun 15, 2026
71dd8fb
feat(ai): add UnifiedModelFilter for consistent model filtering acros…
VoidX3D Jun 15, 2026
d599acb
refactor(ai): unify DeepSeek/Groq/Mistral to GenericOpenAiClient
VoidX3D Jun 15, 2026
5d08f1b
feat(ai): add CUSTOM provider entry to AiProvider enum
VoidX3D Jun 15, 2026
b1f3c80
feat(ai): add CUSTOM provider and createClientWithUrl to AiClientFactory
VoidX3D Jun 15, 2026
a5fdfef
feat(ai): add CUSTOM to provider fallback chain in AiProviderSupport
VoidX3D Jun 15, 2026
cf7f4b5
feat(ai): add base URL support and CUSTOM provider prefs to AiPrefere…
VoidX3D Jun 15, 2026
c8fd759
feat(ai): add OLLAMA provider entry to AiProvider enum
VoidX3D Jun 15, 2026
c83cc4f
feat(ai): add OLLAMA provider implementation to AiClientFactory
VoidX3D Jun 15, 2026
f13e7da
feat(ai): add OLLAMA to provider fallback chain
VoidX3D Jun 15, 2026
452dcfe
feat(ai): add OLLAMA provider convenience flows to AiPreferencesRepos…
VoidX3D Jun 15, 2026
3abd56b
feat(ai): add SearchableModelSelector composable with search bar
VoidX3D Jun 15, 2026
775766d
feat(ai): add Ollama/Custom provider flows and base URL state to Sett…
VoidX3D Jun 15, 2026
ee57fae
feat(ui): add OLLAMA/CUSTOM provider labels, SearchableModelSelector,…
VoidX3D Jun 15, 2026
ca27d41
chore: remove unused DeepSeekAiClient, GroqAiClient, MistralAiClient …
VoidX3D Jun 15, 2026
bd711b5
feat(ai): add topP, topK, maxTokens, presencePenalty, frequencyPenalt…
VoidX3D Jun 15, 2026
70c756b
feat(ai): add topP, maxTokens, presencePenalty, frequencyPenalty to G…
VoidX3D Jun 15, 2026
479104f
feat(ai): add topP, topK, maxTokens, presencePenalty, frequencyPenalt…
VoidX3D Jun 15, 2026
9ddb02b
feat(ai): add generation parameter and song data configuration prefer…
VoidX3D Jun 15, 2026
fa1ccad
feat(ai): overhaul AiSystemPromptEngine with chain-of-thought, few-sh…
VoidX3D Jun 15, 2026
19df14f
feat(ai): fetch and pass generation parameters from preferences in Ai…
VoidX3D Jun 15, 2026
2963295
feat(ai): make digest sample size, mode, and extended fields configur…
VoidX3D Jun 15, 2026
e7a17b6
feat(ai): add generation parameter flows and handlers to SettingsView…
VoidX3D Jun 15, 2026
aba3bbf
feat(ui): add Generation Parameters and Song Data Configuration secti…
VoidX3D Jun 15, 2026
51049de
fix: resolve compilation errors in AI settings UI
VoidX3D Jun 15, 2026
3f10397
fix(ai): add AiResponseCleaner, fix usage tracking model name, robust…
VoidX3D Jun 15, 2026
9ad2e8d
refactor: remove AiMetadataGenerator and fix compilation errors
VoidX3D Jun 15, 2026
e771316
refactor: improve translateLyrics prompt with XML structure
VoidX3D Jun 15, 2026
49d890e
fix: restore playlist generation state tracking
VoidX3D Jun 15, 2026
43d79ca
fix: update API key messages and enhance AI provider key handling
VoidX3D Jun 15, 2026
c5e92a8
feat(removing library tabs): implement customizable tab management (a…
Ayaanh001 Jun 15, 2026
61ea819
minor fix
Ayaanh001 Jun 15, 2026
ca21993
Remove old Arabic translation
Hisham-Alzamzami Jun 17, 2026
358702f
Add Arabic localization for app strings
Hisham-Alzamzami Jun 17, 2026
266e466
Add new Arabic translation
Hisham-Alzamzami Jun 17, 2026
374395f
Merge branch 'PixelPlayerHQ:master' into master
Hisham-Alzamzami Jun 17, 2026
e899976
Add Arabic language support to AppLanguage
Hisham-Alzamzami Jun 17, 2026
f534598
Add Arabic language support to settings
Hisham-Alzamzami Jun 17, 2026
97f6f34
ui: fix layout jump when collapsing telegram channel topics
Ayaanh001 Jun 17, 2026
10661f7
f
Ayaanh001 Jun 17, 2026
4616616
strings: add labels and content descriptions for About screen social …
Ayaanh001 Jun 17, 2026
7d20141
strings(es): translate About screen social links to Spanish
Ayaanh001 Jun 17, 2026
bff3ef9
strings: localize GitHub and Telegram social chips for Arabic
Ayaanh001 Jun 17, 2026
bf45b6f
strings: localize GitHub and Telegram social chips for German
Ayaanh001 Jun 17, 2026
f9da386
strings: localize GitHub and Telegram social chips for French
Ayaanh001 Jun 17, 2026
8ff5822
strings: localize GitHub and Telegram social chips for Indonesian
Ayaanh001 Jun 17, 2026
b237916
strings: localize GitHub and Telegram social chips for Italian
Ayaanh001 Jun 17, 2026
8334d64
strings: localize GitHub and Telegram social chips for Korean
Ayaanh001 Jun 17, 2026
7fc0883
strings: localize GitHub and Telegram social chips for Norwegian Bokmål
Ayaanh001 Jun 17, 2026
5e905f1
strings: localize GitHub and Telegram social chips for Russian
Ayaanh001 Jun 17, 2026
1a1b43c
strings: localize GitHub and Telegram social chips for Turkish
Ayaanh001 Jun 17, 2026
d3e73c0
strings: localize GitHub and Telegram social chips for Chinese (Simpl…
Ayaanh001 Jun 17, 2026
4bec3e7
feat: home screen box column
ZL114514 Jun 17, 2026
0113217
Merge branch 'PixelPlayerHQ:master' into master
Hisham-Alzamzami Jun 18, 2026
0d671d4
feat(i18n): add Japanese translation files (values-ja/)
fujimon0722 Jun 18, 2026
c7e2b0f
feat(i18n): register Japanese locale in AppLanguage and locales_config
fujimon0722 Jun 18, 2026
0deef6e
feat(i18n): add settings_language_japanese label to all language files
fujimon0722 Jun 18, 2026
b93d644
chore(deps): bump com.google.genai:google-genai
dependabot[bot] Jun 18, 2026
fd0a3cb
fix(playlists): prevent lost updates when editing playlist songs conc…
AmrEldeeb5 Jun 18, 2026
bb898f3
chore(deps): bump actions/checkout in the github-actions group
dependabot[bot] Jun 18, 2026
dcf2291
chore(deps): bump com.google.genai:google-genai
dependabot[bot] Jun 18, 2026
941f55d
Merge branch 'PixelPlayerHQ:master' into master
Hisham-Alzamzami Jun 19, 2026
9a262d9
Security hardening, error handling, AI client refactoring, test coverage
daedaevibin Jun 19, 2026
478d795
Fix JVM signature clash: rename defaultModel to providerDefaultModel
daedaevibin Jun 19, 2026
fbcb734
Merge pull request #39 from Veridian-Zenith/dependabot/github_actions…
daedaevibin Jun 19, 2026
a512452
Merge pull request #40 from Veridian-Zenith/dependabot/gradle/gradle-…
daedaevibin Jun 19, 2026
801d9ae
Additional quality, security, and performance improvements
daedaevibin Jun 19, 2026
b568ba3
Fix Netty version, parameter ordering, imports, and Spanish comments
daedaevibin Jun 19, 2026
fa3da6e
Merge pull request #41 from Veridian-Zenith/devin/1781834472-security…
daedaevibin Jun 19, 2026
8e0a8af
Merge upstream PR #2347: Update Strings to show beta 7.5
daedaevibin Jun 19, 2026
9a58434
Merge upstream PR #2352: Restructure Arabic localization resources
daedaevibin Jun 19, 2026
40359d1
Merge upstream PR #2353: Update French lyrics mode strings for consis…
daedaevibin Jun 19, 2026
e6b5616
Merge upstream PR #2355: feat(i18n): add pt-BR localization
daedaevibin Jun 19, 2026
9ab7507
Merge upstream PR #2363: Feat: the opt for tablet
daedaevibin Jun 19, 2026
71fa324
Merge upstream PR #2371: feat(ai): massive architecture overhaul, new…
daedaevibin Jun 19, 2026
459c648
Merge upstream PR #2373: feat(removing library tabs): implement custo…
daedaevibin Jun 19, 2026
e2f9e29
Merge upstream PR #2380: feat: Add complete Arabic translation and co…
daedaevibin Jun 19, 2026
33be37f
Merge upstream PR #2383: ui: fix layout jump when collapsing telegram…
daedaevibin Jun 19, 2026
6827738
Merge upstream PR #2396: Feature/localization ja (Japanese)
daedaevibin Jun 19, 2026
07afb84
Merge upstream PR #2397: chore(deps): bump com.google.genai:google-ge…
daedaevibin Jun 19, 2026
a04999a
Merge upstream PR #2400: fix(playlists): prevent lost playlist edits …
daedaevibin Jun 19, 2026
664fd91
Merge origin/master: resolve AI client conflicts with upstream #2371
daedaevibin Jun 19, 2026
36361c7
fix(i18n): rename values-pt-BR to values-pt-rBR for Android resource …
daedaevibin Jun 19, 2026
94c360d
Merge pull request #42 from Veridian-Zenith/devin/1781837668-consolid…
daedaevibin Jun 19, 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
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,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 Down
2 changes: 1 addition & 1 deletion .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 Down
2 changes: 1 addition & 1 deletion .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 Down
2 changes: 1 addition & 1 deletion .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 Down
2 changes: 1 addition & 1 deletion .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 Down
29 changes: 0 additions & 29 deletions .idea/deploymentTargetSelector.xml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package com.theveloper.pixelplay.data.repository

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.preferencesDataStoreFile
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.theveloper.pixelplay.data.database.LocalPlaylistDao
import com.theveloper.pixelplay.data.database.PixelPlayDatabase
import com.theveloper.pixelplay.data.preferences.PlaylistPreferencesRepository
import com.theveloper.pixelplay.data.preferences.UserPreferencesRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.Json
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

/**
* Regression test for issue #2391:
* "Playlist song count doesn't update when removing songs — only when adding."
*
* Exercises the real PlaylistPreferencesRepository against an in-memory Room DB to
* verify that the song count exposed by userPlaylistsFlow (used by the Playlists menu)
* reflects removals as well as additions.
*/
@RunWith(AndroidJUnit4::class)
class PlaylistSongCountTest {

private lateinit var db: PixelPlayDatabase
private lateinit var dao: LocalPlaylistDao
private lateinit var dataStore: DataStore<Preferences>
private lateinit var repo: PlaylistPreferencesRepository

@Before
fun setup() {
val context = ApplicationProvider.getApplicationContext<Context>()
db = Room.inMemoryDatabaseBuilder(context, PixelPlayDatabase::class.java)
.addCallback(PixelPlayDatabase.createRuntimeArtifactsCallback())
.allowMainThreadQueries()
.build()
dao = db.localPlaylistDao()
dataStore = PreferenceDataStoreFactory.create {
context.preferencesDataStoreFile("test_settings_${System.nanoTime()}")
}
val userPrefs = UserPreferencesRepository(dataStore, Json { ignoreUnknownKeys = true })
repo = PlaylistPreferencesRepository(dao, userPrefs)
}

@After
fun teardown() {
db.close()
}

private suspend fun countFor(playlistId: String): Int =
repo.userPlaylistsFlow.first().first { it.id == playlistId }.songIds.size

@Test
fun menuSongCount_reflectsAddAndRemove() = runTest {
val playlist = repo.createPlaylist(name = "J-Pop", songIds = listOf("10", "20", "30"))
assertEquals("initial count", 3, countFor(playlist.id))

// Remove a song — the bug report says this does NOT update the count.
repo.removeSongFromPlaylist(playlist.id, "20")
assertEquals("after removing one song", 2, countFor(playlist.id))

// Remove another.
repo.removeSongFromPlaylist(playlist.id, "30")
assertEquals("after removing a second song", 1, countFor(playlist.id))

// Adding works per the report — verify it still does.
repo.addSongsToPlaylist(playlist.id, listOf("40"))
assertEquals("after adding one song", 2, countFor(playlist.id))
}

/**
* Reproduces the real-world trigger for issue #2391: removing several songs in
* quick succession. Each edit does an unsynchronized read-modify-write
* (userPlaylistsFlow.first() -> modify -> updatePlaylist), so concurrent removals
* all read the same original list and the last writer wins, silently dropping the
* other removals. The Playlists-menu count (songIds.size) then stays stuck high.
*/
@Test
fun concurrentRemovals_doNotLoseUpdates() = runBlocking {
val playlist = repo.createPlaylist(
name = "Race",
songIds = listOf("1", "2", "3", "4", "5")
)
assertEquals(5, countFor(playlist.id))

// Remove four songs concurrently — "remove one or two of them", fast.
coroutineScope {
listOf("1", "2", "3", "4").forEach { id ->
launch(Dispatchers.IO) { repo.removeSongFromPlaylist(playlist.id, id) }
}
}

assertEquals("All concurrent removals must persist", 1, countFor(playlist.id))
}

/**
* Walks the exact reproduction from issue #2391, asserting the fixed behaviour:
* the song count stays accurate after a quick removal of "one or two" songs, and
* a later addition does not preserve a phantom difference.
*/
@Test
fun issue2391_quickRemoveThenAdd_keepsCountAccurate() = runBlocking {
// Steps 2-3: create a playlist and add a few songs.
val playlist = repo.createPlaylist(
name = "J-Pop",
songIds = listOf("1", "2", "3", "4", "5", "6")
)
assertEquals(6, countFor(playlist.id))

// Step 4: remove one or two of them — quickly, as fast taps do.
coroutineScope {
launch(Dispatchers.IO) { repo.removeSongFromPlaylist(playlist.id, "2") }
launch(Dispatchers.IO) { repo.removeSongFromPlaylist(playlist.id, "4") }
}
// Step 5: the menu count must reflect BOTH removals (the bug left it stuck high).
assertEquals("count after removing two songs", 4, countFor(playlist.id))

// Steps 6-7: adding more must not carry over a phantom difference.
repo.addSongsToPlaylist(playlist.id, listOf("7", "8"))
assertEquals("count after adding two songs", 6, countFor(playlist.id))
}
}
Loading
Loading