Compare commits

..

8 Commits

Author SHA1 Message Date
birdbird
376748b298 Merge branch 'detekt' into 'develop'
Use default locations for Detekt config and baseline.

See merge request ultrasonic/ultrasonic!1017
2023-05-18 10:54:16 +00:00
birdbird
13091948ea Use default locations for Detekt config and baseline. 2023-05-18 10:54:16 +00:00
birdbird
0cfd8e8240 Merge branch 'prefs' into 'develop'
Modernize Activity launching to set custom cache location

See merge request ultrasonic/ultrasonic!1015
2023-05-18 10:32:17 +00:00
birdbird
7a17936855 Modernize Activity launching to set custom cache location 2023-05-18 10:32:17 +00:00
birdbird
1d7328c03e Merge branch 'kotlim' into 'develop'
Apply suggested Kotlin Gradle updates

See merge request ultrasonic/ultrasonic!1016
2023-05-18 10:29:10 +00:00
birdbird
76da209c6d Merge branch 'renovate/robolectric' into 'develop'
Update dependency org.robolectric:robolectric to v4.10.3

See merge request ultrasonic/ultrasonic!1014
2023-05-18 10:26:19 +00:00
tzugen
ddd9c29d7a
Apply suggested Kotlin Gradle updates 2023-05-18 12:22:40 +02:00
Renovate Bot
fe696943a4 Update dependency org.robolectric:robolectric to v4.10.3 2023-05-17 21:32:36 +00:00
13 changed files with 87 additions and 83 deletions

View File

