mirror of
https://github.com/Michatec/Radio.git
synced 2026-06-03 12:20:29 +02:00
Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 213246a0c4 | |||
| ae1e2aa784 | |||
| d654d79bd5 | |||
| 181ebd47df | |||
| 4429ed4057 | |||
| 83752c356f | |||
| c1bc8b3e19 | |||
| 8835cadd6a | |||
| 384926cf08 | |||
| 2cf98b89b3 | |||
| 6fa1e5e2c0 | |||
| 64d0f3a71f | |||
| c9122d74f8 | |||
| 1879827f4b | |||
| 23079649c5 | |||
| 2c7e02889d | |||
| b1bcfa2137 | |||
| 2814ff2cfa | |||
| a9f8efc72d | |||
| a5e27149ba | |||
| 2688f22a6a | |||
| 73edf9d816 | |||
| 9f39b1dbbd | |||
| 5d82d722bd | |||
| 5d7df9550e | |||
| c7b7114010 | |||
| ed8f17e436 | |||
| 2cc2a23e35 | |||
| f7ddc30127 | |||
| bc0eb60e04 | |||
| dcae7bafb5 | |||
| cf3fd0bc56 | |||
| 7d6b0fe136 | |||
| 0faeea7631 | |||
| c45adf07c8 | |||
| acd1b067b3 | |||
| e3a325f568 | |||
| b537df898b | |||
| 61675601f3 | |||
| 6dc5c47b86 | |||
| c40ad0cc4a | |||
| 066206c6dc | |||
| e8e66c24ef | |||
| 56647e7f02 | |||
| a7e0efc913 | |||
| 0569bed475 | |||
| 6e3b187b56 | |||
| c8c0d1783b | |||
| 4974514a81 | |||
| afd34c6485 |
@@ -105,6 +105,15 @@ When **Edit Stations** is enabled:
|
||||
|
||||
</details>
|
||||
|
||||
----------------------------------------
|
||||
|
||||
<details>
|
||||
<summary>⭐ Star History</summary>
|
||||
|
||||
[](https://www.star-history.com/?repos=michatec%2Fradio&type=date&legend=top-left)
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
<table><td>
|
||||
<a href="#start-of-content">↥ Scroll to top</a>
|
||||
|
||||
@@ -5,14 +5,14 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "com.michatec.radio"
|
||||
compileSdk = 36
|
||||
compileSdk = 37
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.michatec.radio"
|
||||
minSdk = 28
|
||||
targetSdk = 36
|
||||
versionCode = 145
|
||||
versionName = "14.5"
|
||||
targetSdk = 37
|
||||
versionCode = 146
|
||||
versionName = "14.6"
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
@@ -31,6 +31,7 @@ android {
|
||||
isCrunchPngs = false
|
||||
proguardFiles.addAll(listOf(getDefaultProguardFile("proguard-android-optimize.txt"), file("proguard-rules.pro")))
|
||||
applicationIdSuffix = ".debug"
|
||||
buildConfigField("boolean", "IS_DEBUG_ENABLED", "true")
|
||||
}
|
||||
|
||||
release {
|
||||
@@ -38,6 +39,7 @@ android {
|
||||
isShrinkResources = true
|
||||
isCrunchPngs = true
|
||||
proguardFiles.addAll(listOf(getDefaultProguardFile("proguard-android-optimize.txt"), file("proguard-rules.pro")))
|
||||
buildConfigField("boolean", "IS_DEBUG_ENABLED", "false")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"
|
||||
tools:ignore="ForegroundServicesPolicy" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
|
||||
<application
|
||||
android:name=".Radio"
|
||||
@@ -48,6 +50,7 @@
|
||||
<activity
|
||||
android:name=".ExpandedControllerActivity"
|
||||
android:exported="false"
|
||||
android:theme="@style/CustomCastExpandedControllerStyle"
|
||||
android:launchMode="singleTask" />
|
||||
|
||||
<!-- Main activity for radio station playback on phone and TV -->
|
||||
@@ -136,6 +139,7 @@
|
||||
<intent-filter>
|
||||
<action android:name="androidx.media3.session.MediaSessionService" />
|
||||
<action android:name="android.media.browse.MediaBrowserService" />
|
||||
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||
<action android:name="com.michatec.radio.action.START_PLAYER_SERVICE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
@@ -148,14 +152,6 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name="androidx.media.session.MediaButtonReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
|
||||
@@ -120,7 +120,7 @@ class AddStationFragment : Fragment(),
|
||||
if (searchEditText != null) {
|
||||
searchEditText.requestFocus()
|
||||
val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.showSoftInput(searchEditText, InputMethodManager.SHOW_IMPLICIT)
|
||||
imm.showSoftInput(searchEditText, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
package com.michatec.radio
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.SeekBar
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.graphics.toColorInt
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.michatec.radio.helpers.PreferencesHelper
|
||||
import com.michatec.radio.helpers.ThemeHelper
|
||||
|
||||
class CustomThemeFragment : Fragment() {
|
||||
|
||||
private lateinit var colorPreview: View
|
||||
private lateinit var hexCode: TextInputEditText
|
||||
private lateinit var seekRed: SeekBar
|
||||
private lateinit var seekGreen: SeekBar
|
||||
private lateinit var seekBlue: SeekBar
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
|
||||
private var currentColor: Int = Color.BLACK
|
||||
private var isUpdatingFromHex = false
|
||||
|
||||
private fun applyColor(
|
||||
color: Int
|
||||
) {
|
||||
updateSeekBars(color)
|
||||
updatePreview(color)
|
||||
}
|
||||
|
||||
private val isAndroidTV: Boolean by lazy {
|
||||
requireContext().packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
return inflater.inflate(R.layout.fragment_custom_theme, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
(activity as? AppCompatActivity)?.supportActionBar?.title = getString(R.string.pref_custom_theme_title)
|
||||
|
||||
colorPreview = view.findViewById(R.id.color_preview)
|
||||
hexCode = view.findViewById(R.id.hex_code)
|
||||
seekRed = view.findViewById(R.id.seek_red)
|
||||
seekGreen = view.findViewById(R.id.seek_green)
|
||||
seekBlue = view.findViewById(R.id.seek_blue)
|
||||
recyclerView = view.findViewById(R.id.color_recycler_view)
|
||||
|
||||
currentColor = PreferencesHelper.loadCustomThemeColor(requireContext())
|
||||
|
||||
applyColor(currentColor)
|
||||
|
||||
val seekBarListener = object : SeekBar.OnSeekBarChangeListener {
|
||||
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
val r = seekRed.progress
|
||||
val g = seekGreen.progress
|
||||
val b = seekBlue.progress
|
||||
currentColor = Color.rgb(r, g, b)
|
||||
updatePreview(currentColor)
|
||||
PreferencesHelper.saveCustomTheme(currentColor, -1)
|
||||
(recyclerView.adapter as? ColorAdapter)?.resetSelection()
|
||||
}
|
||||
}
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
|
||||
}
|
||||
|
||||
seekRed.setOnSeekBarChangeListener(seekBarListener)
|
||||
seekGreen.setOnSeekBarChangeListener(seekBarListener)
|
||||
seekBlue.setOnSeekBarChangeListener(seekBarListener)
|
||||
|
||||
// Clipboard logic (Non-TV)
|
||||
if (!isAndroidTV) {
|
||||
hexCode.setOnClickListener {
|
||||
copyToClipboard(hexCode.text.toString())
|
||||
}
|
||||
hexCode.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||
if (!isUpdatingFromHex) {
|
||||
try {
|
||||
val color = s.toString().toColorInt()
|
||||
currentColor = color
|
||||
isUpdatingFromHex = true
|
||||
applyColor(color)
|
||||
PreferencesHelper.saveCustomTheme(currentColor, -1)
|
||||
(recyclerView.adapter as? ColorAdapter)?.resetSelection()
|
||||
isUpdatingFromHex = false
|
||||
} catch (_: Exception) {}
|
||||
}
|
||||
}
|
||||
override fun afterTextChanged(s: Editable?) {}
|
||||
})
|
||||
} else {
|
||||
hexCode.isFocusable = false
|
||||
hexCode.isFocusableInTouchMode = false
|
||||
}
|
||||
|
||||
setupRecyclerView()
|
||||
}
|
||||
|
||||
private fun copyToClipboard(text: String) {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText(getString(R.string.hex_code), text)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
Toast.makeText(requireContext(), R.string.toastmessage_copied_to_clipboard, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
private fun updateSeekBars(color: Int) {
|
||||
seekRed.progress = Color.red(color)
|
||||
seekGreen.progress = Color.green(color)
|
||||
seekBlue.progress = Color.blue(color)
|
||||
}
|
||||
|
||||
private fun updatePreview(color: Int) {
|
||||
colorPreview.setBackgroundColor(color)
|
||||
if (!isUpdatingFromHex) {
|
||||
isUpdatingFromHex = true
|
||||
hexCode.setText(String.format("#%08X", 0xFFFFFF and color))
|
||||
isUpdatingFromHex = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
recyclerView.layoutManager = GridLayoutManager(requireContext(), 5)
|
||||
val colors = ThemeHelper.getPredefinedColors(requireContext())
|
||||
val adapter = ColorAdapter(colors) { color, index ->
|
||||
currentColor = color
|
||||
applyColor(color)
|
||||
PreferencesHelper.saveCustomTheme(currentColor, index)
|
||||
}
|
||||
recyclerView.adapter = adapter
|
||||
}
|
||||
|
||||
private inner class ColorAdapter(
|
||||
private val colors: List<Int>,
|
||||
private val onColorSelected: (Int, Int) -> Unit
|
||||
) : RecyclerView.Adapter<ColorAdapter.ViewHolder>() {
|
||||
|
||||
private var selectedPosition: Int = -1
|
||||
|
||||
init {
|
||||
selectedPosition = PreferencesHelper.loadCustomThemeIndex()
|
||||
}
|
||||
|
||||
fun resetSelection() {
|
||||
val oldPos = selectedPosition
|
||||
selectedPosition = -1
|
||||
if (oldPos != -1) notifyItemChanged(oldPos)
|
||||
}
|
||||
|
||||
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
val circle: View = view.findViewById(R.id.color_circle)
|
||||
init {
|
||||
view.isFocusable = true
|
||||
view.isFocusableInTouchMode = isAndroidTV
|
||||
view.setOnClickListener {
|
||||
val pos = bindingAdapterPosition
|
||||
if (pos != RecyclerView.NO_POSITION) {
|
||||
val oldPos = selectedPosition
|
||||
selectedPosition = pos
|
||||
if (oldPos != -1) notifyItemChanged(oldPos)
|
||||
notifyItemChanged(selectedPosition)
|
||||
onColorSelected(colors[pos], pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.element_color_circle, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val color = colors[position]
|
||||
val drawable = holder.circle.background as GradientDrawable
|
||||
drawable.setColor(color)
|
||||
|
||||
// Set selection state
|
||||
holder.itemView.isSelected = (position == selectedPosition)
|
||||
}
|
||||
|
||||
override fun getItemCount() = colors.size
|
||||
}
|
||||
}
|
||||
@@ -92,6 +92,9 @@ object Keys {
|
||||
const val PREF_PRESET_DRC: String = "PRESET_DRC"
|
||||
const val PREF_PRESET_STEREO_WIDTH: String = "PRESET_STEREO_WIDTH"
|
||||
const val PREF_LANGUAGE_SELECTED: String = "PRESET_LANGUAGE_SELECTED"
|
||||
const val PREF_CUSTOM_THEME_COLOR: String = "CUSTOM_THEME_COLOR"
|
||||
const val PREF_CUSTOM_THEME_ENABLED: String = "CUSTOM_THEME_ENABLED"
|
||||
const val PREF_CUSTOM_THEME_INDEX: String = "CUSTOM_THEME_INDEX"
|
||||
|
||||
// default const values
|
||||
const val DEFAULT_SIZE_OF_METADATA_HISTORY: Int = 25
|
||||
|
||||
@@ -1,25 +1,35 @@
|
||||
package com.michatec.radio
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.net.Uri
|
||||
import android.util.TypedValue
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.Settings
|
||||
import android.view.View
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.NavigationUI
|
||||
import androidx.navigation.ui.navigateUp
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.michatec.radio.helpers.AppThemeHelper
|
||||
import com.michatec.radio.helpers.FileHelper
|
||||
import com.michatec.radio.helpers.LanguageHelper
|
||||
import com.michatec.radio.helpers.PreferencesHelper
|
||||
import com.michatec.radio.helpers.ThemeHelper
|
||||
import org.woheller69.freeDroidWarn.FreeDroidWarn
|
||||
import java.util.Locale
|
||||
|
||||
@@ -30,6 +40,36 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
/* Main class variables */
|
||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||
private lateinit var mainRoot: View
|
||||
|
||||
// Check if the device running the app is an Android TV instance
|
||||
private val isAndroidTV: Boolean by lazy {
|
||||
packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
|
||||
}
|
||||
|
||||
// request notification permission (for Android 13+)
|
||||
private val permissionLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.RequestPermission()
|
||||
) { isGranted ->
|
||||
if (!isGranted) {
|
||||
val snackbar = Snackbar.make(
|
||||
findViewById(android.R.id.content),
|
||||
R.string.snackbar_failed_permission_notification,
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
// If the user permanently denied the permission, show a link to settings
|
||||
if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.POST_NOTIFICATIONS)) {
|
||||
snackbar.setAction(R.string.fragment_settings_title) {
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = Uri.fromParts("package", packageName, null)
|
||||
}
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
snackbar.setAnchorView(findViewById(R.id.bottom_sheet))
|
||||
snackbar.show()
|
||||
}
|
||||
}
|
||||
|
||||
/* Overrides attachBaseContext from AppCompatActivity */
|
||||
override fun attachBaseContext(newBase: Context) {
|
||||
@@ -57,6 +97,8 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
// set up views
|
||||
setContentView(R.layout.activity_main)
|
||||
mainRoot = findViewById(R.id.main_root)
|
||||
applyCustomTheme()
|
||||
|
||||
// create .nomedia file - if not yet existing
|
||||
FileHelper.createNomediaFile(getExternalFilesDir(null))
|
||||
@@ -72,7 +114,7 @@ class MainActivity : AppCompatActivity() {
|
||||
supportActionBar?.hide()
|
||||
|
||||
// TV-specific loading logic: Hide the overlay once the app is ready
|
||||
if (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
|
||||
if (isAndroidTV) {
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
hideLoadingOverlay()
|
||||
}, 1200)
|
||||
@@ -82,6 +124,11 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
// register listener for changes in shared preferences
|
||||
PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener)
|
||||
|
||||
// request permissions
|
||||
if (!isAndroidTV && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
}
|
||||
|
||||
/* Hides the loading/splash overlay */
|
||||
@@ -94,6 +141,33 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyCustomTheme() {
|
||||
val enabled = PreferencesHelper.loadCustomThemeEnabled()
|
||||
if (enabled) {
|
||||
var color = PreferencesHelper.loadCustomThemeColor(this)
|
||||
val index = PreferencesHelper.loadCustomThemeIndex()
|
||||
|
||||
if (index != -1) {
|
||||
// Color belongs to a predefined group. Update it based on current mode.
|
||||
val colors = ThemeHelper.getPredefinedColors(this)
|
||||
if (index < colors.size) {
|
||||
val updatedColor = colors[index]
|
||||
if (updatedColor != color) {
|
||||
color = updatedColor
|
||||
// Save the updated color to keep preferences in sync with the current mode
|
||||
PreferencesHelper.saveCustomThemeColor(color)
|
||||
}
|
||||
}
|
||||
}
|
||||
mainRoot.setBackgroundColor(color)
|
||||
} else {
|
||||
// Reset to default theme background color
|
||||
val typedValue = TypedValue()
|
||||
theme.resolveAttribute(android.R.attr.colorBackground, typedValue, true)
|
||||
mainRoot.setBackgroundColor(typedValue.data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Overrides onResume from AppCompatActivity */
|
||||
override fun onResume() {
|
||||
@@ -134,6 +208,9 @@ class MainActivity : AppCompatActivity() {
|
||||
Keys.PREF_LANGUAGE_SELECTED -> {
|
||||
LanguageHelper.setLanguage(this, PreferencesHelper.loadSelectedLanguage())
|
||||
}
|
||||
Keys.PREF_CUSTOM_THEME_COLOR, Keys.PREF_CUSTOM_THEME_ENABLED, Keys.PREF_CUSTOM_THEME_INDEX -> {
|
||||
applyCustomTheme()
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.michatec.radio
|
||||
|
||||
import androidx.core.app.NotificationCompat
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
||||
object NotificationSys {
|
||||
private const val CHANNEL_ID = "com.michatec.radio.channel_messages"
|
||||
private const val CHANNEL_NAME = "Notifications"
|
||||
private const val NOTIFICATION_ID = 5000
|
||||
|
||||
fun createNotificationChannel(context: Context) {
|
||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
|
||||
if (notificationManager.getNotificationChannel(CHANNEL_ID) == null) {
|
||||
val channel = NotificationChannel(
|
||||
CHANNEL_ID,
|
||||
CHANNEL_NAME,
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
).apply {
|
||||
description = context.getString(R.string.notification_channel_description)
|
||||
}
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
|
||||
fun showNotification(context: Context, title: String, content: String, intent: Intent? = null, id: Int = NOTIFICATION_ID) {
|
||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
createNotificationChannel(context)
|
||||
|
||||
val targetIntent = intent ?: Intent(context, MainActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
}
|
||||
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
0,
|
||||
targetIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
|
||||
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_notification_app_icon_white_24dp)
|
||||
.setContentTitle(title)
|
||||
.setContentText(content)
|
||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setAutoCancel(true)
|
||||
.build()
|
||||
|
||||
notificationManager.notify(id, notification)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.michatec.radio
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
@@ -95,6 +96,15 @@ class PlayerFragment : Fragment(),
|
||||
private var tempStationUuid: String = String()
|
||||
private var itemTouchHelper: ItemTouchHelper? = null
|
||||
|
||||
// Check if the device running the app is an Android TV instance
|
||||
private val isAndroidTV: Boolean by lazy {
|
||||
context?.packageManager?.hasSystemFeature(PackageManager.FEATURE_LEANBACK) == true
|
||||
}
|
||||
|
||||
private fun isPermissionGranted(context: Context, permission: String): Boolean {
|
||||
return context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
|
||||
/* Overrides onCreate from Fragment */
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -139,7 +149,11 @@ class PlayerFragment : Fragment(),
|
||||
pickSingleMediaLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { imageUri ->
|
||||
if (imageUri == null) {
|
||||
Snackbar.make(requireView(), R.string.toastalert_failed_picking_media, Snackbar.LENGTH_LONG).show()
|
||||
val snackbar = Snackbar.make(requireView(), R.string.toastalert_failed_picking_media, Snackbar.LENGTH_LONG)
|
||||
if (!isAndroidTV) {
|
||||
snackbar.setAnchorView(layout.bottomSheet)
|
||||
}
|
||||
snackbar.show()
|
||||
} else {
|
||||
collection = CollectionHelper.setStationImageWithStationUuid(
|
||||
activity as Context,
|
||||
@@ -294,6 +308,9 @@ class PlayerFragment : Fragment(),
|
||||
if (key == Keys.PREF_PLAYER_METADATA_HISTORY) {
|
||||
requestMetadataUpdate()
|
||||
}
|
||||
if (key == Keys.PREF_CUSTOM_THEME_COLOR || key == Keys.PREF_CUSTOM_THEME_ENABLED || key == Keys.PREF_CUSTOM_THEME_INDEX) {
|
||||
layout.applyCustomTheme(activity as Context)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -490,11 +507,17 @@ class PlayerFragment : Fragment(),
|
||||
// display the TimePicker dialog
|
||||
timePicker.show(requireActivity().supportFragmentManager, "tag")
|
||||
}
|
||||
else -> Snackbar.make(
|
||||
requireView(),
|
||||
R.string.toastmessage_sleep_timer_unable_to_start,
|
||||
Snackbar.LENGTH_SHORT
|
||||
).show()
|
||||
else -> {
|
||||
val snackbar = Snackbar.make(
|
||||
requireView(),
|
||||
R.string.toastmessage_sleep_timer_unable_to_start,
|
||||
Snackbar.LENGTH_SHORT
|
||||
)
|
||||
if (!isAndroidTV) {
|
||||
snackbar.setAnchorView(layout.bottomSheet)
|
||||
}
|
||||
snackbar.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -831,10 +854,10 @@ class PlayerFragment : Fragment(),
|
||||
} else {
|
||||
activity?.packageManager?.getPackageInfo(requireActivity().packageName, 0)?.versionName
|
||||
}
|
||||
if (latestVersion != current) {
|
||||
if (latestVersion != current && !BuildConfig.IS_DEBUG_ENABLED) {
|
||||
// We have an update available, tell our user about it
|
||||
view?.let {
|
||||
Snackbar.make(it, getString(R.string.app_name) + " " + latestVersion + " " + getString(R.string.snackbar_update_available), 10000)
|
||||
val snackbar = Snackbar.make(it, getString(R.string.app_name) + " " + latestVersion + " " + getString(R.string.snackbar_update_available), 10000)
|
||||
.setAction(R.string.snackbar_show) {
|
||||
val releaseurl = getString(R.string.snackbar_url_app_home_page)
|
||||
val i = Intent(Intent.ACTION_VIEW)
|
||||
@@ -847,7 +870,24 @@ class PlayerFragment : Fragment(),
|
||||
ContextCompat.getColor(
|
||||
requireActivity(),
|
||||
R.color.default_neutral_white))
|
||||
.show()
|
||||
|
||||
if (!isAndroidTV) {
|
||||
snackbar.setAnchorView(layout.bottomSheet)
|
||||
}
|
||||
snackbar.show()
|
||||
}
|
||||
if (!isAndroidTV && isPermissionGranted(requireContext(), Manifest.permission.POST_NOTIFICATIONS)) {
|
||||
val releaseUrl = getString(R.string.snackbar_url_app_home_page)
|
||||
val updateIntent = Intent(Intent.ACTION_VIEW, releaseUrl.toUri()).apply {
|
||||
putExtra("SOURCE", "SELF")
|
||||
}
|
||||
NotificationSys.showNotification(
|
||||
requireContext(),
|
||||
"${getString(R.string.app_name)} $latestVersion",
|
||||
getString(R.string.snackbar_update_available),
|
||||
intent = updateIntent,
|
||||
id = 1002
|
||||
)
|
||||
}
|
||||
}
|
||||
}, { error ->
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
import android.util.Log
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import androidx.media.MediaBrowserServiceCompat.BrowserRoot.EXTRA_RECENT
|
||||
import androidx.media3.cast.CastPlayer
|
||||
import androidx.media3.common.*
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
@@ -29,6 +28,7 @@ import com.google.common.collect.ImmutableList
|
||||
import com.google.common.util.concurrent.Futures
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.michatec.radio.core.Collection
|
||||
import com.michatec.radio.core.Station
|
||||
import com.michatec.radio.helpers.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
@@ -132,7 +132,7 @@ class PlayerService : MediaLibraryService(), SharedPreferences.OnSharedPreferenc
|
||||
context: Context,
|
||||
enableFloatOutput: Boolean,
|
||||
enableAudioTrackPlaybackParams: Boolean
|
||||
): AudioSink? {
|
||||
): AudioSink {
|
||||
return DefaultAudioSink.Builder(context)
|
||||
.setAudioProcessors(arrayOf(nativeAudioProcessor))
|
||||
.build()
|
||||
@@ -170,6 +170,14 @@ class PlayerService : MediaLibraryService(), SharedPreferences.OnSharedPreferenc
|
||||
override fun getDuration(): Long {
|
||||
return C.TIME_UNSET // this will hide progress bar for HLS stations in the notification
|
||||
}
|
||||
|
||||
override fun seekToNext() {
|
||||
playNextStation()
|
||||
}
|
||||
|
||||
override fun seekToPrevious() {
|
||||
playPreviousStation()
|
||||
}
|
||||
}
|
||||
player.addListener(playerListener)
|
||||
}
|
||||
@@ -347,6 +355,37 @@ class PlayerService : MediaLibraryService(), SharedPreferences.OnSharedPreferenc
|
||||
}
|
||||
|
||||
|
||||
/* Switches to the next radio station in collection */
|
||||
private fun playNextStation() {
|
||||
val currentMediaId = player.currentMediaItem?.mediaId ?: PreferencesHelper.loadLastPlayedStationUuid()
|
||||
val currentPosition = CollectionHelper.getStationPosition(collection, currentMediaId)
|
||||
if (currentPosition != -1) {
|
||||
val nextPosition = if (currentPosition < collection.stations.size - 1) currentPosition + 1 else 0
|
||||
playStation(collection.stations[nextPosition])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Switches to the previous radio station in collection */
|
||||
private fun playPreviousStation() {
|
||||
val currentMediaId = player.currentMediaItem?.mediaId ?: PreferencesHelper.loadLastPlayedStationUuid()
|
||||
val currentPosition = CollectionHelper.getStationPosition(collection, currentMediaId)
|
||||
if (currentPosition != -1) {
|
||||
val previousPosition = if (currentPosition > 0) currentPosition - 1 else collection.stations.size - 1
|
||||
playStation(collection.stations[previousPosition])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Starts playback of a radio station */
|
||||
private fun playStation(station: Station) {
|
||||
val mediaItem = CollectionHelper.buildMediaItem(this, station)
|
||||
player.setMediaItem(mediaItem)
|
||||
player.prepare()
|
||||
player.play()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Custom MediaSession Callback that handles player commands
|
||||
*/
|
||||
@@ -407,8 +446,8 @@ class PlayerService : MediaLibraryService(), SharedPreferences.OnSharedPreferenc
|
||||
browser: MediaSession.ControllerInfo,
|
||||
params: LibraryParams?
|
||||
): ListenableFuture<LibraryResult<MediaItem>> {
|
||||
return if (params?.extras?.containsKey(EXTRA_RECENT) == true) {
|
||||
// special case: system requested media resumption via EXTRA_RECENT
|
||||
return if (params?.isRecent == true) {
|
||||
// special case: system requested media resumption via isRecent
|
||||
playLastStation = true
|
||||
Futures.immediateFuture(LibraryResult.ofItem(CollectionHelper.getRecent(this@PlayerService, collection), params))
|
||||
} else {
|
||||
@@ -552,8 +591,7 @@ class PlayerService : MediaLibraryService(), SharedPreferences.OnSharedPreferenc
|
||||
stopSelf()
|
||||
}
|
||||
Player.STATE_READY -> {
|
||||
// Playback is paused. For radio, we can stop the service to remove the notification.
|
||||
stopSelf()
|
||||
// Playback is paused. For radio, we keep the service running to allow resumption from headphones.
|
||||
}
|
||||
Player.STATE_BUFFERING -> {
|
||||
// DO NOT stop the service while buffering (especially important for Cast)
|
||||
@@ -562,17 +600,6 @@ class PlayerService : MediaLibraryService(), SharedPreferences.OnSharedPreferenc
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
|
||||
super.onPlayWhenReadyChanged(playWhenReady, reason)
|
||||
if (!playWhenReady) {
|
||||
// Only stop if not buffering and not ready to play (i.e. truly stopped/paused)
|
||||
if (player.playbackState != Player.STATE_BUFFERING) {
|
||||
stopSelf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onPlayerError(error: PlaybackException) {
|
||||
super.onPlayerError(error)
|
||||
Log.d(TAG, "PlayerError occurred: ${error.errorCodeName}")
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.michatec.radio.dialogs.PresetSelectionDialog
|
||||
import com.michatec.radio.dialogs.ThemeSelectionDialog
|
||||
import com.michatec.radio.dialogs.YesNoDialog
|
||||
import com.michatec.radio.helpers.*
|
||||
import android.content.pm.PackageManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -38,6 +39,15 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
|
||||
/* Define log tag */
|
||||
private val TAG: String = SettingsFragment::class.java.simpleName
|
||||
|
||||
// Check if the device running the app is an Android TV instance
|
||||
private val isAndroidTV: Boolean by lazy {
|
||||
context?.packageManager?.hasSystemFeature(PackageManager.FEATURE_LEANBACK) == true
|
||||
}
|
||||
|
||||
private fun isPermissionGranted(context: Context, permission: String): Boolean {
|
||||
return context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
/* Overrides onViewCreated from PreferenceFragmentCompat */
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
@@ -149,7 +159,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
|
||||
|
||||
|
||||
// set up "Buffer Size" preference
|
||||
val preferenceBufferSize = SwitchPreferenceCompat(activity as Context)
|
||||
val preferenceBufferSize = MarqueeSwitchPreference(context)
|
||||
preferenceBufferSize.title = getString(R.string.pref_buffer_size_title)
|
||||
preferenceBufferSize.setIcon(R.drawable.ic_network_check_24dp)
|
||||
preferenceBufferSize.key = Keys.PREF_LARGE_BUFFER_SIZE
|
||||
@@ -159,7 +169,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
|
||||
|
||||
|
||||
// set up "Edit Stream Address" preference
|
||||
val preferenceEnableEditingStreamUri = SwitchPreferenceCompat(activity as Context)
|
||||
val preferenceEnableEditingStreamUri = MarqueeSwitchPreference(context)
|
||||
preferenceEnableEditingStreamUri.title = getString(R.string.pref_edit_station_stream_title)
|
||||
preferenceEnableEditingStreamUri.setIcon(R.drawable.ic_music_note_24dp)
|
||||
preferenceEnableEditingStreamUri.key = Keys.PREF_EDIT_STREAMS_URIS
|
||||
@@ -174,7 +184,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
|
||||
|
||||
|
||||
// set up "Edit Stations" preference
|
||||
val preferenceEnableEditingGeneral = SwitchPreferenceCompat(activity as Context)
|
||||
val preferenceEnableEditingGeneral = MarqueeSwitchPreference(context)
|
||||
preferenceEnableEditingGeneral.title = getString(R.string.pref_edit_station_title)
|
||||
preferenceEnableEditingGeneral.setIcon(R.drawable.ic_edit_24dp)
|
||||
preferenceEnableEditingGeneral.key = Keys.PREF_EDIT_STATIONS
|
||||
@@ -255,6 +265,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
// set up "Visualizer" preference entry
|
||||
val preferenceVisualizer = Preference(context)
|
||||
preferenceVisualizer.title = getString(R.string.pref_visualizer_title)
|
||||
preferenceVisualizer.setIcon(R.drawable.ic_visualizer_24dp)
|
||||
@@ -309,6 +320,38 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
// set up "Test Notification" preference
|
||||
val preferenceTestNotification = Preference(context)
|
||||
preferenceTestNotification.title = getString(R.string.pref_test_notification_title)
|
||||
preferenceTestNotification.setIcon(R.drawable.ic_notification_app_icon_24dp)
|
||||
preferenceTestNotification.summary = getString(R.string.pref_test_notification_summary)
|
||||
preferenceTestNotification.setOnPreferenceClickListener {
|
||||
// show test notification
|
||||
NotificationSys.showNotification(
|
||||
context,
|
||||
getString(R.string.pref_test_notification_title),
|
||||
getString(R.string.notification_test_content),
|
||||
id = 1004
|
||||
)
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
// set up "Security" preference
|
||||
val preferenceSecurity = Preference(context)
|
||||
preferenceSecurity.title = getString(R.string.pref_security_title)
|
||||
preferenceSecurity.setIcon(R.drawable.ic_security_24dp)
|
||||
preferenceSecurity.summary = getString(R.string.pref_security_summary)
|
||||
preferenceSecurity.setOnPreferenceClickListener {
|
||||
// open web browser
|
||||
val intent = Intent().apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
data = "https://github.com/michatec/Radio/blob/master/SECURITY.md".toUri()
|
||||
}
|
||||
startActivity(intent)
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
// set up "Language Selection" preference
|
||||
val preferenceLanguageSelection = Preference(context)
|
||||
preferenceLanguageSelection.title = getString(R.string.pref_language_selection_title)
|
||||
preferenceLanguageSelection.setIcon(R.drawable.ic_language_24dp)
|
||||
@@ -321,6 +364,62 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
// set up "Custom Theme" preference
|
||||
val preferenceCustomTheme = Preference(context)
|
||||
preferenceCustomTheme.title = getString(R.string.pref_custom_theme_title)
|
||||
preferenceCustomTheme.setIcon(R.drawable.ic_rbrush_24dp)
|
||||
preferenceCustomTheme.summary = getString(R.string.pref_custom_theme_summary)
|
||||
preferenceCustomTheme.isEnabled = PreferencesHelper.loadCustomThemeEnabled()
|
||||
preferenceCustomTheme.setOnPreferenceClickListener {
|
||||
findNavController().navigate(R.id.action_settings_to_cstheme)
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
// set up "Custom Theme Enabled" preference
|
||||
val preferenceCustomThemeEnabled = MarqueeSwitchPreference(context)
|
||||
preferenceCustomThemeEnabled.title = getString(R.string.pref_custom_theme_enabled_title)
|
||||
preferenceCustomThemeEnabled.setIcon(R.drawable.ic_rbrush_24dp)
|
||||
preferenceCustomThemeEnabled.summaryOn = getString(R.string.pref_custom_theme_enabled_summary)
|
||||
preferenceCustomThemeEnabled.summaryOff = getString(R.string.pref_custom_theme_disabled_summary)
|
||||
preferenceCustomThemeEnabled.key = Keys.PREF_CUSTOM_THEME_ENABLED
|
||||
preferenceCustomThemeEnabled.setDefaultValue(PreferencesHelper.loadCustomThemeEnabled())
|
||||
preferenceCustomThemeEnabled.setOnPreferenceChangeListener { _, newValue ->
|
||||
when (newValue) {
|
||||
true -> {
|
||||
// enable custom theme
|
||||
preferenceCustomTheme.isEnabled = true
|
||||
}
|
||||
false -> {
|
||||
// disable custom theme
|
||||
preferenceCustomTheme.isEnabled = false
|
||||
}
|
||||
}
|
||||
return@setOnPreferenceChangeListener true
|
||||
}
|
||||
|
||||
// set up "Share the App" preference
|
||||
val preferenceShareApp = Preference(context)
|
||||
preferenceShareApp.title = getString(R.string.pref_share_app_title)
|
||||
preferenceShareApp.setIcon(R.drawable.ic_share_24dp)
|
||||
preferenceShareApp.summary = getString(R.string.pref_share_app_summary)
|
||||
preferenceShareApp.setOnPreferenceClickListener {
|
||||
val shareIntent = Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
type = "text/plain"
|
||||
putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.app_name))
|
||||
putExtra(Intent.EXTRA_TEXT, getString(R.string.pref_share_app_share_text))
|
||||
}
|
||||
startActivity(shareIntent)
|
||||
if (!isAndroidTV && isPermissionGranted(activity as Context, android.Manifest.permission.POST_NOTIFICATIONS)) {
|
||||
NotificationSys.showNotification(
|
||||
context,
|
||||
getString(R.string.pref_share_app_thank_title),
|
||||
getString(R.string.pref_share_app_thank_message),
|
||||
id = 1003
|
||||
)
|
||||
}
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
// set preference categories
|
||||
val preferenceCategoryGeneral = PreferenceCategory(activity as Context)
|
||||
@@ -344,10 +443,17 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
|
||||
|
||||
// setup preference screen
|
||||
screen.addPreference(preferenceAppVersion)
|
||||
screen.addPreference(preferenceShareApp)
|
||||
|
||||
screen.addPreference(preferenceCategoryGeneral)
|
||||
preferenceCategoryGeneral.addPreference(preferenceThemeSelection)
|
||||
preferenceCategoryGeneral.addPreference(preferenceLanguageSelection)
|
||||
preferenceCategoryGeneral.addPreference(preferenceCustomThemeEnabled)
|
||||
preferenceCategoryGeneral.addPreference(preferenceCustomTheme)
|
||||
|
||||
if (!isAndroidTV && isPermissionGranted(activity as Context, android.Manifest.permission.POST_NOTIFICATIONS)) {
|
||||
preferenceCategoryGeneral.addPreference(preferenceTestNotification)
|
||||
}
|
||||
|
||||
screen.addPreference(preferenceCategoryAudioEffects)
|
||||
preferenceCategoryAudioEffects.addPreference(preferenceBassBoost)
|
||||
@@ -375,6 +481,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
|
||||
screen.addPreference(preferenceCategoryLinks)
|
||||
preferenceCategoryLinks.addPreference(preferenceGitHub)
|
||||
preferenceCategoryLinks.addPreference(preferenceLicense)
|
||||
preferenceCategoryLinks.addPreference(preferenceSecurity)
|
||||
|
||||
preferenceScreen = screen
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ class LanguageSelectionDialog(private var languageSelectionDialogListener: Langu
|
||||
Language("de", R.string.pref_language_de),
|
||||
Language("fr", R.string.pref_language_fr),
|
||||
Language("ru", R.string.pref_language_ru),
|
||||
Language("uk", R.string.pref_language_uk),
|
||||
Language("ja", R.string.pref_language_ja),
|
||||
Language("nl", R.string.pref_language_nl),
|
||||
Language("pl", R.string.pref_language_pl),
|
||||
|
||||
@@ -11,6 +11,7 @@ import android.widget.FrameLayout
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import com.michatec.radio.R
|
||||
import androidx.core.view.isEmpty
|
||||
|
||||
class ExtrasHelper {
|
||||
companion object {
|
||||
@@ -69,7 +70,7 @@ class ExtrasHelper {
|
||||
if (currentParent != container) {
|
||||
currentParent?.removeView(visualizerView)
|
||||
// If we injected into a standard preference, don't clear everything, just add
|
||||
if (container is FrameLayout || container.childCount == 0) {
|
||||
if (container is FrameLayout || container.isEmpty()) {
|
||||
container.removeAllViews()
|
||||
}
|
||||
container.addView(visualizerView)
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.michatec.radio.helpers
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.util.Log
|
||||
import com.michatec.radio.R
|
||||
import java.util.Locale
|
||||
|
||||
@@ -16,7 +16,7 @@ class MarqueeSwitchPreference(context: Context) : SwitchPreferenceCompat(context
|
||||
val title = holder.findViewById(android.R.id.title) as? TextView
|
||||
title?.apply {
|
||||
ellipsize = TextUtils.TruncateAt.MARQUEE
|
||||
setSingleLine(true)
|
||||
isSingleLine = true
|
||||
marqueeRepeatLimit = -1 // Repeat indefinitely
|
||||
isSelected = true // Required for marquee to start
|
||||
setHorizontallyScrolling(true)
|
||||
|
||||
@@ -4,12 +4,14 @@ import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.PackageManager
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.gson.Gson
|
||||
import com.michatec.radio.Keys
|
||||
import com.michatec.radio.ui.PlayerState
|
||||
import java.util.*
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
||||
|
||||
/*
|
||||
@@ -362,4 +364,33 @@ object PreferencesHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/* Loads custom theme color */
|
||||
fun loadCustomThemeColor(context: Context): Int {
|
||||
val typedValue = TypedValue()
|
||||
context.theme.resolveAttribute(android.R.attr.colorBackground, typedValue, true)
|
||||
return sharedPreferences.getInt(Keys.PREF_CUSTOM_THEME_COLOR, typedValue.data)
|
||||
}
|
||||
|
||||
/* Saves custom theme color */
|
||||
fun saveCustomThemeColor(color: Int) {
|
||||
sharedPreferences.edit { putInt(Keys.PREF_CUSTOM_THEME_COLOR, color) }
|
||||
}
|
||||
|
||||
/* Loads custom theme index (predefined color index) */
|
||||
fun loadCustomThemeIndex(): Int {
|
||||
return sharedPreferences.getInt(Keys.PREF_CUSTOM_THEME_INDEX, -1)
|
||||
}
|
||||
|
||||
/* Saves custom theme color and index together */
|
||||
fun saveCustomTheme(color: Int, index: Int) {
|
||||
sharedPreferences.edit {
|
||||
putInt(Keys.PREF_CUSTOM_THEME_COLOR, color)
|
||||
putInt(Keys.PREF_CUSTOM_THEME_INDEX, index)
|
||||
}
|
||||
}
|
||||
|
||||
/* Loads whether custom theme is enabled */
|
||||
fun loadCustomThemeEnabled(): Boolean {
|
||||
return sharedPreferences.getBoolean(Keys.PREF_CUSTOM_THEME_ENABLED, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.michatec.radio.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import androidx.core.graphics.toColorInt
|
||||
|
||||
object ThemeHelper {
|
||||
fun getPredefinedColors(context: Context): List<Int> {
|
||||
val isDarkMode = (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
|
||||
return if (isDarkMode) {
|
||||
// Darker colors for dark mode background
|
||||
listOf(
|
||||
"#FF1D3E66".toColorInt(), // Default Dark
|
||||
"#FF3E1D1D".toColorInt(), // Red Dark
|
||||
"#FF1D3E3E".toColorInt(), // Teal Dark
|
||||
"#FF3E1D2E".toColorInt(), // Pink Dark
|
||||
"#FF001A33".toColorInt(), // Dark Blue Dark
|
||||
"#FF1D3E1D".toColorInt(), // Green Dark
|
||||
"#FF3E2E1D".toColorInt(), // Orange Dark
|
||||
"#FF2E1D1D".toColorInt(), // Brown Dark
|
||||
"#FF1D242E".toColorInt(), // Blue Grey Dark
|
||||
"#FF000000".toColorInt() // Black
|
||||
)
|
||||
} else {
|
||||
// Lighter colors for light mode background
|
||||
listOf(
|
||||
"#FFDAE2FF".toColorInt(), // Light Default
|
||||
"#FFFF897D".toColorInt(), // Light Red
|
||||
"#FF4DB6AC".toColorInt(), // Light Teal
|
||||
"#FFF48FB1".toColorInt(), // Light Pink
|
||||
"#FF90CAF9".toColorInt(), // Light Blue
|
||||
"#FFA5D6A7".toColorInt(), // Light Green
|
||||
"#FFFFAB91".toColorInt(), // Light Orange
|
||||
"#FFBCAAA4".toColorInt(), // Light Brown
|
||||
"#FFB0BEC5".toColorInt(), // Light Blue Grey
|
||||
"#FFFFFFFF".toColorInt() // White
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,7 +171,7 @@ class SearchResultAdapter(
|
||||
context: Context,
|
||||
enableFloatOutput: Boolean,
|
||||
enableAudioTrackPlaybackParams: Boolean
|
||||
): AudioSink? {
|
||||
): AudioSink {
|
||||
return DefaultAudioSink.Builder(context)
|
||||
.setAudioProcessors(arrayOf(nativeAudioProcessor))
|
||||
.build()
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.drawable.AnimatedVectorDrawable
|
||||
import java.util.Locale
|
||||
import android.view.View
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
@@ -31,7 +30,9 @@ import com.michatec.radio.core.Station
|
||||
import com.michatec.radio.helpers.DateTimeHelper
|
||||
import com.michatec.radio.helpers.ImageHelper
|
||||
import com.michatec.radio.helpers.PreferencesHelper
|
||||
import com.michatec.radio.helpers.ThemeHelper
|
||||
import com.michatec.radio.helpers.UiHelper
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
/*
|
||||
@@ -42,7 +43,7 @@ data class LayoutHolder(var rootView: View) {
|
||||
/* Main class variables */
|
||||
var recyclerView: RecyclerView = rootView.findViewById(R.id.station_list)
|
||||
val layoutManager: LinearLayoutManager
|
||||
private var bottomSheet: ConstraintLayout? = rootView.findViewById(R.id.bottom_sheet)
|
||||
var bottomSheet: ConstraintLayout? = rootView.findViewById(R.id.bottom_sheet)
|
||||
|
||||
//private var sheetMetadataViews: Group
|
||||
private var sleepTimerRunningViews: Group? = rootView.findViewById(R.id.sleep_timer_running_views)
|
||||
@@ -122,6 +123,9 @@ data class LayoutHolder(var rootView: View) {
|
||||
CastButtonFactory.setUpMediaRouteButton(rootView.context, it)
|
||||
}
|
||||
|
||||
// Apply custom theme color
|
||||
applyCustomTheme(rootView.context)
|
||||
|
||||
// set layout for player
|
||||
setupBottomSheet()
|
||||
}
|
||||
@@ -182,6 +186,9 @@ data class LayoutHolder(var rootView: View) {
|
||||
// update bitrate
|
||||
sheetBitrateView?.text = bitrateText
|
||||
|
||||
// update custom theme
|
||||
applyCustomTheme(context)
|
||||
|
||||
// update click listeners
|
||||
sheetStreamingLinkHeadline?.setOnClickListener {
|
||||
copyToClipboard(
|
||||
@@ -309,6 +316,28 @@ data class LayoutHolder(var rootView: View) {
|
||||
isBuffering = buffering
|
||||
}
|
||||
|
||||
/* Applies custom theme color to the UI */
|
||||
fun applyCustomTheme(context: Context) {
|
||||
val enabled = PreferencesHelper.loadCustomThemeEnabled()
|
||||
if (enabled) {
|
||||
var customColor = PreferencesHelper.loadCustomThemeColor(context)
|
||||
val index = PreferencesHelper.loadCustomThemeIndex()
|
||||
|
||||
if (index != -1) {
|
||||
val colors = ThemeHelper.getPredefinedColors(context)
|
||||
if (index < colors.size) {
|
||||
customColor = colors[index]
|
||||
}
|
||||
}
|
||||
|
||||
rootView.setBackgroundColor(customColor)
|
||||
recyclerView.setBackgroundColor(customColor)
|
||||
} else {
|
||||
rootView.setBackgroundResource(android.R.color.transparent)
|
||||
recyclerView.setBackgroundResource(android.R.color.transparent)
|
||||
}
|
||||
}
|
||||
|
||||
/* Toggles visibility of the download progress indicator */
|
||||
fun toggleDownloadProgressIndicator() {
|
||||
when (PreferencesHelper.loadActiveDownloads()) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24"
|
||||
android:width="24dp">
|
||||
<path
|
||||
android:fillColor="@color/icon_default"
|
||||
android:pathData="M7,14c-1.66,0 -3,1.34 -3,3 0,1.31 -1.16,2 -2,2 0.92,1.22 2.49,2 4,2 2.21,0 4,-1.79 4,-4 0,-1.66 -1.34,-3 -3,-3zM20.71,4.63l-1.34,-1.34c-0.39,-0.39 -1.02,-0.39 -1.41,0L9,12.25 11.75,15l8.96,-8.96c0.39,-0.39 0.39,-1.02 0,-1.41z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="@color/icon_default"
|
||||
android:pathData="M12,1L3,5v6c0,5.55 3.84,10.74 9,12c5.16-1.26 9-6.45 9-12V5l-9,-4z"/>
|
||||
</vector>
|
||||
@@ -4,6 +4,6 @@
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@color/player_sheet_icon"
|
||||
android:fillColor="@color/icon_default"
|
||||
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92s2.92,-1.31 2.92,-2.92 -1.31,-2.92 -2.92,-2.92z" />
|
||||
</vector>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Highlight when focused (TV navigation) -->
|
||||
<item android:state_focused="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#44888888" />
|
||||
<stroke android:width="3dp" android:color="?attr/colorPrimary" />
|
||||
<corners android:radius="12dp" />
|
||||
</shape>
|
||||
</item>
|
||||
<!-- Highlight when selected (Active color) -->
|
||||
<item android:state_selected="true">
|
||||
<shape android:shape="rectangle">
|
||||
<stroke android:width="3dp" android:color="?attr/colorSecondary" />
|
||||
<corners android:radius="12dp" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:drawable="@android:color/transparent" />
|
||||
</selector>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="@android:color/white" />
|
||||
<stroke android:width="2dp" android:color="#CCCCCC" />
|
||||
</shape>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<stroke android:width="3dp" android:color="#000000" />
|
||||
<padding android:bottom="8dp" android:left="8dp" android:right="8dp" android:top="8dp" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent"
|
||||
android:orientation="horizontal"
|
||||
android:padding="24dp">
|
||||
|
||||
<!-- LEFT SIDE: CONTROLS -->
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1.5">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/predefined_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/theme_predefined_colors"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleLarge" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/color_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:spanCount="5"
|
||||
tools:listitem="@layout/element_color_circle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/custom_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="@string/theme_custom_rgb"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleLarge" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/rgb_controls"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/shape_rgb_controls_border"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/red_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/theme_red"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seek_red"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:max="255"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/green_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/theme_green"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seek_green"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:max="255"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/blue_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/theme_blue"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seek_blue"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:max="255"
|
||||
android:focusable="true" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<!-- RIGHT SIDE: PREVIEW & APPLY -->
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/shape_rgb_controls_border">
|
||||
|
||||
<View
|
||||
android:id="@+id/color_preview"
|
||||
android:layout_width="180dp"
|
||||
android:layout_height="180dp"
|
||||
android:background="@android:color/black" />
|
||||
</FrameLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/hex_input_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/hex_code"
|
||||
android:layout_width="160dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:inputType="textCapCharacters"
|
||||
android:maxLength="9"
|
||||
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
|
||||
tools:text="#FF000000" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -2,9 +2,11 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:attr/colorBackground"
|
||||
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_margin="4dp"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:background="@drawable/selector_color_circle">
|
||||
|
||||
<View
|
||||
android:id="@+id/color_circle"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/shape_color_circle" />
|
||||
|
||||
</FrameLayout>
|
||||
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="16dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/predefined_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/theme_predefined_colors"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/color_recycler_view"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/color_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/predefined_label"
|
||||
tools:listitem="@layout/element_color_circle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/custom_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/theme_custom_rgb"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/color_recycler_view" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/rgb_controls"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/shape_rgb_controls_border"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/custom_label">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/red_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/theme_red" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seek_red"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="255"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/green_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/theme_green" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seek_green"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="255"
|
||||
android:focusable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/blue_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/theme_blue" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seek_blue"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="255"
|
||||
android:focusable="true" />
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/color_preview_border"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:background="@drawable/shape_rgb_controls_border"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/rgb_controls">
|
||||
|
||||
<View
|
||||
android:id="@+id/color_preview"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:background="@android:color/black" />
|
||||
</FrameLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/hex_input_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/color_preview_border">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/hex_code"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:inputType="textCapCharacters"
|
||||
android:maxLength="9"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
tools:text="#FF000000" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
@@ -32,6 +32,9 @@
|
||||
<action
|
||||
android:id="@+id/action_settings_to_visualizer"
|
||||
app:destination="@id/visualizer_destination" />
|
||||
<action
|
||||
android:id="@+id/action_settings_to_cstheme"
|
||||
app:destination="@id/custom_theme_destination" />
|
||||
</fragment>
|
||||
|
||||
<!-- EQUALIZER -->
|
||||
@@ -52,4 +55,11 @@
|
||||
android:name="com.michatec.radio.AddStationFragment"
|
||||
android:label="Add Station"
|
||||
tools:layout="@layout/dialog_find_station" />
|
||||
|
||||
<!-- CUSTOM THEME -->
|
||||
<fragment
|
||||
android:id="@+id/custom_theme_destination"
|
||||
android:name="com.michatec.radio.CustomThemeFragment"
|
||||
android:label="Custom Theme"
|
||||
tools:layout="@layout/fragment_custom_theme" />
|
||||
</navigation>
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<string name="notification_stop">Stop</string>
|
||||
<string name="notification_skip_to_previous">Forrige</string>
|
||||
<string name="notification_skip_to_next">Næste</string>
|
||||
<string name="notification_test_content">Dette er en testmeddelelse.</string>
|
||||
<string name="notification_channel_description">Alle meddelelser om app’en.</string>
|
||||
<!-- Onboarding -->
|
||||
<string name="onboarding_app_description">Fordyb dig i lyden du elsker!</string>
|
||||
<string name="onboarding_app_get_started">Kom i gang</string>
|
||||
@@ -84,6 +86,8 @@
|
||||
<string name="pref_theme_selection_title">App-tema</string>
|
||||
<string name="pref_update_station_images_summary">Download nyeste stationsbilleder.</string>
|
||||
<string name="pref_update_station_images_title">Opdater stationsbilleder</string>
|
||||
<string name="pref_test_notification_title">Testmeddelelse</string>
|
||||
<string name="pref_test_notification_summary">Test om meddelelsessystemet virker.</string>
|
||||
<!-- App-genveje -->
|
||||
<string name="shortcut_last_station_disabled_message">Genvej til seneste station er deaktiveret.</string>
|
||||
<string name="shortcut_last_station_long_label">Afspil seneste station</string>
|
||||
@@ -111,6 +115,7 @@
|
||||
<!-- Snackbars -->
|
||||
<string name="snackbar_show">Vis</string>
|
||||
<string name="snackbar_update_available">er tilgængelig!</string>
|
||||
<string name="snackbar_failed_permission_notification">Kunne ikke anmode om meddelelsestilladelse.</string>
|
||||
<!-- Language Selection -->
|
||||
<string name="pref_language_selection_title">Sprog</string>
|
||||
<string name="pref_language_selection_summary">Aktuelt sprog</string>
|
||||
@@ -123,6 +128,8 @@
|
||||
<string name="pref_audio_effects_title">Lydeffekter</string>
|
||||
<string name="pref_bass_boost_title">Bas-forstærkning</string>
|
||||
<string name="pref_bass_boost_summary">Øg basforstærkningen.</string>
|
||||
<string name="pref_security_title">Sikkerhed</string>
|
||||
<string name="pref_security_summary">Lær mere om sikkerheden for denne applikation</string>
|
||||
<string name="pref_reverb_title">Hall</string>
|
||||
<string name="pref_reverb_summary">Juster hall-blanding.</string>
|
||||
<string name="pref_drc_title">Dynamisk rækkeviddekomprimering</string>
|
||||
@@ -152,4 +159,23 @@
|
||||
<string name="media_route_menu_title">Cast</string>
|
||||
<string name="pref_visualizer_title">Spektrumanalysator</string>
|
||||
<string name="pref_visualizer_summary">Vis spektrumanalysatoren.</string>
|
||||
|
||||
<string name="pref_share_app_title">Del app</string>
|
||||
<string name="pref_share_app_summary">Anbefal denne app til en ven.</string>
|
||||
<string name="pref_share_app_share_text">Tjek denne fantastiske radio-app ud: https://github.com/michatec/Radio</string>
|
||||
<string name="pref_share_app_thank_title">Tak skal du have!</string>
|
||||
<string name="pref_share_app_thank_message">En stor tak til dig fra udviklerne.</string>
|
||||
|
||||
<!-- Custom Theme -->
|
||||
<string name="pref_custom_theme_enabled_summary">Aktiverer fanen for brugerdefineret tema.</string>
|
||||
<string name="pref_custom_theme_disabled_summary">Deaktiverer fanen for brugerdefineret tema.</string>
|
||||
<string name="pref_custom_theme_summary">Tilpas applikationens baggrundsfarve.</string>
|
||||
<string name="pref_custom_theme_title">Brugerdefineret tema</string>
|
||||
<string name="pref_custom_theme_enabled_title">Aktiver brugerdefineret tema</string>
|
||||
<string name="theme_predefined_colors">Foruddefinerede farver (Lys/Mørk):</string>
|
||||
<string name="theme_custom_rgb">Brugerdefineret RGB (tilpas venligst til appen):</string>
|
||||
<string name="theme_red">Rød</string>
|
||||
<string name="theme_green">Grøn</string>
|
||||
<string name="theme_blue">Blå</string>
|
||||
<string name="hex_code">Hex-kode</string>
|
||||
</resources>
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<string name="notification_stop">Stopp</string>
|
||||
<string name="notification_skip_to_previous">Zurück</string>
|
||||
<string name="notification_skip_to_next">Nächste</string>
|
||||
<string name="notification_test_content">Dies ist eine Testbenachrichtigung.</string>
|
||||
<string name="notification_channel_description">Alle Benachrichtigungen über die App.</string>
|
||||
<!-- Onboarding -->
|
||||
<string name="onboarding_app_description">Tauche ein in den Sound deiner Wahl!</string>
|
||||
<string name="onboarding_app_get_started">Jetzt starten</string>
|
||||
@@ -93,6 +95,8 @@
|
||||
<string name="pref_theme_selection_title">App-Design</string>
|
||||
<string name="pref_update_station_images_summary">Die neueste Version aller Senderbilder herunterladen.</string>
|
||||
<string name="pref_update_station_images_title">Senderbilder aktualisieren</string>
|
||||
<string name="pref_test_notification_title">Test-Benachrichtigung</string>
|
||||
<string name="pref_test_notification_summary">Testen, ob das Benachrichtigungssystem funktioniert.</string>
|
||||
<!-- Sample Text -->
|
||||
<!-- App Shortcuts -->
|
||||
<string name="shortcut_last_station_disabled_message">Verknüpfung für Wiedergabe des letzten Senders deaktiviert.</string>
|
||||
@@ -122,10 +126,13 @@
|
||||
<!-- Snackbars -->
|
||||
<string name="snackbar_show">Zeigen</string>
|
||||
<string name="snackbar_update_available">ist verfügbar!</string>
|
||||
<string name="snackbar_failed_permission_notification">Fehler bei der Anfrage nach Benachrichtigungsberechtigung.</string>
|
||||
<string name="pref_audio_effects_title">Audio-Effekte</string>
|
||||
<string name="pref_bass_boost_title">Bass-Boost</string>
|
||||
<string name="pref_bass_boost_summary">Erhöhen Sie die Bassverstärkung.</string>
|
||||
<string name="pref_reverb_title">Hall</string>
|
||||
<string name="pref_security_title">Sicherheit</string>
|
||||
<string name="pref_security_summary">Erfahren Sie mehr über die Sicherheit dieser Anwendung</string>
|
||||
<string name="pref_reverb_summary">Reverb-Mix anpassen.</string>
|
||||
<string name="pref_drc_title">Dynamikkompression</string>
|
||||
<string name="pref_drc_summary">Den Dynamikbereich für eine gleichbleibende Lautstärke komprimieren.</string>
|
||||
@@ -153,5 +160,24 @@
|
||||
<string name="media_route_menu_title">Streamen</string>
|
||||
<string name="pref_visualizer_title">Spektrumanzeige</string>
|
||||
<string name="pref_visualizer_summary">Sehe die Spektrumanzeige.</string>
|
||||
<string name="pref_share_app_title">App teilen</string>
|
||||
<string name="pref_share_app_summary">Empfehle diese App einem Freund.</string>
|
||||
<string name="pref_share_app_share_text">Schau dir diese tolle Radio-App an: https://github.com/michatec/Radio</string>
|
||||
<string name="pref_share_app_thank_title">Vielen Dank!</string>
|
||||
<string name="pref_share_app_thank_message">Ein großes Dankeschön von den Entwicklern.</string>
|
||||
|
||||
<string name="loading">Lade…</string>
|
||||
|
||||
<!-- Custom Theme -->
|
||||
<string name="pref_custom_theme_enabled_summary">Aktiviert den Tab für das benutzerdefinierte Design.</string>
|
||||
<string name="pref_custom_theme_disabled_summary">Deaktiviert den Tab für das benutzerdefinierte Design.</string>
|
||||
<string name="pref_custom_theme_summary">Passen Sie die Hintergrundfarbe der Anwendung an.</string>
|
||||
<string name="pref_custom_theme_title">Benutzerdefiniertes Design</string>
|
||||
<string name="pref_custom_theme_enabled_title">Benutzerdefiniertes Design aktivieren</string>
|
||||
<string name="theme_predefined_colors">Vordefinierte Farben (Hell/Dunkel):</string>
|
||||
<string name="theme_custom_rgb">Benutzerdefiniertes RGB (bitte an die App anpassen):</string>
|
||||
<string name="theme_red">Rot</string>
|
||||
<string name="theme_green">Grün</string>
|
||||
<string name="theme_blue">Blau</string>
|
||||
<string name="hex_code">Hex-Code</string>
|
||||
</resources>
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<string name="notification_stop">Διακοπή</string>
|
||||
<string name="notification_skip_to_previous">Προηγούμενο</string>
|
||||
<string name="notification_skip_to_next">Επόμενο</string>
|
||||
<string name="notification_test_content">Αυτή είναι μια δοκιμαστική ειδοποίηση.</string>
|
||||
<string name="notification_channel_description">Όλες οι ειδοποιήσεις σχετικά με την εφαρμογή.</string>
|
||||
<!-- Onboarding -->
|
||||
<string name="onboarding_app_description">Βυθιστείτε στον ήχο της επιλογής σας!</string>
|
||||
<string name="onboarding_app_get_started">Ας ξεκινήσουμε</string>
|
||||
@@ -84,6 +86,8 @@
|
||||
<string name="pref_theme_selection_title">Θέμα Εφαρμογής</string>
|
||||
<string name="pref_update_station_images_summary">Κατεβάστε την τελευταία έκδοση των εικόνων όλων των σταθμών.</string>
|
||||
<string name="pref_update_station_images_title">Ενημέρωση Εικόνων Σταθμών</string>
|
||||
<string name="pref_test_notification_title">Δοκιμαστική Ειδοποίηση</string>
|
||||
<string name="pref_test_notification_summary">Έλεγχος αν το σύστημα ειδοποιήσεων λειτουργεί.</string>
|
||||
<!-- Sample Text -->
|
||||
<!-- App Shortcuts -->
|
||||
<string name="shortcut_last_station_disabled_message">Η συντόμευση για την αναπαραγωγή του τελευταίου σταθμού έχει απενεργοποιηθεί.</string>
|
||||
@@ -113,6 +117,7 @@
|
||||
<!-- Snackbars -->
|
||||
<string name="snackbar_show">Εμφάνισε</string>
|
||||
<string name="snackbar_update_available">είναι διαθέσιμη!</string>
|
||||
<string name="snackbar_failed_permission_notification">Απέτυχε η αίτηση δικαιώματος ειδοποίησης.</string>
|
||||
<!-- Language Selection -->
|
||||
<string name="pref_language_selection_title">Γλώσσα</string>
|
||||
<string name="pref_language_selection_summary">Τρέχουσα γλώσσα</string>
|
||||
@@ -123,6 +128,8 @@
|
||||
<string name="dialog_yes_no_message_update_collection">Κατεβάστε την τελευταία έκδοση όλων των σταθμών;</string>
|
||||
<string name="dialog_yes_no_positive_button_update_collection">Ενημέρωση</string>
|
||||
<string name="pref_audio_effects_title">Ηχητικά Εφέ</string>
|
||||
<string name="pref_security_title">Ασφάλεια</string>
|
||||
<string name="pref_security_summary">Μάθετε περισσότερα για την ασφάλεια αυτής της εφαρμογής</string>
|
||||
<string name="pref_bass_boost_title">Ενίσχυση Μπάσων</string>
|
||||
<string name="pref_bass_boost_summary">Αύξηση της ενίσχυσης μπάσων.</string>
|
||||
<string name="pref_reverb_title">Αντήχηση</string>
|
||||
@@ -154,4 +161,23 @@
|
||||
<string name="media_route_menu_title">Μετάδοση</string>
|
||||
<string name="pref_visualizer_title">Αναλυτής Φάσματος</string>
|
||||
<string name="pref_visualizer_summary">Εμφάνιση του Αναλυτή Φάσματος.</string>
|
||||
|
||||
<string name="pref_share_app_title">Κοινοποίηση Εφαρμογής</string>
|
||||
<string name="pref_share_app_summary">Προτείνετε αυτήν την εφαρμογή σε έναν φίλο.</string>
|
||||
<string name="pref_share_app_share_text">Δείτε αυτήν την καταπληκτική εφαρμογή ραδιοφώνου: https://github.com/michatec/Radio</string>
|
||||
<string name="pref_share_app_thank_title">Σας ευχαριστούμε!</string>
|
||||
<string name="pref_share_app_thank_message">Ένα μεγάλο ευχαριστώ από τους προγραμματιστές.</string>
|
||||
|
||||
<!-- Custom Theme -->
|
||||
<string name="pref_custom_theme_enabled_summary">Ενεργοποιεί την καρτέλα προσαρμοσμένου θέματος.</string>
|
||||
<string name="pref_custom_theme_disabled_summary">Απενεργοποιεί την καρτέλα προσαρμοσμένου θέματος.</string>
|
||||
<string name="pref_custom_theme_summary">Προσαρμόστε το χρώμα φόντου της εφαρμογής.</string>
|
||||
<string name="pref_custom_theme_title">Προσαρμοσμένο Θέμα</string>
|
||||
<string name="pref_custom_theme_enabled_title">Ενεργοποίηση Προσαρμοσμένου Θέματος</string>
|
||||
<string name="theme_predefined_colors">Προκαθορισμένα Χρώματα (Φωτεινό/Σκοτεινό):</string>
|
||||
<string name="theme_custom_rgb">Προσαρμοσμένο RGB (παρακαλώ προσαρμόστε στην εφαρμογή):</string>
|
||||
<string name="theme_red">Κόκκινο</string>
|
||||
<string name="theme_green">Πράσινο</string>
|
||||
<string name="theme_blue">Μπλε</string>
|
||||
<string name="hex_code">Κωδικός Hex</string>
|
||||
</resources>
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<string name="notification_stop">Arrêt</string>
|
||||
<string name="notification_skip_to_previous">Précédent</string>
|
||||
<string name="notification_skip_to_next">Suivant</string>
|
||||
<string name="notification_test_content">Il s’agit d’une notification de test.</string>
|
||||
<string name="notification_channel_description">Toutes les notifications de l’application.</string>
|
||||
<!-- Onboarding -->
|
||||
<string name="onboarding_app_description">Plongez dans le son de votre choix !</string>
|
||||
<string name="onboarding_app_get_started">Commencer maintenant</string>
|
||||
@@ -84,6 +86,8 @@
|
||||
<string name="pref_theme_selection_title">Thème de lapplication</string>
|
||||
<string name="pref_update_station_images_summary">Télécharger la dernière version de toutes les images des stations.</string>
|
||||
<string name="pref_update_station_images_title">Mettre à jour les images des stations</string>
|
||||
<string name="pref_test_notification_title">Notification de test</string>
|
||||
<string name="pref_test_notification_summary">Tester si le système de notification fonctionne.</string>
|
||||
<!-- Raccourcis de l'app -->
|
||||
<string name="shortcut_last_station_disabled_message">Raccourci pour lire la dernière station désactivé.</string>
|
||||
<string name="shortcut_last_station_long_label">Lire la dernière station</string>
|
||||
@@ -111,6 +115,7 @@
|
||||
<!-- Snackbars -->
|
||||
<string name="snackbar_show">Afficher</string>
|
||||
<string name="snackbar_update_available">est disponible !</string>
|
||||
<string name="snackbar_failed_permission_notification">Échec de la demande d’autorisation de notification.</string>
|
||||
<!-- Language Selection -->
|
||||
<string name="pref_language_selection_title">Langue</string>
|
||||
<string name="pref_language_selection_summary">Langue actuelle</string>
|
||||
@@ -123,6 +128,8 @@
|
||||
<string name="pref_audio_effects_title">Effets Audio</string>
|
||||
<string name="pref_bass_boost_title">Amplification des basses</string>
|
||||
<string name="pref_bass_boost_summary">Augmenter l amplification des basses.</string>
|
||||
<string name="pref_security_title">Sécurité</string>
|
||||
<string name="pref_security_summary">En savoir plus sur la sécurité de cette application</string>
|
||||
<string name="pref_reverb_title">Réverbération</string>
|
||||
<string name="pref_reverb_summary">Ajuster le mix de réverbération.</string>
|
||||
<string name="pref_drc_title">Compression Dynamique</string>
|
||||
@@ -152,4 +159,23 @@
|
||||
<string name="media_route_menu_title">Diffuser</string>
|
||||
<string name="pref_visualizer_title">Analyseur de spectre</string>
|
||||
<string name="pref_visualizer_summary">Afficher l analyseur de spectre.</string>
|
||||
|
||||
<string name="pref_share_app_title">Partager l\'application</string>
|
||||
<string name="pref_share_app_summary">Recommandez cette application à un ami.</string>
|
||||
<string name="pref_share_app_share_text">Découvrez cette super application radio : https://github.com/michatec/Radio</string>
|
||||
<string name="pref_share_app_thank_title">Merci beaucoup !</string>
|
||||
<string name="pref_share_app_thank_message">Un grand merci de la part des développeurs.</string>
|
||||
|
||||
<!-- Custom Theme -->
|
||||
<string name="pref_custom_theme_enabled_summary">Active l\'onglet du thème personnalisé.</string>
|
||||
<string name="pref_custom_theme_disabled_summary">Désactive l\'onglet du thème personnalisé.</string>
|
||||
<string name="pref_custom_theme_summary">Personnalisez la couleur d\'arrière-plan de l\'application.</string>
|
||||
<string name="pref_custom_theme_title">Thème personnalisé</string>
|
||||
<string name="pref_custom_theme_enabled_title">Activer le thème personnalisé</string>
|
||||
<string name="theme_predefined_colors">Couleurs prédéfinies (Clair/Sombre) :</string>
|
||||
<string name="theme_custom_rgb">RGB personnalisé (veuillez l\'adapter à l\'application) :</string>
|
||||
<string name="theme_red">Rouge</string>
|
||||
<string name="theme_green">Vert</string>
|
||||
<string name="theme_blue">Bleu</string>
|
||||
<string name="hex_code">Code Hex</string>
|
||||
</resources>
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<string name="notification_stop">停止</string>
|
||||
<string name="notification_skip_to_previous">前へ</string>
|
||||
<string name="notification_skip_to_next">次へ</string>
|
||||
<string name="notification_test_content">テスト通知です。</string>
|
||||
<string name="notification_channel_description">アプリに関するすべての通知。</string>
|
||||
<!-- オンボーディング -->
|
||||
<string name="onboarding_app_description">お気に入りのサウンドの世界に飛び込もう!</string>
|
||||
<string name="onboarding_app_get_started">今すぐ始める</string>
|
||||
@@ -84,6 +86,8 @@
|
||||
<string name="pref_theme_selection_title">アプリテーマ</string>
|
||||
<string name="pref_update_station_images_summary">すべての局画像を最新に更新します。</string>
|
||||
<string name="pref_update_station_images_title">局画像を更新</string>
|
||||
<string name="pref_test_notification_title">テスト通知</string>
|
||||
<string name="pref_test_notification_summary">通知システムが動作するかテストします。</string>
|
||||
<!-- ショートカット -->
|
||||
<string name="shortcut_last_station_disabled_message">最後に再生した局のショートカットは無効になっています。</string>
|
||||
<string name="shortcut_last_station_long_label">最後の局を再生</string>
|
||||
@@ -112,6 +116,7 @@
|
||||
<!-- スナックバー -->
|
||||
<string name="snackbar_show">表示</string>
|
||||
<string name="snackbar_update_available">が利用可能です!</string>
|
||||
<string name="snackbar_failed_permission_notification">通知の権限リクエストに失敗しました。</string>
|
||||
<!-- 言語選択 -->
|
||||
<string name="pref_language_selection_title">言語</string>
|
||||
<string name="pref_language_selection_summary">現在の言語</string>
|
||||
@@ -123,6 +128,8 @@
|
||||
<string name="dialog_yes_no_positive_button_update_collection">更新</string>
|
||||
<string name="pref_audio_effects_title">オーディオエフェクト</string>
|
||||
<string name="pref_bass_boost_title">バスブースト</string>
|
||||
<string name="pref_security_title">セキュリティ</string>
|
||||
<string name="pref_security_summary">このアプリケーションのセキュリティについて詳しく知る</string>
|
||||
<string name="pref_bass_boost_summary">低音を増強します。</string>
|
||||
<string name="pref_reverb_title">リバーブ</string>
|
||||
<string name="pref_reverb_summary">リバーブミスを調整します。</string>
|
||||
@@ -153,4 +160,23 @@
|
||||
<string name="media_route_menu_title">キャスト</string>
|
||||
<string name="pref_visualizer_title">スペクトラムアナライザー</string>
|
||||
<string name="pref_visualizer_summary">スペクトラムアナライザーを表示します。</string>
|
||||
|
||||
<string name="pref_share_app_title">アプリを共有</string>
|
||||
<string name="pref_share_app_summary">このアプリを友達に勧める。</string>
|
||||
<string name="pref_share_app_share_text">この素晴らしいラジオアプリをチェックしてみてください: https://github.com/michatec/Radio</string>
|
||||
<string name="pref_share_app_thank_title">ありがとうございます!</string>
|
||||
<string name="pref_share_app_thank_message">開発者一同より、心から感謝申し上げます。</string>
|
||||
|
||||
<!-- Custom Theme -->
|
||||
<string name="pref_custom_theme_enabled_summary">カスタムテーマタブを有効にします。</string>
|
||||
<string name="pref_custom_theme_disabled_summary">カスタムテーマタブを無効にします。</string>
|
||||
<string name="pref_custom_theme_summary">アプリケーションの背景色をカスタマイズします。</string>
|
||||
<string name="pref_custom_theme_title">カスタムテーマ</string>
|
||||
<string name="pref_custom_theme_enabled_title">カスタムテーマを有効にする</string>
|
||||
<string name="theme_predefined_colors">事前定義された色(ライト/ダーク):</string>
|
||||
<string name="theme_custom_rgb">カスタムRGB(アプリに合わせて調整してください):</string>
|
||||
<string name="theme_red">赤</string>
|
||||
<string name="theme_green">緑</string>
|
||||
<string name="theme_blue">青</string>
|
||||
<string name="hex_code">Hexコード</string>
|
||||
</resources>
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<string name="notification_stop">Stoppen</string>
|
||||
<string name="notification_skip_to_previous">Vorige</string>
|
||||
<string name="notification_skip_to_next">Volgende</string>
|
||||
<string name="notification_test_content">Dit is een testmelding.</string>
|
||||
<string name="notification_channel_description">Alle meldingen over de app.</string>
|
||||
<!-- Onboarding -->
|
||||
<string name="onboarding_app_description">Dompel jezelf onder in het geluid van je keuze!</string>
|
||||
<string name="onboarding_app_get_started">Aan de slag</string>
|
||||
@@ -84,6 +86,8 @@
|
||||
<string name="pref_theme_selection_title">App Thema</string>
|
||||
<string name="pref_update_station_images_summary">Download de laatste versie van alle zenderafbeeldingen.</string>
|
||||
<string name="pref_update_station_images_title">Update Zenderafbeeldingen</string>
|
||||
<string name="pref_test_notification_title">Testmelding</string>
|
||||
<string name="pref_test_notification_summary">Test of het meldingsysteem werkt.</string>
|
||||
<!-- Sample Text -->
|
||||
<!-- App Shortcuts -->
|
||||
<string name="shortcut_last_station_disabled_message">Snelkoppeling voor het afspelen van de laatste zender uitgeschakeld.</string>
|
||||
@@ -113,6 +117,7 @@
|
||||
<!-- Snackbars -->
|
||||
<string name="snackbar_show">Weergeven</string>
|
||||
<string name="snackbar_update_available">is beschikbaar!</string>
|
||||
<string name="snackbar_failed_permission_notification">Kan notificatierechtiging niet aanvragen.</string>
|
||||
<!-- Language Selection -->
|
||||
<string name="pref_language_selection_title">Taal</string>
|
||||
<string name="pref_language_selection_summary">Huidige taal</string>
|
||||
@@ -123,6 +128,8 @@
|
||||
<string name="dialog_yes_no_message_update_collection">Download de laatste versie van alle zenders?</string>
|
||||
<string name="dialog_yes_no_positive_button_update_collection">Bijwerken</string>
|
||||
<string name="pref_audio_effects_title">Audio Effecten</string>
|
||||
<string name="pref_security_title">Securiteit</string>
|
||||
<string name="pref_security_summary">Meer informatie over de beveiliging van deze toepassing</string>
|
||||
<string name="pref_bass_boost_title">Bass Boost</string>
|
||||
<string name="pref_bass_boost_summary">Verhoog de bassversterking.</string>
|
||||
<string name="pref_reverb_title">Reverb</string>
|
||||
@@ -154,4 +161,23 @@
|
||||
<string name="media_route_menu_title">Cast</string>
|
||||
<string name="pref_visualizer_title">Spectrum Analyser</string>
|
||||
<string name="pref_visualizer_summary">Toon de Spectrum Analyser.</string>
|
||||
|
||||
<string name="pref_share_app_title">App delen</string>
|
||||
<string name="pref_share_app_summary">Beveel deze app aan bij een vriend.</string>
|
||||
<string name="pref_share_app_share_text">Bekijk deze geweldige radio-app: https://github.com/michatec/Radio</string>
|
||||
<string name="pref_share_app_thank_title">Bedankt!</string>
|
||||
<string name="pref_share_app_thank_message">Een groot dankjewel van de ontwikkelaars.</string>
|
||||
|
||||
<!-- Custom Theme -->
|
||||
<string name="pref_custom_theme_enabled_summary">Schakelt het tabblad voor het aangepaste thema in.</string>
|
||||
<string name="pref_custom_theme_disabled_summary">Schakelt het tabblad voor het aangepaste thema uit.</string>
|
||||
<string name="pref_custom_theme_summary">Pas de achtergrondkleur van de applicatie aan.</string>
|
||||
<string name="pref_custom_theme_title">Aangepast Thema</string>
|
||||
<string name="pref_custom_theme_enabled_title">Aangepast Thema Inschakelen</string>
|
||||
<string name="theme_predefined_colors">Vooraf gedefinieerde kleuren (Licht/Donker):</string>
|
||||
<string name="theme_custom_rgb">Aangepaste RGB (pas deze aan de app aan):</string>
|
||||
<string name="theme_red">Rood</string>
|
||||
<string name="theme_green">Groen</string>
|
||||
<string name="theme_blue">Blauw</string>
|
||||
<string name="hex_code">Hex-code</string>
|
||||
</resources>
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<string name="notification_stop">Zatrzymaj</string>
|
||||
<string name="notification_skip_to_previous">Poprzedni</string>
|
||||
<string name="notification_skip_to_next">Następny</string>
|
||||
<string name="notification_test_content">To jest powiadomienie testowe.</string>
|
||||
<string name="notification_channel_description">Wszystkie powiadomienia o aplikacji.</string>
|
||||
<!-- Onboarding -->
|
||||
<string name="onboarding_app_description">Zanurz się w dźwięku swojego wyboru!</string>
|
||||
<string name="onboarding_app_get_started">Zaczynamy</string>
|
||||
@@ -84,6 +86,8 @@
|
||||
<string name="pref_theme_selection_title">Motyw aplikacji</string>
|
||||
<string name="pref_update_station_images_summary">Pobierz najnowszą wersję wszystkich obrazów stacji w swojej kolekcji.</string>
|
||||
<string name="pref_update_station_images_title">Aktualizuj zdjęcia stacji</string>
|
||||
<string name="pref_test_notification_title">Testowe powiadomienie</string>
|
||||
<string name="pref_test_notification_summary">Sprawdź, czy system powiadomień działa.</string>
|
||||
<!-- Sample Text -->
|
||||
<!-- App Shortcuts -->
|
||||
<string name="shortcut_last_station_disabled_message">Skrót do odtwarzania ostatniej stacji jest wyłączony.</string>
|
||||
@@ -113,6 +117,7 @@
|
||||
<!-- Snackbars -->
|
||||
<string name="snackbar_show">Wyświetl</string>
|
||||
<string name="snackbar_update_available">jest dostępna!</string>
|
||||
<string name="snackbar_failed_permission_notification">Nie udało się poprosić o pozwolenie na powiadomienia.</string>
|
||||
<!-- Language Selection -->
|
||||
<string name="pref_language_selection_title">Język</string>
|
||||
<string name="pref_language_selection_summary">Aktualny język</string>
|
||||
@@ -123,6 +128,8 @@
|
||||
<string name="dialog_yes_no_message_update_collection">Pobrać najnowszą wersję wszystkich stacji?</string>
|
||||
<string name="dialog_yes_no_positive_button_update_collection">Aktualizuj</string>
|
||||
<string name="pref_audio_effects_title">Efekty Dźwiękowe</string>
|
||||
<string name="pref_security_title">Bezpieczeństwo</string>
|
||||
<string name="pref_security_summary">Dowiedz się więcej o bezpieczeństwie tej aplikacji</string>
|
||||
<string name="pref_bass_boost_title">Wzmocnienie Basów</string>
|
||||
<string name="pref_bass_boost_summary">Zwiększ wzmocnienie basów.</string>
|
||||
<string name="pref_reverb_title">Pogłos</string>
|
||||
@@ -154,4 +161,23 @@
|
||||
<string name="media_route_menu_title">Przesyłanie</string>
|
||||
<string name="pref_visualizer_title">Analizator Widma</string>
|
||||
<string name="pref_visualizer_summary">Pokaż Analizator Widma.</string>
|
||||
|
||||
<string name="pref_share_app_title">Udostępnij aplikację</string>
|
||||
<string name="pref_share_app_summary">Poleć tę aplikację znajomemu.</string>
|
||||
<string name="pref_share_app_share_text">Sprawdź tę świetną aplikację radiową: https://github.com/michatec/Radio</string>
|
||||
<string name="pref_share_app_thank_title">Dziękujemy!</string>
|
||||
<string name="pref_share_app_thank_message">Wielkie podziękowania od deweloperów.</string>
|
||||
|
||||
<!-- Custom Theme -->
|
||||
<string name="pref_custom_theme_enabled_summary">Włącza kartę motywu niestandardowego.</string>
|
||||
<string name="pref_custom_theme_disabled_summary">Wyłącza kartę motywu niestandardowego.</string>
|
||||
<string name="pref_custom_theme_summary">Dostosuj kolor tła aplikacji.</string>
|
||||
<string name="pref_custom_theme_title">Motyw niestandardowy</string>
|
||||
<string name="pref_custom_theme_enabled_title">Włącz motyw niestandardowy</string>
|
||||
<string name="theme_predefined_colors">Predefiniowane kolory (Jasny/Ciemny):</string>
|
||||
<string name="theme_custom_rgb">Niestandardowy RGB (proszę dostosować do aplikacji):</string>
|
||||
<string name="theme_red">Czerwony</string>
|
||||
<string name="theme_green">Zielony</string>
|
||||
<string name="theme_blue">Niebieski</string>
|
||||
<string name="hex_code">Kod Hex</string>
|
||||
</resources>
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<string name="notification_stop">Остановить</string>
|
||||
<string name="notification_skip_to_previous">Предыдущий</string>
|
||||
<string name="notification_skip_to_next">Следующий</string>
|
||||
<string name="notification_test_content">Это тестовое уведомление.</string>
|
||||
<string name="notification_channel_description">Все уведомления о приложении.</string>
|
||||
<!-- Onboarding -->
|
||||
<string name="onboarding_app_description">Погрузитесь в звук по вашему выбору!</string>
|
||||
<string name="onboarding_app_get_started">Начать</string>
|
||||
@@ -84,6 +86,8 @@
|
||||
<string name="pref_theme_selection_title">Тема приложения</string>
|
||||
<string name="pref_update_station_images_summary">Скачать последнюю версию всех изображений станций.</string>
|
||||
<string name="pref_update_station_images_title">Обновить изображения станций</string>
|
||||
<string name="pref_test_notification_title">Тест уведомления</string>
|
||||
<string name="pref_test_notification_summary">Проверить, работает ли система уведомлений.</string>
|
||||
<!-- Sample Text -->
|
||||
<!-- App Shortcuts -->
|
||||
<string name="shortcut_last_station_disabled_message">Ярлык для воспроизведения последней станции отключён.</string>
|
||||
@@ -113,6 +117,7 @@
|
||||
<!-- Snackbars -->
|
||||
<string name="snackbar_show">Показать</string>
|
||||
<string name="snackbar_update_available">доступно!</string>
|
||||
<string name="snackbar_failed_permission_notification">Не удалось запросить разрешение на уведомления.</string>
|
||||
<!-- Language Selection -->
|
||||
<string name="pref_language_selection_title">Язык</string>
|
||||
<string name="pref_language_selection_summary">Текущий язык</string>
|
||||
@@ -123,6 +128,8 @@
|
||||
<string name="dialog_yes_no_message_update_collection">Скачать последнюю версию всех станций?</string>
|
||||
<string name="dialog_yes_no_positive_button_update_collection">Обновить</string>
|
||||
<string name="pref_audio_effects_title">Звуковые эффекты</string>
|
||||
<string name="pref_security_title">Безопасность</string>
|
||||
<string name="pref_security_summary">Узнать больше о безопасности этого приложения</string>
|
||||
<string name="pref_bass_boost_title">Усиление басов</string>
|
||||
<string name="pref_bass_boost_summary">Увеличить усиление басов.</string>
|
||||
<string name="pref_reverb_title">Реверберация</string>
|
||||
@@ -154,4 +161,23 @@
|
||||
<string name="media_route_menu_title">Трансляция</string>
|
||||
<string name="pref_visualizer_title">Анализатор спектра</string>
|
||||
<string name="pref_visualizer_summary">Показать анализатор спектра.</string>
|
||||
|
||||
<string name="pref_share_app_title">Поделиться приложением</string>
|
||||
<string name="pref_share_app_summary">Рекомендовать это приложение другу.</string>
|
||||
<string name="pref_share_app_share_text">Посмотрите это классное радио-приложение: https://github.com/michatec/Radio</string>
|
||||
<string name="pref_share_app_thank_title">Спасибо!</string>
|
||||
<string name="pref_share_app_thank_message">Большое спасибо от разработчиков.</string>
|
||||
|
||||
<!-- Custom Theme -->
|
||||
<string name="pref_custom_theme_enabled_summary">Включает вкладку пользовательской темы.</string>
|
||||
<string name="pref_custom_theme_disabled_summary">Отключает вкладку пользовательской темы.</string>
|
||||
<string name="pref_custom_theme_summary">Настройка цвета фона приложения.</string>
|
||||
<string name="pref_custom_theme_title">Пользовательская тема</string>
|
||||
<string name="pref_custom_theme_enabled_title">Включить пользовательскую тему</string>
|
||||
<string name="theme_predefined_colors">Предустановленные цвета (Светлые/Темные):</string>
|
||||
<string name="theme_custom_rgb">Пользовательский RGB (пожалуйста, адаптируйте к приложению):</string>
|
||||
<string name="theme_red">Красный</string>
|
||||
<string name="theme_green">Зеленый</string>
|
||||
<string name="theme_blue">Синий</string>
|
||||
<string name="hex_code">Hex-код</string>
|
||||
</resources>
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<string name="notification_stop">Зупинити</string>
|
||||
<string name="notification_skip_to_previous">Попередня</string>
|
||||
<string name="notification_skip_to_next">Наступна</string>
|
||||
<string name="notification_test_content">Це тестове сповіщення.</string>
|
||||
<string name="notification_channel_description">Усі сповіщення про застосунок.</string>
|
||||
<!-- Onboarding -->
|
||||
<string name="onboarding_app_description">Пориньте у звук на ваш вибір!</string>
|
||||
<string name="onboarding_app_get_started">Початок роботи</string>
|
||||
@@ -84,6 +86,8 @@
|
||||
<string name="pref_theme_selection_title">Тема застосунку</string>
|
||||
<string name="pref_update_station_images_summary">Завантажити останню версію всіх зображень станцій.</string>
|
||||
<string name="pref_update_station_images_title">Оновити зображення станцій</string>
|
||||
<string name="pref_test_notification_title">Тестове сповіщення</string>
|
||||
<string name="pref_test_notification_summary">Перевірити, чи працює система сповіщень.</string>
|
||||
<!-- Sample Text -->
|
||||
<!-- App Shortcuts -->
|
||||
<string name="shortcut_last_station_disabled_message">Ярлик для відтворення останньої станції вимкнено.</string>
|
||||
@@ -113,6 +117,7 @@
|
||||
<!-- Snackbars -->
|
||||
<string name="snackbar_show">Показати</string>
|
||||
<string name="snackbar_update_available">доступне!</string>
|
||||
<string name="snackbar_failed_permission_notification">Не вдалося запитати дозвіл на сповіщення.</string>
|
||||
<!-- Language Selection -->
|
||||
<string name="pref_language_selection_title">Мова</string>
|
||||
<string name="pref_language_selection_summary">Поточна мова</string>
|
||||
@@ -123,6 +128,8 @@
|
||||
<string name="dialog_yes_no_message_update_collection">Завантажити останню версію всіх станцій?</string>
|
||||
<string name="dialog_yes_no_positive_button_update_collection">Оновити</string>
|
||||
<string name="pref_audio_effects_title">Звукові ефекти</string>
|
||||
<string name="pref_security_title">Безпека</string>
|
||||
<string name="pref_security_summary">Дізнайтеся більше про безпеку цього додатку</string>
|
||||
<string name="pref_bass_boost_title">Підсилення басів</string>
|
||||
<string name="pref_bass_boost_summary">Збільшити підсилення басів.</string>
|
||||
<string name="pref_reverb_title">Реверберація</string>
|
||||
@@ -154,4 +161,23 @@
|
||||
<string name="media_route_menu_title">Трансляція</string>
|
||||
<string name="pref_visualizer_title">Аналізатор спектру</string>
|
||||
<string name="pref_visualizer_summary">Показати аналізатор спектру.</string>
|
||||
|
||||
<string name="pref_share_app_title">Поділитися застосунком</string>
|
||||
<string name="pref_share_app_summary">Рекомендувати цей застосунок другу.</string>
|
||||
<string name="pref_share_app_share_text">Подивіться на цей чудовий радіозастосунок: https://github.com/michatec/Radio</string>
|
||||
<string name="pref_share_app_thank_title">Дякуємо!</string>
|
||||
<string name="pref_share_app_thank_message">Велике спасибі вам від розробників.</string>
|
||||
|
||||
<!-- Custom Theme -->
|
||||
<string name="pref_custom_theme_enabled_summary">Вмикає вкладку користувацької теми.</string>
|
||||
<string name="pref_custom_theme_disabled_summary">Вимикає вкладку користувацької теми.</string>
|
||||
<string name="pref_custom_theme_summary">Налаштуйте колір фону застосунку.</string>
|
||||
<string name="pref_custom_theme_title">Користувацька тема</string>
|
||||
<string name="pref_custom_theme_enabled_title">Увімкнути користувацьку тему</string>
|
||||
<string name="theme_predefined_colors">Попередньо визначені кольори (Світлі/Темні):</string>
|
||||
<string name="theme_custom_rgb">Власний RGB (будь ласка, адаптуйте до застосунку):</string>
|
||||
<string name="theme_red">Червоний</string>
|
||||
<string name="theme_green">Зелений</string>
|
||||
<string name="theme_blue">Синій</string>
|
||||
<string name="hex_code">Hex-код</string>
|
||||
</resources>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<resources>
|
||||
<!-- App Name -->
|
||||
<string name="app_version_name" translatable="false">\"Red\"</string>
|
||||
<string name="app_name" translatable="false">Radio</string>
|
||||
|
||||
<!-- Accessibility Descriptions -->
|
||||
<string name="descr_app_icon">App icon depicting an old radio</string>
|
||||
@@ -49,6 +50,8 @@
|
||||
<string name="notification_stop">Stop</string>
|
||||
<string name="notification_skip_to_previous">Previous</string>
|
||||
<string name="notification_skip_to_next">Next</string>
|
||||
<string name="notification_test_content">This is a test notification.</string>
|
||||
<string name="notification_channel_description">All notifications about the app.</string>
|
||||
|
||||
<!-- Onboarding -->
|
||||
<string name="onboarding_app_description">Immerse yourself in the sound of your choice!</string>
|
||||
@@ -71,6 +74,7 @@
|
||||
<string name="pref_language_pl" translatable="false">🇵🇱 Polski</string>
|
||||
<string name="pref_language_el" translatable="false">🇬🇷 Ελληνικά</string>
|
||||
<string name="pref_language_da" translatable="false">🇩🇰 Dansk</string>
|
||||
<string name="pref_language_uk" translatable="false">🇺🇦 Українська</string>
|
||||
|
||||
|
||||
<!-- Settings -->
|
||||
@@ -124,6 +128,8 @@
|
||||
<string name="pref_github_summary" translatable="false">github.com/michatec/Radio</string>
|
||||
<string name="pref_license_title">This application is open source</string>
|
||||
<string name="pref_license_summary">Licensed under the GPLv3 License</string>
|
||||
<string name="pref_security_title">Security</string>
|
||||
<string name="pref_security_summary">Learn more about the security of this application</string>
|
||||
<string name="pref_links_title">Links</string>
|
||||
<string name="pref_m3u_export_summary">Save your radio stations to an M3U playlist file that can be imported into other players.</string>
|
||||
<string name="pref_m3u_export_title">Export M3U</string>
|
||||
@@ -141,6 +147,13 @@
|
||||
<string name="pref_theme_selection_title">App Theme</string>
|
||||
<string name="pref_update_station_images_summary">Download latest version of all station images.</string>
|
||||
<string name="pref_update_station_images_title">Update Station Images</string>
|
||||
<string name="pref_test_notification_title">Test Notification</string>
|
||||
<string name="pref_test_notification_summary">Test whether the notification system works.</string>
|
||||
<string name="pref_share_app_title">Share App</string>
|
||||
<string name="pref_share_app_summary">Recommend this app to a friend.</string>
|
||||
<string name="pref_share_app_share_text">Check out this awesome radio app: https://github.com/michatec/Radio</string>
|
||||
<string name="pref_share_app_thank_title">Thank You!</string>
|
||||
<string name="pref_share_app_thank_message">A big thank you to you from the developers.</string>
|
||||
|
||||
<!-- Sample Text -->
|
||||
<string name="sample_text_sleep_timer_remaining_time" translatable="false">00:00</string>
|
||||
@@ -182,12 +195,25 @@
|
||||
<string name="snackbar_update_available">is available!</string>
|
||||
<string name="snackbar_url_app_home_page" translatable="false">https://github.com/michatec/Radio/releases/latest</string>
|
||||
<string name="snackbar_github_update_check_url" translatable="false">https://api.github.com/repos/michatec/Radio/releases/latest</string>
|
||||
<string name="app_name" translatable="false">Radio</string>
|
||||
<string name="icon_launcher" translatable="false">Icon launcher.</string>
|
||||
<string name="snackbar_failed_permission_notification">Failed to request notification permission.</string>
|
||||
|
||||
<!-- Extras -->
|
||||
<string name="loading">Loading…</string>
|
||||
<string name="media_route_menu_title">Cast</string>
|
||||
<string name="pref_visualizer_title">Spectrum Analyzer</string>
|
||||
<string name="pref_visualizer_summary">Show the Spectrum Analyzer.</string>
|
||||
|
||||
<!-- Custom Theme -->
|
||||
<string name="pref_custom_theme_enabled_summary">Enables the custom theme tab.</string>
|
||||
<string name="pref_custom_theme_disabled_summary">Disables the custom theme tab.</string>
|
||||
<string name="pref_custom_theme_summary">Customize the application background color.</string>
|
||||
<string name="pref_custom_theme_title">Custom Theme</string>
|
||||
<string name="pref_custom_theme_enabled_title">Enable Custom Theme</string>
|
||||
<string name="theme_predefined_colors">Predefined Colors (Light/Dark):</string>
|
||||
<string name="theme_custom_rgb">Custom RGB (please adapt to the app):</string>
|
||||
<string name="theme_red">Red</string>
|
||||
<string name="theme_green">Green</string>
|
||||
<string name="theme_blue">Blue</string>
|
||||
<string name="hex_code">Hex Code</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
[versions]
|
||||
activityKtx = "1.13.0"
|
||||
agp = "9.1.1"
|
||||
agp = "9.2.1"
|
||||
coreKtx = "1.18.0"
|
||||
freedroidwarn = "V1.11"
|
||||
gson = "2.13.2"
|
||||
kotlin = "2.3.20"
|
||||
freedroidwarn = "V1.13"
|
||||
gson = "2.14.0"
|
||||
kotlin = "2.3.21"
|
||||
leanback = "1.2.0"
|
||||
material = "1.13.0"
|
||||
material = "1.14.0"
|
||||
material3 = "1.4.0"
|
||||
media = "1.7.1"
|
||||
media3 = "1.10.0"
|
||||
navigation = "2.9.7"
|
||||
media = "1.8.0"
|
||||
media3 = "1.10.1"
|
||||
navigation = "2.9.8"
|
||||
paletteKtx = "1.0.0"
|
||||
preferenceKtx = "1.2.1"
|
||||
volley = "1.2.1"
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+3
-1
@@ -1,7 +1,9 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
|
||||
networkTimeout=10000
|
||||
retries=0
|
||||
retryBackOffMs=500
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
||||
Vendored
+10
-21
@@ -23,8 +23,8 @@
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||
setlocal EnableExtensions
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@@ -51,7 +51,7 @@ echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
@@ -65,7 +65,7 @@ echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
@@ -73,21 +73,10 @@ goto fail
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||
@rem which allows us to clear the local environment before executing the java command
|
||||
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
:exitWithErrorLevel
|
||||
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||
|
||||
@@ -13,6 +13,7 @@ dependencyResolutionManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user