diff --git a/build.gradle b/build.gradle index 597d384a..d6d7c22f 100644 --- a/build.gradle +++ b/build.gradle @@ -35,6 +35,13 @@ allprojects { google() maven { url 'https://jitpack.io' } } + + // Set Kotlin JVM target to the same for all subprojects + tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + kotlinOptions { + jvmTarget = "1.8" + } + } } apply from: 'gradle_scripts/jacoco.gradle' diff --git a/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/interceptors/PasswordMD5Interceptor.kt b/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/interceptors/PasswordMD5Interceptor.kt index 75d6a48e..8a1c8388 100644 --- a/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/interceptors/PasswordMD5Interceptor.kt +++ b/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/interceptors/PasswordMD5Interceptor.kt @@ -39,7 +39,7 @@ class PasswordMD5Interceptor(private val password: String) : Interceptor { val md5Digest = MessageDigest.getInstance("MD5") return md5Digest.digest( "$password$salt".toByteArray() - ).toHexBytes().toLowerCase(Locale.getDefault()) + ).toHexBytes().lowercase(Locale.getDefault()) } catch (e: NoSuchAlgorithmException) { throw IllegalStateException(e) } diff --git a/dependencies.gradle b/dependencies.gradle index 9d5e4339..aa0f257b 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -10,7 +10,7 @@ ext.versions = [ androidxcore : "1.5.0", ktlint : "0.37.1", ktlintGradle : "9.2.1", - detekt : "1.17.0", + detekt : "1.17.1", jacoco : "0.8.7", preferences : "1.1.1", media : "1.3.1", @@ -20,16 +20,16 @@ ext.versions = [ androidSupportDesign : "1.3.0", constraintLayout : "2.0.4", multidex : "2.0.1", - room : "2.2.6", - kotlin : "1.4.32", - kotlinxCoroutines : "1.4.3-native-mt", + room : "2.3.0", + kotlin : "1.5.10", + kotlinxCoroutines : "1.5.0-native-mt", viewModelKtx : "2.2.0", retrofit : "2.6.4", jackson : "2.9.5", okhttp : "3.12.13", twitterSerial : "0.1.6", - koin : "2.2.2", + koin : "3.0.2", picasso : "2.71828", sortListView : "1.0.1", diff --git a/fastlane/metadata/android/en-US/changelogs/93.txt b/fastlane/metadata/android/en-US/changelogs/93.txt new file mode 100644 index 00000000..9b17841a --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/93.txt @@ -0,0 +1,14 @@ +Bug fixes +- #411: getContext() can return null in Fragments. +- #415: App crashes when pressing the album cover in player. +- #447: Fix all service notification issues. +- #484: Add error handling to SelectAlbumModel functions. + +Enhancements +- #433: Lock screen playback controls should include next/previous track. +- #476: Remove jcenter(). +- #477: Make all preference operations context-free. +- #485: Remove MusicService. +- #493: Introduce new Generic Fragments, ViewModels, and Adapters for the display of API data. +- #505: Implement server feature checking. +- #506: Convert all remaining Music servic classes to Kotlin. diff --git a/fastlane/metadata/android/es-ES/changelogs/93.txt b/fastlane/metadata/android/es-ES/changelogs/93.txt new file mode 100644 index 00000000..31567094 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/93.txt @@ -0,0 +1,14 @@ +Correción de errores +- #411: getContext() puede retornar fragmentos nulos. +- #415: La aplicación se bloquea al presionar sobre la portada del álbum en el reproductor. +- #447: Solucionar todos los problemas de notificación de servicio. +- #484: Agregar manejo de errores a las funciones de SelectAlbumModel. + +Mejoras +- #433: Los controles de reproducción de la pantalla de bloqueo deben incluir la pista siguiente/anterior. +- #476: Elimina jcenter(). +- #477: Hacer que todas las operaciones de preferencias estén libres de contexto. +- #485: Elimina MusicService. +- #493: Introducir nuevos fragmentos genéricos, modelos de vista y adaptadores para la visualización de datos de API. +- #505: Implementar la verificación de características del servidor. +- #506: Convertir todas las clases de servicios de música restantes a Kotlin. diff --git a/gradle_scripts/android-module-bootstrap.gradle b/gradle_scripts/android-module-bootstrap.gradle index f9fa091a..847827e7 100644 --- a/gradle_scripts/android-module-bootstrap.gradle +++ b/gradle_scripts/android-module-bootstrap.gradle @@ -13,10 +13,6 @@ android { targetSdkVersion versions.targetSdk } - kotlinOptions { - jvmTarget = "1.8" - } - compileOptions { // Sets Java compatibility to Java 8 sourceCompatibility JavaVersion.VERSION_1_8 diff --git a/ultrasonic/build.gradle b/ultrasonic/build.gradle index f8530d95..3d6a9f78 100644 --- a/ultrasonic/build.gradle +++ b/ultrasonic/build.gradle @@ -9,8 +9,8 @@ android { defaultConfig { applicationId "org.moire.ultrasonic" - versionCode 92 - versionName "2.20.0" + versionCode 93 + versionName "2.21.0" minSdkVersion versions.minSdk targetSdkVersion versions.targetSdk @@ -56,7 +56,6 @@ android { kotlinOptions { jvmTarget = "1.8" - freeCompilerArgs += "-Xopt-in=org.koin.core.component.KoinApiExtension" } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -94,7 +93,6 @@ dependencies { implementation other.kotlinStdlib implementation other.kotlinxCoroutines implementation other.koinAndroid - implementation other.koinViewModel implementation other.okhttpLogging implementation other.fastScroll implementation other.sortListView diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/PlayerFragment.java b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/PlayerFragment.java index a2f5881b..4f662d60 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/PlayerFragment.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/PlayerFragment.java @@ -162,7 +162,8 @@ public class PlayerFragment extends Fragment implements GestureDetector.OnGestur setHasOptionsMenu(true); - useFiveStarRating = KoinJavaComponent.get(FeatureStorage.class).isFeatureEnabled(Feature.FIVE_STAR_RATING); + FeatureStorage features = KoinJavaComponent.get(FeatureStorage.class); + useFiveStarRating = features.isFeatureEnabled(Feature.FIVE_STAR_RATING); swipeDistance = (width + height) * PERCENTAGE_OF_SCREEN_FOR_SWIPE / 100; swipeVelocity = swipeDistance; diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/util/CacheCleaner.java b/ultrasonic/src/main/java/org/moire/ultrasonic/util/CacheCleaner.java index a63c8875..c09d6edc 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/CacheCleaner.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/util/CacheCleaner.java @@ -23,7 +23,7 @@ import kotlin.Lazy; import static org.koin.java.KoinJavaComponent.inject; /** - * Responsible for cleaning up files from the offline download cache on the filesystem + * Responsible for cleaning up files from the offline download cache on the filesystem. */ public class CacheCleaner { diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java index f89ed103..82366ed6 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java @@ -594,16 +594,16 @@ public class Util } - private static void showDialog(Context context, int icon, int titleId, int messageId) + // The AlertDialog requires an Activity context, app context is not enough + // See https://stackoverflow.com/questions/5436822/ + public static void showDialog(Context context, int icon, int titleId, String message) { - new AlertDialog.Builder(context).setIcon(icon).setTitle(titleId).setMessage(messageId).setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() - { - @Override - public void onClick(DialogInterface dialog, int i) - { - dialog.dismiss(); - } - }).show(); + new AlertDialog.Builder(context) + .setIcon(icon) + .setTitle(titleId) + .setMessage(message) + .setPositiveButton(R.string.common_ok, (dialog, i) -> dialog.dismiss()) + .show(); } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/NavigationActivity.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/NavigationActivity.kt index ed7245cb..7f8abc29 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/NavigationActivity.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/NavigationActivity.kt @@ -28,8 +28,10 @@ import androidx.navigation.ui.setupWithNavController import androidx.preference.PreferenceManager import com.google.android.material.navigation.NavigationView import org.koin.android.ext.android.inject -import org.koin.android.viewmodel.ext.android.viewModel +import org.koin.androidx.viewmodel.ext.android.viewModel +import org.koin.java.KoinJavaComponent.inject import org.moire.ultrasonic.R +import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline import org.moire.ultrasonic.domain.PlayerState import org.moire.ultrasonic.fragment.OnBackPressedHandler @@ -368,10 +370,18 @@ class NavigationActivity : AppCompatActivity() { } private fun setMenuForServerSetting() { - val visibility = !isOffline() - chatMenuItem?.isVisible = visibility - bookmarksMenuItem?.isVisible = visibility - sharesMenuItem?.isVisible = visibility - podcastsMenuItem?.isVisible = visibility + if (isOffline()) { + chatMenuItem?.isVisible = false + bookmarksMenuItem?.isVisible = false + sharesMenuItem?.isVisible = false + podcastsMenuItem?.isVisible = false + return + } + val activeServerProvider: ActiveServerProvider by inject() + val activeServer = activeServerProvider.getActiveServer() + chatMenuItem?.isVisible = activeServer.chatSupport != false + bookmarksMenuItem?.isVisible = activeServer.bookmarkSupport != false + sharesMenuItem?.isVisible = activeServer.shareSupport != false + podcastsMenuItem?.isVisible = activeServer.podcastSupport != false } } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/AppDatabase.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/AppDatabase.kt index ee265000..e4aa77dc 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/AppDatabase.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/AppDatabase.kt @@ -8,7 +8,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase /** * Room Database to be used to store data for Ultrasonic */ -@Database(entities = [ServerSetting::class], version = 2) +@Database(entities = [ServerSetting::class], version = 3) abstract class AppDatabase : RoomDatabase() { /** @@ -24,3 +24,20 @@ val MIGRATION_1_2: Migration = object : Migration(1, 2) { ) } } + +val MIGRATION_2_3: Migration = object : Migration(2, 3) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( + "ALTER TABLE ServerSetting ADD COLUMN chatSupport INTEGER" + ) + database.execSQL( + "ALTER TABLE ServerSetting ADD COLUMN bookmarkSupport INTEGER" + ) + database.execSQL( + "ALTER TABLE ServerSetting ADD COLUMN shareSupport INTEGER" + ) + database.execSQL( + "ALTER TABLE ServerSetting ADD COLUMN podcastSupport INTEGER" + ) + } +} diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSetting.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSetting.kt index c5749a23..705f526a 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSetting.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSetting.kt @@ -29,7 +29,11 @@ data class ServerSetting( @ColumnInfo(name = "allowSelfSignedCertificate") var allowSelfSignedCertificate: Boolean, @ColumnInfo(name = "ldapSupport") var ldapSupport: Boolean, @ColumnInfo(name = "musicFolderId") var musicFolderId: String?, - @ColumnInfo(name = "minimumApiVersion") var minimumApiVersion: String? + @ColumnInfo(name = "minimumApiVersion") var minimumApiVersion: String?, + @ColumnInfo(name = "chatSupport") var chatSupport: Boolean? = null, + @ColumnInfo(name = "bookmarkSupport") var bookmarkSupport: Boolean? = null, + @ColumnInfo(name = "shareSupport") var shareSupport: Boolean? = null, + @ColumnInfo(name = "podcastSupport") var podcastSupport: Boolean? = null ) { constructor() : this ( -1, 0, "", "", "", "", false, false, false, null, null diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/AppPermanentStorageModule.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/AppPermanentStorageModule.kt index 89c5cbc3..1b430ae1 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/AppPermanentStorageModule.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/AppPermanentStorageModule.kt @@ -2,11 +2,12 @@ package org.moire.ultrasonic.di import androidx.room.Room import org.koin.android.ext.koin.androidContext -import org.koin.android.viewmodel.dsl.viewModel +import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.core.qualifier.named import org.koin.dsl.module import org.moire.ultrasonic.data.AppDatabase import org.moire.ultrasonic.data.MIGRATION_1_2 +import org.moire.ultrasonic.data.MIGRATION_2_3 import org.moire.ultrasonic.fragment.ServerSettingsModel import org.moire.ultrasonic.util.Util @@ -25,6 +26,7 @@ val appPermanentStorage = module { "ultrasonic-database" ) .addMigrations(MIGRATION_1_2) + .addMigrations(MIGRATION_2_3) .fallbackToDestructiveMigrationOnDowngrade() .build() } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListFragment.kt index f5b4b4e4..75b93057 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListFragment.kt @@ -6,7 +6,6 @@ import androidx.fragment.app.viewModels import androidx.lifecycle.LiveData import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.RecyclerView -import org.koin.core.component.KoinApiExtension import org.moire.ultrasonic.R import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.util.Constants @@ -15,7 +14,6 @@ import org.moire.ultrasonic.util.Constants * Displays a list of Albums from the media library * TODO: Check refresh is working */ -@KoinApiExtension class AlbumListFragment : GenericListFragment() { /** diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListModel.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListModel.kt index 7c927044..5a6e1ba8 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListModel.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListModel.kt @@ -5,14 +5,12 @@ import android.os.Bundle import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.swiperefreshlayout.widget.SwipeRefreshLayout -import org.koin.core.component.KoinApiExtension import org.moire.ultrasonic.api.subsonic.models.AlbumListType import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.service.MusicService import org.moire.ultrasonic.util.Constants import org.moire.ultrasonic.util.Util -@KoinApiExtension class AlbumListModel(application: Application) : GenericListModel(application) { val albumList: MutableLiveData> = MutableLiveData() diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistListFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistListFragment.kt index ddda850b..6b48979c 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistListFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistListFragment.kt @@ -3,7 +3,6 @@ package org.moire.ultrasonic.fragment import android.os.Bundle import androidx.fragment.app.viewModels import androidx.lifecycle.LiveData -import org.koin.core.component.KoinApiExtension import org.moire.ultrasonic.R import org.moire.ultrasonic.domain.Artist import org.moire.ultrasonic.util.Constants @@ -11,7 +10,6 @@ import org.moire.ultrasonic.util.Constants /** * Displays the list of Artists from the media library */ -@KoinApiExtension class ArtistListFragment : GenericListFragment() { /** diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistListModel.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistListModel.kt index 2611e3d2..d58e97ca 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistListModel.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistListModel.kt @@ -23,14 +23,12 @@ import android.os.Bundle import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.swiperefreshlayout.widget.SwipeRefreshLayout -import org.koin.core.component.KoinApiExtension import org.moire.ultrasonic.domain.Artist import org.moire.ultrasonic.service.MusicService /** * Provides ViewModel which contains the list of available Artists */ -@KoinApiExtension class ArtistListModel(application: Application) : GenericListModel(application) { private val artists: MutableLiveData> = MutableLiveData() diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistRowAdapter.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistRowAdapter.kt index 30f76f4e..2e312225 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistRowAdapter.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ArtistRowAdapter.kt @@ -96,7 +96,7 @@ class ArtistRowAdapter( } private fun getSectionFromName(name: String): String { - var section = name.first().toUpperCase() + var section = name.first().uppercaseChar() if (!section.isLetter()) section = '#' return section.toString() } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EditServerFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EditServerFragment.kt index 12519813..39dc892d 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EditServerFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EditServerFragment.kt @@ -11,23 +11,28 @@ import androidx.lifecycle.Observer import androidx.navigation.fragment.findNavController import com.google.android.material.switchmaterial.SwitchMaterial import com.google.android.material.textfield.TextInputLayout +import java.io.IOException import java.net.MalformedURLException import java.net.URL +import java.util.Locale import org.koin.android.ext.android.inject -import org.koin.android.viewmodel.ext.android.viewModel +import org.koin.androidx.viewmodel.ext.android.viewModel import org.moire.ultrasonic.BuildConfig import org.moire.ultrasonic.R import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions import org.moire.ultrasonic.api.subsonic.SubsonicClientConfiguration +import org.moire.ultrasonic.api.subsonic.response.SubsonicResponse import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.data.ServerSetting import org.moire.ultrasonic.service.ApiCallResponseChecker import org.moire.ultrasonic.service.MusicServiceFactory +import org.moire.ultrasonic.service.SubsonicRESTException import org.moire.ultrasonic.util.Constants import org.moire.ultrasonic.util.ErrorDialog import org.moire.ultrasonic.util.ModalBackgroundTask import org.moire.ultrasonic.util.Util +import retrofit2.Response import timber.log.Timber /** @@ -295,14 +300,41 @@ class EditServerFragment : Fragment(), OnBackPressedHandler { * Tests if the network connection to the entered Server Settings can be made */ private fun testConnection() { - val task: ModalBackgroundTask = object : ModalBackgroundTask( + val task: ModalBackgroundTask = object : ModalBackgroundTask( activity, false ) { + fun boolToMark(value: Boolean?): String { + if (value == null) + return "⌛" + return if (value) "✔️" else "❌" + } + + fun getProgress(): String { + return String.format( + """ + |%s - ${resources.getString(R.string.button_bar_chat)} + |%s - ${resources.getString(R.string.button_bar_bookmarks)} + |%s - ${resources.getString(R.string.button_bar_shares)} + |%s - ${resources.getString(R.string.button_bar_podcasts)} + """.trimMargin(), + boolToMark(currentServerSetting!!.chatSupport), + boolToMark(currentServerSetting!!.bookmarkSupport), + boolToMark(currentServerSetting!!.shareSupport), + boolToMark(currentServerSetting!!.podcastSupport) + ) + } @Throws(Throwable::class) - override fun doInBackground(): Boolean { - updateProgress(R.string.settings_testing_connection) + override fun doInBackground(): String { + + currentServerSetting!!.chatSupport = null + currentServerSetting!!.bookmarkSupport = null + currentServerSetting!!.shareSupport = null + currentServerSetting!!.podcastSupport = null + + updateProgress(getProgress()) + val configuration = SubsonicClientConfiguration( currentServerSetting!!.url, currentServerSetting!!.userName, @@ -330,17 +362,62 @@ class EditServerFragment : Fragment(), OnBackPressedHandler { pingResponse = subsonicApiClient.api.ping().execute() ApiCallResponseChecker.checkResponseSuccessful(pingResponse) + currentServerSetting!!.chatSupport = isServerFunctionAvailable { + subsonicApiClient.api.getChatMessages().execute() + } + + updateProgress(getProgress()) + + currentServerSetting!!.bookmarkSupport = isServerFunctionAvailable { + subsonicApiClient.api.getBookmarks().execute() + } + + updateProgress(getProgress()) + + currentServerSetting!!.shareSupport = isServerFunctionAvailable { + subsonicApiClient.api.getShares().execute() + } + + updateProgress(getProgress()) + + currentServerSetting!!.podcastSupport = isServerFunctionAvailable { + subsonicApiClient.api.getPodcasts().execute() + } + + updateProgress(getProgress()) + val licenseResponse = subsonicApiClient.api.getLicense().execute() ApiCallResponseChecker.checkResponseSuccessful(licenseResponse) - return licenseResponse.body()!!.license.valid + if (!licenseResponse.body()!!.license.valid) { + return getProgress() + "\n" + + resources.getString(R.string.settings_testing_unlicensed) + } + return getProgress() } - override fun done(licenseValid: Boolean) { - if (licenseValid) { - Util.toast(activity, R.string.settings_testing_ok) - } else { - Util.toast(activity, R.string.settings_testing_unlicensed) + override fun done(responseString: String) { + var dialogText = responseString + if (arrayOf( + currentServerSetting!!.chatSupport, + currentServerSetting!!.bookmarkSupport, + currentServerSetting!!.shareSupport, + currentServerSetting!!.podcastSupport + ).any { x -> x == false } + ) { + dialogText = String.format( + Locale.ROOT, + "%s\n\n%s", + responseString, + resources.getString(R.string.server_editor_disabled_feature) + ) } + + Util.showDialog( + activity, + android.R.drawable.ic_dialog_info, + R.string.settings_testing_ok, + dialogText + ) } override fun error(error: Throwable) { @@ -359,6 +436,18 @@ class EditServerFragment : Fragment(), OnBackPressedHandler { task.execute() } + private fun isServerFunctionAvailable(function: () -> Response): Boolean { + return try { + val response = function() + ApiCallResponseChecker.checkResponseSuccessful(response) + true + } catch (_: IOException) { + false + } catch (_: SubsonicRESTException) { + false + } + } + /** * Finishes the Activity, after confirmation from the user if needed */ diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/GenericListFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/GenericListFragment.kt index 723193ad..2862eaa8 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/GenericListFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/GenericListFragment.kt @@ -13,8 +13,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import org.koin.android.ext.android.inject -import org.koin.android.viewmodel.ext.android.viewModel -import org.koin.core.component.KoinApiExtension +import org.koin.androidx.viewmodel.ext.android.viewModel import org.moire.ultrasonic.R import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.domain.Artist @@ -31,7 +30,6 @@ import org.moire.ultrasonic.view.SelectMusicFolderView * @param T: The type of data which will be used (must extend GenericEntry) * @param TA: The Adapter to use (must extend GenericRowAdapter) */ -@KoinApiExtension abstract class GenericListFragment> : Fragment() { internal val activeServerProvider: ActiveServerProvider by inject() internal val serverSettingsModel: ServerSettingsModel by viewModel() diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/GenericListModel.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/GenericListModel.kt index 810e90f5..bf377eed 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/GenericListModel.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/GenericListModel.kt @@ -15,7 +15,6 @@ import java.net.UnknownHostException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.koin.core.component.KoinApiExtension import org.koin.core.component.KoinComponent import org.koin.core.component.inject import org.moire.ultrasonic.data.ActiveServerProvider @@ -29,7 +28,6 @@ import org.moire.ultrasonic.util.Util /** * An abstract Model, which can be extended to retrieve a list of items from the API */ -@KoinApiExtension open class GenericListModel(application: Application) : AndroidViewModel(application), KoinComponent { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt index a7093210..bde3efd5 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import org.koin.android.ext.android.inject -import org.koin.android.viewmodel.ext.android.viewModel +import org.koin.androidx.viewmodel.ext.android.viewModel import org.moire.ultrasonic.R import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.fragment.EditServerFragment.Companion.EDIT_SERVER_INTENT_INDEX diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionFragment.kt index 08dd7fd7..2d544ef1 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionFragment.kt @@ -33,7 +33,6 @@ import java.util.Random import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.launch import org.koin.android.ext.android.inject -import org.koin.core.component.KoinApiExtension import org.moire.ultrasonic.R import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline import org.moire.ultrasonic.domain.MusicDirectory @@ -60,7 +59,6 @@ import timber.log.Timber * Displays a group of tracks, eg. the songs of an album, of a playlist etc. * TODO: Refactor this fragment and model to extend the GenericListFragment */ -@KoinApiExtension class TrackCollectionFragment : Fragment() { private var refreshAlbumListView: SwipeRefreshLayout? = null diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionModel.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionModel.kt index 45b2d81a..c6ca882a 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionModel.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionModel.kt @@ -13,7 +13,6 @@ import androidx.lifecycle.MutableLiveData import java.util.LinkedList import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.koin.core.component.KoinApiExtension import org.moire.ultrasonic.R import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.service.MusicService @@ -24,7 +23,6 @@ import org.moire.ultrasonic.util.Util * Model for retrieving different collections of tracks from the API * TODO: Refactor this model to extend the GenericListModel */ -@KoinApiExtension class TrackCollectionModel(application: Application) : GenericListModel(application) { private val allSongsId = "-1" diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/AudioFocusHandler.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/AudioFocusHandler.kt index dbd107b8..0d3e7791 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/AudioFocusHandler.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/AudioFocusHandler.kt @@ -18,7 +18,8 @@ import timber.log.Timber class AudioFocusHandler(private val context: Context) { // TODO: This is a circular reference, try to remove it // This should be doable by using the native MediaController framework - private val mediaPlayerControllerLazy = inject(MediaPlayerController::class.java) + private val mediaPlayerControllerLazy = + inject(MediaPlayerController::class.java) private val audioManager by lazy { context.getSystemService(Context.AUDIO_SERVICE) as AudioManager diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/CachedMusicService.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/CachedMusicService.kt index 1086a797..0f280258 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/CachedMusicService.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/CachedMusicService.kt @@ -9,7 +9,8 @@ package org.moire.ultrasonic.service import android.graphics.Bitmap import java.io.InputStream import java.util.concurrent.TimeUnit -import org.koin.java.KoinJavaComponent.inject +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.domain.Bookmark import org.moire.ultrasonic.domain.ChatMessage @@ -31,10 +32,9 @@ import org.moire.ultrasonic.util.TimeLimitedCache import org.moire.ultrasonic.util.Util @Suppress("TooManyFunctions") -class CachedMusicService(private val musicService: MusicService) : MusicService { - private val activeServerProvider = inject( - ActiveServerProvider::class.java - ) +class CachedMusicService(private val musicService: MusicService) : MusicService, KoinComponent { + private val activeServerProvider: ActiveServerProvider by inject() + private val cachedMusicDirectories: LRUCache> private val cachedArtist: LRUCache> private val cachedAlbum: LRUCache> @@ -308,8 +308,8 @@ class CachedMusicService(private val musicService: MusicService) : MusicService } private fun checkSettingsChanged() { - val newUrl = activeServerProvider.value.getRestUrl(null) - val newFolderId = activeServerProvider.value.getActiveServer().musicFolderId + val newUrl = activeServerProvider.getRestUrl(null) + val newFolderId = activeServerProvider.getActiveServer().musicFolderId if (!Util.equals(newUrl, restUrl) || !Util.equals(cachedMusicFolderId, newFolderId)) { cachedMusicFolders.clear() cachedMusicDirectories.clear() diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/DownloadFile.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/DownloadFile.kt index 6c75e62d..fd98da9b 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/DownloadFile.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/DownloadFile.kt @@ -19,8 +19,8 @@ import java.io.IOException import java.io.InputStream import java.io.OutputStream import java.io.RandomAccessFile -import org.koin.core.component.KoinApiExtension -import org.koin.java.KoinJavaComponent.inject +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject import org.moire.ultrasonic.app.UApp import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService @@ -36,11 +36,10 @@ import timber.log.Timber * @author Sindre Mehus * @version $Id$ */ -@KoinApiExtension class DownloadFile( val song: MusicDirectory.Entry, private val save: Boolean -) { +) : KoinComponent { val partialFile: File val completeFile: File private val saveFile: File = FileUtil.getSongFile(song) @@ -59,7 +58,7 @@ class DownloadFile( @Volatile private var completeWhenDone = false - private val downloader = inject(Downloader::class.java) + private val downloader: Downloader by inject() val progress: MutableLiveData = MutableLiveData(0) @@ -201,7 +200,6 @@ class DownloadFile( return String.format("DownloadFile (%s)", song) } - @KoinApiExtension @Suppress("TooGenericExceptionCaught") private inner class DownloadTask : CancellableTask() { override fun execute() { @@ -310,7 +308,7 @@ class DownloadFile( } wifiLock?.release() CacheCleaner().cleanSpace() - downloader.value.checkDownloads() + downloader.checkDownloads() } } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/LocalMediaPlayer.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/LocalMediaPlayer.kt index c3e80f4f..9216b3bd 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/LocalMediaPlayer.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/LocalMediaPlayer.kt @@ -25,7 +25,6 @@ import java.net.URLEncoder import java.util.Locale import kotlin.math.abs import kotlin.math.max -import org.koin.core.component.KoinApiExtension import org.moire.ultrasonic.audiofx.EqualizerController import org.moire.ultrasonic.audiofx.VisualizerController import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline @@ -40,7 +39,6 @@ import timber.log.Timber /** * Represents a Media Player which uses the mobile's resources for playback */ -@KoinApiExtension class LocalMediaPlayer( private val audioFocusHandler: AudioFocusHandler, private val context: Context diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt index 7f88a75d..e8f3c4f0 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt @@ -7,9 +7,9 @@ package org.moire.ultrasonic.service import android.content.Intent -import org.koin.core.component.KoinApiExtension -import org.koin.java.KoinJavaComponent.get -import org.koin.java.KoinJavaComponent.inject +import org.koin.core.component.KoinComponent +import org.koin.core.component.get +import org.koin.core.component.inject import org.moire.ultrasonic.app.UApp import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.domain.MusicDirectory @@ -30,7 +30,6 @@ import timber.log.Timber * This class contains everything that is necessary for the Application UI * to control the Media Player implementation. */ -@KoinApiExtension @Suppress("TooManyFunctions") class MediaPlayerController( private val downloadQueueSerializer: DownloadQueueSerializer, @@ -38,7 +37,7 @@ class MediaPlayerController( private val downloader: Downloader, private val shufflePlayBuffer: ShufflePlayBuffer, private val localMediaPlayer: LocalMediaPlayer -) { +) : KoinComponent { private var created = false var suggestedPlaylistName: String? = null @@ -46,8 +45,8 @@ class MediaPlayerController( var showVisualization = false private var autoPlayStart = false - private val jukeboxMediaPlayer = inject(JukeboxMediaPlayer::class.java).value - private val activeServerProvider = inject(ActiveServerProvider::class.java).value + private val jukeboxMediaPlayer: JukeboxMediaPlayer by inject() + private val activeServerProvider: ActiveServerProvider by inject() fun onCreate() { if (created) return @@ -462,7 +461,8 @@ class MediaPlayerController( @Suppress("TooGenericExceptionCaught") // The interface throws only generic exceptions fun setSongRating(rating: Int) { - if (!get(FeatureStorage::class.java).isFeatureEnabled(Feature.FIVE_STAR_RATING)) return + val features: FeatureStorage = get() + if (!features.isFeatureEnabled(Feature.FIVE_STAR_RATING)) return if (localMediaPlayer.currentPlaying == null) return val song = localMediaPlayer.currentPlaying!!.song song.userRating = rating diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MusicServiceFactory.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MusicServiceFactory.kt index 0f3f33df..02ddb4a5 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MusicServiceFactory.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MusicServiceFactory.kt @@ -18,7 +18,6 @@ */ package org.moire.ultrasonic.service -import org.koin.core.component.KoinApiExtension import org.koin.core.component.KoinComponent import org.koin.core.component.get import org.koin.core.context.loadKoinModules @@ -30,7 +29,6 @@ import org.moire.ultrasonic.di.ONLINE_MUSIC_SERVICE import org.moire.ultrasonic.di.musicServiceModule // TODO Refactor everywhere to use DI way to get MusicService, and then remove this class -@KoinApiExtension object MusicServiceFactory : KoinComponent { @JvmStatic fun getMusicService(): MusicService { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/OfflineMusicService.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/OfflineMusicService.kt index 8e751382..f1fc7f43 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/OfflineMusicService.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/OfflineMusicService.kt @@ -22,7 +22,8 @@ import java.util.Locale import java.util.Random import java.util.concurrent.TimeUnit import java.util.regex.Pattern -import org.koin.java.KoinJavaComponent.inject +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.domain.Artist import org.moire.ultrasonic.domain.Bookmark @@ -47,10 +48,8 @@ import timber.log.Timber // TODO: There are quite a number of deeply nested and complicated functions in this class.. // Simplify them :) @Suppress("TooManyFunctions") -class OfflineMusicService : MusicService { - private val activeServerProvider = inject( - ActiveServerProvider::class.java - ) +class OfflineMusicService : MusicService, KoinComponent { + private val activeServerProvider: ActiveServerProvider by inject() override fun getIndexes(musicFolderId: String?, refresh: Boolean): Indexes { val artists: MutableList = ArrayList() @@ -67,8 +66,8 @@ class OfflineMusicService : MusicService { val ignoredArticlesString = "The El La Los Las Le Les" val ignoredArticles = COMPILE.split(ignoredArticlesString) artists.sortWith { lhsArtist, rhsArtist -> - var lhs = lhsArtist.name!!.toLowerCase(Locale.ROOT) - var rhs = rhsArtist.name!!.toLowerCase(Locale.ROOT) + var lhs = lhsArtist.name!!.lowercase(Locale.ROOT) + var rhs = rhsArtist.name!!.lowercase(Locale.ROOT) val lhs1 = lhs[0] val rhs1 = rhs[0] if (Character.isDigit(lhs1) && !Character.isDigit(rhs1)) { @@ -79,13 +78,13 @@ class OfflineMusicService : MusicService { } for (article in ignoredArticles) { var index = lhs.indexOf( - String.format(Locale.ROOT, "%s ", article.toLowerCase(Locale.ROOT)) + String.format(Locale.ROOT, "%s ", article.lowercase(Locale.ROOT)) ) if (index == 0) { lhs = lhs.substring(article.length + 1) } index = rhs.indexOf( - String.format(Locale.ROOT, "%s ", article.toLowerCase(Locale.ROOT)) + String.format(Locale.ROOT, "%s ", article.lowercase(Locale.ROOT)) ) if (index == 0) { rhs = rhs.substring(article.length + 1) @@ -253,7 +252,7 @@ class OfflineMusicService : MusicService { @Throws(Exception::class) override fun createPlaylist(id: String, name: String, entries: List) { val playlistFile = - FileUtil.getPlaylistFile(activeServerProvider.value.getActiveServer().name, name) + FileUtil.getPlaylistFile(activeServerProvider.getActiveServer().name, name) val fw = FileWriter(playlistFile) val bw = BufferedWriter(fw) try { @@ -668,10 +667,10 @@ class OfflineMusicService : MusicService { } private fun matchCriteria(criteria: SearchCriteria, name: String?): Int { - val query = criteria.query.toLowerCase(Locale.ROOT) + val query = criteria.query.lowercase(Locale.ROOT) val queryParts = COMPILE.split(query) val nameParts = COMPILE.split( - name!!.toLowerCase(Locale.ROOT) + name!!.lowercase(Locale.ROOT) ) var closeness = 0 for (queryPart in queryParts) { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/subsonic/DownloadHandler.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/subsonic/DownloadHandler.kt index 7782d8a0..b30490ac 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/subsonic/DownloadHandler.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/subsonic/DownloadHandler.kt @@ -5,7 +5,6 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import java.util.Collections import java.util.LinkedList -import org.koin.core.component.KoinApiExtension import org.moire.ultrasonic.R import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline import org.moire.ultrasonic.domain.MusicDirectory @@ -20,7 +19,6 @@ import org.moire.ultrasonic.util.Util * Retrieves a list of songs and adds them to the now playing list */ @Suppress("LongParameterList") -@KoinApiExtension class DownloadHandler( val mediaPlayerController: MediaPlayerController, val networkAndStorageChecker: NetworkAndStorageChecker diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/subsonic/ImageLoaderProvider.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/subsonic/ImageLoaderProvider.kt index 549b9e8e..3ee6bf53 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/subsonic/ImageLoaderProvider.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/subsonic/ImageLoaderProvider.kt @@ -1,10 +1,10 @@ package org.moire.ultrasonic.subsonic import android.content.Context -import org.koin.java.KoinJavaComponent.get +import org.koin.core.component.KoinComponent +import org.koin.core.component.get import org.moire.ultrasonic.featureflags.Feature import org.moire.ultrasonic.featureflags.FeatureStorage -import org.moire.ultrasonic.subsonic.loader.image.SubsonicImageLoader import org.moire.ultrasonic.util.ImageLoader import org.moire.ultrasonic.util.LegacyImageLoader import org.moire.ultrasonic.util.Util @@ -12,7 +12,7 @@ import org.moire.ultrasonic.util.Util /** * Handles the lifetime of the Image Loader */ -class ImageLoaderProvider(val context: Context) { +class ImageLoaderProvider(val context: Context) : KoinComponent { private var imageLoader: ImageLoader? = null @Synchronized @@ -33,12 +33,12 @@ class ImageLoaderProvider(val context: Context) { context, Util.getImageLoaderConcurrency() ) - val isNewImageLoaderEnabled = get(FeatureStorage::class.java) - .isFeatureEnabled(Feature.NEW_IMAGE_DOWNLOADER) + val features: FeatureStorage = get() + val isNewImageLoaderEnabled = features.isFeatureEnabled(Feature.NEW_IMAGE_DOWNLOADER) imageLoader = if (isNewImageLoaderEnabled) { SubsonicImageLoaderProxy( legacyImageLoader, - get(SubsonicImageLoader::class.java) + get() ) } else { legacyImageLoader diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/view/SongView.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/view/SongView.kt index 165f4ab1..3a4638c7 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/view/SongView.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/view/SongView.kt @@ -24,8 +24,9 @@ import android.graphics.drawable.Drawable import android.text.TextUtils import android.view.LayoutInflater import android.widget.Checkable -import org.koin.java.KoinJavaComponent.get -import org.koin.java.KoinJavaComponent.inject +import org.koin.core.component.KoinComponent +import org.koin.core.component.get +import org.koin.core.component.inject import org.moire.ultrasonic.R import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline import org.moire.ultrasonic.domain.MusicDirectory @@ -42,7 +43,7 @@ import timber.log.Timber /** * Used to display songs and videos in a `ListView`. */ -class SongView(context: Context) : UpdateView(context), Checkable { +class SongView(context: Context) : UpdateView(context), Checkable, KoinComponent { var entry: MusicDirectory.Entry? = null private set @@ -55,10 +56,9 @@ class SongView(context: Context) : UpdateView(context), Checkable { private var downloadFile: DownloadFile? = null private var playing = false private var viewHolder: SongViewHolder? = null - - private val useFiveStarRating: Boolean = - get(FeatureStorage::class.java).isFeatureEnabled(Feature.FIVE_STAR_RATING) - private val mediaPlayerControllerLazy = inject(MediaPlayerController::class.java) + private val features: FeatureStorage = get() + private val useFiveStarRating: Boolean = features.isFeatureEnabled(Feature.FIVE_STAR_RATING) + private val mediaPlayerController: MediaPlayerController by inject() fun setLayout(song: MusicDirectory.Entry) { @@ -96,7 +96,7 @@ class SongView(context: Context) : UpdateView(context), Checkable { updateBackground() entry = song - downloadFile = mediaPlayerControllerLazy.value.getDownloadFileForSong(song) + downloadFile = mediaPlayerController.getDownloadFileForSong(song) val artist = StringBuilder(60) var bitRate: String? = null @@ -223,7 +223,7 @@ class SongView(context: Context) : UpdateView(context), Checkable { public override fun update() { updateBackground() - downloadFile = mediaPlayerControllerLazy.value.getDownloadFileForSong(entry) + downloadFile = mediaPlayerController.getDownloadFileForSong(entry) updateDownloadStatus(downloadFile!!) @@ -254,7 +254,7 @@ class SongView(context: Context) : UpdateView(context), Checkable { if (rating > 4) starDrawable else starHollowDrawable ) - val playing = mediaPlayerControllerLazy.value.currentPlaying === downloadFile + val playing = mediaPlayerController.currentPlaying === downloadFile if (playing) { if (!this.playing) { diff --git a/ultrasonic/src/main/res/values-cs/strings.xml b/ultrasonic/src/main/res/values-cs/strings.xml index eae638c6..e1fc4b29 100644 --- a/ultrasonic/src/main/res/values-cs/strings.xml +++ b/ultrasonic/src/main/res/values-cs/strings.xml @@ -297,7 +297,6 @@ Zobrazovat číslo skladby Připojovat číslo skladby při zobrazování skladby Test připojení - Testuji připojení… Připojení je v pořádku Připojení je v pořádku. Server bez licence. Světlý @@ -445,7 +444,6 @@ Posunout níž Ověření Rozšířené možnosti - 1 skladba %d skladby diff --git a/ultrasonic/src/main/res/values-de/strings.xml b/ultrasonic/src/main/res/values-de/strings.xml index 32b362a5..ee0c65bf 100644 --- a/ultrasonic/src/main/res/values-de/strings.xml +++ b/ultrasonic/src/main/res/values-de/strings.xml @@ -296,7 +296,6 @@ Titelnummer anzeigen Titel mit Nummer anzeigen Verbindung testen - Teste Verbindung… Verbindung OK Verbindung OK, Server nicht lizensiert. Hell diff --git a/ultrasonic/src/main/res/values-es/strings.xml b/ultrasonic/src/main/res/values-es/strings.xml index 5c2520ba..1225d7eb 100644 --- a/ultrasonic/src/main/res/values-es/strings.xml +++ b/ultrasonic/src/main/res/values-es/strings.xml @@ -309,7 +309,6 @@ Mostrar número de pista Incluir el número de pista cuando se muestre una canción Comprobar conexión - Comprobado conexión… La conexión es correcta La conexión es correcta. Servidor sin licencia. Claro @@ -459,6 +458,7 @@ Bajar Autenticación Configuración avanzada + Una o más funciones se han deshabilitado porque el servidor no las admite.\nPuedes ejecutar esta prueba nuevamente en cualquier momento. 1 canción diff --git a/ultrasonic/src/main/res/values-fr/strings.xml b/ultrasonic/src/main/res/values-fr/strings.xml index f2f65ed8..8e9ba787 100644 --- a/ultrasonic/src/main/res/values-fr/strings.xml +++ b/ultrasonic/src/main/res/values-fr/strings.xml @@ -297,7 +297,6 @@ Afficher le numéro du titre Inclure son numero lors de l\'affichage d\'un titre Tester la connexion - Connexion en cours de test… Connexion correcte Connexion correcte. Serveur sans licence. Clair @@ -447,6 +446,7 @@ Déplacer vers le bas Authentification Paramètres avancés + Une ou plusieurs fonctionnalités ont été désactivées car le serveur ne les prend pas en charge.\nVous pouvez réexécuter ce test à tout moment. 1 titre diff --git a/ultrasonic/src/main/res/values-hu/strings.xml b/ultrasonic/src/main/res/values-hu/strings.xml index c185bcf5..c913b846 100644 --- a/ultrasonic/src/main/res/values-hu/strings.xml +++ b/ultrasonic/src/main/res/values-hu/strings.xml @@ -15,6 +15,13 @@ Csevegés (Chat) Ultrasonic főoldal Lejátszó + Lejátszás + Szünet + Ismétlés + Véletlen sorrendű + Állj + Következő + Előző Podcast Nincsenek podcast-csatornák regisztrálva Podcast @@ -32,8 +39,11 @@ Név OK Tárolás (Megőrzés az eszközön) + Szünet + Lejátszás Lejátszás (Utolsóként) Lejátszás (Következőként) + Előző lejátszása Lejátszás Véletlen sorrendű lejátszás Nyilvános @@ -256,6 +266,8 @@ Az alkalmazás folytatja a szüneteltetett lejátszást a fejhallgató behelyezésekor a készülékbe. Képernyő ébrentartása a letöltés alatt, a magasabb letöltési sebesség érdekében. Képernyő ébrentartása + Ne felejtsd el beállítani a Scrobble szolgáltatónál használt felhasználóneved és jelszavad a szervereden + Scrobble engedélyezése 1 10 100 @@ -297,11 +309,11 @@ Sorszám megjelenítése Dalok sorszámának megjelenítése. Kapcsolat tesztelése - Kapcsolat tesztelése… Kapcsolat OK! Kapcsolat OK! A kiszolgálónak nincs licence! Világos Sötét + Fekete Téma Engedélyezze az önaláírt HTTPS tanúsítványt Az LDAP-felhasználók támogatásának engedélyezése @@ -401,6 +413,8 @@ Minden Bluetooth eszköz Csak audio (A2DP) eszközök Kikapcsolva + Egy gombos Lejátszás/Szünet a Bluetooth eszközökön + Régebbi Bluetooth eszközök esetén segíthet, ha a Lejátszás/Szünet nem működik megfelelően Hibakeresési lehetőségek Hibakeresési napló írása fájlba A naplófájlok elérhetőek a következő helyen: %1$s/%2$s @@ -444,7 +458,6 @@ Lejjebb mozgat Bejelentkezés Haladó beállítások - 1 dal %d dal diff --git a/ultrasonic/src/main/res/values-it/strings.xml b/ultrasonic/src/main/res/values-it/strings.xml index a74532b5..043368a8 100644 --- a/ultrasonic/src/main/res/values-it/strings.xml +++ b/ultrasonic/src/main/res/values-it/strings.xml @@ -289,7 +289,6 @@ Visualizza numero traccia Includi numero traccia quando visualizzi una canzone Prova Connessione - Collaudo connessione… Connessione OK Connessione OK. Server senza licenza. Chiaro diff --git a/ultrasonic/src/main/res/values-nl/strings.xml b/ultrasonic/src/main/res/values-nl/strings.xml index 41c77857..2b2da416 100644 --- a/ultrasonic/src/main/res/values-nl/strings.xml +++ b/ultrasonic/src/main/res/values-nl/strings.xml @@ -266,6 +266,8 @@ Het afspelen wordt hervat zodra er een hoofdtelefoon wordt aangesloten. Door het scherm aan te houden tijdens het downloaden, wordt de downloadsnelheid verhoogd. Scherm aan houden + Let op: stel je gebruikersnaam en wachtwoord van je scrobble-dienst(en) in op je Subsonic-server + Scrobbelen 1 10 100 @@ -307,7 +309,6 @@ Itemnummer tonen Itemnummer tonen tijdens tonen van nummers Verbinding testen - Bezig met testen van verbinding… Verbinding is goed Verbinding is goed; geen serverlicentie. Licht @@ -457,6 +458,7 @@ Omlaag Authenticatie Geavanceerde instellingen + Eén of meerdere functies zijn uitgeschakeld omdat de server ze niet ondersteunt.\nVoer deze test later opnieuw uit. 1 nummer diff --git a/ultrasonic/src/main/res/values-pl/strings.xml b/ultrasonic/src/main/res/values-pl/strings.xml index 12d063bb..c09b4479 100644 --- a/ultrasonic/src/main/res/values-pl/strings.xml +++ b/ultrasonic/src/main/res/values-pl/strings.xml @@ -295,7 +295,6 @@ Wyświetlaj numer utworu Dołącza numer utworu podczas wyświetlania utworu Testuj połączenie - Trwa testowanie połączenia… Połączenie jest OK Połączenie jest OK. Brak licencji na serwerze. Jasny diff --git a/ultrasonic/src/main/res/values-pt-rBR/strings.xml b/ultrasonic/src/main/res/values-pt-rBR/strings.xml index 9989f711..826a45e4 100644 --- a/ultrasonic/src/main/res/values-pt-rBR/strings.xml +++ b/ultrasonic/src/main/res/values-pt-rBR/strings.xml @@ -297,7 +297,6 @@ Mostrar o Número da Faixa Incluir o número da faixa quando mostrando uma música Teste de Conexão - Testando conexão… Conexão OK Conexão OK. Servidor não licenciado. Claro @@ -447,7 +446,6 @@ Para baixo Autenticação Configurações avançadas - %d música %d músicas diff --git a/ultrasonic/src/main/res/values-pt/strings.xml b/ultrasonic/src/main/res/values-pt/strings.xml index d607c8c4..74a7d3d4 100644 --- a/ultrasonic/src/main/res/values-pt/strings.xml +++ b/ultrasonic/src/main/res/values-pt/strings.xml @@ -295,7 +295,6 @@ Mostrar o Número da Faixa Incluir o número da faixa quando mostrando uma música Teste de Conexão - Testando conexão… Conexão OK Conexão OK. Servidor não licenciado. Claro diff --git a/ultrasonic/src/main/res/values-ru/strings.xml b/ultrasonic/src/main/res/values-ru/strings.xml index 277f7d6b..76d8f0c0 100644 --- a/ultrasonic/src/main/res/values-ru/strings.xml +++ b/ultrasonic/src/main/res/values-ru/strings.xml @@ -290,7 +290,6 @@ Показать номер трека Включить номер дорожки при отображении песни Тестовое соединение - Тестирование соединения… Успешное соединение Успешное соединение. Сервер нелицензионный. Светлая diff --git a/ultrasonic/src/main/res/values-zh-rCN/strings.xml b/ultrasonic/src/main/res/values-zh-rCN/strings.xml index 9ebc2ebc..716b65f4 100644 --- a/ultrasonic/src/main/res/values-zh-rCN/strings.xml +++ b/ultrasonic/src/main/res/values-zh-rCN/strings.xml @@ -220,7 +220,6 @@ 显示通知 总是显示通知 测试连接 - 测试连接… 连接正常 连接正常, 服务器未授权。 主题 @@ -301,7 +300,6 @@ 下移 认证 高级设置 - 用户名或密码错误 缺少必需的参数。 未找到请求的数据。 diff --git a/ultrasonic/src/main/res/values/strings.xml b/ultrasonic/src/main/res/values/strings.xml index 7ab179e0..f0733e73 100644 --- a/ultrasonic/src/main/res/values/strings.xml +++ b/ultrasonic/src/main/res/values/strings.xml @@ -311,7 +311,6 @@ Show Track Number Include track number when displaying a song Test Connection - Testing connection… Connection is OK Connection is OK. Server unlicensed. Light @@ -462,6 +461,7 @@ Move down Authentication Advanced settings + One or more features were disabled because the server doesn\'t support them.\nYou can run this test again anytime. 1 song