@ -2,6 +2,7 @@ apply from: bootstrap.androidModule
apply plugin: 'kotlin-kapt'
dependencies {
implementation libs.core
implementation libs.roomRuntime
implementation libs.roomKtx
kapt libs.room

View File

@ -34,7 +34,7 @@ mockito = "5.3.1"
mockitoKotlin = "4.1.0"
kluent = "1.73"
apacheCodecs = "1.15"
robolectric = "4.10.2"
robolectric = "4.10.3"
timber = "5.0.1"
fastScroll = "2.0.1"
colorPicker = "2.2.4"

View File

@ -2,9 +2,9 @@
* This module provides a base for for submodules which depend on the Android runtime
*/
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'org.jetbrains.kotlin.android'
apply from: "${project.rootDir}/gradle_scripts/code_quality.gradle"
apply plugin: 'kotlin-kapt'
apply plugin: 'org.jetbrains.kotlin.kapt'
android {
compileSdkVersion versions.compileSdk

View File

@ -25,8 +25,6 @@ if (isCodeQualityEnabled) {
// Builds the AST in parallel. Rules are always executed in parallel.
// Can lead to speedups in larger projects.
parallel = true
baseline = file("${rootProject.projectDir}/detekt-baseline.xml")
config = files("${rootProject.projectDir}/detekt-config.yml")
}
}
tasks.detekt.jvmTarget = "17"

View File

@ -2,7 +2,7 @@
* This module provides a base for for pure kotlin modules
*/
apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'
apply plugin: 'org.jetbrains.kotlin.kapt'
apply from: "${project.rootDir}/gradle_scripts/code_quality.gradle"
sourceSets {

View File

@ -1,6 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'org.jetbrains.kotlin.android'
apply plugin: 'org.jetbrains.kotlin.kapt'
apply plugin: "androidx.navigation.safeargs.kotlin"
apply from: "../gradle_scripts/code_quality.gradle"

View File

@ -1,9 +1,9 @@
<?xml version='1.0' encoding='UTF-8'?>
<?xml version="1.0" ?>
<SmellBaseline>
<ManuallySuppressedIssues>
<ID>TooManyFunctions:PlaybackService.kt$PlaybackService : MediaLibraryServiceKoinComponentCoroutineScope</ID>
<ID>UnusedPrivateMember:UApp.kt$private fun VmPolicy.Builder.detectAllExceptSocket(): VmPolicy.Builder</ID>
<ID>ImplicitDefaultLocale:EditServerFragment.kt$EditServerFragment.&lt;no name provided>$String.format( "%s %s", resources.getString(R.string.settings_connection_failure), getErrorMessage(error) )</ID>
<ID>ImplicitDefaultLocale:EditServerFragment.kt$EditServerFragment.&lt;no name provided&gt;$String.format( "%s %s", resources.getString(R.string.settings_connection_failure), getErrorMessage(error) )</ID>
<ID>ImplicitDefaultLocale:FileLoggerTree.kt$FileLoggerTree$String.format("Failed to write log to %s", file)</ID>
<ID>ImplicitDefaultLocale:FileLoggerTree.kt$FileLoggerTree$String.format("Log file rotated, logging into file %s", file?.name)</ID>
<ID>ImplicitDefaultLocale:FileLoggerTree.kt$FileLoggerTree$String.format("Logging into file %s", file?.name)</ID>
@ -13,7 +13,7 @@
<ID>LongMethod:PlaylistsFragment.kt$PlaylistsFragment$override fun onContextItemSelected(menuItem: MenuItem): Boolean</ID>
<ID>LongMethod:ShareHandler.kt$ShareHandler$private fun showDialog( fragment: Fragment, shareDetails: ShareDetails, swipe: SwipeRefreshLayout?, cancellationToken: CancellationToken, additionalId: String? )</ID>
<ID>LongMethod:SharesFragment.kt$SharesFragment$override fun onContextItemSelected(menuItem: MenuItem): Boolean</ID>
<ID>LongParameterList:ServerRowAdapter.kt$ServerRowAdapter$( private var context: Context, passedData: Array&lt;ServerSetting>, private val model: ServerSettingsModel, private val activeServerProvider: ActiveServerProvider, private val manageMode: Boolean, private val serverDeletedCallback: ((Int) -> Unit), private val serverEditRequestedCallback: ((Int) -> Unit) )</ID>
<ID>LongParameterList:ServerRowAdapter.kt$ServerRowAdapter$( private var context: Context, passedData: Array&lt;ServerSetting&gt;, private val model: ServerSettingsModel, private val activeServerProvider: ActiveServerProvider, private val manageMode: Boolean, private val serverDeletedCallback: ((Int) -&gt; Unit), private val serverEditRequestedCallback: ((Int) -&gt; Unit) )</ID>
<ID>MagicNumber:ActiveServerProvider.kt$ActiveServerProvider$8192</ID>
<ID>MagicNumber:JukeboxMediaPlayer.kt$JukeboxMediaPlayer$0.05f</ID>
<ID>MagicNumber:JukeboxMediaPlayer.kt$JukeboxMediaPlayer$50</ID>

View File

@ -13,7 +13,7 @@ import static org.koin.java.KoinJavaComponent.inject;
public class UltrasonicIntentReceiver extends BroadcastReceiver
{
private Lazy<MediaPlayerLifecycleSupport> lifecycleSupport = inject(MediaPlayerLifecycleSupport.class);
private final Lazy<MediaPlayerLifecycleSupport> lifecycleSupport = inject(MediaPlayerLifecycleSupport.class);
@Override
public void onReceive(Context context, Intent intent)

View File

@ -1,14 +1,11 @@
package org.moire.ultrasonic.fragment
import android.app.Activity
import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.DocumentsContract
import android.provider.SearchRecentSuggestions
import android.view.View
import androidx.annotation.StringRes
@ -38,6 +35,7 @@ import org.moire.ultrasonic.util.Constants
import org.moire.ultrasonic.util.ErrorDialog
import org.moire.ultrasonic.util.FileUtil.ultrasonicDirectory
import org.moire.ultrasonic.util.InfoDialog
import org.moire.ultrasonic.util.SelectCacheActivityContract
import org.moire.ultrasonic.util.Settings
import org.moire.ultrasonic.util.Settings.id3TagsEnabledOnline
import org.moire.ultrasonic.util.Settings.preferences
@ -100,64 +98,14 @@ class SettingsFragment :
updateCustomPreferences()
}
/**
* This function will be called when we return from the file picker
* with a new custom cache location
*
* TODO: This method has been deprecated in favor of using the Activity Result API
* which brings increased type safety via an ActivityResultContract and the prebuilt
* contracts for common intents available in
* androidx.activity.result.contract.ActivityResultContracts,
* provides hooks for testing, and allow receiving results in separate,
* testable classes independent from your fragment.
* Use registerForActivityResult(ActivityResultContract, ActivityResultCallback) with the
* appropriate ActivityResultContract and handling the result in the callback.
*/
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
if (
requestCode == SELECT_CACHE_ACTIVITY &&
resultCode == Activity.RESULT_OK &&
resultData != null
) {
val read = (resultData.flags and Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
val write = (resultData.flags and Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
val persist = (resultData.flags and Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0
if (read && write && persist) {
if (resultData.data != null) {
// The result data contains a URI for the document or directory that
// the user selected.
val uri = resultData.data!!
val contentResolver = UApp.applicationContext().contentResolver
contentResolver.takePersistableUriPermission(uri, RW_FLAG)
setCacheLocation(uri.toString())
setupCacheLocationPreference()
return
}
}
ErrorDialog.Builder(requireContext())
.setMessage(R.string.settings_cache_location_error)
.show()
}
if (Settings.cacheLocationUri == "") {
Settings.customCacheLocation = false
customCacheLocation?.isChecked = false
setupCacheLocationPreference()
}
}
override fun onResume() {
super.onResume()
val preferences = preferences
preferences.registerOnSharedPreferenceChangeListener(this)
}
override fun onPause() {
super.onPause()
val prefs = preferences
prefs.unregisterOnSharedPreferenceChangeListener(this)
preferences.unregisterOnSharedPreferenceChangeListener(this)
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
@ -249,19 +197,31 @@ class SettingsFragment :
}
private fun selectCacheLocation() {
// Choose a directory using the system's file picker.
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
if (Settings.cacheLocationUri != "" && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Settings.cacheLocationUri)
}
intent.addFlags(RW_FLAG)
intent.addFlags(PERSISTABLE_FLAG)
startActivityForResult(intent, SELECT_CACHE_ACTIVITY)
// Start the activity to pick a directory using the system's file picker.
selectCacheActivityContract.launch(Settings.cacheLocationUri)
}
// Custom activity result contract
private val selectCacheActivityContract =
registerForActivityResult(SelectCacheActivityContract()) { uri ->
// parseResult will return the chosen path as an Uri
if (uri != null) {
val contentResolver = UApp.applicationContext().contentResolver
contentResolver.takePersistableUriPermission(uri, RW_FLAG)
setCacheLocation(uri.toString())
setupCacheLocationPreference()
} else {
ErrorDialog.Builder(requireContext())
.setMessage(R.string.settings_cache_location_error)
.show()
if (Settings.cacheLocationUri == "") {
Settings.customCacheLocation = false
customCacheLocation?.isChecked = false
setupCacheLocationPreference()
}
}
}
private fun setupBluetoothDevicePreferences() {
val resumeSetting = Settings.resumeOnBluetoothDevice
val pauseSetting = Settings.pauseOnBluetoothDevice
@ -425,7 +385,6 @@ class SettingsFragment :
}
companion object {
const val SELECT_CACHE_ACTIVITY = 161161
const val RW_FLAG = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
const val PERSISTABLE_FLAG = Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION

View File

@ -0,0 +1,49 @@
/*
* SelectCacheActivityContract.kt
* Copyright (C) 2009-2023 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.util
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.DocumentsContract
import androidx.activity.result.contract.ActivityResultContract
import org.moire.ultrasonic.fragment.SettingsFragment
class SelectCacheActivityContract : ActivityResultContract<String?, Uri?>() {
override fun createIntent(context: Context, input: String?): Intent {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
if (Settings.cacheLocationUri != "" && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, input)
}
intent.addFlags(SettingsFragment.RW_FLAG)
intent.addFlags(SettingsFragment.PERSISTABLE_FLAG)
return intent
}
override fun parseResult(resultCode: Int, intent: Intent?): Uri? {
if (
resultCode == Activity.RESULT_OK &&
intent != null
) {
val read = (intent.flags and Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
val write = (intent.flags and Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
val persist = (intent.flags and Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0
if (read && write && persist) {
if (intent.data != null) {
// The result data contains a URI for the document or directory that
// the user selected.
return intent.data!!
}
}
}
return null
}
}

View File

@ -48,7 +48,6 @@ object Settings {
@JvmStatic
val preloadCount: Int
get() {
val preferences = preferences
val preloadCount =
preferences.getString(getKey(R.string.setting_key_preload_count), "-1")!!
.toInt()
@ -60,7 +59,6 @@ object Settings {
@JvmStatic
val cacheSizeMB: Int
get() {
val preferences = preferences
val cacheSize = preferences.getString(
getKey(R.string.setting_key_cache_size),
"-1"
@ -209,7 +207,6 @@ object Settings {
@JvmStatic
val shareGreeting: String?
get() {
val preferences = preferences
val context = Util.appContext()
val defaultVal = String.format(
context.resources.getString(R.string.share_default_greeting),
@ -278,8 +275,7 @@ object Settings {
}
fun getAllKeys(): List<String> {
val prefs = PreferenceManager.getDefaultSharedPreferences(UApp.applicationContext())
return prefs.all.keys.toList()
return preferences.all.keys.toList()
}
private val appContext: Context

View File

@ -833,6 +833,7 @@ object Util {
Timber.d("Current user preferences")
Timber.d("========================")
val keys = Settings.preferences.all
keys.forEach {
Timber.d("${it.key}: ${it.value}")
}