Skip to content

Commit

Permalink
Merge pull request #613 from OxygenCobalt/v3.2.1-cherrypick
Browse files Browse the repository at this point in the history
Version 3.2.1
  • Loading branch information
OxygenCobalt authored Nov 12, 2023
2 parents 5cd4619 + 0016c77 commit d5017f8
Show file tree
Hide file tree
Showing 81 changed files with 2,405 additions and 1,319 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
# - name: Test app with Gradle
# run: ./gradlew app:testDebug
- name: Test app with Gradle
run: ./gradlew app:testDebug
- name: Build debug APK with Gradle
run: ./gradlew app:packageDebug
- name: Upload debug APK artifact
Expand Down
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog

## dev

#### What's New
- Added ability to rewind/skip tracks by swiping back/forward

#### What's Improved
- Added support for native M4A multi-value tags based on duplicate atoms

#### What's Fixed
- Fixed app restart being required when changing intelligent sorting
or music separator settings
- Fixed widget/notification actions not working on Android 14
- Fixed app crash when using hebrew language
- Fixed app crash when adding to a playlist while in the playlist detail view
- Fixed music loading failing in some cases on Android 14

## 3.2.0

#### What's New
Expand All @@ -16,6 +32,10 @@ aspect ratio setting
#### What's Fixed
- Playlist detail view now respects playback settings


#### Dev/Meta
- Revamped navigation backend

## 3.1.4

#### What's Fixed
Expand Down
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@

Auxio is a local music player with a fast, reliable UI/UX without the many useless features present in other music players. Built off of modern media playback libraries, Auxio has superior library support and listening quality compared to other apps that use outdated android functionality. In short, **It plays music.**

I primarily built Auxio for myself, but you can use it too, I guess.

**The default branch is the development version of the repository. For a stable version, see the master branch.**

## Screenshots
Expand Down Expand Up @@ -60,12 +58,12 @@ precise/original dates, sort tags, and more
- Headset autoplay
- Stylish widgets that automatically adapt to their size
- Completely private and offline
- No rounded album covers (Unless you want them. Then you can.)
- No rounded album covers (by default)

## Permissions

- Storage (`READ_MEDIA_AUDIO`, `READ_EXTERNAL_STORAGE`) to read and play your media files
- Services (`FOREGROUND_SERVICE`, `WAKE_LOCK`) to keep the music playing even if the app itself is in background
- Storage (`READ_MEDIA_AUDIO`, `READ_EXTERNAL_STORAGE`) to read and play your music files
- Services (`FOREGROUND_SERVICE`, `WAKE_LOCK`) to keep the music playing in the background

## Building

