Browse Source

Remove unused fields, methods or classes

merge-requests/2314/head
Nicolas Pomepuy 1 year ago
parent
commit
c79f587dbb
  1. 87
      application/app/src/androidTest/java/org/videolan/vlc/PreferenceMatcher.kt
  2. 10
      application/app/src/androidTest/java/org/videolan/vlc/UtilViewActions.kt
  3. 4
      application/app/src/androidTest/java/org/videolan/vlc/UtilViewMatchers.kt
  4. 6
      application/app/src/androidTest/java/org/videolan/vlc/database/ExternalSubDaoTest.kt
  5. 9
      application/live-plot-graph/src/main/java/org/videolan/liveplotgraph/PlotView.kt
  6. 7
      application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/RemoteAccessServer.kt
  7. 5
      application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/gui/remoteaccess/onboarding/RemoteAccessOnboardingActivity.kt
  8. 4
      application/resources/src/main/java/org/videolan/resources/AndroidDevices.kt
  9. 4
      application/resources/src/main/java/org/videolan/resources/opensubtitles/OpenSubtitlesLimit.kt
  10. 8
      application/resources/src/main/java/org/videolan/resources/util/Helpers.kt
  11. 2
      application/resources/src/main/res/values/strings.xml
  12. 4
      application/television/src/main/java/org/videolan/television/ui/MainTvActivity.kt
  13. 2
      application/television/src/main/java/org/videolan/television/ui/MediaImageCardPresenter.kt
  14. 8
      application/television/src/main/java/org/videolan/television/ui/MediaTvItemAdapter.kt
  15. 10
      application/television/src/main/java/org/videolan/television/ui/MetadataCardPresenter.kt
  16. 4
      application/television/src/main/java/org/videolan/television/ui/VideoDetailsPresenter.kt
  17. 23
      application/television/src/main/java/org/videolan/television/ui/browser/VerticalGridActivity.kt
  18. 8
      application/television/src/main/java/org/videolan/television/ui/preferences/BasePreferenceFragment.kt
  19. 47
      application/tools/src/main/java/org/videolan/tools/AppUtils.kt
  20. 8
      application/tools/src/main/java/org/videolan/tools/BitmapCache.kt
  21. 24
      application/tools/src/main/java/org/videolan/tools/KotlinExtensions.kt
  22. 5
      application/tools/src/main/java/org/videolan/tools/Settings.kt
  23. 2
      application/vlc-android/src/org/videolan/vlc/MediaBrowserInstance.kt
  24. 4
      application/vlc-android/src/org/videolan/vlc/MediaParsingService.kt
  25. 1
      application/vlc-android/src/org/videolan/vlc/gui/BaseActivity.kt
  26. 15
      application/vlc-android/src/org/videolan/vlc/gui/HeaderMediaListActivity.kt
  27. 14
      application/vlc-android/src/org/videolan/vlc/gui/LibrariesActivity.kt
  28. 8
      application/vlc-android/src/org/videolan/vlc/gui/PlaylistFragment.kt
  29. 4
      application/vlc-android/src/org/videolan/vlc/gui/audio/AudioAlbumsSongsFragment.kt
  30. 62
      application/vlc-android/src/org/videolan/vlc/gui/helpers/AudioUtil.kt
  31. 56
      application/vlc-android/src/org/videolan/vlc/gui/helpers/BitmapUtil.kt
  32. 2
      application/vlc-android/src/org/videolan/vlc/gui/helpers/BottomNavigationBehavior.kt
  33. 5
      application/vlc-android/src/org/videolan/vlc/gui/helpers/Navigator.kt
  34. 1
      application/vlc-android/src/org/videolan/vlc/gui/helpers/NotificationHelper.kt
  35. 10
      application/vlc-android/src/org/videolan/vlc/gui/helpers/PlayerOptionsDelegate.kt
  36. 3
      application/vlc-android/src/org/videolan/vlc/gui/helpers/hf/BaseHeadlessFragment.kt
  37. 4
      application/vlc-android/src/org/videolan/vlc/gui/onboarding/OnboardingActivity.kt
  38. 12
      application/vlc-android/src/org/videolan/vlc/gui/video/VideoDelayDelegate.kt
  39. 28
      application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.kt
  40. 32
      application/vlc-android/src/org/videolan/vlc/gui/view/ClickableSwitchPreference.kt
  41. 14
      application/vlc-android/src/org/videolan/vlc/gui/view/FlingViewGroup.kt
  42. 7
      application/vlc-android/src/org/videolan/vlc/gui/view/FocusableTextView.kt
  43. 2
      application/vlc-android/src/org/videolan/vlc/gui/view/RecyclerSectionItemDecoration.kt
  44. 2
      application/vlc-android/src/org/videolan/vlc/gui/view/RecyclerSectionItemGridDecoration.kt
  45. 25
      application/vlc-android/src/org/videolan/vlc/interfaces/OnExpandableListener.kt
  46. 2
      application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt
  47. 18
      application/vlc-android/src/org/videolan/vlc/media/MediaUtils.kt
  48. 1
      application/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt
  49. 14
      application/vlc-android/src/org/videolan/vlc/util/Browserutils.kt
  50. 1
      application/vlc-android/src/org/videolan/vlc/util/ContextOption.kt
  51. 2
      application/vlc-android/src/org/videolan/vlc/util/DialogDelegates.kt
  52. 5
      application/vlc-android/src/org/videolan/vlc/util/FileUtils.kt
  53. 33
      application/vlc-android/src/org/videolan/vlc/util/Kextensions.kt
  54. 34
      application/vlc-android/src/org/videolan/vlc/util/ModelsHelper.kt
  55. 1
      application/vlc-android/src/org/videolan/vlc/util/Permissions.kt
  56. 10
      application/vlc-android/src/org/videolan/vlc/viewmodels/BaseModel.kt
  57. 2
      application/vlc-android/src/org/videolan/vlc/viewmodels/PlaylistModel.kt
  58. 2
      application/vlc-android/src/org/videolan/vlc/viewmodels/SortableModel.kt
  59. 2
      application/vlc-android/src/org/videolan/vlc/widget/utils/WidgetSizeUtil.kt

87
application/app/src/androidTest/java/org/videolan/vlc/PreferenceMatcher.kt

