mirror of
https://gitlab.com/ultrasonic/ultrasonic.git
synced 2025-04-15 08:50:35 +03:00
Merge branch '434-master' into 'master'
Release 4.3.4 See merge request ultrasonic/ultrasonic!995
This commit is contained in:
commit
3a39902c4c
8
fastlane/metadata/android/en-US/changelogs/117.txt
Normal file
8
fastlane/metadata/android/en-US/changelogs/117.txt
Normal file
@ -0,0 +1,8 @@
|
||||
Bug fixes
|
||||
- Fix more exceptions
|
||||
|
||||
Changes since 4.2.0
|
||||
- #827: Make app full compliant Android Auto to publish in Play Store.
|
||||
- #878: "Play shuffled" option for playlists always begins with the first track.
|
||||
- #891: Dump config to log file when logging is enabled.
|
||||
- #854: Remove Videos menu option for servers which don't support it.
|
@ -9,7 +9,7 @@ ktlint = "0.43.2"
|
||||
ktlintGradle = "11.3.1"
|
||||
detekt = "1.22.0"
|
||||
preferences = "1.2.0"
|
||||
media3 = "1.0.0"
|
||||
media3 = "1.0.1"
|
||||
|
||||
androidSupport = "1.6.0"
|
||||
materialDesign = "1.8.0"
|
||||
@ -23,7 +23,8 @@ viewModelKtx = "2.6.1"
|
||||
swipeRefresh = "1.1.0"
|
||||
|
||||
retrofit = "2.9.0"
|
||||
jackson = "2.14.2"
|
||||
## KEEP ON 2.13 branch (https://github.com/FasterXML/jackson-databind/issues/3658#issuecomment-1312633064) for compatibility with API 24
|
||||
jackson = "2.13.5"
|
||||
okhttp = "4.10.0"
|
||||
koin = "3.3.2"
|
||||
picasso = "2.8"
|
||||
|
@ -9,8 +9,8 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.moire.ultrasonic"
|
||||
versionCode 116
|
||||
versionName "4.3.3"
|
||||
versionCode 117
|
||||
versionName "4.3.4"
|
||||
|
||||
minSdkVersion versions.minSdk
|
||||
targetSdkVersion versions.targetSdk
|
||||
|
@ -46,7 +46,7 @@ public class GenreAdapter extends ArrayAdapter<Genre> implements SectionIndexer
|
||||
private final Object[] sections;
|
||||
private final Integer[] positions;
|
||||
|
||||
public GenreAdapter(Context context, List<Genre> genres)
|
||||
public GenreAdapter(@NonNull Context context, List<Genre> genres)
|
||||
{
|
||||
super(context, R.layout.list_item_generic, genres);
|
||||
|
||||
|
@ -401,6 +401,8 @@ open class TrackCollectionFragment(
|
||||
) {
|
||||
// We are coming back from unknown context
|
||||
// and need to ensure Main Thread in order to manipulate the UI
|
||||
// If view is null, our view was disposed in the meantime
|
||||
if (view == null) return
|
||||
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
|
||||
val multipleSelection = viewAdapter.hasMultipleSelection()
|
||||
|
||||
|
@ -102,7 +102,9 @@ class SelectGenreFragment : Fragment() {
|
||||
|
||||
override fun done(result: List<Genre>) {
|
||||
emptyView!!.isVisible = result.isEmpty()
|
||||
genreListView!!.adapter = GenreAdapter(context, result)
|
||||
if (context != null) {
|
||||
genreListView!!.adapter = GenreAdapter(context!!, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
task.execute()
|
||||
|
@ -240,6 +240,8 @@ class ImageLoader(
|
||||
} finally {
|
||||
inputStream.safeClose()
|
||||
}
|
||||
} catch (all: Exception) {
|
||||
Timber.w(all)
|
||||
} finally {
|
||||
cacheInProgress.remove(file)?.countDown()
|
||||
}
|
||||
|
@ -7,11 +7,14 @@
|
||||
|
||||
package org.moire.ultrasonic.subsonic
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import java.util.Collections
|
||||
import java.util.LinkedList
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@ -28,6 +31,7 @@ import org.moire.ultrasonic.util.EntryByDiscAndTrackComparator
|
||||
import org.moire.ultrasonic.util.InfoDialog
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Retrieves a list of songs and adds them to the now playing list
|
||||
@ -39,6 +43,16 @@ class DownloadHandler(
|
||||
) : CoroutineScope by CoroutineScope(Dispatchers.IO) {
|
||||
private val maxSongs = 500
|
||||
|
||||
/**
|
||||
* Exception Handler for Coroutines
|
||||
*/
|
||||
val exceptionHandler = CoroutineExceptionHandler { _, exception ->
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
Timber.w(exception)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Use coroutine here (with proper exception handler)
|
||||
fun download(
|
||||
fragment: Fragment,
|
||||
append: Boolean,
|
||||
@ -210,7 +224,7 @@ class DownloadHandler(
|
||||
isArtist: Boolean
|
||||
) {
|
||||
// Launch the Job
|
||||
val job = launch {
|
||||
val job = launch(exceptionHandler) {
|
||||
val songs: MutableList<Track> =
|
||||
getTracksFromServer(isArtist, id, isDirectory, name, isShare)
|
||||
|
||||
|
@ -10,7 +10,9 @@ package org.moire.ultrasonic.util
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import java.lang.ref.WeakReference
|
||||
import org.moire.ultrasonic.R
|
||||
import timber.log.Timber
|
||||
|
||||
/*
|
||||
* InfoDialog can be used to show some information to the user. Typically it cannot be cancelled,
|
||||
@ -19,24 +21,30 @@ import org.moire.ultrasonic.R
|
||||
open class InfoDialog(
|
||||
context: Context,
|
||||
message: CharSequence?,
|
||||
private val activity: Activity? = null,
|
||||
activity: Activity? = null,
|
||||
private val finishActivityOnClose: Boolean = false
|
||||
) {
|
||||
|
||||
open var builder: MaterialAlertDialogBuilder = Builder(activity ?: context, message)
|
||||
private val activityRef: WeakReference<Activity?> = WeakReference(activity)
|
||||
open var builder: MaterialAlertDialogBuilder = Builder(activityRef.get() ?: context, message)
|
||||
|
||||
fun show() {
|
||||
builder.setOnCancelListener {
|
||||
if (finishActivityOnClose) {
|
||||
activity!!.finish()
|
||||
activityRef.get()?.finish()
|
||||
}
|
||||
}
|
||||
builder.setPositiveButton(R.string.common_ok) { _, _ ->
|
||||
if (finishActivityOnClose) {
|
||||
activity!!.finish()
|
||||
activityRef.get()?.finish()
|
||||
}
|
||||
}
|
||||
builder.create().show()
|
||||
|
||||
// If the app was put into the background in the meantime this would fail
|
||||
try {
|
||||
builder.create().show()
|
||||
} catch (all: Exception) {
|
||||
Timber.w(all, "Failed to create dialog")
|
||||
}
|
||||
}
|
||||
|
||||
class Builder(context: Context) : MaterialAlertDialogBuilder(context) {
|
||||
@ -93,7 +101,6 @@ class ConfirmationDialog(
|
||||
activity: Activity? = null,
|
||||
finishActivityOnClose: Boolean = false
|
||||
) : InfoDialog(context, message, activity, finishActivityOnClose) {
|
||||
|
||||
override var builder: MaterialAlertDialogBuilder = Builder(activity ?: context, message)
|
||||
|
||||
class Builder(context: Context) : MaterialAlertDialogBuilder(context) {
|
||||
|
@ -273,7 +273,7 @@ class StorageFile(
|
||||
}
|
||||
|
||||
private fun getStorageFileForParentDirectory(path: String): StorageFile? {
|
||||
val parentPath = FileUtil.getParentPath(path)!!
|
||||
val parentPath = FileUtil.getParentPath(path) ?: return null
|
||||
if (storageFilePathDictionary.containsKey(parentPath))
|
||||
return storageFilePathDictionary[parentPath]!!
|
||||
if (notExistingPathDictionary.contains(parentPath)) return null
|
||||
|
@ -133,19 +133,24 @@ object Util {
|
||||
@JvmStatic
|
||||
@SuppressLint("ShowToast") // Invalid warning
|
||||
fun toast(context: Context?, message: CharSequence?, shortDuration: Boolean) {
|
||||
if (toast == null) {
|
||||
toast = Toast.makeText(
|
||||
context,
|
||||
message,
|
||||
if (shortDuration) Toast.LENGTH_SHORT else Toast.LENGTH_LONG
|
||||
)
|
||||
toast!!.setGravity(Gravity.CENTER, 0, 0)
|
||||
} else {
|
||||
toast!!.setText(message)
|
||||
toast!!.duration =
|
||||
if (shortDuration) Toast.LENGTH_SHORT else Toast.LENGTH_LONG
|
||||
// If called after doing some background processing, our context might have expired!
|
||||
try {
|
||||
if (toast == null) {
|
||||
toast = Toast.makeText(
|
||||
context,
|
||||
message,
|
||||
if (shortDuration) Toast.LENGTH_SHORT else Toast.LENGTH_LONG
|
||||
)
|
||||
toast!!.setGravity(Gravity.CENTER, 0, 0)
|
||||
} else {
|
||||
toast!!.setText(message)
|
||||
toast!!.duration =
|
||||
if (shortDuration) Toast.LENGTH_SHORT else Toast.LENGTH_LONG
|
||||
}
|
||||
toast!!.show()
|
||||
} catch (_: Exception) {
|
||||
// Ignore
|
||||
}
|
||||
toast!!.show()
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user