From 4b4853374c6ed6c5f0d82d19b2c47f1c12d31aa2 Mon Sep 17 00:00:00 2001 From: Nite Date: Sun, 10 Oct 2021 14:03:53 +0200 Subject: [PATCH 01/17] Moved server selector to the navigation menu --- .../ultrasonic/fragment/SettingsFragment.java | 19 ----- .../ultrasonic/activity/NavigationActivity.kt | 36 +++++++-- .../ultrasonic/data/ActiveServerProvider.kt | 5 ++ .../moire/ultrasonic/data/ServerSettingDao.kt | 6 ++ .../moire/ultrasonic/fragment/MainFragment.kt | 45 ----------- .../org/moire/ultrasonic/util/Constants.kt | 1 - .../src/main/res/layout/main_buttons.xml | 32 -------- .../src/main/res/layout/navigation_header.xml | 74 ++++++++++++------- .../src/main/res/layout/song_list_item.xml | 3 +- .../main/res/navigation/navigation_graph.xml | 6 -- ultrasonic/src/main/res/values/colors.xml | 3 +- ultrasonic/src/main/res/values/strings.xml | 1 + ultrasonic/src/main/res/values/styles.xml | 2 +- ultrasonic/src/main/res/values/themes.xml | 7 +- ultrasonic/src/main/res/xml/settings.xml | 9 --- 15 files changed, 99 insertions(+), 150 deletions(-) diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java index 3a7253d7..57106064 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java @@ -55,7 +55,6 @@ import static org.moire.ultrasonic.fragment.ServerSelectorFragment.SERVER_SELECT public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener { - private Preference addServerPreference; private ListPreference theme; private ListPreference maxBitrateWifi; private ListPreference maxBitrateMobile; @@ -110,7 +109,6 @@ public class SettingsFragment extends PreferenceFragmentCompat super.onViewCreated(view, savedInstanceState); FragmentTitle.Companion.setTitle(this, R.string.menu_settings); - addServerPreference = findPreference(Constants.PREFERENCES_KEY_SERVERS_EDIT); theme = findPreference(Constants.PREFERENCES_KEY_THEME); maxBitrateWifi = findPreference(Constants.PREFERENCES_KEY_MAX_BITRATE_WIFI); maxBitrateMobile = findPreference(Constants.PREFERENCES_KEY_MAX_BITRATE_MOBILE); @@ -141,7 +139,6 @@ public class SettingsFragment extends PreferenceFragmentCompat debugLogToFile = findPreference(Constants.PREFERENCES_KEY_DEBUG_LOG_TO_FILE); showArtistPicture = findPreference(Constants.PREFERENCES_KEY_SHOW_ARTIST_PICTURE); - setupServersCategory(); sharingDefaultGreeting.setText(Settings.getShareGreeting()); setupClearSearchPreference(); setupGaplessControlSettingsV14(); @@ -394,22 +391,6 @@ public class SettingsFragment extends PreferenceFragmentCompat } } - private void setupServersCategory() { - addServerPreference.setPersistent(false); - addServerPreference.setTitle(getResources().getString(R.string.settings_server_manage_servers)); - addServerPreference.setEnabled(true); - - addServerPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - Bundle bundle = new Bundle(); - bundle.putBoolean(SERVER_SELECTOR_MANAGE_MODE, true); - Navigation.findNavController(getView()).navigate(R.id.settingsToServerSelector, bundle); - return true; - } - }); - } - private void update() { theme.setSummary(theme.getEntry()); maxBitrateWifi.setSummary(maxBitrateWifi.getEntry()); 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 f2e9a626..ce29e4f2 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/NavigationActivity.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/NavigationActivity.kt @@ -12,12 +12,14 @@ import android.view.KeyEvent import android.view.Menu import android.view.MenuItem import android.view.View +import android.widget.Button import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.core.view.GravityCompat import androidx.drawerlayout.widget.DrawerLayout import androidx.fragment.app.FragmentContainerView import androidx.navigation.NavController +import androidx.navigation.Navigation import androidx.navigation.findNavController import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.AppBarConfiguration @@ -31,7 +33,7 @@ import org.koin.android.ext.android.inject import org.koin.androidx.viewmodel.ext.android.viewModel import org.moire.ultrasonic.R import org.moire.ultrasonic.data.ActiveServerProvider -import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline +import org.moire.ultrasonic.data.ServerSettingDao import org.moire.ultrasonic.domain.PlayerState import org.moire.ultrasonic.fragment.OnBackPressedHandler import org.moire.ultrasonic.fragment.ServerSettingsModel @@ -65,6 +67,7 @@ class NavigationActivity : AppCompatActivity() { private var navigationView: NavigationView? = null private var drawerLayout: DrawerLayout? = null private var host: NavHostFragment? = null + private var selectServerButton: Button? = null private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var nowPlayingEventListener: NowPlayingEventListener @@ -77,9 +80,12 @@ class NavigationActivity : AppCompatActivity() { private val nowPlayingEventDistributor: NowPlayingEventDistributor by inject() private val themeChangedEventDistributor: ThemeChangedEventDistributor by inject() private val permissionUtil: PermissionUtil by inject() + private val activeServerProvider: ActiveServerProvider by inject() + private val serverRepository: ServerSettingDao by inject() private var infoDialogDisplayed = false private var currentFragmentId: Int = 0 + private var cachedServerCount: Int = 0 override fun onCreate(savedInstanceState: Bundle?) { setUncaughtExceptionHandler() @@ -140,7 +146,7 @@ class NavigationActivity : AppCompatActivity() { } // Hides menu items for Offline mode - setMenuForServerSetting() + setMenuForServerCapabilities() } // Determine first run and migrate server settings to DB as early as possible @@ -179,12 +185,25 @@ class NavigationActivity : AppCompatActivity() { nowPlayingEventDistributor.subscribe(nowPlayingEventListener) themeChangedEventDistributor.subscribe(themeChangedEventListener) + + serverRepository.liveServerCount().observe(this, { count -> + cachedServerCount = count ?: 0 + setSelectServerButtonText() + }) + ActiveServerProvider.liveActiveServerId.observe(this, { setSelectServerButtonText() }) + } + + private fun setSelectServerButtonText() { + val activeServerName = activeServerProvider.getActiveServer().name + if (cachedServerCount == 0) + selectServerButton?.text = getString(R.string.main_setup_server, activeServerName) + else selectServerButton?.text = activeServerName } override fun onResume() { super.onResume() - setMenuForServerSetting() + setMenuForServerCapabilities() // Lifecycle support's constructor registers some event receivers so it should be created early lifecycleSupport.onCreate() @@ -232,6 +251,12 @@ class NavigationActivity : AppCompatActivity() { bookmarksMenuItem = navigationView?.menu?.findItem(R.id.bookmarksFragment) sharesMenuItem = navigationView?.menu?.findItem(R.id.sharesFragment) podcastsMenuItem = navigationView?.menu?.findItem(R.id.podcastFragment) + selectServerButton = navigationView?.getHeaderView(0)?.findViewById(R.id.header_select_server) + selectServerButton?.setOnClickListener { + if (drawerLayout?.isDrawerVisible(GravityCompat.START) == true) + this.drawerLayout?.closeDrawer(GravityCompat.START) + navController.navigate(R.id.serverSelectorFragment) + } } private fun setupActionBar(navController: NavController, appBarConfig: AppBarConfiguration) { @@ -381,15 +406,14 @@ class NavigationActivity : AppCompatActivity() { nowPlayingView?.visibility = View.GONE } - private fun setMenuForServerSetting() { - if (isOffline()) { + private fun setMenuForServerCapabilities() { + if (ActiveServerProvider.isOffline()) { chatMenuItem?.isVisible = false bookmarksMenuItem?.isVisible = false sharesMenuItem?.isVisible = false podcastsMenuItem?.isVisible = false return } - val activeServerProvider: ActiveServerProvider by inject() val activeServer = activeServerProvider.getActiveServer() chatMenuItem?.isVisible = activeServer.chatSupport != false bookmarksMenuItem?.isVisible = activeServer.bookmarkSupport != false diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ActiveServerProvider.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ActiveServerProvider.kt index 6b7d6d5f..75ee4fbe 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ActiveServerProvider.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ActiveServerProvider.kt @@ -1,5 +1,7 @@ package org.moire.ultrasonic.data +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.room.Room import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -178,6 +180,7 @@ class ActiveServerProvider( companion object { const val METADATA_DB = "$DB_FILENAME-meta-" + val liveActiveServerId: MutableLiveData = MutableLiveData(getActiveServerId()) /** * Queries if the Active Server is the "Offline" mode of Ultrasonic @@ -205,6 +208,8 @@ class ActiveServerProvider( val editor = preferences.edit() editor.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, serverId) editor.apply() + + liveActiveServerId.postValue(serverId) } /** diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSettingDao.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSettingDao.kt index c715892e..b09149cc 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSettingDao.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSettingDao.kt @@ -63,6 +63,12 @@ interface ServerSettingDao { @Query("SELECT COUNT(*) FROM serverSetting") suspend fun count(): Int? + /** + * Retrieves the count of rows in the table as a LiveData + */ + @Query("SELECT COUNT(*) FROM serverSetting") + fun liveServerCount(): LiveData + /** * Retrieves the greatest value of the Id column in the table */ diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/MainFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/MainFragment.kt index abb65951..56d33651 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/MainFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/MainFragment.kt @@ -7,14 +7,10 @@ import android.view.ViewGroup import android.widget.AdapterView import android.widget.AdapterView.OnItemClickListener import android.widget.ListView -import android.widget.TextView import androidx.fragment.app.Fragment import androidx.navigation.Navigation -import java.util.Locale import org.koin.core.component.KoinComponent -import org.koin.core.component.inject import org.moire.ultrasonic.R -import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline import org.moire.ultrasonic.util.Constants import org.moire.ultrasonic.util.MergeAdapter @@ -27,8 +23,6 @@ import org.moire.ultrasonic.util.Util class MainFragment : Fragment(), KoinComponent { private var list: ListView? = null - private lateinit var serverButton: View - private lateinit var serverTextView: TextView private lateinit var musicTitle: View private lateinit var artistsButton: View private lateinit var albumsButton: View @@ -48,8 +42,6 @@ class MainFragment : Fragment(), KoinComponent { private lateinit var albumsAlphaByArtistButton: View private lateinit var videosButton: View - private val activeServerProvider: ActiveServerProvider by inject() - override fun onCreate(savedInstanceState: Bundle?) { Util.applyTheme(this.context) super.onCreate(savedInstanceState) @@ -65,7 +57,6 @@ class MainFragment : Fragment(), KoinComponent { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { list = view.findViewById(R.id.main_list) - cachedActiveServerProperties = getActiveServerProperties() setupButtons() @@ -78,7 +69,6 @@ class MainFragment : Fragment(), KoinComponent { super.onResume() var shouldRestart = false val currentId3Setting = Settings.shouldUseId3Tags - val currentActiveServerProperties = getActiveServerProperties() // If setting has changed... if (currentId3Setting != shouldUseId3) { @@ -86,12 +76,6 @@ class MainFragment : Fragment(), KoinComponent { shouldRestart = true } - // or the server has changed... - if (currentActiveServerProperties != cachedActiveServerProperties) { - cachedActiveServerProperties = currentActiveServerProperties - shouldRestart = true - } - // then setup the list anew. if (shouldRestart) { if (list != null) setupMenuList(list!!) @@ -100,8 +84,6 @@ class MainFragment : Fragment(), KoinComponent { private fun setupButtons() { val buttons = layoutInflater.inflate(R.layout.main_buttons, list, false) - serverButton = buttons.findViewById(R.id.main_select_server) - serverTextView = serverButton.findViewById(R.id.main_select_server_2) musicTitle = buttons.findViewById(R.id.main_music) artistsButton = buttons.findViewById(R.id.main_artists_button) albumsButton = buttons.findViewById(R.id.main_albums_button) @@ -123,15 +105,10 @@ class MainFragment : Fragment(), KoinComponent { } private fun setupMenuList(list: ListView) { - // Set title - val activeServerName = activeServerProvider.getActiveServer().name - serverTextView.text = activeServerName // TODO: Should use RecyclerView val adapter = MergeAdapter() - adapter.addView(serverButton, true) - shouldUseId3 = Settings.shouldUseId3Tags if (!isOffline()) { @@ -177,9 +154,6 @@ class MainFragment : Fragment(), KoinComponent { private val listListener = OnItemClickListener { _: AdapterView<*>?, view: View, _: Int, _: Long -> when { - view === serverButton -> { - showServers() - } view === albumsNewestButton -> { showAlbumList("newest", R.string.main_albums_newest) } @@ -225,20 +199,6 @@ class MainFragment : Fragment(), KoinComponent { } } - private fun getActiveServerProperties(): String { - val server = activeServerProvider.getActiveServer() - return String.format( - Locale.ROOT, - "%s;%s;%s;%s;%s;%s", - server.url, - server.userName, - server.password, - server.allowSelfSignedCertificate, - server.ldapSupport, - server.minimumApiVersion - ) - } - private fun showStarredSongs() { val bundle = Bundle() bundle.putInt(Constants.INTENT_EXTRA_NAME_STARRED, 1) @@ -281,12 +241,7 @@ class MainFragment : Fragment(), KoinComponent { Navigation.findNavController(requireView()).navigate(R.id.mainToTrackCollection, bundle) } - private fun showServers() { - Navigation.findNavController(requireView()).navigate(R.id.mainToServerSelector) - } - companion object { private var shouldUseId3 = false - private var cachedActiveServerProperties: String? = null } } 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 908974c4..135ed3d2 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Constants.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/Constants.kt @@ -54,7 +54,6 @@ object Constants { // Preferences keys. const val PREFERENCES_KEY_SERVER_INSTANCE = "serverInstanceId" - const val PREFERENCES_KEY_SERVERS_EDIT = "editServers" const val PREFERENCES_KEY_THEME = "theme" const val PREFERENCES_KEY_THEME_LIGHT = "light" const val PREFERENCES_KEY_THEME_DARK = "dark" diff --git a/ultrasonic/src/main/res/layout/main_buttons.xml b/ultrasonic/src/main/res/layout/main_buttons.xml index cbdd8ca6..bc27ea5b 100644 --- a/ultrasonic/src/main/res/layout/main_buttons.xml +++ b/ultrasonic/src/main/res/layout/main_buttons.xml @@ -2,38 +2,6 @@ - - - - - - - - - - - - - - @@ -10,32 +13,53 @@ + a:src="@drawable/ic_launcher_background" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - + + + a:gravity="center_vertical" + a:paddingStart="16dp" + a:paddingLeft="16dp" + a:text="@string/common.appname" + a:textAppearance="@style/TextAppearance.AppCompat.Title" + app:layout_constraintBottom_toBottomOf="@+id/img_profile" + app:layout_constraintStart_toEndOf="@+id/img_profile" + app:layout_constraintTop_toTopOf="@+id/img_profile" /> - +