@ -1,11 +1,9 @@
package org.videolan.vlc
import org.hamcrest.Matchers.`is`
import android.content.res.Resources
import androidx.preference.Preference
import org.hamcrest.Description
import org.hamcrest.Matcher
import org.hamcrest.Matchers.`is`
import org.hamcrest.TypeSafeMatcher
/** A collection of hamcrest matchers that match [Preference]s.
@ -24,48 +22,6 @@ object PreferenceMatchers {
}
}
fun withSummary(resourceId: Int): Matcher<Preference> {
return object : TypeSafeMatcher<Preference>() {
private var resourceName: String? = null
private var expectedText: String? = null
override fun describeTo(description: Description) {
description.appendText(" with summary string from resource id: ")
description.appendValue(resourceId)
if (null != resourceName) {
description.appendText("[")
description.appendText(resourceName)
description.appendText("]")
}
if (null != expectedText) {
description.appendText(" value: ")
description.appendText(expectedText)
}
}
public override fun matchesSafely(preference: Preference): Boolean {
if (null == expectedText) {
try {
expectedText = preference.context.resources.getString(resourceId)
resourceName = preference.context.resources.getResourceEntryName(resourceId)
} catch (ignored: Resources.NotFoundException) {
/* view could be from a context unaware of the resource id. */
}
}
return if (null != expectedText) {
expectedText == preference.summary.toString()
} else {
false
}
}
}
}
fun withSummaryText(summary: String): Matcher<Preference> {
return withSummaryText(`is`(summary))
}
fun withSummaryText(summaryMatcher: Matcher<String>): Matcher<Preference> {
return object : TypeSafeMatcher<Preference>() {
override fun describeTo(description: Description) {
@ -80,47 +36,6 @@ object PreferenceMatchers {
}
}
fun withTitle(resourceId: Int): Matcher<Preference> {
return object : TypeSafeMatcher<Preference>() {
private var resourceName: String? = null
private var expectedText: String? = null
override fun describeTo(description: Description) {
description.appendText(" with title string from resource id: ")
description.appendValue(resourceId)
if (null != resourceName) {
description.appendText("[")
description.appendText(resourceName)
description.appendText("]")
}
if (null != expectedText) {
description.appendText(" value: ")
description.appendText(expectedText)
}
}
public override fun matchesSafely(preference: Preference): Boolean {
if (null == expectedText) {
try {
expectedText = preference.context.resources.getString(resourceId)
resourceName = preference.context.resources.getResourceEntryName(resourceId)
} catch (ignored: Resources.NotFoundException) {
/* view could be from a context unaware of the resource id. */
}
}
return if (null != expectedText && preference.title != null) {
expectedText == preference.title.toString()
} else {
false
}
}
}
}
fun withTitleText(title: String): Matcher<Preference> {
return withTitleText(`is`(title))
}
fun withTitleText(titleMatcher: Matcher<String>): Matcher<Preference> {
return object : TypeSafeMatcher<Preference>() {
override fun describeTo(description: Description) {

10
application/app/src/androidTest/java/org/videolan/vlc/UtilViewActions.kt

@ -8,7 +8,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.matcher.ViewMatchers.isEnabled
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
import androidx.test.runner.lifecycle.Stage
@ -82,15 +81,6 @@ class OrientationChangeAction internal constructor(private val orientation: Int)
}
}
class ForceClickAction : ViewAction {
override fun getConstraints() = isEnabled()
override fun getDescription() = "Force click a view even if 90% condition is not satisfied"
override fun perform(uiController: UiController?, view: View?) {
view?.performClick()
}
}
fun orientationLandscape(): ViewAction {
return OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
}

4
application/app/src/androidTest/java/org/videolan/vlc/UtilViewMatchers.kt

@ -55,7 +55,7 @@ class RecyclerViewMatcher(@IdRes private val recyclerViewId: Int) {
override fun matchesSafely(view: View): Boolean {
if (!triedMatch && childView == null) {
if (recyclerView == null) recyclerView = view.rootView.findViewById(recyclerViewId) as RecyclerView
if (recyclerView == null) recyclerView = view.rootView.findViewById<RecyclerView>(recyclerViewId)!!
triedMatch = true
recyclerView?.run {
if (id == recyclerViewId) {
@ -117,7 +117,7 @@ class MediaRecyclerViewMatcher<VH : SelectorViewHolder<out ViewDataBinding>>(@Id
private fun fillMatchesIfRequired(mapVH: MutableMap<View, VH>, rootView: View, condition: ((VH) -> Boolean)): Boolean {
if (recyclerView == null || mapVH.isEmpty()) {
recyclerView = rootView.findViewById(recyclerViewId) as RecyclerView
recyclerView = rootView.findViewById<RecyclerView>(recyclerViewId)!!
if (recyclerView!!.id == recyclerViewId) {
val it = (0 until recyclerView!!.adapter!!.itemCount).iterator()
while (it.hasNext()) {

6
application/app/src/androidTest/java/org/videolan/vlc/database/ExternalSubDaoTest.kt

@ -21,7 +21,10 @@
package org.videolan.vlc.database
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.hamcrest.Matchers.*
import org.hamcrest.Matchers.equalTo
import org.hamcrest.Matchers.hasItem
import org.hamcrest.Matchers.`is`
import org.hamcrest.Matchers.not
import org.junit.Assert.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@ -30,7 +33,6 @@ import org.videolan.vlc.util.getValue
@RunWith(AndroidJUnit4::class)
class ExternalSubDaoTest: DbTest() {
private lateinit var database: MediaDatabase
@Test fun insertTwoSubtitleForEachOfTwoMedias_GetShouldReturnTwoForEachOne() {
val foo = "/storage/emulated/foo.mkv"
val bar = "/storage/emulated/bar.mkv"

9
application/live-plot-graph/src/main/java/org/videolan/liveplotgraph/PlotView.kt

@ -97,10 +97,6 @@ class PlotView : FrameLayout {
listeners.add(listener)
}
fun removeListener(listener: PlotViewDataChangeListener) {
listeners.remove(listener)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
@ -243,11 +239,6 @@ class PlotView : FrameLayout {
}
}
data class GraphPoint(val x: Float, val y: Float) {
var dx: Float = 0F
var dy: Float = 0F
}
interface PlotViewDataChangeListener {
fun onDataChanged(data: List<Pair<LineGraph, String>>)
}

7
application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/RemoteAccessServer.kt

@ -822,13 +822,6 @@ class RemoteAccessServer(private val context: Context) : PlaybackService.Callbac
}
}
fun sslEnabled():Boolean {
if (::engine.isInitialized) {
return engine.environment.connectors.firstOrNull { it.type.name == "HTTPS" } != null
}
return false
}
/**
* Get IP address from first non-localhost interface
* @param useIPv4 true=return ipv4, false=return ipv6

5
application/remote-access-server/src/main/java/org/videolan/vlc/remoteaccessserver/gui/remoteaccess/onboarding/RemoteAccessOnboardingActivity.kt

@ -25,7 +25,6 @@
package org.videolan.vlc.remoteaccessserver.gui.remoteaccess.onboarding
import android.os.Bundle
import android.view.View
import android.widget.Button
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
@ -113,10 +112,6 @@ class RemoteAccessOnboardingActivity : AppCompatActivity(), OnboardingFragmentLi
}
}
fun manageNextVisibility(visible: Boolean) {
nextButton.visibility = if (visible) View.VISIBLE else View.GONE
}
}
enum class FragmentName {

4
application/resources/src/main/java/org/videolan/resources/AndroidDevices.kt

@ -144,10 +144,6 @@ object AndroidDevices {
isPhone = tm == null || tm.phoneType != TelephonyManager.PHONE_TYPE_NONE
}
fun hasExternalStorage(): Boolean {
return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
}
fun showInternalStorage() = Build.BRAND !in arrayOf("Swisscom", "BouyguesTelecom") && Build.BOARD != "sprint"
@TargetApi(VERSION_CODES.HONEYCOMB_MR1)

4
application/resources/src/main/java/org/videolan/resources/opensubtitles/OpenSubtitlesLimit.kt

@ -37,10 +37,6 @@ data class OpenSubtitlesLimit (
if (resetTime != null && Date().after(resetTime)) return max
return max - requests
}
fun getRemainingText(): String {
val remaining = getRemaining()
return "$remaining/$max"
}
fun getResetTime(context:Context): String {
if (resetTime == null) return ""

8
application/resources/src/main/java/org/videolan/resources/util/Helpers.kt

@ -16,7 +16,8 @@ import org.videolan.medialibrary.interfaces.media.VideoGroup
import org.videolan.medialibrary.media.MediaLibraryItem
import org.videolan.resources.AppContextProvider
import org.videolan.resources.R
import java.util.*
import java.util.Calendar
import java.util.Date
const val LENGTH_DAY = 24 * 60 * 60
const val LENGTH_WEEK = 7 * LENGTH_DAY
@ -125,8 +126,3 @@ fun applyOverscanMargin(activity: Activity) {
activity.findViewById<View>(android.R.id.content).setPadding(hm, vm, hm, vm)
}
fun applyOverscanMargin(view: View) {
val hm = view.resources.getDimensionPixelSize(R.dimen.tv_overscan_horizontal)
val vm = view.resources.getDimensionPixelSize(R.dimen.tv_overscan_vertical)
view.setPadding(hm + view.paddingLeft, vm + view.paddingTop, hm + view.paddingRight, vm + view.paddingBottom)
}

2
application/resources/src/main/res/values/strings.xml

@ -261,8 +261,6 @@
<string name="load_2_period" translatable="false">..</string>
<string name="load_3_period" translatable="false">...</string>
<string name="encountered_error_title">Playback error</string>
<string name="encountered_error_message">VLC encountered an error with this media.\nPlease try refreshing the media library.</string>
<string name="invalid_location">The location %1$s cannot be played.</string>
<string name="missing_location">This media is from a unavailable storage and cannot be played.</string>

4
application/television/src/main/java/org/videolan/television/ui/MainTvActivity.kt

@ -125,10 +125,6 @@ class MainTvActivity : BaseTvActivity(), StoragePermissionsDelegate.CustomAction
scheduler.scheduleAction(HIDE_LOADING, 500)
}
fun hideLoading() {
scheduler.scheduleAction(HIDE_LOADING, 500)
}
override fun onStorageAccessGranted() {
refresh()
}

2
application/television/src/main/java/org/videolan/television/ui/MediaImageCardPresenter.kt

@ -115,8 +115,6 @@ class MediaImageCardPresenter(private val context: Activity, private val imageTy
companion object {
private const val TAG = "CardPresenter"
private val CARD_WIDTH_POSTER = 100.dp
private val CARD_HEIGHT_POSTER = 150.dp

8
application/television/src/main/java/org/videolan/television/ui/MediaTvItemAdapter.kt

@ -152,14 +152,6 @@ class MediaTvItemAdapter(type: Int, private val eventsHandler: IEventsHandler<Me
return getItem(layoutPosition)?.let { eventsHandler.onLongClick(view, layoutPosition, it) } ?: false
}
fun onImageClick(v: View) {
getItem(layoutPosition)?.let { eventsHandler.onImageClick(v, layoutPosition, it) }
}
fun onMainActionClick(v: View) {
getItem(layoutPosition)?.let { eventsHandler.onMainActionClick(v, layoutPosition, it) }
}
abstract fun getItem(layoutPosition: Int): MediaLibraryItem?
abstract val eventsHandler: IEventsHandler<MediaLibraryItem>

10
application/television/src/main/java/org/videolan/television/ui/MetadataCardPresenter.kt

@ -59,7 +59,6 @@ import androidx.core.net.toUri
import androidx.leanback.widget.Presenter
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
import org.videolan.moviepedia.database.models.MediaMetadataWithImages
import org.videolan.moviepedia.database.models.Person
import org.videolan.moviepedia.database.models.tvEpisodeSubtitle
import org.videolan.television.R
import org.videolan.tools.dp
@ -85,15 +84,6 @@ class MetadataCardPresenter(private val context: Activity) : Presenter() {
view.findViewById<View>(R.id.container).background = ContextCompat.getDrawable(context, R.drawable.tv_card_background)
}
fun updateCardViewImage(item: Person) {
downloadIcon(cover, item.image?.toUri())
}
fun updateCardViewImage(image: Drawable?) {
cover.setImageDrawable(image)
cover.scaleType = ImageView.ScaleType.FIT_CENTER
}
fun updateCardViewImage(image: Uri?) {
cover.setImageDrawable(defaultCardImage)
cover.scaleType = ImageView.ScaleType.FIT_CENTER

4
application/television/src/main/java/org/videolan/television/ui/VideoDetailsPresenter.kt

@ -30,9 +30,8 @@ import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.databinding.DataBindingUtil
import androidx.leanback.graphics.ColorOverlayDimmer
import org.videolan.television.databinding.TvVideoDetailsBinding
import org.videolan.television.R
import org.videolan.television.databinding.TvVideoDetailsBinding
class VideoDetailsPresenter(private val context: Context, private val screenWidth: Int) : FullWidthRowPresenter() {
@ -61,7 +60,6 @@ class VideoDetailsPresenter(private val context: Context, private val screenWidt
}
inner class VideoDetailsViewHolder(view: View) : ViewHolder(view) {
val colorDimmer = ColorOverlayDimmer.createDefault(view.context)
val container = view.findViewById<ConstraintLayout>(R.id.container)
}
}

23
application/television/src/main/java/org/videolan/television/ui/browser/VerticalGridActivity.kt

@ -32,7 +32,23 @@ import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import org.videolan.medialibrary.MLServiceLocator
import org.videolan.medialibrary.media.MediaLibraryItem
import org.videolan.resources.*
import org.videolan.resources.CATEGORY
import org.videolan.resources.CATEGORY_ALBUMS
import org.videolan.resources.CATEGORY_ARTISTS
import org.videolan.resources.CATEGORY_GENRES
import org.videolan.resources.CATEGORY_PLAYLISTS
import org.videolan.resources.CATEGORY_SONGS
import org.videolan.resources.CATEGORY_VIDEOS
import org.videolan.resources.FAVORITE_TITLE
import org.videolan.resources.HEADER_CATEGORIES
import org.videolan.resources.HEADER_DIRECTORIES
import org.videolan.resources.HEADER_MOVIES
import org.videolan.resources.HEADER_NETWORK
import org.videolan.resources.HEADER_PLAYLISTS
import org.videolan.resources.HEADER_TV_SHOW
import org.videolan.resources.HEADER_VIDEO
import org.videolan.resources.ITEM
import org.videolan.resources.KEY_URI
import org.videolan.resources.util.parcelable
import org.videolan.television.R
import org.videolan.television.databinding.TvVerticalGridBinding
@ -41,7 +57,6 @@ import org.videolan.television.ui.browser.interfaces.BrowserActivityInterface
import org.videolan.television.ui.browser.interfaces.DetailsFragment
import org.videolan.vlc.BuildConfig
import org.videolan.vlc.interfaces.BrowserFragmentInterface
import org.videolan.vlc.interfaces.Sortable
import org.videolan.vlc.viewmodels.browser.TYPE_FILE
import org.videolan.vlc.viewmodels.browser.TYPE_NETWORK
@ -124,10 +139,6 @@ class VerticalGridActivity : BaseTvActivity(), BrowserActivityInterface {
lifecycleScope.launch { binding.tvFragmentEmpty.visibility = if (empty) View.VISIBLE else View.GONE }
}
fun sort(v: View) {
(fragment as Sortable).sort(v)
}
interface OnKeyPressedListener {
/**
* a key has been pressed

8
application/television/src/main/java/org/videolan/television/ui/preferences/BasePreferenceFragment.kt

@ -23,7 +23,6 @@
package org.videolan.television.ui.preferences
import android.app.Fragment
import android.content.Intent
import android.os.Bundle
import androidx.leanback.preference.LeanbackPreferenceFragment
@ -32,7 +31,6 @@ import androidx.preference.Preference
import androidx.preference.PreferenceDialogFragment
import org.videolan.television.ui.dialogs.ConfirmationTvActivity
import org.videolan.tools.Settings
import org.videolan.vlc.R
import org.videolan.vlc.gui.preferences.PreferenceVisibilityManager
const val RESTART_CODE = 10001
@ -50,12 +48,6 @@ abstract class BasePreferenceFragment : LeanbackPreferenceFragment() {
addPreferencesFromResource(getXml())
}
protected fun loadFragment(fragment: Fragment) {
activity.fragmentManager.beginTransaction().replace(R.id.fragment_placeholder, fragment)
.addToBackStack("main")
.commit()
}
protected fun buildPreferenceDialogFragment(preference: Preference): PreferenceDialogFragment? {
return if (preference is EditTextPreference) {
CustomEditTextPreferenceDialogFragment.newInstance(preference.getKey()).apply {

47
application/tools/src/main/java/org/videolan/tools/AppUtils.kt

@ -1,47 +0,0 @@
/*
* ************************************************************************
* AppUtils.kt
* *************************************************************************
* Copyright © 2022 VLC authors and VideoLAN
* Author: Nicolas POMEPUY
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.tools
import android.content.Context
import android.os.Build
import android.os.Environment
import android.os.StatFs
@Suppress("DEPRECATION")
object AppUtils {
fun totalMemory(): Long {
val statFs = StatFs(Environment.getRootDirectory().absolutePath)
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
statFs.blockCountLong * statFs.blockSizeLong
else (statFs.blockCount * statFs.blockSize).toLong()
}
fun freeMemory(): Long {
val statFs = StatFs(Environment.getRootDirectory().absolutePath)
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
statFs.availableBlocksLong * statFs.blockSizeLong
else (statFs.availableBlocks * statFs.blockSize).toLong()
}
}

8
application/tools/src/main/java/org/videolan/tools/BitmapCache.kt

@ -87,14 +87,6 @@ object BitmapCache {
}
}
private fun getBitmapFromMemCache(resId: Int): Bitmap? {
return getBitmapFromMemCache("res:$resId")
}
private fun addBitmapToMemCache(resId: Int, bitmap: Bitmap?) {
addBitmapToMemCache("res:$resId", bitmap)
}
@Synchronized
fun clear() {
memCache.evictAll()

24
application/tools/src/main/java/org/videolan/tools/KotlinExtensions.kt

@ -25,7 +25,11 @@ package org.videolan.tools
import android.annotation.SuppressLint
import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo
import android.content.*
import android.content.ClipData
import android.content.ClipboardManager
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.content.res.Resources
@ -34,7 +38,6 @@ import android.net.Uri
import android.util.Patterns
import android.util.TypedValue
import android.view.View
import androidx.annotation.AttrRes
import androidx.annotation.DrawableRes
import androidx.core.content.getSystemService
import androidx.lifecycle.Lifecycle
@ -45,10 +48,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ObsoleteCoroutinesApi
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.yield
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
@ -87,15 +87,6 @@ fun <T> CoroutineScope.conflatedActor(time: Long = 2000L, action: suspend (T) ->
}
}
fun Context.getColorFromAttr(
@AttrRes attrColor: Int,
typedValue: TypedValue = TypedValue(),
resolveRefs: Boolean = true
): Int {
theme.resolveAttribute(attrColor, typedValue, resolveRefs)
return typedValue.data
}
fun Context.copy(label: String, text: String) {
applicationContext.getSystemService<ClipboardManager>()?.run {
setPrimaryClip(ClipData.newPlainText(label, text))
@ -136,11 +127,6 @@ fun String?.isValidUrl(): Boolean {
return !isNullOrEmpty() && Patterns.WEB_URL.matcher(this).matches()
}
fun View.clicks(): Flow<Unit> = callbackFlow {
setOnClickListener { trySend(Unit) }
awaitClose { setOnClickListener(null) }
}
@SuppressLint("MissingPermission")
fun Context.isConnected(): Boolean {
return getSystemService<ConnectivityManager>()?.activeNetworkInfo?.isConnected == true

5
application/tools/src/main/java/org/videolan/tools/Settings.kt

@ -266,7 +266,6 @@ const val RESULT_UPDATE_SEEN_MEDIA = Activity.RESULT_FIRST_USER + 4
const val RESULT_UPDATE_ARTISTS = Activity.RESULT_FIRST_USER + 5
const val BETA_WELCOME = "beta_welcome"
const val CRASH_DONT_ASK_AGAIN = "crash_dont_ask_again"
const val PLAYBACK_HISTORY = "playback_history"
const val AUDIO_RESUME_PLAYBACK = "audio_resume_playback"
@ -424,14 +423,10 @@ const val KEY_FRAGMENT_ID = "fragment_id"
class DeviceInfo(context: Context) {
val pm = context.packageManager
val tm = context.getSystemService<TelephonyManager>()!!
val isPhone = tm.phoneType != TelephonyManager.PHONE_TYPE_NONE
val hasTsp = pm.hasSystemFeature("android.hardware.touchscreen")
val isAndroidTv = pm.hasSystemFeature("android.software.leanback")
val watchDevices = isAndroidTv && Build.MODEL.startsWith("Bouygtel")
val isChromeBook = pm.hasSystemFeature("org.chromium.arc.device_management")
val isTv = isAndroidTv || !isChromeBook && !hasTsp
val isAmazon = "Amazon" == Build.MANUFACTURER
}
@Suppress("UNCHECKED_CAST")

2
application/vlc-android/src/org/videolan/vlc/MediaBrowserInstance.kt

@ -9,8 +9,6 @@ import org.videolan.vlc.MediaBrowserInstance.init
object MediaBrowserInstance :
SingletonHolder<MediaBrowserCompat, Context>({ init(it.applicationContext) }) {
private lateinit var mediaBrowser: MediaBrowserCompat
fun init(context: Context): MediaBrowserCompat {
return MediaBrowserCompat(
context,

4
application/vlc-android/src/org/videolan/vlc/MediaParsingService.kt

@ -609,10 +609,6 @@ fun Context.reloadLibrary() {
launchForeground(Intent(ACTION_RELOAD, null, this, MediaParsingService::class.java))
}
fun Context.rescan() {
launchForeground(Intent(ACTION_FORCE_RELOAD, null, this, MediaParsingService::class.java))
}
private sealed class MLAction
private class DiscoverStorage(val path: String) : MLAction()
private class DiscoverFolder(val path: String) : MLAction()

1
application/vlc-android/src/org/videolan/vlc/gui/BaseActivity.kt

@ -51,7 +51,6 @@ import org.videolan.vlc.viewmodels.DisplaySettingsViewModel
abstract class BaseActivity : AppCompatActivity() {
private var currentNightMode: Int = 0
private var startColor: Int = 0
lateinit var settings: SharedPreferences
private var lastDisplayedOTPCode = ""

15
application/vlc-android/src/org/videolan/vlc/gui/HeaderMediaListActivity.kt

@ -124,7 +124,6 @@ import org.videolan.vlc.util.ContextOption.CTX_RENAME
import org.videolan.vlc.util.ContextOption.CTX_SET_RINGTONE
import org.videolan.vlc.util.ContextOption.CTX_SHARE
import org.videolan.vlc.util.ContextOption.Companion.createCtxPlaylistItemFlags
import org.videolan.vlc.util.FileUtils
import org.videolan.vlc.util.Permissions
import org.videolan.vlc.util.ThumbnailsProvider
import org.videolan.vlc.util.getScreenWidth
@ -136,7 +135,6 @@ import org.videolan.vlc.viewmodels.PlaylistModel
import org.videolan.vlc.viewmodels.mobile.PlaylistViewModel
import org.videolan.vlc.viewmodels.mobile.getViewModel
import java.security.SecureRandom
import java.util.LinkedList
import kotlin.math.min
open class HeaderMediaListActivity : AudioPlayerContainerActivity(), IEventsHandler<MediaLibraryItem>, IListEventsHandler, ActionMode.Callback, View.OnClickListener, CtxActionReceiver, Filterable, SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener {
@ -633,19 +631,6 @@ open class HeaderMediaListActivity : AudioPlayerContainerActivity(), IEventsHand
dialog.show(supportFragmentManager, ConfirmDeleteDialog::class.simpleName)
}
private fun deleteMedia(mw: MediaLibraryItem) = lifecycleScope.launch(Dispatchers.IO) {
val foldersToReload = LinkedList<String>()
for (media in mw.tracks) {
val path = media.uri.path
val parentPath = FileUtils.getParent(path)
if (parentPath != null && FileUtils.deleteFile(path) && media.id > 0L && !foldersToReload.contains(parentPath)) {
foldersToReload.add(parentPath)
} else
UiTools.snacker(this@HeaderMediaListActivity, getString(R.string.msg_delete_failed, media.title))
}
for (folder in foldersToReload) mediaLibrary.reload(folder)
}
override fun onClick(v: View) {
MediaUtils.playTracks(this, viewModel.tracksProvider, 0)
}

14
application/vlc-android/src/org/videolan/vlc/gui/LibrariesActivity.kt

@ -6,21 +6,27 @@ import android.view.LayoutInflater
import android.view.MenuItem
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.*
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.appbar.MaterialToolbar
import com.squareup.moshi.*
import kotlinx.parcelize.Parcelize
import com.squareup.moshi.Json
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import org.videolan.resources.AndroidDevices
import org.videolan.resources.AppContextProvider
import org.videolan.resources.util.applyOverscanMargin
import org.videolan.vlc.R
import org.videolan.vlc.databinding.LibraryItemBinding
import org.videolan.vlc.databinding.LicenseActivityBinding
import org.videolan.vlc.gui.dialogs.LicenseDialog
import org.videolan.vlc.gui.helpers.SelectorViewHolder
import org.videolan.resources.util.applyOverscanMargin
/**
* Activity showing the different libraries used by VLC for Android and their licenses

8
application/vlc-android/src/org/videolan/vlc/gui/PlaylistFragment.kt

@ -119,8 +119,12 @@ class PlaylistFragment : BaseAudioBrowser<PlaylistsViewModel>(), SwipeRefreshLay
setupLayoutManager()
playlists.adapter = playlistAdapter
fastScroller = view.rootView.findViewById(R.id.songs_fast_scroller_playlist) as FastScroller
fastScroller.attachToCoordinator(requireActivity().findViewById(R.id.appbar) as AppBarLayout, requireActivity().findViewById(R.id.coordinator) as CoordinatorLayout, requireActivity().findViewById(R.id.fab) as FloatingActionButton)
fastScroller = view.rootView.findViewById<FastScroller>(R.id.songs_fast_scroller_playlist)!!
fastScroller.attachToCoordinator(
requireActivity().findViewById<AppBarLayout>(R.id.appbar)!!,
requireActivity().findViewById<CoordinatorLayout>(R.id.coordinator)!!,
requireActivity().findViewById<FloatingActionButton>(R.id.fab)!!
)
viewModel.provider.pagedList.observe(viewLifecycleOwner) {
@Suppress("UNCHECKED_CAST")
playlistAdapter.submitList(it as PagedList<MediaLibraryItem>)

4
application/vlc-android/src/org/videolan/vlc/gui/audio/AudioAlbumsSongsFragment.kt

@ -120,8 +120,8 @@ class AudioAlbumsSongsFragment : BaseAudioBrowser<AlbumSongsViewModel>(), SwipeR
spacing = resources.getDimension(R.dimen.kl_small).toInt()
val itemSize = RecyclerSectionItemGridDecoration.getItemSize(requireActivity().getScreenWidth(), nbColumns, spacing, 16.dp)
val albumsList = viewPager.getChildAt(MODE_ALBUM).findViewById(R.id.audio_list) as RecyclerView
val songsList = viewPager.getChildAt(MODE_SONG).findViewById(R.id.audio_list) as RecyclerView
val albumsList: RecyclerView = viewPager.getChildAt(MODE_ALBUM).findViewById(R.id.audio_list)
val songsList: RecyclerView = viewPager.getChildAt(MODE_SONG).findViewById(R.id.audio_list)
lists = arrayOf(albumsList, songsList)
val titles = arrayOf(getString(R.string.albums), getString(R.string.songs))

62
application/vlc-android/src/org/videolan/vlc/gui/helpers/AudioUtil.kt

@ -19,9 +19,7 @@
*/
package org.videolan.vlc.gui.helpers
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Bitmap.CompressFormat
import android.graphics.BitmapFactory
import android.media.RingtoneManager
import android.net.Uri
@ -32,7 +30,6 @@ import android.webkit.MimeTypeMap
import android.widget.Toast
import androidx.annotation.WorkerThread
import androidx.core.content.contentValuesOf
import androidx.core.net.toUri
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
@ -41,7 +38,6 @@ import kotlinx.coroutines.withContext
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.medialibrary.interfaces.media.MediaWrapper
import org.videolan.tools.BitmapCache
import org.videolan.tools.CloseableUtils
import org.videolan.tools.HttpImageLoader
import org.videolan.tools.removeFileScheme
import org.videolan.vlc.R
@ -49,13 +45,8 @@ import org.videolan.vlc.gui.helpers.UiTools.snackerConfirm
import org.videolan.vlc.util.Permissions
import org.videolan.vlc.util.isSchemeHttpOrHttps
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
object AudioUtil {
const val TAG = "VLC/AudioUtil"
@ -137,59 +128,6 @@ object AudioUtil {
}
}
private fun getCoverFromMediaStore(context: Context, media: MediaWrapper): String? {
val album = media.albumName ?: return null
val contentResolver = context.contentResolver
val uri = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI
val cursor = contentResolver.query(uri, arrayOf(MediaStore.Audio.Albums.ALBUM, MediaStore.Audio.Albums.ALBUM_ART),
MediaStore.Audio.Albums.ALBUM + " LIKE ?",
arrayOf(album), null)
if (cursor == null) {
// do nothing
} else if (!cursor.moveToFirst()) {
// do nothing
cursor.close()
} else {
val titleColumn = cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART)
val albumArt = cursor.getString(titleColumn)
cursor.close()
return albumArt
}
return null
}
@Throws(IOException::class)
private fun writeBitmap(bitmap: Bitmap?, path: String) {
var out: OutputStream? = null
try {
val file = File(path)
if (file.exists() && file.length() > 0)
return
out = BufferedOutputStream(FileOutputStream(file), 4096)
bitmap?.compress(CompressFormat.JPEG, 90, out)
} catch (e: Exception) {
Log.e(TAG, "writeBitmap failed : " + e.message)
} finally {
CloseableUtils.close(out)
}
}
/**
* Load cover art from the published ArtworkProvider using a ContentResolver.
*/
fun fetchBitmapFromContentResolver(context: Context, path: String?): Bitmap? {
try {
val uri = path!!.toUri()
val inputStream: InputStream? = context.contentResolver.openInputStream(uri)
inputStream?.use {
return BitmapFactory.decodeStream(it)
}
} catch (e: Exception) {
Log.e(TAG, "Could not load image from: $path", e)
}
return null
}
//TODO Make it a suspend function to get rid of runBlocking {... }
@WorkerThread
fun readCoverBitmap(requestedPath: String?, width: Int): Bitmap? {

56
application/vlc-android/src/org/videolan/vlc/gui/helpers/BitmapUtil.kt

@ -35,7 +35,6 @@ import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.StateListDrawable
import android.graphics.drawable.VectorDrawable
import android.net.Uri
import android.os.Build
@ -50,7 +49,6 @@ import androidx.annotation.WorkerThread
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.graphics.drawable.toDrawable
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
import org.videolan.medialibrary.interfaces.media.MediaWrapper
import org.videolan.resources.AppContextProvider
@ -167,27 +165,6 @@ object BitmapUtil {
}
fun getBitmapFromVectorDrawable(context: Context, @DrawableRes drawableId: Int, width: Int = -1, height: Int = -1): Bitmap? {
var drawable: Drawable = ContextCompat.getDrawable(context, drawableId) ?: return null
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
drawable = DrawableCompat.wrap(drawable).mutate()
}
return when (drawable) {
is BitmapDrawable -> drawable.bitmap
is VectorDrawableCompat, is VectorDrawable -> {
val bitmap = if (width > 0 && height > 0)
Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
else
Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
bitmap
}
else -> BitmapFactory.decodeResource(context.resources, drawableId)
}
}
fun vectorToBitmap(context: Context, @DrawableRes resVector: Int, width: Int? = null, height: Int? = null): Bitmap {
val drawable = AppCompatResources.getDrawable(context, resVector) ?: throw IllegalStateException("Invalid drawable")
val b = Bitmap.createBitmap(width ?: drawable.intrinsicWidth, height
@ -213,26 +190,6 @@ object BitmapUtil {
return bitmapResult
}
fun makeTransparentBackground(context: Context, width: Int = 48.dp): Bitmap {
val colorLight = ContextCompat.getColor(context, R.color.grey500)
val colorDark = ContextCompat.getColor(context, R.color.grey700)
val paint = Paint()
val bitmapResult = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmapResult)
var iter = 0
val squareSize = width / 6F
for (i in 0..5) {
for (j in 0..5) {
paint.color = if (iter % 2 == 0) colorDark else colorLight
canvas.drawRect(i * squareSize, j * squareSize, (i + 1) * squareSize, (j + 1) * squareSize, paint)
iter++
}
iter++
}
return bitmapResult
}
/**
* Cut a [Bitmap] into a round one
* @param the [Bitmap] to use
@ -386,19 +343,6 @@ object BitmapUtil {
}
/**
* Constructs a [StateListDrawable] from a drawable and colors
* @param drawable the drawable to use
* @param color the color for the normal state
* @param pressedColor the color for the pressed state
* @return a [StateListDrawable]
*/
fun Context.getColoredStateListDawable(@DrawableRes drawable: Int, color: Int, pressedColor: Int) = StateListDrawable().apply {
addState(intArrayOf(android.R.attr.state_focused), getColoredBitmapFromColor(drawable, pressedColor).toDrawable(resources))
addState(intArrayOf(android.R.attr.state_pressed), getColoredBitmapFromColor(drawable, pressedColor).toDrawable(resources))
addState(intArrayOf(android.R.attr.state_enabled), getColoredBitmapFromColor(drawable, color).toDrawable(resources))
}
/**
* Get a colored [Bitmap] from a drawable
* @param drawableRes the drawable resource to use

2
application/vlc-android/src/org/videolan/vlc/gui/helpers/BottomNavigationBehavior.kt

@ -24,7 +24,6 @@
package org.videolan.vlc.gui.helpers
import android.animation.ValueAnimator
import android.content.Context
import android.os.Parcel
import android.os.Parcelable
@ -49,7 +48,6 @@ class BottomNavigationBehavior<V : View>(context: Context, attrs: AttributeSet)
private var height = 0
private var currentState = STATE_SCROLLED_UP
private var offsetAnimator: ValueAnimator? = null
private var player: FrameLayout? = null
private val playerBehavior: PlayerBehavior<*>?
get() {

5
application/vlc-android/src/org/videolan/vlc/gui/helpers/Navigator.kt

@ -131,11 +131,6 @@ class Navigator : NavigationBarView.OnItemSelectedListener, DefaultLifecycleObse
private fun idIsExtension(id: Int) = id in 1..100
private fun clearBackstackFromClass(clazz: Class<*>) {
val fm = activity.supportFragmentManager
while (clazz.isInstance(currentFragment)) if (!fm.popBackStackImmediate()) break
}
override fun reloadPreferences() {
currentFragmentId = settings.getInt(KEY_FRAGMENT_ID, defaultFragmentId)
}

1
application/vlc-android/src/org/videolan/vlc/gui/helpers/NotificationHelper.kt

@ -64,7 +64,6 @@ private const val REMOTE_ACCESS_CHANNEL_ID = "vlc_remote_access"
private const val REMOTE_ACCESS_OTP_CHANNEL_ID = "vlc_remote_access_otp"
const val MISC_CHANNEL_ID = "misc"
private const val RECOMMENDATION_CHANNEL_ID = "vlc_recommendations"
const val REMOTE_ACCESS_NOTIFICATION_ID = 44
const val REMOTE_ACCESS_CODE_ID = 45
object NotificationHelper {

10
application/vlc-android/src/org/videolan/vlc/gui/helpers/PlayerOptionsDelegate.kt

@ -343,16 +343,6 @@ class PlayerOptionsDelegate(val activity: FragmentActivity, val service: Playbac
hide()
}
private fun showValueControls(action: Int) {
val controller = (activity as? VideoPlayerActivity)?.delayDelegate ?: return
when (action) {
ACTION_AUDIO_DELAY -> controller.showAudioDelaySetting()
ACTION_SPU_DELAY -> controller.showSubsDelaySetting()
else -> return
}
hide()
}
private fun setRepeatMode() {
when (service.repeatType) {
PlaybackStateCompat.REPEAT_MODE_NONE -> {

3
application/vlc-android/src/org/videolan/vlc/gui/helpers/hf/BaseHeadlessFragment.kt

@ -23,7 +23,6 @@
package org.videolan.vlc.gui.helpers.hf
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
@ -50,8 +49,6 @@ open class BaseHeadlessFragment : Fragment() {
.commitAllowingStateLoss()
}
}
protected fun PermissionResults.granted() = isNotEmpty() && get(0) == PackageManager.PERMISSION_GRANTED
}
class PermissionViewmodel : ViewModel() {

4
application/vlc-android/src/org/videolan/vlc/gui/onboarding/OnboardingActivity.kt

@ -189,10 +189,6 @@ class OnboardingActivity : AppCompatActivity(), OnboardingFragmentListener {
if (viewModel.currentFragment == FragmentName.THEME) nextButton.text = getString(R.string.done)
}
fun manageNextVisibility(visible: Boolean) {
nextButton.visibility = if (visible) View.VISIBLE else View.GONE
}
}
enum class FragmentName {

12
application/vlc-android/src/org/videolan/vlc/gui/video/VideoDelayDelegate.kt

@ -38,7 +38,12 @@ import androidx.core.animation.doOnEnd
import androidx.core.content.ContextCompat
import com.google.android.material.animation.ArgbEvaluatorCompat
import com.google.android.material.button.MaterialButton
import org.videolan.tools.*
import org.videolan.tools.AUDIO_DELAY_GLOBAL
import org.videolan.tools.Settings
import org.videolan.tools.putSingle
import org.videolan.tools.setGone
import org.videolan.tools.setInvisible
import org.videolan.tools.setVisible
import org.videolan.vlc.PlaybackService
import org.videolan.vlc.R
import org.videolan.vlc.gui.helpers.OnRepeatListenerKey
@ -300,9 +305,4 @@ class VideoDelayDelegate(private val player: VideoPlayerActivity) : View.OnClick
}
}
private val btSaveListener = View.OnClickListener {
player.service?.run {
settings.putSingle(KEY_BLUETOOTH_DELAY, player.service?.audioDelay ?: 0L)
}
}
}

28
application/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.kt

@ -248,7 +248,6 @@ import kotlin.math.roundToInt
open class VideoPlayerActivity : AppCompatActivity(), PlaybackService.Callback, PlaylistAdapter.IPlayer, OnClickListener, OnLongClickListener, StoragePermissionsDelegate.CustomActionController, TextWatcher, IDialogManager, KeycodeListener {
private var warnMetered = false
var hasPhysicalNotch: Boolean = false
private var subtitlesExtraPath: String? = null
private lateinit var startedScope: CoroutineScope
@ -744,18 +743,6 @@ open class VideoPlayerActivity : AppCompatActivity(), PlaybackService.Callback,
}
}
private fun hideSearchField(): Boolean {
if (overlayDelegate.playlistSearchText.visibility != View.VISIBLE) return false
overlayDelegate.playlistSearchText.editText?.apply {
removeTextChangedListener(this@VideoPlayerActivity)
setText("")
addTextChangedListener(this@VideoPlayerActivity)
}
UiTools.setKeyboardVisibility(overlayDelegate.playlistSearchText, false)
return true
}
override fun onResume() {
overridePendingTransition(0, 0)
super.onResume()
@ -1774,17 +1761,6 @@ open class VideoPlayerActivity : AppCompatActivity(), PlaybackService.Callback,
overlayDelegate.updatePlaybackSpeedChip()
}
private fun encounteredError() {
if (isFinishing || service?.hasNext() == true) return
/* Encountered Error, exit player with a message */
alertDialog = AlertDialog.Builder(this@VideoPlayerActivity)
.setOnCancelListener { exit(RESULT_PLAYBACK_ERROR) }
.setPositiveButton(R.string.ok) { _, _ -> exit(RESULT_PLAYBACK_ERROR) }
.setTitle(R.string.encountered_error_title)
.setMessage(R.string.encountered_error_message)
.create().apply { show() }
}
private fun handleVout(voutCount: Int) {
handler.removeCallbacks(switchAudioRunnable)
@ -2105,10 +2081,6 @@ open class VideoPlayerActivity : AppCompatActivity(), PlaybackService.Callback,
handler.sendEmptyMessage(START_PLAYBACK)
}
fun hideOptions() {
optionsDelegate?.hide()
}
private fun showNavMenu() {
if (menuIdx >= 0) service?.titleIdx = menuIdx
}

32
application/vlc-android/src/org/videolan/vlc/gui/view/ClickableSwitchPreference.kt

@ -1,32 +0,0 @@
package org.videolan.vlc.gui.view
import android.content.Context
import android.view.View
import androidx.appcompat.widget.SwitchCompat
import androidx.preference.PreferenceViewHolder
import androidx.preference.TwoStatePreference
class ClickableSwitchPreference(context: Context) : TwoStatePreference(context, null, androidx.preference.R.attr.switchPreferenceCompatStyle, 0) {
private var switchView: View? = null
private var switchClickListener: View.OnClickListener? = null
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
switchView = holder.findViewById(androidx.preference.R.id.switchWidget)
switchView!!.setOnClickListener(switchClickListener)
//for some reason, it does not initialize itself;
(switchView as SwitchCompat).isChecked = isChecked
(switchView as SwitchCompat).setOnCheckedChangeListener { _, _ -> }
}
fun setOnSwitchClickListener(listener: View.OnClickListener) {
switchClickListener = listener
}
override fun onClick() {
//Do not call super.onClick();
}
}

14
application/vlc-android/src/org/videolan/vlc/gui/view/FlingViewGroup.kt

@ -22,7 +22,11 @@ package org.videolan.vlc.gui.view
import android.content.Context
import android.util.AttributeSet
import android.view.*
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.View
import android.view.ViewConfiguration
import android.view.ViewGroup
import android.widget.Scroller
import kotlin.math.absoluteValue
@ -39,7 +43,6 @@ abstract class FlingViewGroup(context: Context, attrs: AttributeSet) : ViewGroup
private var lastX: Float = 0.toFloat()
private var lastInterceptDownY: Float = 0.toFloat()
private var initialMotionEventX: Float = 0.toFloat()
private var initialMotionX: Float = 0.toFloat()
private var initialMotionY: Float = 0.toFloat()
@ -221,13 +224,6 @@ abstract class FlingViewGroup(context: Context, attrs: AttributeSet) : ViewGroup
invalidate()
}
fun smoothScrollTo(position: Int) {
this.position = position
val delta = position * width - scrollX
scroller.startScroll(scrollX, 0, delta, 0, 300)
invalidate()
}
companion object {
const val TAG = "VLC/FlingViewGroup"
private const val TOUCH_STATE_MOVE = 0

7
application/vlc-android/src/org/videolan/vlc/gui/view/FocusableTextView.kt

@ -25,7 +25,11 @@
package org.videolan.vlc.gui.view
import android.content.Context
import android.graphics.*
import android.graphics.Canvas
import android.graphics.ColorFilter
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.Gravity
@ -87,7 +91,6 @@ open class FocusableTextView : androidx.appcompat.widget.AppCompatTextView {
override fun setColorFilter(colorFilter: ColorFilter?) {}
override fun setAlpha(i: Int) {}
var pressed = false
override fun onStateChange(states: IntArray): Boolean {
invalidateSelf()
return true

2
application/vlc-android/src/org/videolan/vlc/gui/view/RecyclerSectionItemDecoration.kt

@ -34,7 +34,7 @@ class RecyclerSectionItemDecoration(private val headerOffset: Int, private val s
if (!::headerView.isInitialized) {
headerView = inflateHeaderView(parent)
header = headerView.findViewById(R.id.section_header) as TextView
header = headerView.findViewById<TextView>(R.id.section_header)!!
fixLayoutSize(headerView, parent)
}

2
application/vlc-android/src/org/videolan/vlc/gui/view/RecyclerSectionItemGridDecoration.kt

@ -63,7 +63,7 @@ class RecyclerSectionItemGridDecoration(private val headerOffset: Int, private v
if (!::headerView.isInitialized) {
headerView = inflateHeaderView(parent)
header = headerView.findViewById(R.id.section_header) as TextView
header = headerView.findViewById<TextView>(R.id.section_header)!!
fixLayoutSize(headerView, parent)
}

25
application/vlc-android/src/org/videolan/vlc/interfaces/OnExpandableListener.kt

@ -1,25 +0,0 @@
/*****************************************************************************
* OnExpandableListener.java
*
* Copyright © 2013 VLC authors and VideoLAN
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*/
package org.videolan.vlc.interfaces
interface OnExpandableListener {
fun onDismiss()
}

2
application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt

@ -45,7 +45,6 @@ import org.videolan.resources.CONTENT_STYLE_GRID_ITEM_HINT_VALUE
import org.videolan.resources.CONTENT_STYLE_LIST_ITEM_HINT_VALUE
import org.videolan.resources.CONTENT_STYLE_PLAYABLE_HINT
import org.videolan.resources.EXTRA_BROWSER_ICON_SIZE
import org.videolan.resources.EXTRA_CONTENT_STYLE_GROUP_TITLE_HINT
import org.videolan.resources.EXTRA_CONTENT_STYLE_SINGLE_ITEM
import org.videolan.resources.EXTRA_RELATIVE_MEDIA_ID
import org.videolan.tools.KEY_ARTISTS_SHOW_ALL
@ -114,7 +113,6 @@ class MediaSessionBrowser {
companion object {
private const val TAG = "VLC/MediaSessionBrowser"
private val instance = MediaSessionBrowser()
// Root item
// MediaIds are all strings. Maintain in uri parsable format.

18
application/vlc-android/src/org/videolan/vlc/media/MediaUtils.kt

@ -319,13 +319,6 @@ object MediaUtils {
}
}
fun openStream(context: Context?, uri: String?) {
if (uri == null || context == null) return
SuspendDialogCallback(context) { service ->
service.loadLocation(uri)
}
}
fun getMediaArtist(ctx: Context, media: MediaWrapper?): String = when {
media == null -> getMediaString(ctx, R.string.unknown_artist)
media.type == MediaWrapper.TYPE_VIDEO -> ""
@ -616,17 +609,6 @@ fun List<Folder>.getAll(type: Int = Folder.TYPE_FOLDER_VIDEO, sort: Int = Medial
it.getAll(type, sort, desc, onlyFavorites)
}
private fun Array<MediaLibraryItem>.toList() = flatMap {
if (it is VideoGroup) {
it.media(Medialibrary.SORT_DEFAULT, false, true, false, it.mediaCount(), 0).toList()
} else listOf(it as MediaWrapper)
}
fun MediaContentResolver.canHandle(id: String) : Boolean {
for (i in 0 until size()) if (id.startsWith(keyAt(i))) return true
return false
}
suspend fun MediaContentResolver.getList(context: Context, id: String) : ResumableList {
for ( i in 0 until size()) if (id.startsWith(keyAt(i))) return valueAt(i).getList(context, id)
return null

1
application/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt

@ -665,7 +665,6 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
val time = player.mediaplayer.time
val length = player.getLength()
val canSwitchToVideo = player.canSwitchToVideo()
val rate = player.getRate()
launch(Dispatchers.IO) innerLaunch@ {
val media = if (entryUrl != null) medialibrary.getMedia(entryUrl) else medialibrary.findMedia(currentMedia) ?: return@innerLaunch
if (showAudioPlayer.value != true) BaseBrowserFragment.needRefresh.postValue(true)

14
application/vlc-android/src/org/videolan/vlc/util/Browserutils.kt

@ -59,8 +59,6 @@ fun Uri.isSD() = this.path != null && this.path?.startsWith("/storage") == true
fun String?.isSchemeSMB() = this == "smb"
fun String?.isSchemeFD() = this == "fd"
fun String?.isSchemeDistant() = !this.isSchemeFile()
fun String.isMissing() = this == "missing://"
fun convertFavorites(browserFavs: List<BrowserFav>?) = browserFavs?.filter {
@ -74,15 +72,3 @@ fun convertFavorites(browserFavs: List<BrowserFav>?) = browserFavs?.filter {
}
} ?: emptyList()
/**
* Converts a [BrowserFav] to a [MediaWrapper]
* @return a [MediaWrapper]
*/
fun convertFavorite(browserFav: BrowserFav): MediaWrapper? {
return MLServiceLocator.getAbstractMediaWrapper(browserFav.uri).apply {
setDisplayTitle(Uri.decode(browserFav.title))
type = MediaWrapper.TYPE_DIR
browserFav.iconUrl?.let { artworkURL = Uri.decode(it) }
setStateFlags(MediaLibraryItem.FLAG_FAVORITE)
}
}

1
application/vlc-android/src/org/videolan/vlc/util/ContextOption.kt

@ -41,7 +41,6 @@ enum class ContextOption : Flag {
CTX_GO_TO_FOLDER,
CTX_GROUP_SIMILAR,
CTX_INFORMATION,
CTX_ITEM_DL,
CTX_MARK_ALL_AS_PLAYED,
CTX_MARK_ALL_AS_UNPLAYED,
CTX_MARK_AS_PLAYED,

2
application/vlc-android/src/org/videolan/vlc/util/DialogDelegates.kt

@ -12,8 +12,6 @@ import videolan.org.commontools.LiveEvent
private const val TAG = "DialogDelegate"
interface IDialogHandler
interface IDialogDelegate {
fun observeDialogs(lco: LifecycleOwner, manager: IDialogManager)
}

5
application/vlc-android/src/org/videolan/vlc/util/FileUtils.kt

@ -301,16 +301,11 @@ object FileUtils {
return deleted
}
fun String.isInternalStorage() = startsWith(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY)
private fun asyncRecursiveDelete(path: String, callback: Callback?) {
asyncRecursiveDelete(File(path), callback)
}
fun asyncRecursiveDelete(path: String) {
asyncRecursiveDelete(path, null)
}
private fun asyncRecursiveDelete(fileOrDirectory: File, callback: Callback?) {
runIO(Runnable {
if (!fileOrDirectory.exists() || !fileOrDirectory.canWrite())

33
application/vlc-android/src/org/videolan/vlc/util/Kextensions.kt

@ -29,15 +29,23 @@ import androidx.databinding.BindingAdapter
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.*
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import org.videolan.libvlc.Media
import org.videolan.libvlc.interfaces.IMedia
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.medialibrary.MLServiceLocator
import org.videolan.medialibrary.Tools
@ -62,7 +70,7 @@ import java.net.URI
import java.net.URISyntaxException
import java.security.SecureRandom
import java.text.Normalizer
import java.util.*
import java.util.Locale
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
@ -86,12 +94,8 @@ fun String.validateLocation(): Boolean {
return true
}
inline fun <reified T : ViewModel> Fragment.getModelWithActivity() = ViewModelProvider(requireActivity()).get(T::class.java)
inline fun <reified T : ViewModel> Fragment.getModel() = ViewModelProvider(this).get(T::class.java)
inline fun <reified T : ViewModel> FragmentActivity.getModel() = ViewModelProvider(this).get(T::class.java)
fun Media?.canExpand() = this != null && (type == IMedia.Type.Directory || type == IMedia.Type.Playlist)
fun FragmentActivity.share(file: File) {
val intentShareFile = Intent(Intent.ACTION_SEND)
val fileWithinMyDir = File(file.path)
@ -529,17 +533,6 @@ fun ViewPager2.findCurrentFragment(fragmentManager: FragmentManager): Fragment?
return fragmentManager.findFragmentByTag("f$currentItem")
}
/**
* Finds the [ViewPager2] fragment at a specified position
* @param fragmentManager: The used [FragmentManager]
* @param position: The position to look at
*
* @return the fragment if found
*/
fun ViewPager2.findFragmentAt(fragmentManager: FragmentManager, position: Int): Fragment? {
return fragmentManager.findFragmentByTag("f$position")
}
/**
* Merges the current sorted mutable list with another sorted list based on a selected property.
*

34
application/vlc-android/src/org/videolan/vlc/util/ModelsHelper.kt

@ -5,17 +5,42 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.videolan.libvlc.MediaPlayer
import org.videolan.libvlc.interfaces.IMedia
import org.videolan.medialibrary.interfaces.Medialibrary.*
import org.videolan.medialibrary.interfaces.Medialibrary.NbMedia
import org.videolan.medialibrary.interfaces.Medialibrary.SORT_ALBUM
import org.videolan.medialibrary.interfaces.Medialibrary.SORT_ALPHA
import org.videolan.medialibrary.interfaces.Medialibrary.SORT_ARTIST
import org.videolan.medialibrary.interfaces.Medialibrary.SORT_DEFAULT
import org.videolan.medialibrary.interfaces.Medialibrary.SORT_DURATION
import org.videolan.medialibrary.interfaces.Medialibrary.SORT_FILENAME
import org.videolan.medialibrary.interfaces.Medialibrary.SORT_FILESIZE
import org.videolan.medialibrary.interfaces.Medialibrary.SORT_INSERTIONDATE
import org.videolan.medialibrary.interfaces.Medialibrary.SORT_LASTMODIFICATIONDATE
import org.videolan.medialibrary.interfaces.Medialibrary.SORT_PLAYCOUNT
import org.videolan.medialibrary.interfaces.Medialibrary.SORT_RELEASEDATE
import org.videolan.medialibrary.interfaces.Medialibrary.TrackId
import org.videolan.medialibrary.interfaces.media.Album
import org.videolan.medialibrary.interfaces.media.MediaWrapper
import org.videolan.medialibrary.media.DummyItem
import org.videolan.medialibrary.media.MediaLibraryItem
import org.videolan.medialibrary.media.Storage
import org.videolan.resources.util.*
import org.videolan.resources.util.getLength
import org.videolan.resources.util.getTimeCategory
import org.videolan.resources.util.getTimeCategoryString
import org.videolan.resources.util.getYear
import org.videolan.resources.util.isSpecialItem
import org.videolan.tools.Settings
import org.videolan.vlc.PlaybackService
import java.util.*
import java.util.Locale
import kotlin.Boolean
import kotlin.Comparator
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.getValue
import kotlin.lazy
import kotlin.math.floor
import kotlin.takeIf
import kotlin.toString
object ModelsHelper {
@ -101,9 +126,6 @@ object ModelsHelper {
else array
}
fun MediaLibraryItem.getFirstLetter(): String {
return if (title.isEmpty() || !Character.isLetter(title[0]) || isSpecialItem()) "#" else title.substring(0, 1).uppercase(Locale.getDefault())
}
fun MediaLibraryItem.getDiscNumberString(): String? = if (this is MediaWrapper && this.discNumber != 0) "Disc ${this.discNumber}" else null

1
application/vlc-android/src/org/videolan/vlc/util/Permissions.kt

@ -61,7 +61,6 @@ object Permissions {
var timeAsked: Long = -1L
const val PERMISSION_STORAGE_TAG = 255
const val PERMISSION_SETTINGS_TAG = 254
const val PERMISSION_WRITE_STORAGE_TAG = 253
const val MANAGE_EXTERNAL_STORAGE = 256

10
application/vlc-android/src/org/videolan/vlc/viewmodels/BaseModel.kt

@ -33,8 +33,6 @@ import org.videolan.medialibrary.media.MediaLibraryItem
import org.videolan.tools.CoroutineContextProvider
import org.videolan.tools.livedata.LiveDataset
import org.videolan.vlc.util.FilterDelegate
import org.videolan.vlc.util.ModelsHelper
import org.videolan.vlc.util.map
private const val TAG = "VLC/BaseModel"
@ -45,14 +43,6 @@ abstract class BaseModel<T : MediaLibraryItem>(context: Context, val coroutineCo
val dataset = LiveDataset<T>()
open val loading = MutableLiveData<Boolean>().apply { value = false }
val categories by lazy(LazyThreadSafetyMode.NONE) {
viewModelScope.map(dataset) { ModelsHelper.splitList(sort, it!!.toList()) }
}
val sections by lazy(LazyThreadSafetyMode.NONE) {
viewModelScope.map(dataset) { ModelsHelper.generateSections(sort, it!!.toList()) }
}
@Suppress("UNCHECKED_CAST")
@OptIn(ObsoleteCoroutinesApi::class)
protected val updateActor by lazy {

2
application/vlc-android/src/org/videolan/vlc/viewmodels/PlaylistModel.kt

@ -245,8 +245,6 @@ class PlaylistModel : ViewModel(), PlaybackService.Callback by EmptyPBSCallback
private suspend fun canSwitchToVideo() = withContext(Dispatchers.IO) { service?.playlistManager?.player?.canSwitchToVideo() ?: false }
fun toggleABRepeat() = service?.playlistManager?.toggleABRepeat()
val videoTrackCount
get() = service?.videoTracksCount ?: 0

2
application/vlc-android/src/org/videolan/vlc/viewmodels/SortableModel.kt

@ -18,8 +18,6 @@ abstract class SortableModel(protected val context: Context): ViewModel(), Refre
var filterQuery : String? = null
fun getKey() = sortKey
override fun sort(sort: Int) {
if (canSortBy(sort)) {
desc = when (this.sort) {

2
application/vlc-android/src/org/videolan/vlc/widget/utils/WidgetSizeUtil.kt

@ -55,6 +55,4 @@ object WidgetSizeUtil {
private fun getWidgetSizeInDp(context: Context, widgetId: Int, key: String): Int =
getAppWidgetManager(context).getAppWidgetOptions(widgetId).getInt(key, 0)
private fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt()
}
Loading…
Cancel
Save