diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/LyricsFragment.java b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/LyricsFragment.java deleted file mode 100644 index f7f87b17..00000000 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/LyricsFragment.java +++ /dev/null @@ -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 task = new FragmentBackgroundTask(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(); - } -} diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/NavigationActivity.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/NavigationActivity.kt index a0c607c0..1502032d 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/NavigationActivity.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/NavigationActivity.kt @@ -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) } } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/FolderSelectorBinder.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/FolderSelectorBinder.kt index 0f7d7f1f..6b1d83ee 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/FolderSelectorBinder.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/FolderSelectorBinder.kt @@ -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 } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewBinder.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewBinder.kt index f6b96d10..a182166e 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewBinder.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewBinder.kt @@ -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(), 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) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EditServerFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EditServerFragment.kt index ed66cef3..47e094cb 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EditServerFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EditServerFragment.kt @@ -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() + @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 -> diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EntryListFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EntryListFragment.kt index 0cd26e32..c693c59c 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EntryListFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/EntryListFragment.kt @@ -64,7 +64,7 @@ abstract class EntryListFragment : MultiListFragment() { RxBus.musicFolderChangedEventObservable.subscribe { if (!listModel.isOffline()) { val currentSetting = listModel.activeServer - currentSetting.musicFolderId = it + currentSetting.musicFolderId = it.id serverSettingsModel.updateItem(currentSetting) } listModel.refresh(refreshListView!!) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/PlayerFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/PlayerFragment.kt index a19e4cda..7bf3095b 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/PlayerFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/PlayerFragment.kt @@ -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 = 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) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SearchFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SearchFragment.kt index d3b5d7f2..cfb8d0d8 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SearchFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SearchFragment.kt @@ -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(), KoinComponent { private var searchResult: SearchResult? = null @@ -69,6 +67,8 @@ class SearchFragment : MultiListFragment(), KoinComponent { private var cancellationToken: CancellationToken? = null + private val navArgs by navArgs() + override val listModel: SearchListModel by viewModels() override val mainLayout: Int = R.layout.search @@ -133,14 +133,10 @@ class SearchFragment : MultiListFragment(), 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(), 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) { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt index ffc6e9a5..370b470e 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt @@ -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) } } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/legacy/LyricsFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/legacy/LyricsFragment.kt new file mode 100644 index 00000000..05d0f05c --- /dev/null +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/legacy/LyricsFragment.kt @@ -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() + + 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 = object : FragmentBackgroundTask( + 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() + } +} diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.kt index dab9adee..f2a0c79a 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.kt @@ -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() diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/RxBus.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/RxBus.kt index dd8e19f0..7a7461ef 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/RxBus.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/RxBus.kt @@ -25,9 +25,9 @@ class RxBus { val themeChangedEventObservable: Observable = themeChangedEventPublisher.observeOn(mainThread()) - val musicFolderChangedEventPublisher: PublishSubject = + val musicFolderChangedEventPublisher: PublishSubject = PublishSubject.create() - val musicFolderChangedEventObservable: Observable = + val musicFolderChangedEventObservable: Observable = musicFolderChangedEventPublisher.observeOn(mainThread()) val playerStatePublisher: PublishSubject = @@ -93,6 +93,10 @@ class RxBus { val state: DownloadStatus, val progress: Int? ) + + data class Folder( + val id: String? + ) } operator fun CompositeDisposable.plusAssign(disposable: Disposable) { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Constants.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Constants.kt index a1135e6b..351de91c 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Constants.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Constants.kt @@ -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! diff --git a/ultrasonic/src/main/res/menu/nowplaying.xml b/ultrasonic/src/main/res/menu/nowplaying.xml index 40a469f5..1a9c79cc 100644 --- a/ultrasonic/src/main/res/menu/nowplaying.xml +++ b/ultrasonic/src/main/res/menu/nowplaying.xml @@ -35,6 +35,11 @@ a:icon="@drawable/ic_menu_remove_all" app:showAsAction="ifRoom|withText" a:title="@string/download.menu_clear_playlist"/> + + + + @@ -272,7 +284,14 @@ + android:name="org.moire.ultrasonic.fragment.legacy.LyricsFragment" > + + + @@ -280,10 +299,18 @@ android:id="@+id/serverSelectorFragment" android:name="org.moire.ultrasonic.fragment.ServerSelectorFragment" > + android:name="org.moire.ultrasonic.fragment.EditServerFragment" > + + + \ No newline at end of file