From 418fa31410700eb57413d33d2b006c883c9c0b4b Mon Sep 17 00:00:00 2001 From: Nguyen Duc Tuan Minh Date: Thu, 8 Aug 2024 23:16:46 +0700 Subject: [PATCH] Fixed #470 Fixed #472 Fixed #474 Fixed #475 Fixed #476 Fixed #477 --- .idea/CrowdinSettingsPlugin.xml | 9 + .idea/other.xml | 252 ++++++++++++++++++ .idea/render.experimental.xml | 2 +- .../simpmusic/adapter/home/HomeItemAdapter.kt | 131 --------- .../com/maxrave/simpmusic/common/Config.kt | 7 +- .../simpmusic/data/parser/ChartParser.kt | 9 +- .../simpmusic/data/parser/HomeParser.kt | 33 ++- .../com/maxrave/simpmusic/extension/AllExt.kt | 19 +- .../com/maxrave/simpmusic/extension/UIExt.kt | 9 + .../simpmusic/service/SimpleMediaService.kt | 7 +- .../service/SimpleMediaSessionCallback.kt | 3 +- .../com/maxrave/simpmusic/ui/MainActivity.kt | 3 +- .../ui/fragment/home/SettingsFragment.kt | 14 +- .../ui/fragment/other/AlbumFragment.kt | 18 +- .../ui/fragment/other/ArtistFragment.kt | 13 +- .../fragment/other/LocalPlaylistFragment.kt | 7 +- .../ui/fragment/other/PlaylistFragment.kt | 19 +- .../ui/fragment/other/PodcastFragment.kt | 22 +- .../ui/fragment/player/FullscreenFragment.kt | 1 + .../ui/screen/player/NowPlayingScreen.kt | 7 +- .../maxrave/kotlinytmusicscraper/YouTube.kt | 15 +- .../kotlinytmusicscraper/models/YTItem.kt | 19 ++ .../maxrave/kotlinytmusicscraper/test/main.kt | 35 --- 23 files changed, 433 insertions(+), 221 deletions(-) create mode 100644 .idea/CrowdinSettingsPlugin.xml create mode 100644 .idea/other.xml delete mode 100644 app/src/main/java/com/maxrave/simpmusic/adapter/home/HomeItemAdapter.kt diff --git a/.idea/CrowdinSettingsPlugin.xml b/.idea/CrowdinSettingsPlugin.xml new file mode 100644 index 00000000..68268a84 --- /dev/null +++ b/.idea/CrowdinSettingsPlugin.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/.idea/other.xml b/.idea/other.xml new file mode 100644 index 00000000..4604c446 --- /dev/null +++ b/.idea/other.xml @@ -0,0 +1,252 @@ + + + + + + \ No newline at end of file diff --git a/.idea/render.experimental.xml b/.idea/render.experimental.xml index 9a5015fb..11b5bb5f 100644 --- a/.idea/render.experimental.xml +++ b/.idea/render.experimental.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/app/src/main/java/com/maxrave/simpmusic/adapter/home/HomeItemAdapter.kt b/app/src/main/java/com/maxrave/simpmusic/adapter/home/HomeItemAdapter.kt deleted file mode 100644 index 4ba5c42a..00000000 --- a/app/src/main/java/com/maxrave/simpmusic/adapter/home/HomeItemAdapter.kt +++ /dev/null @@ -1,131 +0,0 @@ -package com.maxrave.simpmusic.adapter.home - -import android.content.Context -import android.os.Bundle -import android.util.Log -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.navigation.NavController -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import coil.load -import com.maxrave.simpmusic.R -import com.maxrave.simpmusic.common.Config -import com.maxrave.simpmusic.data.model.browse.album.Track -import com.maxrave.simpmusic.data.model.home.Content -import com.maxrave.simpmusic.data.model.home.HomeItem -import com.maxrave.simpmusic.databinding.ItemHomeBinding -import com.maxrave.simpmusic.extension.navigateSafe -import com.maxrave.simpmusic.extension.toTrack -import com.maxrave.simpmusic.service.PlaylistType -import com.maxrave.simpmusic.service.QueueData - -class HomeItemAdapter( - private var homeItemList: ArrayList, - var context: Context, - val navController: NavController, - private val onLongClickListener: HomeItemContentAdapter.OnSongOrVideoLongClickListener, - private val setQueueData: (queue: QueueData, type: String) -> Unit -) : RecyclerView.Adapter() { - inner class ViewHolder(var binding: ItemHomeBinding) : RecyclerView.ViewHolder(binding.root) - - fun updateData(newData: ArrayList) { - homeItemList.clear() - homeItemList.addAll(newData) - notifyDataSetChanged() - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val binding = ItemHomeBinding.inflate(LayoutInflater.from(parent.context), parent, false) - return ViewHolder(binding) - } - - override fun getItemCount(): Int { - return homeItemList.size - } - - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val homeItem = homeItemList[position] - holder.binding.tvTitle.text = homeItem.title - if (homeItem.subtitle == null) { - holder.binding.tvSubtitle.visibility = View.GONE - holder.binding.ivArtist.visibility = View.GONE - } else { - holder.binding.tvSubtitle.text = homeItem.subtitle - holder.binding.tvSubtitle.visibility = View.VISIBLE - } - if (!homeItem.thumbnail.isNullOrEmpty()) { - holder.binding.ivArtist.visibility = View.VISIBLE - holder.binding.ivArtist.load(homeItem.thumbnail.lastOrNull()?.url) - } else { - holder.binding.ivArtist.visibility = View.GONE - } - if (homeItem.channelId != null) { - holder.binding.tvTitle.isClickable = true - holder.binding.tvTitle.isFocusable = true - val attr = - context.obtainStyledAttributes(intArrayOf(android.R.attr.selectableItemBackgroundBorderless)) - holder.binding.tvTitle.foreground = attr.getDrawable(0) - attr.recycle() - holder.binding.tvTitle.setOnClickListener { - val args = Bundle() - args.putString("channelId", homeItem.channelId) - navController.navigateSafe(R.id.action_global_artistFragment, args) - } - } - val layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) - val tempContentList = homeItem.contents.toCollection(ArrayList()) - tempContentList.removeIf { it == null } - val itemAdapter = HomeItemContentAdapter(tempContentList as ArrayList, context) - holder.binding.childRecyclerview.apply { - this.adapter = itemAdapter - this.layoutManager = layoutManager - } - itemAdapter.setOnSongClickListener(object : HomeItemContentAdapter.onSongItemClickListener { - override fun onSongItemClick(position: Int) { - val firstQueue: Track = homeItemList[holder.bindingAdapterPosition].contents[position]!!.toTrack() - setQueueData( - QueueData( - listTracks = arrayListOf(firstQueue), - firstPlayedTrack = firstQueue, - playlistId = "RDAMVM${homeItemList[holder.bindingAdapterPosition].contents[position]?.videoId}", - playlistName = homeItem.title, - playlistType = PlaylistType.RADIO, - continuation = null - ), - Config.SONG_CLICK - ) - } - }) - itemAdapter.setOnPlaylistClickListener(object : HomeItemContentAdapter.onPlaylistItemClickListener{ - override fun onPlaylistItemClick(position: Int) { - val args = Bundle() - Log.d("HomeItemAdapter", "onPlaylistItemClick: ${homeItemList[holder.bindingAdapterPosition].contents[position]?.playlistId}") - args.putString("id", homeItemList[holder.bindingAdapterPosition].contents[position]?.playlistId) - navController.navigateSafe(R.id.action_global_playlistFragment, args) - } - }) - itemAdapter.setOnAlbumClickListener(object : HomeItemContentAdapter.onAlbumItemClickListener{ - override fun onAlbumItemClick(position: Int) { - val args = Bundle() - Log.d("HomeItemAdapter", "onAlbumItemClick: ${homeItemList[holder.bindingAdapterPosition].contents[position]?.browseId}") - args.putString("browseId", homeItemList[holder.bindingAdapterPosition].contents[position]?.browseId) - navController.navigateSafe(R.id.action_global_albumFragment, args) - } - }) - itemAdapter.setOnArtistClickListener(object : - HomeItemContentAdapter.onArtistItemClickListener { - override fun onArtistItemClick(position: Int) { - val args = Bundle() - val channelId = - homeItemList[holder.bindingAdapterPosition].contents[position]?.browseId - ?: homeItemList[holder.bindingAdapterPosition].contents[position]?.playlistId - Log.d("HomeItemAdapter", "onArtistItemClick: $channelId") - args.putString("channelId", channelId) - navController.navigateSafe(R.id.action_global_artistFragment, args) - } - }) - itemAdapter.setOnSongOrVideoLongClickListener(onLongClickListener) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/maxrave/simpmusic/common/Config.kt b/app/src/main/java/com/maxrave/simpmusic/common/Config.kt index 975604db..82706fe3 100644 --- a/app/src/main/java/com/maxrave/simpmusic/common/Config.kt +++ b/app/src/main/java/com/maxrave/simpmusic/common/Config.kt @@ -5,11 +5,6 @@ import java.time.LocalDateTime import java.time.Month object Config { - enum class SyncState { - LINE_SYNCED, - UNSYNCED, - NOT_FOUND, - } const val SPOTIFY_LOG_IN_URL: String = "https://accounts.spotify.com/en/login" const val SPOTIFY_ACCOUNT_URL = "https://accounts.spotify.com/en/status" @@ -203,7 +198,7 @@ object SUPPORTED_LANGUAGE { "fr-FR", "es-ES", "zh-CN", - "in-ID", + "id-ID", "ar-SA", "ja-JP", "zh-Hant-TW", diff --git a/app/src/main/java/com/maxrave/simpmusic/data/parser/ChartParser.kt b/app/src/main/java/com/maxrave/simpmusic/data/parser/ChartParser.kt index c994a56b..c8834034 100644 --- a/app/src/main/java/com/maxrave/simpmusic/data/parser/ChartParser.kt +++ b/app/src/main/java/com/maxrave/simpmusic/data/parser/ChartParser.kt @@ -105,7 +105,14 @@ fun parseChart(data: SectionListRenderer?): Chart? { id = it.navigationEndpoint?.browseEndpoint?.browseId ) }?.toMutableList()?.apply { - removeLastOrNull() + runCatching{ removeAt(this.lastIndex) } + .onSuccess { + Log.i("parse_mixed_content", "Removed last artist") + } + .onFailure { + Log.e("parse_mixed_content", "Failed to remove last artist") + it.printStackTrace() + } } ?: return null, duration = null, durationSeconds = null, diff --git a/app/src/main/java/com/maxrave/simpmusic/data/parser/HomeParser.kt b/app/src/main/java/com/maxrave/simpmusic/data/parser/HomeParser.kt index b3e0bb0f..500db454 100644 --- a/app/src/main/java/com/maxrave/simpmusic/data/parser/HomeParser.kt +++ b/app/src/main/java/com/maxrave/simpmusic/data/parser/HomeParser.kt @@ -137,7 +137,14 @@ fun parseMixedContent(data: List?, context: Context Regex("\\d") ) == true ) { - artists.removeLast() + runCatching{ artists.removeAt(artists.lastIndex) } + .onSuccess { + Log.i("parse_mixed_content", "Removed last artist") + } + .onFailure { + Log.e("parse_mixed_content", "Failed to remove last artist") + it.printStackTrace() + } } Log.w("Song", ytItem.toString()) if (ytItem != null) { @@ -178,7 +185,14 @@ fun parseMixedContent(data: List?, context: Context Regex("\\d") ) == true ) { - artists.removeLast() + runCatching{ artists.removeAt(artists.lastIndex) } + .onSuccess { + Log.i("parse_mixed_content", "Removed last artist") + } + .onFailure { + Log.e("parse_mixed_content", "Failed to remove last artist") + it.printStackTrace() + } } if (ytItem != null) { listContent.add( @@ -702,17 +716,24 @@ fun parseNewRelease(explore: ExplorePage, context: Context): ArrayList HomeItem( title = context.getString(R.string.music_video), contents = explore.musicVideo.map { videoItem -> - val artists = videoItem?.artists?.map { + val artists = videoItem.artists.map { Artist( name = it.name, id = it.id ) - }?.toMutableList() - if (artists?.lastOrNull()?.id == null && artists?.lastOrNull()?.name?.contains( + }.toMutableList() + if (artists.lastOrNull()?.id == null && artists.lastOrNull()?.name?.contains( Regex("\\d") ) == true ) { - artists.removeLast() + runCatching{ artists.removeAt(artists.lastIndex) } + .onSuccess { + Log.i("parse_mixed_content", "Removed last artist") + } + .onFailure { + Log.e("parse_mixed_content", "Failed to remove last artist") + it.printStackTrace() + } } Content( album = videoItem.album?.let { diff --git a/app/src/main/java/com/maxrave/simpmusic/extension/AllExt.kt b/app/src/main/java/com/maxrave/simpmusic/extension/AllExt.kt index 2eb46388..918d4dc0 100644 --- a/app/src/main/java/com/maxrave/simpmusic/extension/AllExt.kt +++ b/app/src/main/java/com/maxrave/simpmusic/extension/AllExt.kt @@ -60,12 +60,14 @@ import java.io.InputStream import java.io.OutputStream import java.time.LocalDateTime import java.time.temporal.ChronoUnit +import java.util.Locale import java.util.concurrent.TimeUnit import java.util.zip.ZipInputStream import java.util.zip.ZipOutputStream val Context.dataStore by preferencesDataStore(name = SETTINGS_FILENAME) +@Suppress("deprecation") fun Context.isMyServiceRunning(serviceClass: Class) = try { (getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) @@ -927,7 +929,22 @@ fun formatDuration(duration: Long): String { TimeUnit.SECONDS.convert(duration, TimeUnit.MILLISECONDS) - minutes * TimeUnit.SECONDS.convert(1, TimeUnit.MINUTES) ) - return String.format("%02d:%02d", minutes, seconds) + return "%02d:%02d".format(minutes, seconds) +} + +fun String?.format(vararg data: Any): String { + return try { + if (this != null) { + String.format(Locale.getDefault(), this, data) + } + else { + "" + } + } + catch (e: Exception) { + e.printStackTrace() + "" + } } fun parseTimestampToMilliseconds(timestamp: String): Double { diff --git a/app/src/main/java/com/maxrave/simpmusic/extension/UIExt.kt b/app/src/main/java/com/maxrave/simpmusic/extension/UIExt.kt index 8a7f4d5b..c284423b 100644 --- a/app/src/main/java/com/maxrave/simpmusic/extension/UIExt.kt +++ b/app/src/main/java/com/maxrave/simpmusic/extension/UIExt.kt @@ -7,6 +7,7 @@ import android.graphics.Point import android.os.Build import android.util.Log import android.view.View +import androidx.annotation.ColorInt import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.infiniteRepeatable import androidx.compose.animation.core.rememberInfiniteTransition @@ -268,6 +269,7 @@ fun Context.getActivityOrNull(): Activity? { } @Composable +@Suppress("DEPRECATION") fun getScreenSizeInfo(): ScreenSizeInfo { val context = LocalContext.current val activity = context.getActivityOrNull() @@ -387,4 +389,11 @@ fun LazyListState.isScrollingUp(): Boolean { } } }.value +} + +@Suppress("DEPRECATION") +fun setStatusBarsColor(@ColorInt color: Int, activity: Activity) { + if (Build.VERSION.SDK_INT < 35) { + activity.window.statusBarColor = color + } } \ No newline at end of file diff --git a/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaService.kt b/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaService.kt index c26ace69..cdf155f9 100644 --- a/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaService.kt +++ b/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaService.kt @@ -376,7 +376,12 @@ class SimpleMediaService : MediaLibraryService() { .setAudioProcessorChain( DefaultAudioSink.DefaultAudioProcessorChain( emptyArray(), - SilenceSkippingAudioProcessor(2_000_000, 20_000, 256), + SilenceSkippingAudioProcessor( + 2_000_000, (20_000/2_000_000).toFloat(), + 2_000_000, + 0, + 256 + ), SonicAudioProcessor() ) ) diff --git a/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaSessionCallback.kt b/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaSessionCallback.kt index e9068e1e..cf90cfff 100644 --- a/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaSessionCallback.kt +++ b/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaSessionCallback.kt @@ -16,6 +16,7 @@ import androidx.media3.session.MediaLibraryService import androidx.media3.session.MediaLibraryService.MediaLibrarySession import androidx.media3.session.MediaSession import androidx.media3.session.SessionCommand +import androidx.media3.session.SessionError import androidx.media3.session.SessionResult import com.google.common.collect.ImmutableList import com.google.common.util.concurrent.Futures @@ -322,7 +323,7 @@ class SimpleMediaSessionCallback LibraryResult.ofItem(it.toMediaItem(), null) } ?: mainRepository.getFullMetadata(mediaId).first()?.let { LibraryResult.ofItem(it.toTrack().toMediaItemWithoutPath(), null) - } ?: LibraryResult.ofError(LibraryResult.RESULT_ERROR_UNKNOWN) + } ?: LibraryResult.ofError(SessionError.ERROR_UNKNOWN) } @UnstableApi diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/MainActivity.kt b/app/src/main/java/com/maxrave/simpmusic/ui/MainActivity.kt index 8277d0aa..d17f6a92 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/MainActivity.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/MainActivity.kt @@ -74,6 +74,7 @@ import javax.inject.Inject @UnstableApi @AndroidEntryPoint +@Suppress("DEPRECATION") class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding val viewModel by viewModels() @@ -282,7 +283,7 @@ class MainActivity : AppCompatActivity() { binding.miniplayer.visibility = View.GONE } binding.root.addOnLayoutChangeListener { - v, + _, left, top, right, diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/home/SettingsFragment.kt b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/home/SettingsFragment.kt index 4fc7fe61..baa1f4f2 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/home/SettingsFragment.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/home/SettingsFragment.kt @@ -4,6 +4,7 @@ import android.app.usage.StorageStatsManager import android.content.Intent import android.media.audiofx.AudioEffect import android.net.Uri +import android.os.Build import android.os.Bundle import android.os.storage.StorageManager import android.util.Log @@ -664,9 +665,20 @@ class SettingsFragment : Fragment() { )] }.onSuccess { temp -> binding.tvLanguage.text = temp + val code = SUPPORTED_LANGUAGE.codes.getOrNull(checkedIndex) val localeList = LocaleListCompat.forLanguageTags( - SUPPORTED_LANGUAGE.codes.getOrNull(checkedIndex) + if (code == "id-ID") { + if (Build.VERSION.SDK_INT >= 35) { + "id-ID" + } else { + "in-ID" + } + } + else { + code + } ) + Log.d("Language", localeList.toString()) sharedViewModel.activityRecreate() AppCompatDelegate.setApplicationLocales(localeList) } diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/AlbumFragment.kt b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/AlbumFragment.kt index e1d6456b..26081bdb 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/AlbumFragment.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/AlbumFragment.kt @@ -52,6 +52,7 @@ import com.maxrave.simpmusic.extension.indexMap import com.maxrave.simpmusic.extension.navigateSafe import com.maxrave.simpmusic.extension.removeConflicts import com.maxrave.simpmusic.extension.setEnabledAll +import com.maxrave.simpmusic.extension.setStatusBarsColor import com.maxrave.simpmusic.extension.toAlbumEntity import com.maxrave.simpmusic.extension.toArrayListTrack import com.maxrave.simpmusic.extension.toListName @@ -101,8 +102,7 @@ class AlbumFragment : Fragment() { override fun onDestroyView() { super.onDestroyView() requireArguments().clear() - requireActivity().window.statusBarColor = - ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark) + setStatusBarsColor(ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark), requireActivity()) _binding = null } @@ -603,16 +603,18 @@ class AlbumFragment : Fragment() { binding.topAppBar.background = viewModel.gradientDrawable.value if (viewModel.gradientDrawable.value != null) { if (viewModel.gradientDrawable.value?.colors != null) { - requireActivity().window.statusBarColor = - viewModel.gradientDrawable.value - ?.colors!! - .first() + setStatusBarsColor(viewModel.gradientDrawable.value + ?.colors!! + .first(), requireActivity()) + } } } else { binding.topAppBar.background = null - requireActivity().window.statusBarColor = - ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark) + setStatusBarsColor( + ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark), + requireActivity(), + ) } } lifecycleScope.launch { diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/ArtistFragment.kt b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/ArtistFragment.kt index e846ff77..37a9fbf9 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/ArtistFragment.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/ArtistFragment.kt @@ -54,6 +54,7 @@ import com.maxrave.simpmusic.extension.connectArtists import com.maxrave.simpmusic.extension.navigateSafe import com.maxrave.simpmusic.extension.removeConflicts import com.maxrave.simpmusic.extension.setEnabledAll +import com.maxrave.simpmusic.extension.setStatusBarsColor import com.maxrave.simpmusic.extension.toListName import com.maxrave.simpmusic.extension.toSongEntity import com.maxrave.simpmusic.extension.toTrack @@ -100,7 +101,7 @@ class ArtistFragment : Fragment() { override fun onDestroyView() { super.onDestroyView() requireArguments().clear() - requireActivity().window.statusBarColor = ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark) + setStatusBarsColor(ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark), requireActivity()) _binding = null } @@ -491,15 +492,17 @@ class ArtistFragment : Fragment() { binding.toolBar.background = viewModel.gradientDrawable.value if (viewModel.gradientDrawable.value != null) { if (viewModel.gradientDrawable.value?.colors != null) { - requireActivity().window.statusBarColor = + setStatusBarsColor( viewModel.gradientDrawable.value ?.colors!! - .first() + .first(), + requireActivity() + ) } } } else { binding.toolBar.background = null - requireActivity().window.statusBarColor = ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark) + setStatusBarsColor(ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark), requireActivity()) Log.d("ArtistFragment", "Expanded") } } @@ -594,7 +597,7 @@ class ArtistFragment : Fragment() { } tvSubscribers.text = it.subscribers if (it.views == null) { - tvViews.text = "" + tvViews.text = getString(R.string.unknown) } else { tvViews.text = it.views.toString() } diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/LocalPlaylistFragment.kt b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/LocalPlaylistFragment.kt index 371bb16c..e05a33ec 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/LocalPlaylistFragment.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/LocalPlaylistFragment.kt @@ -31,6 +31,7 @@ import com.maxrave.simpmusic.adapter.playlist.SuggestItemAdapter import com.maxrave.simpmusic.common.DownloadState import com.maxrave.simpmusic.data.model.browse.album.Track import com.maxrave.simpmusic.databinding.FragmentLocalPlaylistBinding +import com.maxrave.simpmusic.extension.setStatusBarsColor import com.maxrave.simpmusic.ui.screen.library.PlaylistScreen import com.maxrave.simpmusic.ui.theme.AppTheme import com.maxrave.simpmusic.viewModel.LocalPlaylistViewModel @@ -1007,8 +1008,10 @@ class LocalPlaylistFragment : Fragment() { override fun onDestroyView() { super.onDestroyView() - requireActivity().window.statusBarColor = - ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark) + setStatusBarsColor( + ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark), + requireActivity() + ) _binding = null } diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/PlaylistFragment.kt b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/PlaylistFragment.kt index a9e326f9..017f17b4 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/PlaylistFragment.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/PlaylistFragment.kt @@ -49,6 +49,7 @@ import com.maxrave.simpmusic.extension.connectArtists import com.maxrave.simpmusic.extension.navigateSafe import com.maxrave.simpmusic.extension.removeConflicts import com.maxrave.simpmusic.extension.setEnabledAll +import com.maxrave.simpmusic.extension.setStatusBarsColor import com.maxrave.simpmusic.extension.toArrayListTrack import com.maxrave.simpmusic.extension.toListName import com.maxrave.simpmusic.extension.toListVideoId @@ -99,8 +100,10 @@ class PlaylistFragment : Fragment() { override fun onDestroyView() { super.onDestroyView() requireArguments().clear() - requireActivity().window.statusBarColor = - ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark) + setStatusBarsColor( + ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark), + requireActivity() + ) _binding = null } @@ -799,18 +802,22 @@ class PlaylistFragment : Fragment() { binding.collapsingToolbarLayout.isTitleEnabled = true if (viewModel.gradientDrawable.value != null) { if (viewModel.gradientDrawable.value?.colors != null) { - requireActivity().window.statusBarColor = + setStatusBarsColor( viewModel.gradientDrawable.value ?.colors!! - .first() + .first(), + requireActivity() + ) } } } else { binding.collapsingToolbarLayout.isTitleEnabled = false binding.topAppBar.background = null binding.topAppBarLayout.background = viewModel.gradientDrawable.value - requireActivity().window.statusBarColor = - ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark) + setStatusBarsColor( + ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark), + requireActivity() + ) } } binding.btShuffle.setOnClickListener { diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/PodcastFragment.kt b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/PodcastFragment.kt index 57ac321c..63ad5bc7 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/PodcastFragment.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/other/PodcastFragment.kt @@ -31,6 +31,7 @@ import com.maxrave.simpmusic.data.model.browse.album.Track import com.maxrave.simpmusic.data.model.podcast.PodcastBrowse import com.maxrave.simpmusic.databinding.BottomSheetPlaylistMoreBinding import com.maxrave.simpmusic.databinding.FragmentPodcastBinding +import com.maxrave.simpmusic.extension.setStatusBarsColor import com.maxrave.simpmusic.extension.toListTrack import com.maxrave.simpmusic.extension.toTrack import com.maxrave.simpmusic.service.PlaylistType @@ -66,8 +67,10 @@ class PodcastFragment : Fragment() { override fun onDestroyView() { super.onDestroyView() - requireActivity().window.statusBarColor = - ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark) + setStatusBarsColor( + ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark), + requireActivity() + ) _binding = null } @@ -102,15 +105,19 @@ class PodcastFragment : Fragment() { binding.collapsingToolbarLayout.isTitleEnabled = true if (viewModel.gradientDrawable.value != null) { if (viewModel.gradientDrawable.value?.colors != null) { - requireActivity().window.statusBarColor = - viewModel.gradientDrawable.value?.colors!!.first() + setStatusBarsColor( + viewModel.gradientDrawable.value?.colors!!.first(), + requireActivity() + ) } } } else { binding.collapsingToolbarLayout.isTitleEnabled = false binding.topAppBar.background = null - requireActivity().window.statusBarColor = - ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark) + setStatusBarsColor( + ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark), + requireActivity() + ) } } binding.btPlayPause.setOnClickListener { @@ -216,8 +223,7 @@ class PodcastFragment : Fragment() { } private fun fetchDataFromViewModel() { - val response = viewModel.podcastBrowse.value - when (response) { + when (val response = viewModel.podcastBrowse.value) { is Resource.Success -> { response.data?.let { with(binding) { diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/player/FullscreenFragment.kt b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/player/FullscreenFragment.kt index 5f81ed95..0c6df5b6 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/player/FullscreenFragment.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/player/FullscreenFragment.kt @@ -68,6 +68,7 @@ class FullscreenFragment : Fragment() { private val binding by lazy { BottomSheetFullscreenBinding.inflate(layoutInflater) } private var showJob: Job? = null + @Suppress("DEPRECATION") override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/screen/player/NowPlayingScreen.kt b/app/src/main/java/com/maxrave/simpmusic/ui/screen/player/NowPlayingScreen.kt index 0a340404..3dbf65d4 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/screen/player/NowPlayingScreen.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/screen/player/NowPlayingScreen.kt @@ -903,7 +903,7 @@ fun NowPlayingScreen( //Control Button Layout Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween, + horizontalArrangement = Arrangement.SpaceEvenly, modifier = Modifier .fillMaxWidth() .height(96.dp) @@ -1402,7 +1402,10 @@ fun NowPlayingScreen( ) Spacer(modifier = Modifier.height(10.dp)) Text( - text = stringResource(id = R.string.view_count, String.format(java.util.Locale.getDefault(), "%,d", screenDataState.songInfoData?.viewCount)), + text = stringResource( + id = R.string.view_count, + "%,d".format(screenDataState.songInfoData?.viewCount) + ), style = typo.labelMedium, color = Color.White, ) diff --git a/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/YouTube.kt b/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/YouTube.kt index d3018f31..e1764b15 100644 --- a/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/YouTube.kt +++ b/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/YouTube.kt @@ -20,6 +20,7 @@ import com.maxrave.kotlinytmusicscraper.models.SongInfo import com.maxrave.kotlinytmusicscraper.models.SongItem import com.maxrave.kotlinytmusicscraper.models.VideoItem import com.maxrave.kotlinytmusicscraper.models.WatchEndpoint +import com.maxrave.kotlinytmusicscraper.models.YTItemType import com.maxrave.kotlinytmusicscraper.models.YouTubeClient.Companion.ANDROID_MUSIC import com.maxrave.kotlinytmusicscraper.models.YouTubeClient.Companion.WEB import com.maxrave.kotlinytmusicscraper.models.YouTubeClient.Companion.WEB_REMIX @@ -648,17 +649,21 @@ object YouTube { // .orEmpty() ExplorePage( released = - response.contents?.singleColumnBrowseResultsRenderer?.tabs?.firstOrNull()?.tabRenderer?.content?.sectionListRenderer?.contents?.firstOrNull()?.gridRenderer?.items - ?.mapNotNull { it.musicTwoRowItemRenderer } - ?.mapNotNull(RelatedPage::fromMusicTwoRowItemRenderer) - .orEmpty() as List, + response.contents?.singleColumnBrowseResultsRenderer?.tabs?.firstOrNull()?.tabRenderer?.content?.sectionListRenderer?.contents?.firstOrNull()?.gridRenderer?.items + ?.mapNotNull { it.musicTwoRowItemRenderer } + ?.mapNotNull(RelatedPage::fromMusicTwoRowItemRenderer) + .orEmpty().mapNotNull { + if (it.type == YTItemType.PLAYLIST) it as? PlaylistItem else null + }, musicVideo = response.contents?.singleColumnBrowseResultsRenderer?.tabs?.firstOrNull()?.tabRenderer?.content?.sectionListRenderer?.contents?.lastOrNull()?.musicCarouselShelfRenderer?.contents?.mapNotNull { it.musicTwoRowItemRenderer } ?.mapNotNull( ArtistPage::fromMusicTwoRowItemRenderer, - ).orEmpty() as List, + ).orEmpty().mapNotNull { + if (it.type == YTItemType.VIDEO) it as? VideoItem else null + }, ) } diff --git a/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/models/YTItem.kt b/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/models/YTItem.kt index 1966f5fe..99225c1b 100644 --- a/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/models/YTItem.kt +++ b/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/models/YTItem.kt @@ -6,6 +6,7 @@ sealed class YTItem { abstract val thumbnail: String abstract val explicit: Boolean abstract val shareLink: String + abstract val type: YTItemType } data class Artist( @@ -31,6 +32,8 @@ data class SongItem( ) : YTItem() { override val shareLink: String get() = "https://music.youtube.com/watch?v=$id" + override val type: YTItemType + get() = YTItemType.SONG } data class VideoItem( override val id: String, @@ -47,6 +50,8 @@ data class VideoItem( ): YTItem() { override val shareLink: String get() = "https://music.youtube.com/watch?v=$id" + override val type: YTItemType + get() = YTItemType.VIDEO } data class AlbumItem( @@ -62,6 +67,8 @@ data class AlbumItem( ) : YTItem() { override val shareLink: String get() = "https://music.youtube.com/playlist?list=$playlistId" + override val type: YTItemType + get() = YTItemType.ALBUM } data class PlaylistItem( @@ -78,6 +85,8 @@ data class PlaylistItem( get() = false override val shareLink: String get() = "https://music.youtube.com/playlist?list=$id" + override val type: YTItemType + get() = YTItemType.PLAYLIST } data class ArtistItem( @@ -92,4 +101,14 @@ data class ArtistItem( get() = false override val shareLink: String get() = "https://music.youtube.com/channel/$id" + override val type: YTItemType + get() = YTItemType.ARTIST } + +enum class YTItemType { + SONG, + VIDEO, + ALBUM, + PLAYLIST, + ARTIST +} \ No newline at end of file diff --git a/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/test/main.kt b/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/test/main.kt index aa3915cb..6e750559 100644 --- a/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/test/main.kt +++ b/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/test/main.kt @@ -14,9 +14,6 @@ import com.maxrave.kotlinytmusicscraper.models.YouTubeLocale import com.maxrave.kotlinytmusicscraper.models.response.spotify.TokenResponse import io.ktor.client.call.body import io.ktor.client.statement.bodyAsText -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlin.random.Random @@ -75,38 +72,6 @@ fun testSongInfo() { } } -fun testPlayerYouTube() { - runBlocking { - var time = 0 - var isLoading = true - GlobalScope.launch { - while (isLoading) { - delay(100) - time += 100 - println("Loading... $time") - } - } - YouTube.apply { - locale = YouTubeLocale("VN", "vi") - }.player("QZrZbEEAOZ8").onSuccess { - println(it) - isLoading = false - println("\nTime $time ms") - }.onFailure { - it.printStackTrace() - isLoading = false - println("\nTime $time ms") - } - } -} - -suspend fun timer() { - GlobalScope.launch { - delay(1000) - println("World!") - } -} - fun testPlayer() { runBlocking { Ytmusic().apply {