8 Commits

Author SHA1 Message Date
d270574365 refactor(helpers): minor code cleanup and documentation fixes 2026-03-30 15:37:35 +02:00
f96bdc6f07 style(ui): hide loading layout directly 2026-03-30 12:01:37 +02:00
7d63f16c2c chore: cleanup AppThemeHelper and add loading string 2026-03-30 11:34:16 +02:00
47ff40e676 style(ui): remove navigation bar color overrides and redundant v27 styles 2026-03-30 11:12:21 +02:00
dad709f5df feat(ui): implement edge-to-edge support and improve splash transition
- Enable edge-to-edge display in `MainActivity` and handle window insets in `PlayerFragment`.
- Add a fade-out animation when hiding the loading overlay.
- Sync player state with the controller during setup and reset playing state in preferences on service destruction.
- Simplify splash screen drawable and update background color attributes in layout.
- Remove manual navigation bar color overrides.
2026-03-30 11:06:41 +02:00
89b13e152c refactor(ui): improve intent handling and collection view state
- Update `handleStartIntent` and `handleStartPlayer` in `PlayerFragment` to ensure intents are only cleared if successfully handled and stations are valid.
- Refine star icon rendering in `CollectionAdapter` by clearing color filters when appropriate.
- Remove obsolete commented-out code and update log messages in `PlayerFragment`, `PlayerService`, and `LayoutHolder`.
- Uncomment maintenance preference updates in `SettingsFragment`.
- Reformat code for better readability in `CollectionAdapter`.
2026-03-30 10:22:05 +02:00
1eefe1acc4 Merge remote-tracking branch 'origin/main' 2026-03-30 09:18:34 +02:00
1fa8102e1c feat(ui): implement station reordering via DPAD for TV navigation 2026-03-30 09:18:15 +02:00
25 changed files with 163 additions and 133 deletions

View File

