mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-27 23:40:33 +05:30
Bump minSdk to 26
This commit is contained in:
parent
cde9bc33e5
commit
4adcbb9719
@ -13,7 +13,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.github.libretube"
|
||||
minSdk = 21
|
||||
minSdk = 26
|
||||
targetSdk = 34
|
||||
versionCode = 59
|
||||
versionName = "0.27.0"
|
||||
|
@ -3,17 +3,13 @@ package com.github.libretube.compat
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
|
||||
object PictureInPictureCompat {
|
||||
fun isPictureInPictureAvailable(context: Context): Boolean {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
|
||||
context.packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
|
||||
}
|
||||
|
||||
fun isInPictureInPictureMode(activity: Activity): Boolean {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && activity.isInPictureInPictureMode
|
||||
}
|
||||
fun isPictureInPictureAvailable(context: Context) =
|
||||
context.packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
|
||||
|
||||
fun isInPictureInPictureMode(activity: Activity) = activity.isInPictureInPictureMode
|
||||
|
||||
fun setPictureInPictureParams(activity: Activity, params: PictureInPictureParamsCompat) {
|
||||
if (isPictureInPictureAvailable(activity)) {
|
||||
|
@ -1,22 +1,8 @@
|
||||
package com.github.libretube.extensions
|
||||
|
||||
import android.icu.text.CompactDecimalFormat
|
||||
import android.os.Build
|
||||
import com.github.libretube.helpers.LocaleHelper
|
||||
import kotlin.math.pow
|
||||
|
||||
fun Long?.formatShort(): String {
|
||||
val value = this ?: 0
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
CompactDecimalFormat
|
||||
.getInstance(LocaleHelper.getAppLocale(), CompactDecimalFormat.CompactStyle.SHORT)
|
||||
.format(value)
|
||||
} else {
|
||||
val units = arrayOf("", "K", "M", "B", "T")
|
||||
for (i in units.size downTo 1) {
|
||||
val step = 1000.0.pow(i.toDouble())
|
||||
if (value > step) return "%3.0f%s".format(value / step, units[i]).trim()
|
||||
}
|
||||
value.toString()
|
||||
}
|
||||
}
|
||||
fun Long?.formatShort(): String = CompactDecimalFormat
|
||||
.getInstance(LocaleHelper.getAppLocale(), CompactDecimalFormat.CompactStyle.SHORT)
|
||||
.format(this ?: 0)
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.github.libretube.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.core.content.ContextCompat
|
||||
|
||||
object DisplayHelper {
|
||||
@ -9,17 +8,5 @@ object DisplayHelper {
|
||||
* Detect whether the device supports HDR as the ExoPlayer doesn't handle it properly
|
||||
* Returns false below SDK 24
|
||||
*/
|
||||
fun supportsHdr(context: Context): Boolean {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val display = ContextCompat.getDisplayOrDefault(context)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
display.isHdr
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
display.hdrCapabilities?.supportedHdrTypes?.isNotEmpty() ?: false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
fun supportsHdr(context: Context) = ContextCompat.getDisplayOrDefault(context).isHdr
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package com.github.libretube.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.os.bundleOf
|
||||
@ -40,15 +39,12 @@ object DownloadHelper {
|
||||
private const val VIDEO_MIMETYPE = "video/*"
|
||||
|
||||
fun getDownloadDir(context: Context, path: String): Path {
|
||||
val storageDir = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
context.filesDir
|
||||
} else {
|
||||
val storageDir =
|
||||
try {
|
||||
context.getExternalFilesDir(null)!!
|
||||
} catch (e: Exception) {
|
||||
context.filesDir
|
||||
}
|
||||
}
|
||||
return (storageDir.toPath() / path).createDirectories()
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ package com.github.libretube.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.telephony.TelephonyManager
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.os.ConfigurationCompat
|
||||
@ -29,7 +28,7 @@ object LocaleHelper {
|
||||
|
||||
fun updateLanguage(context: Context) {
|
||||
val locale = getAppLocale()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) updateResources(context, locale)
|
||||
updateResources(context, locale)
|
||||
updateResourcesLegacy(context, locale)
|
||||
}
|
||||
|
||||
|
@ -3,29 +3,20 @@ package com.github.libretube.helpers
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkCapabilities
|
||||
import android.os.Build
|
||||
import androidx.core.content.getSystemService
|
||||
|
||||
object NetworkHelper {
|
||||
/**
|
||||
* Detect whether network is available
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
fun isNetworkAvailable(context: Context): Boolean {
|
||||
// In case we are using a VPN, we return true since we might be using reverse tethering
|
||||
val connectivityManager = context.getSystemService<ConnectivityManager>() ?: return false
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
val activeNetwork = connectivityManager.activeNetwork
|
||||
val caps = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false
|
||||
return caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) ||
|
||||
caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
|
||||
} else {
|
||||
// activeNetworkInfo might return null instead of the VPN, so better check it explicitly
|
||||
val networkInfo = connectivityManager.activeNetworkInfo
|
||||
?: connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_VPN)
|
||||
return networkInfo?.isConnected == true
|
||||
}
|
||||
val activeNetwork = connectivityManager.activeNetwork
|
||||
val caps = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false
|
||||
return caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) ||
|
||||
caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,6 @@ import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.text.Spanned
|
||||
import android.view.Window
|
||||
import androidx.annotation.ColorInt
|
||||
@ -35,12 +34,7 @@ object ThemeHelper {
|
||||
* Set the background color of the status bar
|
||||
*/
|
||||
private fun setStatusBarColor(context: Context, window: Window) {
|
||||
window.statusBarColor =
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M && !isDarkMode(context)) {
|
||||
getThemeColor(context, com.google.android.material.R.attr.colorOnBackground)
|
||||
} else {
|
||||
getThemeColor(context, android.R.attr.colorBackground)
|
||||
}
|
||||
window.statusBarColor = getThemeColor(context, android.R.attr.colorBackground)
|
||||
WindowCompat.getInsetsController(window, window.decorView)
|
||||
.isAppearanceLightStatusBars = !isDarkMode(context)
|
||||
}
|
||||
@ -54,11 +48,7 @@ object ThemeHelper {
|
||||
@ColorInt bottomNavColor: Int?
|
||||
) {
|
||||
window.navigationBarColor =
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M && !isDarkMode(context)) {
|
||||
getThemeColor(context, com.google.android.material.R.attr.colorOnBackground)
|
||||
} else {
|
||||
bottomNavColor ?: getThemeColor(context, android.R.attr.colorBackground)
|
||||
}
|
||||
bottomNavColor ?: getThemeColor(context, android.R.attr.colorBackground)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.github.libretube.ui.base
|
||||
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.github.libretube.R
|
||||
@ -40,11 +39,6 @@ open class BaseActivity : AppCompatActivity() {
|
||||
ThemeHelper.updateTheme(this)
|
||||
if (isDialogActivity) ThemeHelper.applyDialogActivityTheme(this)
|
||||
|
||||
// Set the navigation and statusBar color if SDK < 23
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
ThemeHelper.setSystemBarColors(this, window)
|
||||
}
|
||||
|
||||
// set the apps language
|
||||
LocaleHelper.updateLanguage(this)
|
||||
|
||||
|
@ -733,27 +733,23 @@ class PlayerFragment : Fragment(R.layout.fragment_player), OnlinePlayerOptions {
|
||||
DownloadHelper.startDownloadDialog(requireContext(), childFragmentManager, videoId)
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
binding.relPlayerScreenshot.setOnClickListener {
|
||||
if (!this::streams.isInitialized) return@setOnClickListener
|
||||
val surfaceView =
|
||||
binding.player.videoSurfaceView as? SurfaceView ?: return@setOnClickListener
|
||||
binding.relPlayerScreenshot.setOnClickListener {
|
||||
if (!this::streams.isInitialized) return@setOnClickListener
|
||||
val surfaceView =
|
||||
binding.player.videoSurfaceView as? SurfaceView ?: return@setOnClickListener
|
||||
|
||||
val bmp = Bitmap.createBitmap(
|
||||
surfaceView.width,
|
||||
surfaceView.height,
|
||||
Bitmap.Config.ARGB_8888
|
||||
)
|
||||
val bmp = Bitmap.createBitmap(
|
||||
surfaceView.width,
|
||||
surfaceView.height,
|
||||
Bitmap.Config.ARGB_8888
|
||||
)
|
||||
|
||||
PixelCopy.request(surfaceView, bmp, { _ ->
|
||||
screenshotBitmap = bmp
|
||||
val currentPosition =
|
||||
playerController.currentPosition.toFloat() / 1000
|
||||
openScreenshotFile.launch("${streams.title}-${currentPosition}.png")
|
||||
}, Handler(Looper.getMainLooper()))
|
||||
}
|
||||
} else {
|
||||
binding.relPlayerScreenshot.isGone = true
|
||||
PixelCopy.request(surfaceView, bmp, { _ ->
|
||||
screenshotBitmap = bmp
|
||||
val currentPosition =
|
||||
playerController.currentPosition.toFloat() / 1000
|
||||
openScreenshotFile.launch("${streams.title}-${currentPosition}.png")
|
||||
}, Handler(Looper.getMainLooper()))
|
||||
}
|
||||
|
||||
binding.playerChannel.setOnClickListener {
|
||||
|
@ -68,7 +68,7 @@ class DescriptionLayout(
|
||||
this.streams = streams
|
||||
|
||||
val views = streams.views.formatShort()
|
||||
val date = TextUtils.formatRelativeDate(context, streams.uploaded ?: -1L)
|
||||
val date = TextUtils.formatRelativeDate(streams.uploaded ?: -1L)
|
||||
binding.run {
|
||||
playerViewsInfo.text = context.getString(R.string.normal_views, views, TextUtils.SEPARATOR + date)
|
||||
|
||||
@ -135,7 +135,7 @@ class DescriptionLayout(
|
||||
val isNewStateExpanded = binding.descLinLayout.isGone
|
||||
if (!isNewStateExpanded) {
|
||||
// show a short version of the view count and date
|
||||
val formattedDate = TextUtils.formatRelativeDate(context, streams.uploaded ?: -1L)
|
||||
val formattedDate = TextUtils.formatRelativeDate(streams.uploaded ?: -1L)
|
||||
binding.playerViewsInfo.text = context.getString(R.string.normal_views, streams.views.formatShort(), TextUtils.SEPARATOR + formattedDate)
|
||||
|
||||
// limit the title height to two lines
|
||||
|
@ -3,7 +3,6 @@ package com.github.libretube.util
|
||||
import android.content.Context
|
||||
import android.icu.text.RelativeDateTimeFormatter
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.text.format.DateUtils
|
||||
import androidx.core.text.isDigitsOnly
|
||||
import com.github.libretube.BuildConfig
|
||||
@ -111,7 +110,7 @@ object TextUtils {
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun formatRelativeDate(context: Context, unixTime: Long): CharSequence {
|
||||
fun formatRelativeDate(unixTime: Long): CharSequence {
|
||||
val date = LocalDateTime.ofInstant(Instant.ofEpochMilli(unixTime), ZoneId.systemDefault())
|
||||
val now = LocalDateTime.now()
|
||||
val months = date.until(now, ChronoUnit.MONTHS)
|
||||
@ -119,22 +118,13 @@ object TextUtils {
|
||||
return if (months > 0) {
|
||||
val years = months / 12
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val (timeFormat, time) = if (years > 0) {
|
||||
RelativeDateTimeFormatter.RelativeUnit.YEARS to years
|
||||
} else {
|
||||
RelativeDateTimeFormatter.RelativeUnit.MONTHS to months
|
||||
}
|
||||
RelativeDateTimeFormatter.getInstance()
|
||||
.format(time.toDouble(), RelativeDateTimeFormatter.Direction.LAST, timeFormat)
|
||||
val (timeFormat, time) = if (years > 0) {
|
||||
RelativeDateTimeFormatter.RelativeUnit.YEARS to years
|
||||
} else {
|
||||
val (timeAgoRes, time) = if (years > 0) {
|
||||
R.plurals.years_ago to years
|
||||
} else {
|
||||
R.plurals.months_ago to months
|
||||
}
|
||||
context.resources.getQuantityString(timeAgoRes, time.toInt(), time)
|
||||
RelativeDateTimeFormatter.RelativeUnit.MONTHS to months
|
||||
}
|
||||
RelativeDateTimeFormatter.getInstance()
|
||||
.format(time.toDouble(), RelativeDateTimeFormatter.Direction.LAST, timeFormat)
|
||||
} else {
|
||||
val weeks = date.until(now, ChronoUnit.WEEKS)
|
||||
val minResolution = if (weeks > 0) DateUtils.WEEK_IN_MILLIS else 0L
|
||||
@ -161,7 +151,7 @@ object TextUtils {
|
||||
context.getString(R.string.view_count, it)
|
||||
}
|
||||
val uploadDate = uploaded.takeIf { it > 0 }?.let {
|
||||
formatRelativeDate(context, it)
|
||||
formatRelativeDate(it)
|
||||
}
|
||||
return listOfNotNull(uploader, viewsString, uploadDate).joinToString(SEPARATOR)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user