mirror of
https://gitlab.com/ultrasonic/ultrasonic.git
synced 2025-04-17 01:32:23 +03:00
Merge branch 'safeArgs2' into 'develop'
Finish SafeArgs Closes #510 See merge request ultrasonic/ultrasonic!802
This commit is contained in:
commit
1a354765f9
@ -1,103 +0,0 @@
|
||||
package org.moire.ultrasonic.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import org.moire.ultrasonic.R;
|
||||
import org.moire.ultrasonic.domain.Lyrics;
|
||||
import org.moire.ultrasonic.service.MusicService;
|
||||
import org.moire.ultrasonic.service.MusicServiceFactory;
|
||||
import org.moire.ultrasonic.util.BackgroundTask;
|
||||
import org.moire.ultrasonic.util.CancellationToken;
|
||||
import org.moire.ultrasonic.util.Constants;
|
||||
import org.moire.ultrasonic.util.FragmentBackgroundTask;
|
||||
import org.moire.ultrasonic.util.Util;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Displays the lyrics of a song
|
||||
*/
|
||||
public class LyricsFragment extends Fragment {
|
||||
|
||||
private TextView artistView;
|
||||
private TextView titleView;
|
||||
private TextView textView;
|
||||
private SwipeRefreshLayout swipe;
|
||||
private CancellationToken cancellationToken;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
Util.applyTheme(this.getContext());
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.lyrics, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
cancellationToken = new CancellationToken();
|
||||
Timber.d("Lyrics set title");
|
||||
FragmentTitle.Companion.setTitle(this, R.string.download_menu_lyrics);
|
||||
|
||||
swipe = view.findViewById(R.id.lyrics_refresh);
|
||||
swipe.setEnabled(false);
|
||||
artistView = view.findViewById(R.id.lyrics_artist);
|
||||
titleView = view.findViewById(R.id.lyrics_title);
|
||||
textView = view.findViewById(R.id.lyrics_text);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
cancellationToken.cancel();
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
private void load()
|
||||
{
|
||||
BackgroundTask<Lyrics> task = new FragmentBackgroundTask<Lyrics>(getActivity(), true, swipe, cancellationToken)
|
||||
{
|
||||
@Override
|
||||
protected Lyrics doInBackground() throws Throwable
|
||||
{
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments == null) return null;
|
||||
String artist = arguments.getString(Constants.INTENT_ARTIST);
|
||||
String title = arguments.getString(Constants.INTENT_TITLE);
|
||||
MusicService musicService = MusicServiceFactory.getMusicService();
|
||||
return musicService.getLyrics(artist, title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(Lyrics result)
|
||||
{
|
||||
if (result != null && result.getArtist() != null)
|
||||
{
|
||||
artistView.setText(result.getArtist());
|
||||
titleView.setText(result.getTitle());
|
||||
textView.setText(result.getText());
|
||||
}
|
||||
else
|
||||
{
|
||||
artistView.setText(R.string.lyrics_nomatch);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
}
|
@ -49,6 +49,7 @@ import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.app.UApp
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.data.ServerSettingDao
|
||||
import org.moire.ultrasonic.fragment.MainFragmentDirections
|
||||
import org.moire.ultrasonic.fragment.OnBackPressedHandler
|
||||
import org.moire.ultrasonic.model.ServerSettingsModel
|
||||
import org.moire.ultrasonic.provider.SearchSuggestionProvider
|
||||
@ -377,10 +378,8 @@ class NavigationActivity : AppCompatActivity() {
|
||||
)
|
||||
suggestions.saveRecentQuery(query, null)
|
||||
|
||||
val bundle = Bundle()
|
||||
bundle.putString(Constants.INTENT_QUERY, query)
|
||||
bundle.putBoolean(Constants.INTENT_AUTOPLAY, autoPlay)
|
||||
findNavController(R.id.nav_host_fragment).navigate(R.id.searchFragment, bundle)
|
||||
val action = MainFragmentDirections.toSearchFragment(query, autoPlay)
|
||||
findNavController(R.id.nav_host_fragment).navigate(action)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ class FolderSelectorBinder(context: Context) :
|
||||
menuItem.isChecked = true
|
||||
folderName.text = musicFolderName
|
||||
|
||||
RxBus.musicFolderChangedEventPublisher.onNext(selectedFolderId)
|
||||
RxBus.musicFolderChangedEventPublisher.onNext(RxBus.Folder(selectedFolderId))
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -5,7 +5,9 @@ import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.PopupMenu
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.drakeet.multitype.ItemViewBinder
|
||||
import org.koin.core.component.KoinComponent
|
||||
@ -13,6 +15,7 @@ import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.domain.Identifiable
|
||||
import org.moire.ultrasonic.domain.Track
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
class TrackViewBinder(
|
||||
val onItemClick: (Track, Int) -> Unit,
|
||||
val onContextMenuClick: ((MenuItem, Track) -> Boolean)? = null,
|
||||
@ -20,13 +23,18 @@ class TrackViewBinder(
|
||||
val draggable: Boolean,
|
||||
context: Context,
|
||||
val lifecycleOwner: LifecycleOwner,
|
||||
val createContextMenu: (View, Track) -> PopupMenu = { view, _ ->
|
||||
Utils.createPopupMenu(
|
||||
view,
|
||||
R.menu.context_menu_track
|
||||
)
|
||||
}
|
||||
) : ItemViewBinder<Identifiable, TrackViewHolder>(), KoinComponent {
|
||||
|
||||
var startDrag: ((TrackViewHolder) -> Unit)? = null
|
||||
|
||||
// Set our layout files
|
||||
val layout = R.layout.list_item_track
|
||||
private val contextMenuLayout = R.menu.context_menu_track
|
||||
|
||||
private val imageHelper: Utils.ImageHelper = Utils.ImageHelper(context)
|
||||
|
||||
@ -62,7 +70,7 @@ class TrackViewBinder(
|
||||
|
||||
holder.itemView.setOnLongClickListener {
|
||||
if (onContextMenuClick != null) {
|
||||
val popup = Utils.createPopupMenu(holder.itemView, contextMenuLayout)
|
||||
val popup = createContextMenu(holder.itemView, track)
|
||||
|
||||
popup.setOnMenuItemClickListener { menuItem ->
|
||||
onContextMenuClick.invoke(menuItem, track)
|
||||
|
@ -16,6 +16,7 @@ import android.widget.ImageView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.skydoves.colorpickerview.ColorPickerDialog
|
||||
@ -56,9 +57,6 @@ private const val DIALOG_PADDING = 12
|
||||
* Displays a form where server settings can be created / edited
|
||||
*/
|
||||
class EditServerFragment : Fragment(), OnBackPressedHandler {
|
||||
companion object {
|
||||
const val EDIT_SERVER_INTENT_INDEX = "index"
|
||||
}
|
||||
|
||||
private val serverSettingsModel: ServerSettingsModel by viewModel()
|
||||
private val activeServerProvider: ActiveServerProvider by inject()
|
||||
@ -79,6 +77,8 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
|
||||
private var currentColor: Int = 0
|
||||
private var selectedColor: Int? = null
|
||||
|
||||
private val navArgs by navArgs<EditServerFragmentArgs>()
|
||||
|
||||
@Override
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Util.applyTheme(this.context)
|
||||
@ -107,15 +107,10 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
|
||||
saveButton = view.findViewById(R.id.edit_save)
|
||||
testButton = view.findViewById(R.id.edit_test)
|
||||
|
||||
val index = arguments?.getInt(
|
||||
EDIT_SERVER_INTENT_INDEX,
|
||||
-1
|
||||
) ?: -1
|
||||
|
||||
if (index != -1) {
|
||||
if (navArgs.index != -1) {
|
||||
// Editing an existing server
|
||||
FragmentTitle.setTitle(this, R.string.server_editor_label)
|
||||
val serverSetting = serverSettingsModel.getServerSetting(index)
|
||||
val serverSetting = serverSettingsModel.getServerSetting(navArgs.index)
|
||||
serverSetting.observe(
|
||||
viewLifecycleOwner
|
||||
) { t ->
|
||||
|
@ -64,7 +64,7 @@ abstract class EntryListFragment<T : GenericEntry> : MultiListFragment<T>() {
|
||||
RxBus.musicFolderChangedEventObservable.subscribe {
|
||||
if (!listModel.isOffline()) {
|
||||
val currentSetting = listModel.activeServer
|
||||
currentSetting.musicFolderId = it
|
||||
currentSetting.musicFolderId = it.id
|
||||
serverSettingsModel.updateItem(currentSetting)
|
||||
}
|
||||
listModel.refresh(refreshListView!!)
|
||||
|
@ -14,8 +14,6 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.ContextMenu
|
||||
import android.view.ContextMenu.ContextMenuInfo
|
||||
import android.view.GestureDetector
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
@ -26,10 +24,10 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.AdapterView.AdapterContextMenuInfo
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.SeekBar
|
||||
import android.widget.SeekBar.OnSeekBarChangeListener
|
||||
import android.widget.TextView
|
||||
@ -71,9 +69,11 @@ import org.koin.core.component.KoinComponent
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.adapters.BaseAdapter
|
||||
import org.moire.ultrasonic.adapters.TrackViewBinder
|
||||
import org.moire.ultrasonic.api.subsonic.models.AlbumListType
|
||||
import org.moire.ultrasonic.audiofx.EqualizerController
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
|
||||
import org.moire.ultrasonic.domain.Identifiable
|
||||
import org.moire.ultrasonic.domain.MusicDirectory
|
||||
import org.moire.ultrasonic.domain.Track
|
||||
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle
|
||||
import org.moire.ultrasonic.service.MediaPlayerController
|
||||
@ -85,7 +85,6 @@ import org.moire.ultrasonic.subsonic.NetworkAndStorageChecker
|
||||
import org.moire.ultrasonic.subsonic.ShareHandler
|
||||
import org.moire.ultrasonic.util.CancellationToken
|
||||
import org.moire.ultrasonic.util.CommunicationError
|
||||
import org.moire.ultrasonic.util.Constants
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import org.moire.ultrasonic.util.toTrack
|
||||
@ -346,8 +345,6 @@ class PlayerFragment :
|
||||
|
||||
initPlaylistDisplay()
|
||||
|
||||
registerForContextMenu(playlistView)
|
||||
|
||||
EqualizerController.get().observe(
|
||||
requireActivity()
|
||||
) { equalizerController ->
|
||||
@ -546,55 +543,54 @@ class PlayerFragment :
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateContextMenu(menu: ContextMenu, view: View, menuInfo: ContextMenuInfo?) {
|
||||
super.onCreateContextMenu(menu, view, menuInfo)
|
||||
if (view === playlistView) {
|
||||
val info = menuInfo as AdapterContextMenuInfo?
|
||||
val track = viewAdapter.getCurrentList()[info!!.position] as Track
|
||||
val menuInflater = requireActivity().menuInflater
|
||||
menuInflater.inflate(R.menu.nowplaying_context, menu)
|
||||
private fun onCreateContextMenu(view: View, track: Track): PopupMenu {
|
||||
val popup = PopupMenu(view.context, view)
|
||||
val inflater: MenuInflater = popup.menuInflater
|
||||
inflater.inflate(R.menu.nowplaying_context, popup.menu)
|
||||
|
||||
if (track.parent == null) {
|
||||
val menuItem = menu.findItem(R.id.menu_show_album)
|
||||
if (menuItem != null) {
|
||||
menuItem.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
if (isOffline() || !Settings.shouldUseId3Tags) {
|
||||
menu.findItem(R.id.menu_show_artist)?.isVisible = false
|
||||
}
|
||||
|
||||
if (isOffline()) {
|
||||
menu.findItem(R.id.menu_lyrics)?.isVisible = false
|
||||
if (track.parent == null) {
|
||||
val menuItem = popup.menu.findItem(R.id.menu_show_album)
|
||||
if (menuItem != null) {
|
||||
menuItem.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
if (isOffline() || !Settings.shouldUseId3Tags) {
|
||||
popup.menu.findItem(R.id.menu_show_artist)?.isVisible = false
|
||||
}
|
||||
|
||||
popup.menu.findItem(R.id.menu_lyrics)?.isVisible = !isOffline()
|
||||
popup.show()
|
||||
return popup
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
// TODO Why is Track null?
|
||||
return menuItemSelected(item.itemId, null) || super.onOptionsItemSelected(item)
|
||||
return menuItemSelected(item.itemId, currentSong) || super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun onContextMenuItemSelected(
|
||||
menuItem: MenuItem,
|
||||
item: MusicDirectory.Child
|
||||
): Boolean {
|
||||
if (item !is Track) return false
|
||||
return menuItemSelected(menuItem.itemId, item)
|
||||
}
|
||||
|
||||
@Suppress("ComplexMethod", "LongMethod", "ReturnCount")
|
||||
private fun menuItemSelected(menuItemId: Int, track: Track?): Boolean {
|
||||
val bundle: Bundle
|
||||
|
||||
when (menuItemId) {
|
||||
R.id.menu_show_artist -> {
|
||||
if (track == null) return false
|
||||
|
||||
if (Settings.shouldUseId3Tags) {
|
||||
PlayerFragmentDirections.playerToSelectAlbum(
|
||||
val action = PlayerFragmentDirections.playerToAlbumsList(
|
||||
type = AlbumListType.BY_ARTIST,
|
||||
id = track.artistId,
|
||||
name = track.artist,
|
||||
parentId = track.artistId,
|
||||
isArtist = true,
|
||||
title = track.artist,
|
||||
offset = 0,
|
||||
size = 1000
|
||||
)
|
||||
bundle = Bundle()
|
||||
|
||||
Navigation.findNavController(requireView())
|
||||
.navigate(R.id.playerToSelectAlbum, bundle)
|
||||
findNavController().navigate(action)
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -614,11 +610,9 @@ class PlayerFragment :
|
||||
return true
|
||||
}
|
||||
R.id.menu_lyrics -> {
|
||||
if (track == null) return false
|
||||
bundle = Bundle()
|
||||
bundle.putString(Constants.INTENT_ARTIST, track.artist)
|
||||
bundle.putString(Constants.INTENT_TITLE, track.title)
|
||||
Navigation.findNavController(requireView()).navigate(R.id.playerToLyrics, bundle)
|
||||
if (track?.artist == null || track.title == null) return false
|
||||
val action = PlayerFragmentDirections.playerToLyrics(track.artist!!, track.title!!)
|
||||
Navigation.findNavController(requireView()).navigate(action)
|
||||
return true
|
||||
}
|
||||
R.id.menu_remove -> {
|
||||
@ -672,9 +666,9 @@ class PlayerFragment :
|
||||
return true
|
||||
}
|
||||
R.id.menu_item_star -> {
|
||||
if (currentSong == null) return true
|
||||
if (track == null) return true
|
||||
|
||||
val isStarred = currentSong!!.starred
|
||||
val isStarred = track.starred
|
||||
|
||||
mediaPlayerController.controller?.setRating(
|
||||
HeartRating(!isStarred)
|
||||
@ -685,10 +679,10 @@ class PlayerFragment :
|
||||
override fun onSuccess(result: SessionResult?) {
|
||||
if (isStarred) {
|
||||
starMenuItem.setIcon(hollowStar)
|
||||
currentSong!!.starred = false
|
||||
track.starred = false
|
||||
} else {
|
||||
starMenuItem.setIcon(fullStar)
|
||||
currentSong!!.starred = true
|
||||
track.starred = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -704,11 +698,11 @@ class PlayerFragment :
|
||||
return true
|
||||
}
|
||||
R.id.menu_item_bookmark_set -> {
|
||||
if (currentSong == null) return true
|
||||
if (track == null) return true
|
||||
|
||||
val songId = currentSong!!.id
|
||||
val songId = track.id
|
||||
val playerPosition = mediaPlayerController.playerPosition
|
||||
currentSong!!.bookmarkPosition = playerPosition
|
||||
track.bookmarkPosition = playerPosition
|
||||
val bookmarkTime = Util.formatTotalDuration(playerPosition.toLong(), true)
|
||||
Thread {
|
||||
val musicService = getMusicService()
|
||||
@ -726,10 +720,10 @@ class PlayerFragment :
|
||||
return true
|
||||
}
|
||||
R.id.menu_item_bookmark_delete -> {
|
||||
if (currentSong == null) return true
|
||||
if (track == null) return true
|
||||
|
||||
val bookmarkSongId = currentSong!!.id
|
||||
currentSong!!.bookmarkPosition = 0
|
||||
val bookmarkSongId = track.id
|
||||
track.bookmarkPosition = 0
|
||||
Thread {
|
||||
val musicService = getMusicService()
|
||||
try {
|
||||
@ -758,10 +752,10 @@ class PlayerFragment :
|
||||
return true
|
||||
}
|
||||
R.id.menu_item_share_song -> {
|
||||
if (currentSong == null) return true
|
||||
if (track == null) return true
|
||||
|
||||
val tracks: MutableList<Track?> = ArrayList()
|
||||
tracks.add(currentSong)
|
||||
tracks.add(track)
|
||||
|
||||
shareHandler.createShare(
|
||||
this,
|
||||
@ -856,6 +850,8 @@ class PlayerFragment :
|
||||
draggable = true,
|
||||
context = requireContext(),
|
||||
lifecycleOwner = viewLifecycleOwner,
|
||||
createContextMenu = { view, track -> onCreateContextMenu(view, track) },
|
||||
onContextMenuClick = { menu, id -> onContextMenuItemSelected(menu, id) },
|
||||
).apply {
|
||||
this.startDrag = { holder ->
|
||||
dragTouchHelper.startDrag(holder)
|
||||
|
@ -19,6 +19,7 @@ import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
@ -46,7 +47,6 @@ import org.moire.ultrasonic.subsonic.ShareHandler
|
||||
import org.moire.ultrasonic.subsonic.VideoPlayer.Companion.playVideo
|
||||
import org.moire.ultrasonic.util.CancellationToken
|
||||
import org.moire.ultrasonic.util.CommunicationError
|
||||
import org.moire.ultrasonic.util.Constants
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import org.moire.ultrasonic.util.Util.toast
|
||||
@ -54,8 +54,6 @@ import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Initiates a search on the media library and displays the results
|
||||
*
|
||||
* TODO: Move to SafeArgs
|
||||
*/
|
||||
class SearchFragment : MultiListFragment<Identifiable>(), KoinComponent {
|
||||
private var searchResult: SearchResult? = null
|
||||
@ -69,6 +67,8 @@ class SearchFragment : MultiListFragment<Identifiable>(), KoinComponent {
|
||||
|
||||
private var cancellationToken: CancellationToken? = null
|
||||
|
||||
private val navArgs by navArgs<SearchFragmentArgs>()
|
||||
|
||||
override val listModel: SearchListModel by viewModels()
|
||||
|
||||
override val mainLayout: Int = R.layout.search
|
||||
@ -133,14 +133,10 @@ class SearchFragment : MultiListFragment<Identifiable>(), KoinComponent {
|
||||
MoreButtonBinder()
|
||||
)
|
||||
|
||||
// Fragment was started with a query (e.g. from voice search), try to execute search right away
|
||||
val arguments = arguments
|
||||
if (arguments != null) {
|
||||
val query = arguments.getString(Constants.INTENT_QUERY)
|
||||
val autoPlay = arguments.getBoolean(Constants.INTENT_AUTOPLAY, false)
|
||||
if (query != null) {
|
||||
return search(query, autoPlay)
|
||||
}
|
||||
// If the fragment was started with a query (e.g. from voice search),
|
||||
// try to execute search right away
|
||||
if (navArgs.query != null) {
|
||||
return search(navArgs.query!!, navArgs.autoplay)
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,10 +152,8 @@ class SearchFragment : MultiListFragment<Identifiable>(), KoinComponent {
|
||||
val searchableInfo = searchManager.getSearchableInfo(requireActivity().componentName)
|
||||
searchView!!.setSearchableInfo(searchableInfo)
|
||||
|
||||
val arguments = arguments
|
||||
val autoPlay = arguments != null &&
|
||||
arguments.getBoolean(Constants.INTENT_AUTOPLAY, false)
|
||||
val query = arguments?.getString(Constants.INTENT_QUERY)
|
||||
val autoPlay = navArgs.autoplay
|
||||
val query = navArgs.query
|
||||
|
||||
// If started with a query, enter it to the searchView
|
||||
if (query != null) {
|
||||
|
@ -16,7 +16,6 @@ import org.moire.ultrasonic.adapters.ServerRowAdapter
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.OFFLINE_DB_ID
|
||||
import org.moire.ultrasonic.data.ServerSetting
|
||||
import org.moire.ultrasonic.fragment.EditServerFragment.Companion.EDIT_SERVER_INTENT_INDEX
|
||||
import org.moire.ultrasonic.model.ServerSettingsModel
|
||||
import org.moire.ultrasonic.service.MediaPlayerController
|
||||
import org.moire.ultrasonic.util.ErrorDialog
|
||||
@ -25,8 +24,6 @@ import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Displays the list of configured servers, they can be selected or edited
|
||||
*
|
||||
* TODO: Manage mode is unused. Remove it...
|
||||
*/
|
||||
class ServerSelectorFragment : Fragment() {
|
||||
|
||||
@ -143,8 +140,7 @@ class ServerSelectorFragment : Fragment() {
|
||||
* Starts the Edit Server Fragment to edit the details of a server
|
||||
*/
|
||||
private fun editServerByIndex(index: Int) {
|
||||
val bundle = Bundle()
|
||||
bundle.putInt(EDIT_SERVER_INTENT_INDEX, index)
|
||||
findNavController().navigate(R.id.serverSelectorToEditServer, bundle)
|
||||
val action = ServerSelectorFragmentDirections.toEditServer(index)
|
||||
findNavController().navigate(action)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* LyricsFragment.kt
|
||||
* Copyright (C) 2009-2022 Ultrasonic developers
|
||||
*
|
||||
* Distributed under terms of the GNU GPLv3 license.
|
||||
*/
|
||||
|
||||
package org.moire.ultrasonic.fragment.legacy
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.domain.Lyrics
|
||||
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle
|
||||
import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService
|
||||
import org.moire.ultrasonic.util.BackgroundTask
|
||||
import org.moire.ultrasonic.util.CancellationToken
|
||||
import org.moire.ultrasonic.util.FragmentBackgroundTask
|
||||
import org.moire.ultrasonic.util.Util.applyTheme
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Displays the lyrics of a song
|
||||
*
|
||||
* TODO: This file has been converted from Java, but not modernized yet.
|
||||
*/
|
||||
class LyricsFragment : Fragment() {
|
||||
private var artistView: TextView? = null
|
||||
private var titleView: TextView? = null
|
||||
private var textView: TextView? = null
|
||||
private var swipe: SwipeRefreshLayout? = null
|
||||
private var cancellationToken: CancellationToken? = null
|
||||
|
||||
private val navArgs by navArgs<LyricsFragmentArgs>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
applyTheme(this.context)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
return inflater.inflate(R.layout.lyrics, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
cancellationToken = CancellationToken()
|
||||
Timber.d("Lyrics set title")
|
||||
setTitle(this, R.string.download_menu_lyrics)
|
||||
swipe = view.findViewById(R.id.lyrics_refresh)
|
||||
swipe?.isEnabled = false
|
||||
artistView = view.findViewById(R.id.lyrics_artist)
|
||||
titleView = view.findViewById(R.id.lyrics_title)
|
||||
textView = view.findViewById(R.id.lyrics_text)
|
||||
load()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
cancellationToken!!.cancel()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
private fun load() {
|
||||
val task: BackgroundTask<Lyrics> = object : FragmentBackgroundTask<Lyrics>(
|
||||
activity, true, swipe, cancellationToken
|
||||
) {
|
||||
@Throws(Throwable::class)
|
||||
override fun doInBackground(): Lyrics {
|
||||
val musicService = getMusicService()
|
||||
return musicService.getLyrics(navArgs.artist, navArgs.title)!!
|
||||
}
|
||||
|
||||
override fun done(result: Lyrics) {
|
||||
if (result.artist != null) {
|
||||
artistView!!.text = result.artist
|
||||
titleView!!.text = result.title
|
||||
textView!!.text = result.text
|
||||
} else {
|
||||
artistView!!.setText(R.string.lyrics_nomatch)
|
||||
}
|
||||
}
|
||||
}
|
||||
task.execute()
|
||||
}
|
||||
}
|
@ -28,9 +28,6 @@ import timber.log.Timber
|
||||
|
||||
/**
|
||||
* This class is responsible for handling received events for the Media Player implementation
|
||||
*
|
||||
* TODO: Remove this class. Each component should listen to the lifecycleEvents and act on them
|
||||
* independently
|
||||
*/
|
||||
class MediaPlayerLifecycleSupport : KoinComponent {
|
||||
private val playbackStateSerializer by inject<PlaybackStateSerializer>()
|
||||
|
@ -25,9 +25,9 @@ class RxBus {
|
||||
val themeChangedEventObservable: Observable<Unit> =
|
||||
themeChangedEventPublisher.observeOn(mainThread())
|
||||
|
||||
val musicFolderChangedEventPublisher: PublishSubject<String> =
|
||||
val musicFolderChangedEventPublisher: PublishSubject<Folder> =
|
||||
PublishSubject.create()
|
||||
val musicFolderChangedEventObservable: Observable<String> =
|
||||
val musicFolderChangedEventObservable: Observable<Folder> =
|
||||
musicFolderChangedEventPublisher.observeOn(mainThread())
|
||||
|
||||
val playerStatePublisher: PublishSubject<StateWithTrack> =
|
||||
@ -93,6 +93,10 @@ class RxBus {
|
||||
val state: DownloadStatus,
|
||||
val progress: Int?
|
||||
)
|
||||
|
||||
data class Folder(
|
||||
val id: String?
|
||||
)
|
||||
}
|
||||
|
||||
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
|
||||
|
@ -15,14 +15,6 @@ object Constants {
|
||||
const val REST_PROTOCOL_VERSION = "1.7.0"
|
||||
const val REST_CLIENT_ID = "Ultrasonic"
|
||||
|
||||
// Legacy names for intent extras, in those fragments which don't use SafeArgs yet.
|
||||
const val INTENT_ARTIST = "subsonic.artist"
|
||||
const val INTENT_TITLE = "subsonic.title"
|
||||
const val INTENT_AUTOPLAY = "subsonic.playall"
|
||||
const val INTENT_QUERY = "subsonic.query"
|
||||
const val INTENT_ALBUM_LIST_TYPE = "subsonic.albumlisttype"
|
||||
const val INTENT_SHOW_PLAYER = "subsonic.showplayer"
|
||||
|
||||
// Names for Intent Actions
|
||||
const val CMD_PROCESS_KEYCODE = "org.moire.ultrasonic.CMD_PROCESS_KEYCODE"
|
||||
const val CMD_PLAY = "org.moire.ultrasonic.CMD_PLAY"
|
||||
@ -32,6 +24,7 @@ object Constants {
|
||||
const val CMD_STOP = "org.moire.ultrasonic.CMD_STOP"
|
||||
const val CMD_PREVIOUS = "org.moire.ultrasonic.CMD_PREVIOUS"
|
||||
const val CMD_NEXT = "org.moire.ultrasonic.CMD_NEXT"
|
||||
const val INTENT_SHOW_PLAYER = "org.moire.ultrasonic.SHOW_PLAYER"
|
||||
|
||||
// Legacy Preferences keys
|
||||
// Warning: Don't add any new here!
|
||||
|
@ -35,6 +35,11 @@
|
||||
a:icon="@drawable/ic_menu_remove_all"
|
||||
app:showAsAction="ifRoom|withText"
|
||||
a:title="@string/download.menu_clear_playlist"/>
|
||||
<item
|
||||
a:id="@+id/menu_lyrics"
|
||||
a:icon="@drawable/ic_library"
|
||||
app:showAsAction="ifRoom|withText"
|
||||
a:title="@string/download.menu_lyrics"/>
|
||||
<item
|
||||
a:id="@+id/menu_item_bookmark_set"
|
||||
a:icon="@drawable/ic_menu_bookmark"
|
||||
|
@ -212,6 +212,15 @@
|
||||
<action
|
||||
android:id="@+id/searchToAlbumsList"
|
||||
app:destination="@id/albumListFragment" />
|
||||
<argument
|
||||
android:name="query"
|
||||
app:argType="string"
|
||||
app:nullable="true"
|
||||
android:defaultValue="@null" />
|
||||
<argument
|
||||
android:name="autoplay"
|
||||
app:argType="boolean"
|
||||
android:defaultValue="false" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/playlistsFragment"
|
||||
@ -263,6 +272,9 @@
|
||||
<action
|
||||
android:id="@+id/playerToSelectAlbum"
|
||||
app:destination="@id/trackCollectionFragment" />
|
||||
<action
|
||||
android:id="@+id/playerToAlbumsList"
|
||||
app:destination="@id/albumListFragment" />
|
||||
<action
|
||||
android:id="@+id/playerToLyrics"
|
||||
app:destination="@id/lyricsFragment" />
|
||||
@ -272,7 +284,14 @@
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/lyricsFragment"
|
||||
android:name="org.moire.ultrasonic.fragment.LyricsFragment" />
|
||||
android:name="org.moire.ultrasonic.fragment.legacy.LyricsFragment" >
|
||||
<argument
|
||||
android:name="artist"
|
||||
app:argType="string" />
|
||||
<argument
|
||||
android:name="title"
|
||||
app:argType="string" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/equalizerFragment"
|
||||
android:name="org.moire.ultrasonic.fragment.EqualizerFragment" />
|
||||
@ -280,10 +299,18 @@
|
||||
android:id="@+id/serverSelectorFragment"
|
||||
android:name="org.moire.ultrasonic.fragment.ServerSelectorFragment" >
|
||||
<action
|
||||
android:id="@+id/serverSelectorToEditServer"
|
||||
android:id="@+id/toEditServer"
|
||||
app:destination="@id/editServerFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/editServerFragment"
|
||||
android:name="org.moire.ultrasonic.fragment.EditServerFragment" />
|
||||
android:name="org.moire.ultrasonic.fragment.EditServerFragment" >
|
||||
<argument
|
||||
android:name="index"
|
||||
app:argType="integer"
|
||||
android:defaultValue="-1" />
|
||||
</fragment>
|
||||
<action
|
||||
android:id="@+id/toSearchFragment"
|
||||
app:destination="@id/searchFragment" />
|
||||
</navigation>
|
Loading…
x
Reference in New Issue
Block a user