/* * Copyright (c) 2020 Hemanth Savarla. * * Licensed under the GNU General Public License v3 * * This is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * */ package code.name.monkey.retromusic.activities import android.content.Intent import android.content.SharedPreferences import android.content.SharedPreferences.OnSharedPreferenceChangeListener import android.net.Uri import android.os.Bundle import android.provider.MediaStore import androidx.lifecycle.lifecycleScope import androidx.navigation.contains import androidx.navigation.ui.setupWithNavController import code.name.monkey.retromusic.* import code.name.monkey.retromusic.activities.base.AbsCastActivity import code.name.monkey.retromusic.databinding.SlidingMusicPanelLayoutBinding import code.name.monkey.retromusic.extensions.* import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewFragment import code.name.monkey.retromusic.fragments.home.HomeFragment import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.SearchQueryHelper.getSongs import code.name.monkey.retromusic.model.CategoryInfo import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.repository.PlaylistSongsLoader import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.util.AppRater import code.name.monkey.retromusic.util.PreferenceUtil import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.launch import org.koin.android.ext.android.get class MainActivity : AbsCastActivity(), OnSharedPreferenceChangeListener { companion object { const val TAG = "MainActivity" const val EXPAND_PANEL = "expand_panel" } override fun createContentView(): SlidingMusicPanelLayoutBinding { return wrapSlidingMusicPanel() } override fun onCreate(savedInstanceState: Bundle?) { setDrawUnderStatusBar() super.onCreate(savedInstanceState) setTaskDescriptionColorAuto() hideStatusBar() updateTabs() AppRater.appLaunched(this) setupNavigationController() if (!hasPermissions()) { findNavController(R.id.fragment_container).navigate(R.id.permissionFragment) } } private fun setupNavigationController() { val navController = findNavController(R.id.fragment_container) val navInflater = navController.navInflater val navGraph = navInflater.inflate(R.navigation.main_graph) val categoryInfo: CategoryInfo = PreferenceUtil.libraryCategory.first { it.visible } if (categoryInfo.visible) { if (!navGraph.contains(PreferenceUtil.lastTab)) PreferenceUtil.lastTab = categoryInfo.category.id navGraph.setStartDestination( if (PreferenceUtil.rememberLastTab) { PreferenceUtil.lastTab.let { if (it == 0) { categoryInfo.category.id } else { it } } } else categoryInfo.category.id ) } navController.graph = navGraph bottomNavigationView.setupWithNavController(navController) // Scroll Fragment to top bottomNavigationView.setOnItemReselectedListener { currentFragment(R.id.fragment_container) .also { if (it is AbsRecyclerViewFragment<*, *>) { it.scrollToTop() } if (it is HomeFragment) { it.scrollToTop() } } } // This is more like a work-around as for start destination of navGraph // enterTransition won't work as expected navGraph.setStartDestination(R.id.libraryFragment) navController.addOnDestinationChangedListener { _, destination, _ -> when (destination.id) { R.id.action_home, R.id.action_song, R.id.action_album, R.id.action_artist, R.id.action_folder, R.id.action_playlist, R.id.action_genre -> { // Save the last tab if (PreferenceUtil.rememberLastTab) { saveTab(destination.id) } // Show Bottom Navigation Bar setBottomNavVisibility(visible = true, animate = true) } R.id.playing_queue_fragment -> { setBottomNavVisibility(visible = false) hideBottomSheet(true) } else -> setBottomNavVisibility(visible = false, animate = true) // Hide Bottom Navigation Bar } } } private fun saveTab(id: Int) { PreferenceUtil.lastTab = id } override fun onSupportNavigateUp(): Boolean = findNavController(R.id.fragment_container).navigateUp() override fun onResume() { super.onResume() PreferenceUtil.registerOnSharedPreferenceChangedListener(this) val expand = extra(EXPAND_PANEL).value ?: false if (expand && PreferenceUtil.isExpandPanel) { expandPanel() intent.removeExtra(EXPAND_PANEL) } } override fun onDestroy() { super.onDestroy() PreferenceUtil.unregisterOnSharedPreferenceChangedListener(this) } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { if (key == GENERAL_THEME || key == MATERIAL_YOU || key == BLACK_THEME || key == ADAPTIVE_COLOR_APP || key == USER_NAME || key == TOGGLE_FULL_SCREEN || key == TOGGLE_VOLUME || key == ROUND_CORNERS || key == CAROUSEL_EFFECT || key == NOW_PLAYING_SCREEN_ID || key == TOGGLE_GENRE || key == BANNER_IMAGE_PATH || key == PROFILE_IMAGE_PATH || key == CIRCULAR_ALBUM_ART || key == KEEP_SCREEN_ON || key == TOGGLE_SEPARATE_LINE || key == TOGGLE_HOME_BANNER || key == TOGGLE_ADD_CONTROLS || key == ALBUM_COVER_STYLE || key == HOME_ARTIST_GRID_STYLE || key == ALBUM_COVER_TRANSFORM || key == DESATURATED_COLOR || key == EXTRA_SONG_INFO || key == TAB_TEXT_MODE || key == LANGUAGE_NAME || key == LIBRARY_CATEGORIES) { postRecreate() } } override fun onServiceConnected() { super.onServiceConnected() intent ?: return handlePlaybackIntent(intent) } private fun handlePlaybackIntent(intent: Intent) { lifecycleScope.launch(IO) { val uri: Uri? = intent.data val mimeType: String? = intent.type var handled = false if (intent.action != null && intent.action == MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH ) { val songs: List = getSongs(intent.extras!!) if (MusicPlayerRemote.shuffleMode == MusicService.SHUFFLE_MODE_SHUFFLE) { MusicPlayerRemote.openAndShuffleQueue(songs, true) } else { MusicPlayerRemote.openQueue(songs, 0, true) } handled = true } if (uri != null && uri.toString().isNotEmpty()) { MusicPlayerRemote.playFromUri(uri) handled = true } else if (MediaStore.Audio.Playlists.CONTENT_TYPE == mimeType) { val id = parseLongFromIntent(intent, "playlistId", "playlist") if (id >= 0L) { val position: Int = intent.getIntExtra("position", 0) val songs: List = PlaylistSongsLoader.getPlaylistSongList(get(), id) MusicPlayerRemote.openQueue(songs, position, true) handled = true } } else if (MediaStore.Audio.Albums.CONTENT_TYPE == mimeType) { val id = parseLongFromIntent(intent, "albumId", "album") if (id >= 0L) { val position: Int = intent.getIntExtra("position", 0) val songs = libraryViewModel.albumById(id).songs MusicPlayerRemote.openQueue( songs, position, true ) handled = true } } else if (MediaStore.Audio.Artists.CONTENT_TYPE == mimeType) { val id = parseLongFromIntent(intent, "artistId", "artist") if (id >= 0L) { val position: Int = intent.getIntExtra("position", 0) val songs: List = libraryViewModel.artistById(id).songs MusicPlayerRemote.openQueue( songs, position, true ) handled = true } } if (handled) { setIntent(Intent()) } } } private fun parseLongFromIntent( intent: Intent, longKey: String, stringKey: String ): Long { var id = intent.getLongExtra(longKey, -1) if (id < 0) { val idString = intent.getStringExtra(stringKey) if (idString != null) { try { id = idString.toLong() } catch (e: NumberFormatException) { println(e.message) } } } return id } }