Skip to content

Commit

Permalink
Replace deprecated menu functions with MenuProvider (#3776)
Browse files Browse the repository at this point in the history
* Squash merge Migrate to MenuProvider (#2974) by @NotWoods

* Merge fixes

* Update sensor detail fragment menu for multiserver

* Menu fixes/additions

 - Add HelpMenuProvider to Android Auto favorites
 - Fix notification history fragment having no view because of missing super call
 - Fix crash in device controls view if a server that is offline is selected

* ktlint

* Simplify some code

 - Undo formatting change in SettingsActivity
 - Don't require each activity to convert the string to URIs if we can do it in one place

* Remove setHasOptionsMenu(false) usage
  • Loading branch information
jpelgrom authored Aug 19, 2023
1 parent 01326db commit f722de9
Show file tree
Hide file tree
Showing 27 changed files with 489 additions and 559 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.net.toUri
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.lifecycle.Lifecycle
Expand All @@ -19,8 +19,8 @@ import com.google.android.gms.wearable.CapabilityInfo
import com.google.android.gms.wearable.Node
import com.google.android.gms.wearable.NodeClient
import com.google.android.gms.wearable.Wearable
import io.homeassistant.companion.android.R
import io.homeassistant.companion.android.databinding.ActivitySettingsWearBinding
import io.homeassistant.companion.android.settings.HelpMenuProvider
import io.homeassistant.companion.android.settings.wear.views.SettingsWearMainView
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
Expand All @@ -41,19 +41,6 @@ class SettingsWearActivity : AppCompatActivity(), CapabilityClient.OnCapabilityC
private var wearNodesWithApp: Set<Node>? = null
private var allConnectedNodes: List<Node>? = null

override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_activity_settings_wear, menu)
return true
}

override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
menu?.findItem(R.id.get_help)?.let {
it.isVisible = true
it.intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://companion.home-assistant.io/docs/wear-os"))
}
return true
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

Expand All @@ -70,6 +57,8 @@ class SettingsWearActivity : AppCompatActivity(), CapabilityClient.OnCapabilityC
openPlayStoreOnWearDevicesWithoutApp()
}

addMenuProvider(HelpMenuProvider("https://companion.home-assistant.io/docs/wear-os/wear-os".toUri()))

// Perform the initial update of the UI
updateUI()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.homeassistant.companion.android.settings

import android.content.Intent
import android.content.Intent.ACTION_VIEW
import android.net.Uri
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.core.net.toUri
import androidx.core.view.MenuHost
import androidx.core.view.MenuProvider
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import io.homeassistant.companion.android.R

/**
* Adds a "Get Help" menu option that opens the given [helpLink] in the browser.
*/
class HelpMenuProvider(private val helpLink: Uri) : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.menu_help, menu)
}

override fun onPrepareMenu(menu: Menu) {
menu.findItem(R.id.get_help).apply {
intent = Intent(ACTION_VIEW, helpLink)
}
}

// Don't handle the help item so the intent is automatically launched
override fun onMenuItemSelected(menuItem: MenuItem) = false
}

/**
* Wrapper around [MenuHost.addMenuProvider] to attach a [HelpMenuProvider] to a fragment's parent activity.
*/
fun Fragment.addHelpMenuProvider(helpLink: String) {
val menuHost: MenuHost = requireActivity()
menuHost.addMenuProvider(HelpMenuProvider(helpLink.toUri()), viewLifecycleOwner, Lifecycle.State.RESUMED)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView
import androidx.biometric.BiometricManager
import androidx.fragment.app.commit
import dagger.hilt.EntryPoint
Expand Down Expand Up @@ -50,17 +48,6 @@ class SettingsActivity : BaseActivity() {
}
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_activity_settings, menu)

(menu.findItem(R.id.action_search)?.actionView as SearchView).apply {
queryHint = getString(commonR.string.search_sensors)
maxWidth = Integer.MAX_VALUE
}

return true
}

override fun onCreate(savedInstanceState: Bundle?) {
val entryPoint = EntryPointAccessors.fromActivity(this, SettingsFragmentFactoryEntryPoint::class.java)
supportFragmentManager.fragmentFactory = entryPoint.getSettingsFragmentFactory()
Expand Down Expand Up @@ -93,6 +80,7 @@ class SettingsActivity : BaseActivity() {
} else {
SettingsFragment::class.java
}

settingsNavigation == "notification_history" -> NotificationHistoryFragment::class.java
settingsNavigation?.startsWith("sensors/") == true -> SensorDetailFragment::class.java
settingsNavigation?.startsWith("tiles/") == true -> ManageTilesFragment::class.java
Expand Down Expand Up @@ -240,6 +228,7 @@ class SettingsActivity : BaseActivity() {
}
}

/** Used to inject classes before [onCreate] */
@EntryPoint
@InstallIn(ActivityComponent::class)
interface SettingsFragmentFactoryEntryPoint {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package io.homeassistant.companion.android.settings.controls

import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
Expand All @@ -14,9 +11,9 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import com.google.accompanist.themeadapter.material.MdcTheme
import dagger.hilt.android.AndroidEntryPoint
import io.homeassistant.companion.android.R
import io.homeassistant.companion.android.common.data.integration.ControlsAuthRequiredSetting
import io.homeassistant.companion.android.common.data.servers.ServerManager
import io.homeassistant.companion.android.settings.addHelpMenuProvider
import io.homeassistant.companion.android.settings.controls.views.ManageControlsView
import javax.inject.Inject
import io.homeassistant.companion.android.common.R as commonR
Expand All @@ -30,21 +27,6 @@ class ManageControlsSettingsFragment : Fragment() {

val viewModel: ManageControlsViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}

@Deprecated("Deprecated in Java")
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)

