Skip to content

Commit

Permalink
new Add Station dialog that opens when a user selects to open an M3U …
Browse files Browse the repository at this point in the history
…or PLS file from storage
  • Loading branch information
y20k authored and jamal2362 committed Sep 27, 2023
1 parent 3dbb5ab commit 06a1913
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 24 deletions.
42 changes: 28 additions & 14 deletions app/src/main/java/com/jamal2367/urlradio/PlayerFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import com.jamal2367.urlradio.collection.CollectionAdapter
import com.jamal2367.urlradio.collection.CollectionViewModel
import com.jamal2367.urlradio.core.Collection
import com.jamal2367.urlradio.core.Station
import com.jamal2367.urlradio.dialogs.AddStationDialog
import com.jamal2367.urlradio.dialogs.FindStationDialog
import com.jamal2367.urlradio.dialogs.YesNoDialog
import com.jamal2367.urlradio.extensions.*
Expand All @@ -78,7 +79,8 @@ import java.util.*
*/
class PlayerFragment : Fragment(),
SharedPreferences.OnSharedPreferenceChangeListener,
FindStationDialog.FindFindStationDialogListener,
FindStationDialog.FindStationDialogListener,
AddStationDialog.AddStationDialogListener,
CollectionAdapter.CollectionAdapterListener,
YesNoDialog.YesNoDialogListener {

Expand Down Expand Up @@ -322,6 +324,15 @@ class PlayerFragment : Fragment(),
}


/* Overrides onAddStationDialog from AddDialog */
override fun onAddStationDialog(station: Station) {
if (station.streamContent.isNotEmpty() && station.streamContent != Keys.MIME_TYPE_UNSUPPORTED) {
// add station and save collection
collection = CollectionHelper.addStation(activity as Context, collection, station)
}
}