@@ -83,11 +83,12 @@ You can help out the radio-browser.info community by [adding the missing station
When **Edit Stations** is enabled:
- Press **← (Left)** on the remote to open the detailed station editing area
- Press **2** or **Back** to close the editing area
- Press **3** or **Back** to close the editing area
**General TV** Controls:
- Press **0** or **DEL** to remove the selected radio station
- Press **1** or **SPACE** to make the selected radio station favourite
- Press **2** or **PLUS** to reorder the selected radio station
</details>

View File

@@ -6,8 +6,10 @@ import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.View
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.view.isVisible
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.NavigationUI
@@ -28,6 +30,7 @@ class MainActivity : AppCompatActivity() {
/* Overrides onCreate from AppCompatActivity */
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
setTheme(R.style.AppTheme)
super.onCreate(savedInstanceState)
@@ -49,11 +52,11 @@ class MainActivity : AppCompatActivity() {
NavigationUI.setupWithNavController(toolbar, navController, appBarConfiguration)
supportActionBar?.hide()
// TV-specific loading logic
// TV-specific loading logic: Hide the overlay once the app is ready
if (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
Handler(Looper.getMainLooper()).postDelayed({
findViewById<View>(R.id.loading_layout)?.visibility = View.GONE
}, 1500)
hideLoadingOverlay()
}, 1200)
} else {
findViewById<View>(R.id.loading_layout)?.visibility = View.GONE
}
@@ -62,6 +65,18 @@ class MainActivity : AppCompatActivity() {
PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener)
}
/* Hides the loading/splash overlay */
private fun hideLoadingOverlay() {
findViewById<View>(R.id.loading_layout)?.let { overlay ->
if (overlay.isVisible) {
overlay.animate()
.alpha(0f)
.setDuration(500)
.withEndAction { overlay.visibility = View.GONE }
}
}
}
/* Overrides onResume from AppCompatActivity */
override fun onResume() {
@@ -75,7 +90,6 @@ class MainActivity : AppCompatActivity() {
/* Overrides onSupportNavigateUp from AppCompatActivity */
override fun onSupportNavigateUp(): Boolean {
// Taken from: https://developer.android.com/guide/navigation/navigation-ui#action_bar
val navHostFragment = supportFragmentManager.findFragmentById(R.id.main_host_container) as NavHostFragment
val navController = navHostFragment.navController
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()

View File

@@ -22,6 +22,9 @@ import androidx.annotation.OptIn
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.media3.common.MediaItem
@@ -167,8 +170,11 @@ class PlayerFragment : Fragment(),
// hide action bar
(activity as AppCompatActivity).supportActionBar?.hide()
// set the same background color of the player sheet for the navigation bar
requireActivity().window.navigationBarColor = ContextCompat.getColor(requireActivity(), R.color.player_sheet_background)
ViewCompat.setOnApplyWindowInsetsListener(layout.rootView) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.updatePadding(bottom = systemBars.bottom)
insets
}
// associate the ItemTouchHelper with the RecyclerView
itemTouchHelper = ItemTouchHelper(ItemTouchHelperCallback())
itemTouchHelper?.attachToRecyclerView(layout.recyclerView)
@@ -242,7 +248,6 @@ class PlayerFragment : Fragment(),
// load player state
playerState = PreferencesHelper.loadPlayerState()
// recreate player ui
// setupPlaybackControls()
updatePlayerViews()
updateStationListState()
togglePeriodicSleepTimerUpdateRequest()
@@ -250,7 +255,7 @@ class PlayerFragment : Fragment(),
observeCollectionViewModel()
// handle navigation arguments
handleNavigationArguments()
// // handle start intent - if started via tap on rss link
// handle start intent - if started via tap on rss link
handleStartIntent()
// start watching for changes in shared preferences
PreferencesHelper.registerPreferenceChangeListener(this as SharedPreferences.OnSharedPreferenceChangeListener)
@@ -405,6 +410,13 @@ class PlayerFragment : Fragment(),
private fun setupController() {
val controller: MediaController = this.controller ?: return
controller.addListener(playerListener)
// Sync local playerState with actual controller state
if (playerState.isPlaying != controller.isPlaying) {
playerState.isPlaying = controller.isPlaying
updatePlayerViews()
}
requestMetadataUpdate()
// handle start intent
handleStartIntent()
@@ -561,15 +573,27 @@ class PlayerFragment : Fragment(),
/* Handles this activity's start intent */
private fun handleStartIntent() {
if ((activity as Activity).intent.action != null) {
when ((activity as Activity).intent.action) {
Keys.ACTION_SHOW_PLAYER -> handleShowPlayer()
Intent.ACTION_VIEW -> handleViewIntent()
Keys.ACTION_START -> handleStartPlayer()
val intent = (activity as Activity).intent
if (intent.action != null && intent.action?.isNotEmpty() == true) {
var handled = false
when (intent.action) {
Keys.ACTION_SHOW_PLAYER -> {
handleShowPlayer()
handled = true
}
Intent.ACTION_VIEW -> {
handleViewIntent()
handled = true
}
Keys.ACTION_START -> {
handled = handleStartPlayer()
}
}
if (handled) {
// clear intent action to prevent double calls
(activity as Activity).intent.action = ""
intent.action = ""
}
}
}
@@ -590,12 +614,12 @@ class PlayerFragment : Fragment(),
val scheme: String = intentUri.scheme ?: String()
// CASE: intent is a web link
if (scheme.startsWith("http")) {
Log.i(TAG, "Transistor was started to handle a web link.")
Log.i(TAG, "Radio was started to handle a web link.")
stationList.addAll(CollectionHelper.createStationsFromUrl(intentUri.toString()))
}
// CASE: intent is a local file
else if (scheme.startsWith("content")) {
Log.i(TAG, "Transistor was started to handle a local audio playlist.")
Log.i(TAG, "Radio was started to handle a local audio playlist.")
stationList.addAll(CollectionHelper.createStationListFromContentUri(activity as Context, intentUri))
}
withContext(Main) {
@@ -612,17 +636,30 @@ class PlayerFragment : Fragment(),
/* Handles START_PLAYER_SERVICE request from App Shortcut */
private fun handleStartPlayer() {
private fun handleStartPlayer(): Boolean {
if (controller == null || collection.stations.isEmpty()) {
return false
}
val intent: Intent = (activity as Activity).intent
if (intent.hasExtra(Keys.EXTRA_START_LAST_PLAYED_STATION)) {
controller?.play(activity as Context, CollectionHelper.getStation(collection, playerState.stationUuid))
val station = CollectionHelper.getStation(collection, playerState.stationUuid)
if (station.isValid()) {
controller?.play(activity as Context, station)
return true
}
} else if (intent.hasExtra(Keys.EXTRA_STATION_UUID)) {
val uuid: String = intent.getStringExtra(Keys.EXTRA_STATION_UUID) ?: String()
controller?.play(activity as Context, CollectionHelper.getStation(collection, uuid))
val station = CollectionHelper.getStation(collection, uuid)
if (station.isValid()) {
controller?.play(activity as Context, station)
return true
}
} else if (intent.hasExtra(Keys.EXTRA_STREAM_URI)) {
val streamUri: String = intent.getStringExtra(Keys.EXTRA_STREAM_URI) ?: String()
controller?.playStreamDirectly(streamUri)
return true
}
return false
}
@@ -640,9 +677,9 @@ class PlayerFragment : Fragment(),
collection = it
// updates current station in player views
playerState = PreferencesHelper.loadPlayerState()
// // get station
// get station
val station: Station = CollectionHelper.getStation(collection, playerState.stationUuid)
// // update player views
// update player views
layout.updatePlayerViews(activity as Context, station, playerState.isPlaying)
// handle start intent
handleStartIntent()

View File

@@ -81,7 +81,8 @@ class PlayerService : MediaLibraryService() {
/* Overrides onDestroy from Service */
override fun onDestroy() {
// player.removeAnalyticsListener(analyticsListener)
// Reset playing state in preferences
PreferencesHelper.saveIsPlaying(false)
player.removeListener(playerListener)
player.release()
mediaLibrarySession.release()
@@ -241,11 +242,6 @@ class PlayerService : MediaLibraryService() {
async(Dispatchers.Default) { FileHelper.readCollectionSuspended(context) }
// wait for result and update collection
collection = deferred.await()
// // special case: trigger metadata view update for stations that have no metadata
// if (player.isPlaying && station.name == getCurrentMetadata()) {
// station = CollectionHelper.getStation(collection, station.uuid)
// updateMetadata(null)
// }
}
}
@@ -429,7 +425,6 @@ class PlayerService : MediaLibraryService() {
currentMediaId,
isPlaying
)
//updatePlayerState(station, playbackState)
if (isPlaying) {
// playback is active
@@ -506,10 +501,6 @@ class PlayerService : MediaLibraryService() {
// try to reconnect every 5 seconds - up to 20 times
if (loadErrorInfo.errorCount <= Keys.DEFAULT_MAX_RECONNECTION_COUNT && loadErrorInfo.exception is HttpDataSource.HttpDataSourceException) {
return Keys.RECONNECTION_WAIT_INTERVAL
// } else {
// CoroutineScope(Main).launch {
// player.stop()
// }
}
return C.TIME_UNSET
}

View File

@@ -21,7 +21,6 @@ import com.michatec.radio.dialogs.ErrorDialog
import com.michatec.radio.dialogs.ThemeSelectionDialog
import com.michatec.radio.dialogs.YesNoDialog
import com.michatec.radio.helpers.*
import com.michatec.radio.helpers.AppThemeHelper.getColor
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
@@ -46,7 +45,6 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
(activity as AppCompatActivity).supportActionBar?.show()
(activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true)
(activity as AppCompatActivity).supportActionBar?.title = getString(R.string.fragment_settings_title)
requireActivity().window.navigationBarColor = getColor(requireContext(), android.R.attr.colorBackground)
}
/* Overrides onCreatePreferences from PreferenceFragmentCompat */
@@ -245,7 +243,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
val preferenceCategoryMaintenance = PreferenceCategory(activity as Context)
preferenceCategoryMaintenance.title = getString(R.string.pref_maintenance_title)
preferenceCategoryMaintenance.contains(preferenceUpdateStationImages)
// preferenceCategoryMaintenance.contains(preferenceUpdateCollection)
preferenceCategoryMaintenance.contains(preferenceUpdateCollection)
val preferenceCategoryImportExport = PreferenceCategory(activity as Context)
preferenceCategoryImportExport.title = getString(R.string.pref_backup_import_export_title)
@@ -549,7 +547,6 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
requestRestoreCollectionLauncher.launch(intent)
} catch (exception: Exception) {
Log.e(TAG, "Unable to open file picker for ZIP.\n$exception")
// Toast.makeText(activity as Context, R.string.toast_message_install_file_helper, Toast.LENGTH_LONG).show()
}
}
}

View File

@@ -3,6 +3,7 @@ package com.michatec.radio.collection
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.content.res.ColorStateList
import android.text.Editable
import android.text.TextWatcher
import android.view.KeyEvent
@@ -14,8 +15,8 @@ import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView
import androidx.constraintlayout.widget.Group
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.core.view.isGone
import androidx.core.view.isVisible
@@ -25,6 +26,7 @@ import androidx.navigation.findNavController
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.textfield.TextInputEditText
import com.michatec.radio.Keys
@@ -54,6 +56,7 @@ class CollectionAdapter(
private var expandedStationUuid: String = PreferencesHelper.loadStationListStreamUuid()
private var expandedStationPosition: Int = -1
var isExpandedForEdit: Boolean = false
private var reorderStationUuid: String = ""
/* Listener Interface */
@@ -184,6 +187,15 @@ class CollectionAdapter(
setPlaybackProgress(stationViewHolder, station)
setDownloadProgress(stationViewHolder, station)
// highlight if reordering
if (reorderStationUuid == station.uuid) {
stationViewHolder.stationCardView.setStrokeColor(
ColorStateList.valueOf(
ContextCompat.getColor(context, R.color.cardview_reordering)
)
)
}
// show / hide edit views
when (expandedStationPosition) {
// show edit views
@@ -310,6 +322,21 @@ class CollectionAdapter(
}
}
/* Shows / hides the reorder highlight for a station */
private fun toggleReorderMode(position: Int, stationUuid: String) {
if (reorderStationUuid == stationUuid) {
reorderStationUuid = ""
saveCollectionAfterDragDrop()
} else {
// collapse edit views if necessary
if (isExpandedForEdit) {
toggleEditViews(expandedStationPosition, expandedStationUuid)
}
reorderStationUuid = stationUuid
}
notifyItemChanged(position)
}
/* Shows / hides the edit view for a station */
@SuppressLint("NotifyDataSetChanged")
@@ -345,12 +372,16 @@ class CollectionAdapter(
when (station.starred) {
true -> {
if (station.imageColor != -1) {
// stationViewHolder.stationCardView.setCardBackgroundColor(station.imageColor)
stationViewHolder.stationStarredView.setColorFilter(station.imageColor)
} else {
stationViewHolder.stationStarredView.clearColorFilter()
}
stationViewHolder.stationStarredView.isVisible = true
}
false -> stationViewHolder.stationStarredView.isGone = true
false -> {
stationViewHolder.stationStarredView.clearColorFilter()
stationViewHolder.stationStarredView.isGone = true
}
}
}
@@ -378,6 +409,7 @@ class CollectionAdapter(
false -> stationViewHolder.playButtonView.visibility = View.INVISIBLE
}
stationViewHolder.stationCardView.setOnClickListener {
if (reorderStationUuid.isNotEmpty()) return@setOnClickListener
if (expandedStationPosition == stationViewHolder.bindingAdapterPosition) return@setOnClickListener
collectionAdapterListener.onPlayButtonTapped(station.uuid)
}
@@ -394,9 +426,35 @@ class CollectionAdapter(
collectionAdapterListener.onPlayButtonTapped(station.uuid)
}
// TV improvement: Allow opening edit view with DPAD_LEFT
// TV improvement: Allow reordering with DPAD
stationViewHolder.stationCardView.setOnKeyListener { _, keyCode, event ->
if (event.action == KeyEvent.ACTION_DOWN) {
// Reorder mode handling
if (reorderStationUuid == station.uuid) {
when (keyCode) {
KeyEvent.KEYCODE_DPAD_UP -> {
val currentPos = stationViewHolder.bindingAdapterPosition
if (currentPos > 0) {
onItemMove(currentPos, currentPos - 1)
}
return@setOnKeyListener true
}
KeyEvent.KEYCODE_DPAD_DOWN -> {
val currentPos = stationViewHolder.bindingAdapterPosition
if (currentPos < collection.stations.size - 1) {
onItemMove(currentPos, currentPos + 1)
}
return@setOnKeyListener true
}
KeyEvent.KEYCODE_NUMPAD_2, KeyEvent.KEYCODE_2, KeyEvent.KEYCODE_PLUS,
KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_DPAD_CENTER -> {
toggleReorderMode(stationViewHolder.bindingAdapterPosition, station.uuid)
return@setOnKeyListener true
}
else -> return@setOnKeyListener true // Consume other keys in reorder mode
}
}
when (keyCode) {
KeyEvent.KEYCODE_DPAD_LEFT -> {
if (editStationsEnabled && expandedStationPosition != stationViewHolder.bindingAdapterPosition) {
@@ -405,7 +463,7 @@ class CollectionAdapter(
return@setOnKeyListener true
}
}
KeyEvent.KEYCODE_NUMPAD_2, KeyEvent.KEYCODE_2, KeyEvent.KEYCODE_BACK -> {
KeyEvent.KEYCODE_NUMPAD_3, KeyEvent.KEYCODE_3, KeyEvent.KEYCODE_BACK -> {
if (expandedStationPosition == stationViewHolder.bindingAdapterPosition) {
val position: Int = stationViewHolder.bindingAdapterPosition
toggleEditViews(position, station.uuid)
@@ -420,6 +478,10 @@ class CollectionAdapter(
toggleStarredStation(context, stationViewHolder.bindingAdapterPosition)
return@setOnKeyListener true
}
KeyEvent.KEYCODE_NUMPAD_2, KeyEvent.KEYCODE_2, KeyEvent.KEYCODE_PLUS -> {
toggleReorderMode(stationViewHolder.bindingAdapterPosition, station.uuid)
return@setOnKeyListener true
}
}
}
false
@@ -703,7 +765,7 @@ class CollectionAdapter(
*/
private class StationViewHolder(stationCardLayout: View) :
RecyclerView.ViewHolder(stationCardLayout) {
val stationCardView: CardView = stationCardLayout.findViewById(R.id.station_card)
val stationCardView: MaterialCardView = stationCardLayout.findViewById(R.id.station_card)
val stationImageView: ImageView = stationCardLayout.findViewById(R.id.station_icon)
val stationNameView: TextView = stationCardLayout.findViewById(R.id.station_name)
val stationStarredView: ImageView = stationCardLayout.findViewById(R.id.starred_icon)

View File

@@ -27,28 +27,6 @@ class ThemeSelectionDialog(private var themeSelectionDialogListener: ThemeSelect
private lateinit var dialog: AlertDialog
/* Update radio buttons to reflect current theme */
private fun updateRadioButtons(
context: Context,
radioFollowSystem: RadioButton,
radioLight: RadioButton,
radioDark: RadioButton
) {
val currentTheme = AppThemeHelper.getCurrentTheme(context)
when (currentTheme) {
context.getString(R.string.pref_theme_selection_mode_device_default) -> {
radioFollowSystem.isChecked = true
}
context.getString(R.string.pref_theme_selection_mode_light) -> {
radioLight.isChecked = true
}
context.getString(R.string.pref_theme_selection_mode_dark) -> {
radioDark.isChecked = true
}
}
}
/* Construct and show dialog */
fun show(context: Context) {
// prepare dialog builder

View File

@@ -1,11 +1,7 @@
package com.michatec.radio.helpers
import android.content.Context
import android.content.res.TypedArray
import android.util.Log
import android.util.TypedValue
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.appcompat.app.AppCompatDelegate
import com.michatec.radio.Keys
import com.michatec.radio.R
@@ -19,8 +15,6 @@ object AppThemeHelper {
/* Define log tag */
private val TAG: String = AppThemeHelper::class.java.simpleName
private val sTypedValue = TypedValue()
/* Sets app theme */
fun setTheme(nightModeState: String) {
when (nightModeState) {
@@ -62,14 +56,4 @@ object AppThemeHelper {
else -> context.getString(R.string.pref_theme_selection_mode_device_default)
}
}
@ColorInt
fun getColor(context: Context, @AttrRes resource: Int): Int {
val a: TypedArray = context.obtainStyledAttributes(sTypedValue.data, intArrayOf(resource))
val color = a.getColor(0, 0)
a.recycle()
return color
}
}

View File

@@ -53,7 +53,7 @@ object BackupHelper {
Snackbar.make(view, R.string.toastmessage_restored, Snackbar.LENGTH_LONG).show()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
// bypass "ZipException" for Android 14 or above applications when zip file names contain ".." or start with "/"
// bypass "ZipException" for Android 14 or above applications when zip file names contain "." or start with "/"
dalvik.system.ZipPathValidator.clearCallback()
}

View File

@@ -299,7 +299,7 @@ object CollectionHelper {
}
/* Returns the children stations under under root (simple media library structure: root > stations) */
/* Returns the children stations under root (simple media library structure: root > stations) */
fun getChildren(context: Context, collection: Collection): List<MediaItem> {
val mediaItems: MutableList<MediaItem> = mutableListOf()
collection.stations.forEach { station ->

View File

@@ -17,14 +17,14 @@ object DateTimeHelper {
/* Main class variables */
private const val pattern: String = "EEE, dd MMM yyyy HH:mm:ss Z"
private val dateFormat: SimpleDateFormat = SimpleDateFormat(pattern, Locale.ENGLISH)
private const val PATTERN: String = "EEE, dd MMM yyyy HH:mm:ss Z"
private val dateFormat: SimpleDateFormat = SimpleDateFormat(PATTERN, Locale.ENGLISH)
/* Converts RFC 2822 string representation of a date to DATE */
fun convertFromRfc2822(dateString: String): Date {
val date: Date = try {
// parse date string using standard pattern
// parse date string using standard PATTERN
dateFormat.parse((dateString)) ?: Keys.DEFAULT_DATE
} catch (e: Exception) {
Log.w(TAG, "Unable to parse. Trying an alternative Date format. $e")
@@ -37,7 +37,7 @@ object DateTimeHelper {
/* Converts a DATE to its RFC 2822 string representation */
fun convertToRfc2822(date: Date): String {
val dateFormat = SimpleDateFormat(pattern, Locale.ENGLISH)
val dateFormat = SimpleDateFormat(PATTERN, Locale.ENGLISH)
return dateFormat.format(date)
}

View File

@@ -370,7 +370,7 @@ object DownloadHelper {
private fun determineAllowedNetworkTypes(type: Int, ignoreWifiRestriction: Boolean): Int {
var allowedNetworkTypes: Int =
(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
// restrict download of audio files to WiFi if necessary
// restrict download of audio files to Wi-Fi if necessary
if (type == Keys.FILE_TYPE_AUDIO) {
if (!ignoreWifiRestriction && !PreferencesHelper.downloadOverMobile()) {
allowedNetworkTypes = DownloadManager.Request.NETWORK_WIFI

View File

@@ -115,7 +115,7 @@ object NetworkHelper {
}
/* Creates a http connection from given url string */
/* Creates an http connection from given url string */
private fun createConnection(urlString: String, redirectCount: Int = 0): HttpURLConnection? {
var connection: HttpURLConnection? = null

View File

@@ -21,7 +21,6 @@ object ShortcutHelper {
/* Places shortcut on Home screen */
fun placeShortcut(context: Context, station: Station) {
// credit: https://medium.com/@BladeCoder/using-support-library-26-0-0-you-can-do-bb75911e01e8
if (ShortcutManagerCompat.isRequestPinShortcutSupported(context)) {
val shortcut: ShortcutInfoCompat = ShortcutInfoCompat.Builder(context, station.name)
.setShortLabel(station.name)

View File

@@ -128,7 +128,6 @@ data class LayoutHolder(var rootView: View) {
if (!isPlaying) {
metadataView?.text = station.name
sheetMetadataHistoryView?.text = station.name
// sheetMetadataHistoryView.isSelected = true
}
// update name
@@ -289,11 +288,9 @@ data class LayoutHolder(var rootView: View) {
val animatedVectorDrawable = playButtonView.drawable as? AnimatedVectorDrawable
animatedVectorDrawable?.start()
sheetSleepTimerStartButtonView?.isVisible = true
// bufferingIndicator.isVisible = false
} else {
playButtonView.setImageResource(R.drawable.ic_player_play_symbol_42dp)
sheetSleepTimerStartButtonView?.isVisible = false
// bufferingIndicator.isVisible = isBuffering
}
}

View File

@@ -4,9 +4,6 @@
<item
android:width="160dp"
android:height="160dp"
android:gravity="center">
<bitmap
android:gravity="center"
android:src="@mipmap/ic_launcher" />
</item>
android:drawable="@mipmap/ic_launcher" />
</layer-list>

View File

@@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/colorBackground"
android:fitsSystemWindows="true"
tools:context=".MainActivity">

View File

@@ -32,4 +32,5 @@
<color name="player_sheet_text_main">@android:color/system_neutral1_50</color>
<color name="player_sheet_icon">@android:color/system_neutral1_50</color>
<color name="cardview_reordering">@android:color/system_accent1_100</color>
</resources>

View File

@@ -31,9 +31,6 @@
<!-- Don't show light status bar -->
<item name="android:statusBarColor">@android:color/transparent</item>
<!-- Set Navigation Bar color -->
<item name="android:navigationBarColor">@color/player_sheet_background</item>
<!-- Set splash screen icon background color -->
<item name="android:windowSplashScreenIconBackgroundColor">@color/splashBackgroundColor</item>
</style>

View File

@@ -31,4 +31,5 @@
<color name="player_sheet_text_main">#FFFFFFFF</color>
<color name="player_sheet_icon">#FFFFFFFF</color>
<color name="cardview_reordering">#FFDAE2FF</color>
</resources>

View File

@@ -3,6 +3,5 @@
<style name="SplashTheme" parent="Theme.Material3.DayNight.NoActionBar">
<item name="android:windowBackground">@drawable/splash_screen</item>
<item name="android:statusBarColor">@color/splashBackgroundColor</item>
<item name="android:navigationBarColor">@color/splashBackgroundColor</item>
</style>
</resources>

View File

@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Set AppCompats colors -->
<item name="colorPrimary">#FF495D92</item>
<item name="colorAccent">#FF495D92</item>
<item name="android:textColorHighlight">#FF495D92</item>
<item name="colorControlHighlight">#33000000</item>
<item name="android:colorControlHighlight">#33000000</item>
<item name="android:colorFocusedHighlight">#80000000</item>
<!-- Do not use primary colored elevation overlays to present a visual hierarchy - TOO COLORFUL -->
<item name="elevationOverlayEnabled">false</item>
<!-- Switch Theming -->
<item name="switchPreferenceCompatStyle">@style/Preference.SwitchPreferenceCompat.Material3</item>
<!-- Material Alert Dialog Theming -->
<item name="alertDialogTheme">@style/ThemeOverlay.App.AlertDialogTheme</item>
<!-- Use "light" Status Bar -->
<item name="android:windowLightStatusBar">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<!-- Use "light" Navigation Bar -->
<item name="android:windowLightNavigationBar">true</item>
</style>
</resources>

View File

@@ -37,4 +37,5 @@
<color name="default_neutral_medium_light">@android:color/system_neutral1_300</color>
<color name="default_neutral_dark">@android:color/system_neutral1_600</color>
<color name="cardview_reordering">@android:color/system_accent1_900</color>
</resources>

View File

@@ -39,5 +39,5 @@
<color name="default_neutral_85percent">#D9313033</color>
<color name="splashBackgroundColor">#FF1D3E66</color>
<color name="cardview_reordering">#161C2C</color>
</resources>

View File

@@ -141,5 +141,7 @@
<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>
<!-- Extras -->
<string name="loading">Loading...</string>
</resources>