musikr: start unwinding di use
Musikr is eventually going to be an entirely independent gradle module with a DI-agnostic API, start removing some of the directives (but not all since some are kinda thorny to untangle)
This commit is contained in:
parent
34217696c2
commit
59df1c3d57
19 changed files with 73 additions and 286 deletions
|
@ -53,18 +53,14 @@ interface MusicSettings : Settings<MusicSettings.Listener> {
|
|||
}
|
||||
}
|
||||
|
||||
class MusicSettingsImpl
|
||||
@Inject
|
||||
constructor(
|
||||
@ApplicationContext context: Context,
|
||||
private val musicLocationFactory: MusicLocation.Factory
|
||||
) : Settings.Impl<MusicSettings.Listener>(context), MusicSettings {
|
||||
class MusicSettingsImpl @Inject constructor(@ApplicationContext private val context: Context) :
|
||||
Settings.Impl<MusicSettings.Listener>(context), MusicSettings {
|
||||
override var musicLocations: List<MusicLocation>
|
||||
get() {
|
||||
val dirs =
|
||||
sharedPreferences.getStringSet(getString(R.string.set_key_music_locations), null)
|
||||
?: emptySet()
|
||||
return dirs.mapNotNull { musicLocationFactory.existing(Uri.parse(it)) }
|
||||
return dirs.mapNotNull { MusicLocation.existing(context, Uri.parse(it)) }
|
||||
}
|
||||
set(value) {
|
||||
sharedPreferences.edit {
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
|
||||
package org.oxycblt.auxio.music
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
@ -49,10 +51,11 @@ import timber.log.Timber as L
|
|||
class MusicViewModel
|
||||
@Inject
|
||||
constructor(
|
||||
@ApplicationContext context: Context,
|
||||
private val listSettings: ListSettings,
|
||||
private val musicRepository: MusicRepository,
|
||||
private val externalPlaylistManager: ExternalPlaylistManager
|
||||
private val musicRepository: MusicRepository
|
||||
) : ViewModel(), MusicRepository.UpdateListener, MusicRepository.IndexingListener {
|
||||
private val externalPlaylistManager = ExternalPlaylistManager.from(context)
|
||||
|
||||
private val _indexingState = MutableStateFlow<IndexingState?>(null)
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
package org.oxycblt.auxio.music.locations
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.ContentResolver
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
|
@ -50,7 +48,6 @@ class MusicSourcesDialog :
|
|||
ViewBindingMaterialDialogFragment<DialogMusicLocationsBinding>(), LocationAdapter.Listener {
|
||||
private val locationAdapter = LocationAdapter(this)
|
||||
private var openDocumentTreeLauncher: ActivityResultLauncher<Uri?>? = null
|
||||
@Inject lateinit var musicLocationFactory: MusicLocation.Factory
|
||||
@Inject lateinit var musicSettings: MusicSettings
|
||||
|
||||
override fun onCreateBinding(inflater: LayoutInflater) =
|
||||
|
@ -102,7 +99,7 @@ class MusicSourcesDialog :
|
|||
|
||||
val locations =
|
||||
savedInstanceState?.getStringArrayList(KEY_PENDING_LOCATIONS)?.mapNotNull {
|
||||
musicLocationFactory.existing(Uri.parse(it))
|
||||
MusicLocation.existing(requireContext(), Uri.parse(it))
|
||||
} ?: musicSettings.musicLocations
|
||||
|
||||
locationAdapter.addAll(locations)
|
||||
|
@ -126,8 +123,6 @@ class MusicSourcesDialog :
|
|||
requireBinding().locationsEmpty.isVisible = locationAdapter.locations.isEmpty()
|
||||
}
|
||||
|
||||
@Inject lateinit var contentResolver: ContentResolver
|
||||
|
||||
/**
|
||||
* Add a Document Tree [Uri] chosen by the user to the current [MusicLocation]s.
|
||||
*
|
||||
|
@ -140,11 +135,7 @@ class MusicSourcesDialog :
|
|||
L.d("No URI given (user closed the dialog)")
|
||||
return
|
||||
}
|
||||
val takeFlags: Int =
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
contentResolver.takePersistableUriPermission(uri, takeFlags)
|
||||
|
||||
val location = musicLocationFactory.new(uri)
|
||||
val location = MusicLocation.new(requireContext(), uri)
|
||||
|
||||
if (location != null) {
|
||||
locationAdapter.add(location)
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
* FsModule.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.musikr.fs
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface FsModule {
|
||||
@Binds
|
||||
fun musicLocationFactory(
|
||||
musicLocationFactoryImpl: MusicLocationFactoryImpl
|
||||
): MusicLocation.Factory
|
||||
}
|
|
@ -22,8 +22,6 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.provider.DocumentsContract
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import org.oxycblt.musikr.fs.path.DocumentPathFactory
|
||||
import org.oxycblt.musikr.fs.query.contentResolverSafe
|
||||
|
||||
|
@ -42,43 +40,34 @@ class MusicLocation internal constructor(val uri: Uri, val path: Path) {
|
|||
return "$uri=${volumeId}:${path.components.unixString}"
|
||||
}
|
||||
|
||||
interface Factory {
|
||||
fun new(uri: Uri): MusicLocation?
|
||||
|
||||
fun existing(uri: Uri): MusicLocation?
|
||||
}
|
||||
}
|
||||
|
||||
class MusicLocationFactoryImpl
|
||||
@Inject
|
||||
constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val documentPathFactory: DocumentPathFactory
|
||||
) : MusicLocation.Factory {
|
||||
override fun new(uri: Uri): MusicLocation? {
|
||||
if (!DocumentsContract.isTreeUri(uri)) return null
|
||||
val path = documentPathFactory.unpackDocumentTreeUri(uri) ?: return null
|
||||
val notPersisted =
|
||||
context.contentResolverSafe.persistedUriPermissions.none {
|
||||
it.uri == uri && it.isReadPermission && it.isWritePermission
|
||||
companion object {
|
||||
fun new(context: Context, uri: Uri): MusicLocation? {
|
||||
if (!DocumentsContract.isTreeUri(uri)) return null
|
||||
val documentPathFactory = DocumentPathFactory.from(context)
|
||||
val path = documentPathFactory.unpackDocumentTreeUri(uri) ?: return null
|
||||
val notPersisted =
|
||||
context.contentResolverSafe.persistedUriPermissions.none {
|
||||
it.uri == uri && it.isReadPermission && it.isWritePermission
|
||||
}
|
||||
if (notPersisted) {
|
||||
context.contentResolverSafe.takePersistableUriPermission(
|
||||
uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
}
|
||||
if (notPersisted) {
|
||||
context.contentResolverSafe.takePersistableUriPermission(
|
||||
uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
return MusicLocation(uri, path)
|
||||
}
|
||||
return MusicLocation(uri, path)
|
||||
}
|
||||
|
||||
override fun existing(uri: Uri): MusicLocation? {
|
||||
if (!DocumentsContract.isTreeUri(uri)) return null
|
||||
val notPersisted =
|
||||
context.contentResolverSafe.persistedUriPermissions.none {
|
||||
it.uri == uri && it.isReadPermission && it.isWritePermission
|
||||
}
|
||||
if (notPersisted) return null
|
||||
val path = documentPathFactory.unpackDocumentTreeUri(uri) ?: return null
|
||||
return MusicLocation(uri, path)
|
||||
fun existing(context: Context, uri: Uri): MusicLocation? {
|
||||
val documentPathFactory = DocumentPathFactory.from(context)
|
||||
if (!DocumentsContract.isTreeUri(uri)) return null
|
||||
val notPersisted =
|
||||
context.contentResolverSafe.persistedUriPermissions.none {
|
||||
it.uri == uri && it.isReadPermission && it.isWritePermission
|
||||
}
|
||||
if (notPersisted) return null
|
||||
val path = documentPathFactory.unpackDocumentTreeUri(uri) ?: return null
|
||||
return MusicLocation(uri, path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ import android.net.Uri
|
|||
import android.provider.DocumentsContract
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
import org.oxycblt.musikr.fs.Components
|
||||
import org.oxycblt.musikr.fs.Path
|
||||
import org.oxycblt.musikr.fs.Volume
|
||||
|
@ -68,11 +67,17 @@ interface DocumentPathFactory {
|
|||
* @return The [Path] instance, or null if the path could not be deserialized.
|
||||
*/
|
||||
fun fromDocumentId(path: String): Path?
|
||||
|
||||
companion object {
|
||||
fun from(context: Context): DocumentPathFactory {
|
||||
val volumeManager = VolumeManager.from(context)
|
||||
val pathInterpreter = MediaStorePathInterpreter.Factory.from(volumeManager)
|
||||
return DocumentPathFactoryImpl(context, volumeManager, pathInterpreter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DocumentPathFactoryImpl
|
||||
@Inject
|
||||
constructor(
|
||||
private class DocumentPathFactoryImpl(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val volumeManager: VolumeManager,
|
||||
private val mediaStorePathInterpreterFactory: MediaStorePathInterpreter.Factory
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Auxio Project
|
||||
* PathModule.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.musikr.fs.path
|
||||
|
||||
import android.content.Context
|
||||
import android.os.storage.StorageManager
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import org.oxycblt.auxio.util.getSystemServiceCompat
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
class PathModule {
|
||||
@Provides
|
||||
fun volumeManager(@ApplicationContext context: Context): VolumeManager =
|
||||
VolumeManagerImpl(context.getSystemServiceCompat(StorageManager::class))
|
||||
|
||||
@Provides
|
||||
fun mediaStorePathInterpreterFactory(
|
||||
volumeManager: VolumeManager
|
||||
): MediaStorePathInterpreter.Factory = MediaStorePathInterpreter.Factory.from(volumeManager)
|
||||
}
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface PathBindsModule {
|
||||
@Binds
|
||||
fun documentPathFactory(documentTreePathFactory: DocumentPathFactoryImpl): DocumentPathFactory
|
||||
}
|
|
@ -21,7 +21,6 @@ package org.oxycblt.musikr.fs.path
|
|||
import android.content.Context
|
||||
import android.os.storage.StorageManager
|
||||
import android.os.storage.StorageVolume
|
||||
import javax.inject.Inject
|
||||
import org.oxycblt.musikr.fs.Components
|
||||
import org.oxycblt.musikr.fs.Volume
|
||||
|
||||
|
@ -40,10 +39,14 @@ interface VolumeManager {
|
|||
* @see StorageManager.getStorageVolumes
|
||||
*/
|
||||
fun getVolumes(): List<Volume>
|
||||
|
||||
companion object {
|
||||
fun from(context: Context): VolumeManager =
|
||||
VolumeManagerImpl(context.getSystemService(StorageManager::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
class VolumeManagerImpl @Inject constructor(private val storageManager: StorageManager) :
|
||||
VolumeManager {
|
||||
private class VolumeManagerImpl(private val storageManager: StorageManager) : VolumeManager {
|
||||
override fun getInternalVolume(): Volume.Internal =
|
||||
InternalVolumeImpl(storageManager.primaryStorageVolume)
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@ import android.content.ContentResolver
|
|||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.provider.DocumentsContract
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
|
@ -36,6 +34,10 @@ import org.oxycblt.musikr.fs.Path
|
|||
|
||||
interface DeviceFiles {
|
||||
fun explore(locations: Flow<MusicLocation>): Flow<DeviceFile>
|
||||
|
||||
companion object {
|
||||
fun from(context: Context): DeviceFiles = DeviceFilesImpl(context.contentResolverSafe)
|
||||
}
|
||||
}
|
||||
|
||||
data class DeviceFile(
|
||||
|
@ -47,10 +49,7 @@ data class DeviceFile(
|
|||
)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class DeviceFilesImpl @Inject constructor(@ApplicationContext private val context: Context) :
|
||||
DeviceFiles {
|
||||
private val contentResolver = context.contentResolverSafe
|
||||
|
||||
private class DeviceFilesImpl(private val contentResolver: ContentResolver) : DeviceFiles {
|
||||
override fun explore(locations: Flow<MusicLocation>): Flow<DeviceFile> =
|
||||
locations.flatMapMerge { location ->
|
||||
exploreImpl(
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Auxio Project
|
||||
* QueryModule.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.musikr.fs.query
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
class QueryProvidesModule {
|
||||
@Provides
|
||||
fun contentResolver(@ApplicationContext context: Context): ContentResolver =
|
||||
context.contentResolverSafe
|
||||
}
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface QueryBindsModule {
|
||||
@Binds fun deviceFiles(deviceFilesImpl: DeviceFilesImpl): DeviceFiles
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
* GraphModule.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.musikr.graph
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface GraphModule {
|
||||
@Binds fun musicGraphFactory(interpreter: MusicGraphFactoryImpl): MusicGraph.Factory
|
||||
}
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
package org.oxycblt.musikr.graph
|
||||
|
||||
import javax.inject.Inject
|
||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||
import org.oxycblt.musikr.Music
|
||||
import org.oxycblt.musikr.tag.interpret.PreAlbum
|
||||
|
@ -39,15 +38,11 @@ data class MusicGraph(
|
|||
fun build(): MusicGraph
|
||||
}
|
||||
|
||||
interface Factory {
|
||||
fun builder(): Builder
|
||||
companion object {
|
||||
fun builder(): Builder = MusicGraphBuilderImpl()
|
||||
}
|
||||
}
|
||||
|
||||
class MusicGraphFactoryImpl @Inject constructor() : MusicGraph.Factory {
|
||||
override fun builder(): MusicGraph.Builder = MusicGraphBuilderImpl()
|
||||
}
|
||||
|
||||
private class MusicGraphBuilderImpl : MusicGraph.Builder {
|
||||
private val songVertices = mutableMapOf<Music.UID, SongVertex>()
|
||||
private val albumVertices = mutableMapOf<PreAlbum, AlbumVertex>()
|
||||
|
|
|
@ -43,7 +43,6 @@ class EvaluateStepImpl
|
|||
@Inject
|
||||
constructor(
|
||||
private val tagInterpreter: TagInterpreter,
|
||||
private val musicGraphFactory: MusicGraph.Factory,
|
||||
private val libraryFactory: LibraryFactory
|
||||
) : EvaluateStep {
|
||||
override suspend fun evaluate(
|
||||
|
@ -56,7 +55,7 @@ constructor(
|
|||
.map { tagInterpreter.interpret(it.file, it.tags, it.cover, interpretation) }
|
||||
.flowOn(Dispatchers.Main)
|
||||
.buffer(Channel.UNLIMITED)
|
||||
val graphBuilder = musicGraphFactory.builder()
|
||||
val graphBuilder = MusicGraph.builder()
|
||||
preSongs.collect { graphBuilder.add(it) }
|
||||
val graph = graphBuilder.build()
|
||||
return libraryFactory.create(graph)
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
package org.oxycblt.musikr.pipeline
|
||||
|
||||
import android.content.Context
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -33,9 +35,10 @@ interface ExploreStep {
|
|||
fun explore(locations: List<MusicLocation>): Flow<ExploreNode>
|
||||
}
|
||||
|
||||
class ExploreStepImpl @Inject constructor(private val deviceFiles: DeviceFiles) : ExploreStep {
|
||||
class ExploreStepImpl @Inject constructor(@ApplicationContext private val context: Context) :
|
||||
ExploreStep {
|
||||
override fun explore(locations: List<MusicLocation>) =
|
||||
deviceFiles
|
||||
DeviceFiles.from(context)
|
||||
.explore(locations.asFlow())
|
||||
.mapNotNull {
|
||||
when {
|
||||
|
|
|
@ -27,7 +27,6 @@ import kotlinx.coroutines.flow.filterIsInstance
|
|||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import org.oxycblt.ktaglib.KTagLib
|
||||
import org.oxycblt.musikr.Storage
|
||||
import org.oxycblt.musikr.cache.CachedSong
|
||||
import org.oxycblt.musikr.cover.Cover
|
||||
|
@ -36,7 +35,6 @@ import org.oxycblt.musikr.fs.query.DeviceFile
|
|||
import org.oxycblt.musikr.metadata.MetadataExtractor
|
||||
import org.oxycblt.musikr.tag.parse.ParsedTags
|
||||
import org.oxycblt.musikr.tag.parse.TagParser
|
||||
import timber.log.Timber
|
||||
|
||||
interface ExtractStep {
|
||||
fun extract(storage: Storage, nodes: Flow<ExploreNode>): Flow<ExtractedMusic>
|
||||
|
|
|
@ -20,8 +20,6 @@ package org.oxycblt.musikr.playlist
|
|||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import org.oxycblt.musikr.Playlist
|
||||
import org.oxycblt.musikr.fs.Components
|
||||
import org.oxycblt.musikr.fs.Path
|
||||
|
@ -56,6 +54,12 @@ interface ExternalPlaylistManager {
|
|||
* @return True if the playlist was successfully exported, false otherwise.
|
||||
*/
|
||||
suspend fun export(playlist: Playlist, uri: Uri, config: ExportConfig): Boolean
|
||||
|
||||
companion object {
|
||||
fun from(context: Context): ExternalPlaylistManager =
|
||||
ExternalPlaylistManagerImpl(
|
||||
context, DocumentPathFactory.from(context), M3U.from(context))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,10 +85,8 @@ data class ImportedPlaylist(val name: String?, val paths: List<PossiblePaths>)
|
|||
|
||||
typealias PossiblePaths = List<Path>
|
||||
|
||||
class ExternalPlaylistManagerImpl
|
||||
@Inject
|
||||
constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
class ExternalPlaylistManagerImpl(
|
||||
private val context: Context,
|
||||
private val documentPathFactory: DocumentPathFactory,
|
||||
private val m3u: M3U
|
||||
) : ExternalPlaylistManager {
|
||||
|
|
|
@ -17,17 +17,3 @@
|
|||
*/
|
||||
|
||||
package org.oxycblt.musikr.playlist
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface PlaylistModule {
|
||||
@Binds
|
||||
fun externalPlaylistManager(
|
||||
externalPlaylistManager: ExternalPlaylistManagerImpl
|
||||
): ExternalPlaylistManager
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@ interface M3U {
|
|||
companion object {
|
||||
/** The mime type used for M3U files by the android system. */
|
||||
const val MIME_TYPE = "audio/x-mpegurl"
|
||||
|
||||
fun from(context: Context): M3U = M3UImpl(context, VolumeManager.from(context))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Auxio Project
|
||||
* M3UModule.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.musikr.playlist.m3u
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface PlaylistModule {
|
||||
@Binds fun m3u(m3u: M3UImpl): M3U
|
||||
}
|
Loading…
Reference in a new issue