/* Overrides onPlayButtonTapped from CollectionAdapterListener */
override fun onPlayButtonTapped(stationUuid: String) {
// CASE: the selected station is playing
Expand All @@ -339,10 +350,7 @@ class PlayerFragment : Fragment(),

/* Overrides onAddNewButtonTapped from CollectionAdapterListener */
override fun onAddNewButtonTapped() {
FindStationDialog(
activity as Activity,
this as FindStationDialog.FindFindStationDialogListener
).show()
FindStationDialog(activity as Activity, this as FindStationDialog.FindStationDialogListener).show()
}


Expand Down Expand Up @@ -589,26 +597,32 @@ class PlayerFragment : Fragment(),
val intentUri: Uri? = (activity as Activity).intent.data
if (intentUri != null) {
CoroutineScope(IO).launch {
// get station list from intent source
val stationList: MutableList<Station> = mutableListOf()
val scheme: String = intentUri.scheme ?: String()
// CASE: intent is a web link
if (scheme.startsWith("http")) {
Log.i(TAG, "URL Radio was started to handle a web link.")
Log.i(TAG, "Transistor was started to handle a web link.")
stationList.addAll(CollectionHelper.createStationsFromUrl(intentUri.toString()))
} else if (scheme.startsWith("content")) {
Log.i(TAG, "URL Radio was started to handle a local audio playlist.")
}
// CASE: intent is a local file
else if (scheme.startsWith("content")) {
Log.i(TAG, "Transistor was started to handle a local audio playlist.")
stationList.addAll(CollectionHelper.createStationListFromContentUri(activity as Context, intentUri))
}
if (stationList.isNotEmpty()) {
// todo hand over station list to a new AddStationDialog
Log.e(TAG, stationList.toString()) // todo remove
} else {
// invalid address
Toast.makeText(context, R.string.toastmessage_station_not_valid, Toast.LENGTH_LONG).show()
withContext(Main) {
if (stationList.isNotEmpty()) {
AddStationDialog(activity as Activity, stationList, this@PlayerFragment as AddStationDialog.AddStationDialogListener).show()
} else {
// invalid address
Toast.makeText(context, R.string.toastmessage_station_not_valid, Toast.LENGTH_LONG).show()
}
}
}
}
}


/* Handles START_PLAYER_SERVICE request from App Shortcut */
private fun handleStartPlayer() {
val intent: Intent = (activity as Activity).intent
Expand Down
134 changes: 134 additions & 0 deletions app/src/main/java/com/jamal2367/urlradio/dialogs/AddStationDialog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* AddStationDialog.kt
* Implements the AddStationDialog class
* A AddStationDialog shows a dialog with list of stations to import
*
* This file is part of
* TRANSISTOR - Radio App for Android
*
* Copyright (c) 2015-23 - Y20K.org
* Licensed under the MIT-License
* http://opensource.org/licenses/MIT
*/


package com.jamal2367.urlradio.dialogs

import android.content.Context
import android.view.LayoutInflater
import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.jamal2367.urlradio.R
import com.jamal2367.urlradio.collection.CollectionAdapter
import com.jamal2367.urlradio.core.Station
import com.jamal2367.urlradio.search.SearchResultAdapter


/*
* AddStationDialog class
*/
class AddStationDialog (
private val context: Context,
private val stationList: List<Station>,
private val listener: AddStationDialogListener) :
SearchResultAdapter.SearchResultAdapterListener {


/* Interface used to communicate back to activity */
interface AddStationDialogListener {
fun onAddStationDialog(station: Station)
}


/* Define log tag */
private val TAG = AddStationDialog::class.java.simpleName


/* Main class variables */
private lateinit var dialog: AlertDialog
private lateinit var stationSearchResultList: RecyclerView
private lateinit var searchResultAdapter: SearchResultAdapter
private var station: Station = Station()


/* Overrides onSearchResultTapped from SearchResultAdapterListener */
override fun onSearchResultTapped(result: Station) {
station = result
// make add button clickable
activateAddButton()
}


/* Construct and show dialog */
fun show() {
// prepare dialog builder
val builder = MaterialAlertDialogBuilder(context)

// set title
builder.setTitle(R.string.dialog_add_station_title)

// get views
val inflater = LayoutInflater.from(context)
val view = inflater.inflate(R.layout.dialog_add_station, null)
stationSearchResultList = view.findViewById(R.id.station_list)

// set up list of search results
setupRecyclerView(context)

// add okay ("Add") button
builder.setPositiveButton(R.string.dialog_find_station_button_add) { _, _ ->
// listen for click on add button
listener.onAddStationDialog(station)
searchResultAdapter.stopPrePlayback()
}
// add cancel button
builder.setNegativeButton(R.string.dialog_generic_button_cancel) { _, _ ->
searchResultAdapter.stopPrePlayback()
}
// handle outside-click as "no"
builder.setOnCancelListener {
searchResultAdapter.stopPrePlayback()
}

// set dialog view
builder.setView(view)

// create and display dialog
dialog = builder.create()
dialog.show()

// initially disable "Add" button
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false
}


/* Sets up list of results (RecyclerView) */
private fun setupRecyclerView(context: Context) {
searchResultAdapter = SearchResultAdapter(this, stationList)
stationSearchResultList.adapter = searchResultAdapter
val layoutManager: LinearLayoutManager = object: LinearLayoutManager(context) {
override fun supportsPredictiveItemAnimations(): Boolean {
return true
}
}
stationSearchResultList.layoutManager = layoutManager
stationSearchResultList.itemAnimator = DefaultItemAnimator()
}


/* Implement activateAddButton to enable the "Add" button */
override fun activateAddButton() {
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = true
}


/* Implement deactivateAddButton to disable the "Add" button */
override fun deactivateAddButton() {
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ import com.jamal2367.urlradio.search.SearchResultAdapter
* FindStationDialog class
*/
class FindStationDialog (
private var context: Context,
private var listener: FindFindStationDialogListener):
private val context: Context,
private val listener: FindStationDialogListener):
SearchResultAdapter.SearchResultAdapterListener,
RadioBrowserSearch.RadioBrowserSearchListener,
DirectInputCheck.DirectInputCheckListener {

/* Interface used to communicate back to activity */
interface FindFindStationDialogListener {
interface FindStationDialogListener {
fun onFindStationDialog(station: Station) {
}
}
Expand All @@ -71,7 +71,7 @@ class FindStationDialog (
private var station: Station = Station()


/* Overrides onSearchResultTapped from RadioBrowserResultAdapterListener */
/* Overrides onSearchResultTapped from SearchResultAdapterListener */
override fun onSearchResultTapped(result: Station) {
station = result
// hide keyboard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,18 +156,15 @@ class SearchResultAdapter(
private fun performPrePlayback(context: Context, streamUri: String) {
if (streamUri.contains(".m3u8")) {
// release previous player if it exists
exoPlayer?.stop()
exoPlayer?.release()
exoPlayer = null
stopPrePlayback()

// show toast when no playback is possible
Toast.makeText(context, R.string.toastmessage_preview_playback_failed, Toast.LENGTH_SHORT).show()
} else {
stopRadioPlayback(context)

exoPlayer?.stop()
exoPlayer?.release()
exoPlayer = null
// release previous player if it exists
stopPrePlayback()

// create a new instance of ExoPlayer
exoPlayer = ExoPlayer.Builder(context).build()
Expand Down
22 changes: 22 additions & 0 deletions app/src/main/res/layout/dialog_add_station.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/station_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:paddingTop="16dp"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0" />

</androidx.constraintlayout.widget.ConstraintLayout>
1 change: 1 addition & 0 deletions app/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<string name="descr_player_playback_button">Start/Pause</string>
<string name="descr_player_station_image">Senderbild</string>
<!-- Dialogs -->
<string name="dialog_add_station_title">Station hinzufügen</string>
<string name="dialog_edit_station_name">Sendername</string>
<string name="dialog_edit_stream_uri">Stream-Adresse</string>
<string name="dialog_error_message_default">Ein Fehler ist aufgetreten</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<string name="descr_player_station_image">Station image</string>

<!-- Dialogs -->
<string name="dialog_add_station_title">Add Station</string>
<string name="dialog_edit_station_name">Station name</string>
<string name="dialog_edit_stream_uri">Stream address</string>
<string name="dialog_error_message_default">An error occurred</string>
Expand Down

0 comments on commit 06a1913

Please sign in to comment.