menu.findItem(R.id.get_help)?.let {
it.isVisible = true
it.intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://companion.home-assistant.io/docs/integrations/android-device-controls"))
}
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand All @@ -69,6 +51,10 @@ class ManageControlsSettingsFragment : Fragment() {
}
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
addHelpMenuProvider("https://companion.home-assistant.io/docs/integrations/android-device-controls")
}

override fun onResume() {
super.onResume()
activity?.title = getString(commonR.string.controls_setting_title)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ fun ManageControlsView(
)
}
}
items(entitiesList[selectedServer]!!.size, key = { "$selectedServer.${entitiesList[selectedServer]?.get(it)?.entityId}" }) { index ->
items(entitiesList[selectedServer]?.size ?: 0, key = { "$selectedServer.${entitiesList[selectedServer]?.get(it)?.entityId}" }) { index ->
val entity = entitiesList[selectedServer]?.get(index) as Entity<Map<String, Any>>
ManageControlsEntity(
entityName = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
Expand All @@ -16,11 +18,13 @@ import android.widget.ScrollView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar
import androidx.core.content.FileProvider
import androidx.core.view.MenuHost
import androidx.core.view.MenuProvider
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import com.google.android.material.tabs.TabLayout
import dagger.hilt.android.AndroidEntryPoint
Expand Down Expand Up @@ -49,33 +53,45 @@ class LogFragment : Fragment() {
private var crashLog: String? = null
private var currentLog = ""

@Deprecated("Deprecated in Java")
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.share_log -> {
shareLog()
return true
}
R.id.refresh_log -> {
refreshLog()
}
private var toolbarGroupVisible = false
set(value) {
field = value
activity?.invalidateMenu()
}
return super.onOptionsItemSelected(item)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val menuHost: MenuHost = requireActivity()
menuHost.addMenuProvider(
object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.menu_fragment_log, menu)
}

override fun onPrepareMenu(menu: Menu) {
menu.setGroupVisible(R.id.log_toolbar_group, toolbarGroupVisible)
}

setHasOptionsMenu(true)
override fun onMenuItemSelected(menuItem: MenuItem) = when (menuItem.itemId) {
R.id.share_log -> {
shareLog()
true
}
R.id.refresh_log -> {
refreshLog()
true
}
else -> false
}
},
viewLifecycleOwner,
Lifecycle.State.RESUMED
)

requireView().findViewById<TabLayout>(R.id.logTabLayout)
.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
showLog()
}
override fun onTabSelected(tab: TabLayout.Tab?) = showLog()

override fun onTabUnselected(tab: TabLayout.Tab?) {
}
override fun onTabUnselected(tab: TabLayout.Tab?) {}

override fun onTabReselected(tab: TabLayout.Tab?) {
(requireView().findViewById<ScrollView>(R.id.logScrollview))?.apply {
Expand All @@ -95,17 +111,13 @@ class LogFragment : Fragment() {

private fun refreshLog() = lifecycleScope.launch(Dispatchers.Main) {
if (view != null && activity != null) {
val toolbar = requireActivity().findViewById<Toolbar>(R.id.toolbar)

toolbar.menu.setGroupVisible(R.id.log_toolbar_group, false)
showHideLogLoader(true)

// Runs with Dispatcher IO
processLog = LogcatReader.readLog()
crashLog = getLatestFatalCrash(requireContext(), prefsRepository.isCrashReporting())

showLog()
toolbar.menu.setGroupVisible(R.id.log_toolbar_group, true)
showHideLogLoader(false)
}
}
Expand Down Expand Up @@ -227,6 +239,7 @@ class LogFragment : Fragment() {
}

private fun showHideLogLoader(show: Boolean) {
toolbarGroupVisible = !show
if (view != null) {
val logLoader = requireView().findViewById<LinearLayout>(R.id.logLoader)
val logContents = requireView().findViewById<LinearLayout>(R.id.logContents)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package io.homeassistant.companion.android.settings.notification

import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
Expand All @@ -14,7 +11,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import com.google.accompanist.themeadapter.material.MdcTheme
import dagger.hilt.android.AndroidEntryPoint
import io.homeassistant.companion.android.R
import io.homeassistant.companion.android.settings.addHelpMenuProvider
import io.homeassistant.companion.android.settings.notification.views.NotificationChannelView
import io.homeassistant.companion.android.common.R as commonR

Expand All @@ -23,21 +20,6 @@ class NotificationChannelFragment : Fragment() {

val viewModel: NotificationViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}

@Deprecated("Deprecated in Java")
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)

menu.findItem(R.id.get_help)?.let {
it.isVisible = true
it.intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-channels"))
}
}

@RequiresApi(Build.VERSION_CODES.O)
override fun onCreateView(
inflater: LayoutInflater,
Expand All @@ -53,6 +35,10 @@ class NotificationChannelFragment : Fragment() {
}
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
addHelpMenuProvider("https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-channels")
}

override fun onResume() {
super.onResume()
activity?.title = getString(commonR.string.notification_channels)
Expand Down
Loading

0 comments on commit f722de9

Please sign in to comment.