Expand Down
20 changes: 13 additions & 7 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ android {

defaultConfig {
applicationId namespace
versionName "3.2.0"
versionCode 35
versionName "3.2.1"
versionCode 36

minSdk 24
targetSdk 34
Expand Down Expand Up @@ -85,9 +85,9 @@ dependencies {
// --- SUPPORT ---

// General
implementation "androidx.core:core-ktx:1.10.1"
implementation "androidx.core:core-ktx:1.12.0"
implementation "androidx.appcompat:appcompat:1.6.1"
implementation "androidx.activity:activity-ktx:1.7.2"
implementation "androidx.activity:activity-ktx:1.8.0"
implementation "androidx.fragment:fragment-ktx:1.6.1"

// Components
Expand All @@ -100,7 +100,7 @@ dependencies {
implementation "androidx.viewpager2:viewpager2:1.0.0"

// Lifecycle
def lifecycle_version = "2.6.1"
def lifecycle_version = "2.6.2"
implementation "androidx.lifecycle:lifecycle-common:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
Expand All @@ -117,7 +117,7 @@ dependencies {
implementation "androidx.preference:preference-ktx:1.2.1"

// Database
def room_version = '2.6.0-alpha03'
def room_version = '2.6.0-rc01'
implementation "androidx.room:room-runtime:$room_version"
ksp "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
Expand All @@ -134,17 +134,23 @@ dependencies {
// Material
// TODO: Exactly figure out the conditions that the 1.7.0 ripple bug occurred so you can just
// PR a fix.
implementation "com.google.android.material:material:1.10.0-alpha06"
implementation "com.google.android.material:material:1.10.0"

// Dependency Injection
implementation "com.google.dagger:dagger:$hilt_version"
kapt "com.google.dagger:dagger-compiler:$hilt_version"
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"

// Logging
implementation 'com.jakewharton.timber:timber:5.0.1'

// Testing
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
testImplementation "junit:junit:4.13.2"
testImplementation "io.mockk:mockk:1.13.7"
testImplementation "org.robolectric:robolectric:4.9"
testImplementation 'androidx.test:core-ktx:1.5.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
Expand Down
40 changes: 0 additions & 40 deletions app/src/androidTest/java/org/oxycblt/auxio/StubTest.kt

This file was deleted.

5 changes: 5 additions & 0 deletions app/src/main/java/org/oxycblt/auxio/Auxio.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import org.oxycblt.auxio.home.HomeSettings
import org.oxycblt.auxio.image.ImageSettings
import org.oxycblt.auxio.playback.PlaybackSettings
import org.oxycblt.auxio.ui.UISettings
import timber.log.Timber

/**
* A simple, rational music player for android.
Expand All @@ -44,6 +45,10 @@ class Auxio : Application() {

override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}

// Migrate any settings that may have changed in an app update.
imageSettings.migrate()
playbackSettings.migrate()
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/org/oxycblt/auxio/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ class MainActivity : AppCompatActivity() {
logD("Activity created")
}

override fun onStart() {
super.onStart()
override fun onResume() {
super.onResume()

startService(Intent(this, IndexerService::class.java))
startService(Intent(this, PlaybackService::class.java))
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/org/oxycblt/auxio/MainFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ class MainFragment :
}

override fun onPreDraw(): Boolean {
// TODO: Due to draw caching even *this* isn't effective enough to avoid the bottom
// sheets continually getting stuck. I need something with even more frequent updates,
// or otherwise bottom sheets get stuck.

// We overload CoordinatorLayout far too much to rely on any of it's typical
// listener functionality. Just update all transitions before every draw. Should
// probably be cheap enough.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,11 @@ class PlaylistDetailFragment :
logD("Deleting ${decision.playlist}")
PlaylistDetailFragmentDirections.deletePlaylist(decision.playlist.uid)
}
is PlaylistDecision.Add,
is PlaylistDecision.Add -> {
logD("Adding ${decision.songs.size} songs to a playlist")
PlaylistDetailFragmentDirections.addToPlaylist(
decision.songs.map { it.uid }.toTypedArray())
}
is PlaylistDecision.New -> error("Unexpected playlist decision $decision")
}
findNavController().navigateSafe(directions)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ constructor(
// Apply the new configuration possibly set in flipTo. This should occur even if
// a flip was canceled by a hide.
pendingConfig?.run {
this@FlipFloatingActionButton.logD("Applying pending configuration")
logD("Applying pending configuration")
setImageResource(iconRes)
contentDescription = context.getString(contentDescriptionRes)
setOnClickListener(clickListener)
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/org/oxycblt/auxio/music/MusicSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ interface MusicSettings : Settings<MusicSettings.Listener> {
/** Whether to be actively watching for changes in the music library. */
val shouldBeObserving: Boolean
/** A [String] of characters representing the desired characters to denote multi-value tags. */
var multiValueSeparators: String
var separators: String
/** Whether to enable more advanced sorting by articles and numbers. */
val intelligentSorting: Boolean

Expand Down Expand Up @@ -85,7 +85,7 @@ class MusicSettingsImpl @Inject constructor(@ApplicationContext context: Context
override val shouldBeObserving: Boolean
get() = sharedPreferences.getBoolean(getString(R.string.set_key_observing), false)

override var multiValueSeparators: String
override var separators: String
// Differ from convention and store a string of separator characters instead of an int
// code. This makes it easier to use and more extendable.
get() = sharedPreferences.getString(getString(R.string.set_key_separators), "") ?: ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import org.oxycblt.auxio.music.info.Date
import org.oxycblt.auxio.music.metadata.correctWhitespace
import org.oxycblt.auxio.music.metadata.splitEscaped

@Database(entities = [CachedSong::class], version = 34, exportSchema = false)
@Database(entities = [CachedSong::class], version = 36, exportSchema = false)
abstract class CacheDatabase : RoomDatabase() {
abstract fun cachedSongsDao(): CachedSongsDao
}
Expand Down Expand Up @@ -63,9 +63,9 @@ data class CachedSong(
/** @see RawSong */
var durationMs: Long,
/** @see RawSong.replayGainTrackAdjustment */
val replayGainTrackAdjustment: Float?,
val replayGainTrackAdjustment: Float? = null,
/** @see RawSong.replayGainAlbumAdjustment */
val replayGainAlbumAdjustment: Float?,
val replayGainAlbumAdjustment: Float? = null,
/** @see RawSong.musicBrainzId */
var musicBrainzId: String? = null,
/** @see RawSong.name */
Expand Down
23 changes: 14 additions & 9 deletions app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import org.oxycblt.auxio.music.MusicSettings
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.fs.contentResolverSafe
import org.oxycblt.auxio.music.fs.useQuery
import org.oxycblt.auxio.music.info.Name
import org.oxycblt.auxio.music.metadata.Separators
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.unlikelyToBeNull

Expand Down Expand Up @@ -107,7 +109,7 @@ interface DeviceLibrary {
*/
suspend fun create(
rawSongs: Channel<RawSong>,
processedSongs: Channel<RawSong>
processedSongs: Channel<RawSong>,
): DeviceLibraryImpl
}
}
Expand All @@ -118,6 +120,9 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu
rawSongs: Channel<RawSong>,
processedSongs: Channel<RawSong>
): DeviceLibraryImpl {
val nameFactory = Name.Known.Factory.from(musicSettings)
val separators = Separators.from(musicSettings)

val songGrouping = mutableMapOf<Music.UID, SongImpl>()
val albumGrouping = mutableMapOf<RawAlbum.Key, Grouping<RawAlbum, SongImpl>>()
val artistGrouping = mutableMapOf<RawArtist.Key, Grouping<RawArtist, Music>>()
Expand All @@ -127,7 +132,7 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu

// All music information is grouped as it is indexed by other components.
for (rawSong in rawSongs) {
val song = SongImpl(rawSong, musicSettings)
val song = SongImpl(rawSong, nameFactory, separators)
// At times the indexer produces duplicate songs, try to filter these. Comparing by
// UID is sufficient for something like this, and also prevents collisions from
// causing severe issues elsewhere.
Expand Down Expand Up @@ -207,7 +212,7 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu

// Now that all songs are processed, also process albums and group them into their
// respective artists.
val albums = albumGrouping.values.mapTo(mutableSetOf()) { AlbumImpl(it, musicSettings) }
val albums = albumGrouping.values.mapTo(mutableSetOf()) { AlbumImpl(it, nameFactory) }
for (album in albums) {
for (rawArtist in album.rawArtists) {
val key = RawArtist.Key(rawArtist)
Expand Down Expand Up @@ -243,8 +248,8 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu
}

// Artists and genres do not need to be grouped and can be processed immediately.
val artists = artistGrouping.values.mapTo(mutableSetOf()) { ArtistImpl(it, musicSettings) }
val genres = genreGrouping.values.mapTo(mutableSetOf()) { GenreImpl(it, musicSettings) }
val artists = artistGrouping.values.mapTo(mutableSetOf()) { ArtistImpl(it, nameFactory) }
val genres = genreGrouping.values.mapTo(mutableSetOf()) { GenreImpl(it, nameFactory) }

return DeviceLibraryImpl(songGrouping.values.toSet(), albums, artists, genres)
}
Expand All @@ -253,10 +258,10 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu
// TODO: Avoid redundant data creation

class DeviceLibraryImpl(
override val songs: Set<SongImpl>,
override val albums: Set<AlbumImpl>,
override val artists: Set<ArtistImpl>,
override val genres: Set<GenreImpl>
override val songs: Collection<SongImpl>,
override val albums: Collection<AlbumImpl>,
override val artists: Collection<ArtistImpl>,
override val genres: Collection<GenreImpl>
) : DeviceLibrary {
// Use a mapping to make finding information based on it's UID much faster.
private val songUidMap = buildMap { songs.forEach { put(it.uid, it.finalize()) } }
Expand Down
Loading

0 comments on commit d5017f8

Please sign in to comment.