mirror of
https://github.com/home-assistant/android
synced 2024-07-22 10:54:12 +00:00
Tweak onboarding design to be more unified (#2979)
This commit is contained in:
parent
e637b423f2
commit
760aca4fa1
|
@ -74,7 +74,8 @@ class SettingsWearMainView : AppCompatActivity() {
|
|||
url = registerUrl,
|
||||
defaultDeviceName = currentNodes.firstOrNull()?.displayName ?: "unknown",
|
||||
locationTrackingPossible = false,
|
||||
notificationsPossible = false
|
||||
notificationsPossible = false,
|
||||
isWatch = true
|
||||
) // While notifications are technically possible, the app can't handle this for the Wear device
|
||||
)
|
||||
}
|
||||
|
|
|
@ -13,12 +13,14 @@ class OnboardApp : ActivityResultContract<OnboardApp.Input, OnboardApp.Output?>(
|
|||
private const val EXTRA_DEFAULT_DEVICE_NAME = "extra_default_device_name"
|
||||
private const val EXTRA_LOCATION_TRACKING_POSSIBLE = "location_tracking_possible"
|
||||
private const val EXTRA_NOTIFICATIONS_POSSIBLE = "notifications_possible"
|
||||
private const val EXTRA_IS_WATCH = "extra_is_watch"
|
||||
|
||||
fun parseInput(intent: Intent): Input = Input(
|
||||
url = intent.getStringExtra(EXTRA_URL),
|
||||
defaultDeviceName = intent.getStringExtra(EXTRA_DEFAULT_DEVICE_NAME) ?: Build.MODEL,
|
||||
locationTrackingPossible = intent.getBooleanExtra(EXTRA_LOCATION_TRACKING_POSSIBLE, false),
|
||||
notificationsPossible = intent.getBooleanExtra(EXTRA_NOTIFICATIONS_POSSIBLE, true)
|
||||
notificationsPossible = intent.getBooleanExtra(EXTRA_NOTIFICATIONS_POSSIBLE, true),
|
||||
isWatch = intent.getBooleanExtra(EXTRA_IS_WATCH, false)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -26,7 +28,8 @@ class OnboardApp : ActivityResultContract<OnboardApp.Input, OnboardApp.Output?>(
|
|||
val url: String? = null,
|
||||
val defaultDeviceName: String = Build.MODEL,
|
||||
val locationTrackingPossible: Boolean = BuildConfig.FLAVOR == "full",
|
||||
val notificationsPossible: Boolean = true
|
||||
val notificationsPossible: Boolean = true,
|
||||
val isWatch: Boolean = false
|
||||
)
|
||||
|
||||
data class Output(
|
||||
|
@ -53,6 +56,7 @@ class OnboardApp : ActivityResultContract<OnboardApp.Input, OnboardApp.Output?>(
|
|||
putExtra(EXTRA_DEFAULT_DEVICE_NAME, input.defaultDeviceName)
|
||||
putExtra(EXTRA_LOCATION_TRACKING_POSSIBLE, input.locationTrackingPossible)
|
||||
putExtra(EXTRA_NOTIFICATIONS_POSSIBLE, input.notificationsPossible)
|
||||
putExtra(EXTRA_IS_WATCH, input.isWatch)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ class OnboardingActivity : AppCompatActivity() {
|
|||
NotificationManagerCompat.from(this).areNotificationsEnabled()
|
||||
)
|
||||
} else false
|
||||
viewModel.deviceIsWatch = input.isWatch
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
supportFragmentManager.commit {
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package io.homeassistant.companion.android.onboarding
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.mikepenz.iconics.compose.Image
|
||||
import com.mikepenz.iconics.typeface.IIcon
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
||||
@Composable
|
||||
fun OnboardingHeaderView(
|
||||
icon: IIcon,
|
||||
title: String
|
||||
) {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
Image(
|
||||
asset = icon,
|
||||
colorFilter = ColorFilter.tint(colorResource(commonR.color.colorAccent)),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.h5,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.padding(vertical = 16.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -49,6 +49,7 @@ class OnboardingViewModel @Inject constructor(
|
|||
private set
|
||||
var authCode by mutableStateOf("")
|
||||
private set
|
||||
var deviceIsWatch by mutableStateOf(false)
|
||||
val deviceName = mutableStateOf("")
|
||||
val locationTrackingPossible = mutableStateOf(false)
|
||||
var locationTrackingEnabled by mutableStateOf(false)
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
package io.homeassistant.companion.android.onboarding.discovery
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
|
@ -18,17 +14,10 @@ import io.homeassistant.companion.android.onboarding.OnboardingViewModel
|
|||
import io.homeassistant.companion.android.onboarding.authentication.AuthenticationFragment
|
||||
import io.homeassistant.companion.android.onboarding.manual.ManualSetupFragment
|
||||
import javax.inject.Inject
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
||||
@AndroidEntryPoint
|
||||
class DiscoveryFragment @Inject constructor() : Fragment() {
|
||||
|
||||
companion object {
|
||||
|
||||
private const val TAG = "DiscoveryFragment"
|
||||
private const val HOME_ASSISTANT = "https://www.home-assistant.io"
|
||||
}
|
||||
|
||||
private val viewModel by activityViewModels<OnboardingViewModel>()
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -43,7 +32,6 @@ class DiscoveryFragment @Inject constructor() : Fragment() {
|
|||
MdcTheme {
|
||||
DiscoveryView(
|
||||
onboardingViewModel = viewModel,
|
||||
whatIsThisClicked = { openHomeAssistantHomePage() },
|
||||
manualSetupClicked = { navigateToManualSetup() },
|
||||
instanceClicked = { onInstanceClicked(it) }
|
||||
)
|
||||
|
@ -52,18 +40,6 @@ class DiscoveryFragment @Inject constructor() : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun openHomeAssistantHomePage() {
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.data = Uri.parse(HOME_ASSISTANT)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
try {
|
||||
startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to load Home Assistant home page", e)
|
||||
Toast.makeText(context, commonR.string.what_is_this_crash, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToManualSetup() {
|
||||
parentFragmentManager
|
||||
.beginTransaction()
|
||||
|
|
|
@ -4,95 +4,89 @@ import androidx.compose.foundation.clickable
|
|||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material.ContentAlpha
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.LinearProgressIndicator
|
||||
import androidx.compose.material.LocalContentAlpha
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import io.homeassistant.companion.android.R
|
||||
import io.homeassistant.companion.android.onboarding.OnboardingHeaderView
|
||||
import io.homeassistant.companion.android.onboarding.OnboardingViewModel
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
||||
@Composable
|
||||
fun DiscoveryView(
|
||||
onboardingViewModel: OnboardingViewModel,
|
||||
whatIsThisClicked: () -> Unit,
|
||||
manualSetupClicked: () -> Unit,
|
||||
instanceClicked: (instance: HomeAssistantInstance) -> Unit
|
||||
) {
|
||||
val scrollState = rememberScrollState()
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
|
||||
TextButton(
|
||||
onClick = whatIsThisClicked,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(commonR.string.what_is_this)
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = stringResource(id = commonR.string.select_instance),
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(20.dp)
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
) {
|
||||
OnboardingHeaderView(
|
||||
icon = CommunityMaterial.Icon2.cmd_home_search,
|
||||
title = stringResource(id = commonR.string.select_instance)
|
||||
)
|
||||
Column(
|
||||
LinearProgressIndicator(
|
||||
modifier = Modifier.fillMaxWidth(0.25f)
|
||||
.padding(vertical = 16.dp)
|
||||
.height(2.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.verticalScroll(scrollState)
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight()
|
||||
.padding(20.dp)
|
||||
.weight(1f)
|
||||
) {
|
||||
onboardingViewModel.foundInstances.forEach { instance ->
|
||||
items(onboardingViewModel.foundInstances.size, { onboardingViewModel.foundInstances[it].url }) { index ->
|
||||
val instance = onboardingViewModel.foundInstances[index]
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 56.dp)
|
||||
.clickable(onClick = { instanceClicked(instance) })
|
||||
) {
|
||||
Column {
|
||||
Text(
|
||||
text = instance.name,
|
||||
style = TextStyle(
|
||||
fontSize = 20.sp
|
||||
Text(instance.name)
|
||||
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
|
||||
Text(
|
||||
text = instance.url.toString(),
|
||||
fontSize = 14.sp
|
||||
)
|
||||
)
|
||||
Text(
|
||||
text = instance.url.toString(),
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.navigate_next),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
Divider(Modifier.padding(10.dp))
|
||||
Divider(Modifier.padding(8.dp))
|
||||
}
|
||||
}
|
||||
TextButton(
|
||||
onClick = manualSetupClicked,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(10.dp)
|
||||
.padding(top = 16.dp)
|
||||
) {
|
||||
Text(text = stringResource(commonR.string.manual_setup))
|
||||
}
|
||||
|
|
|
@ -17,12 +17,15 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import io.homeassistant.companion.android.onboarding.OnboardingHeaderView
|
||||
import io.homeassistant.companion.android.onboarding.OnboardingViewModel
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
||||
|
@ -42,10 +45,15 @@ fun MobileAppIntegrationView(
|
|||
.padding(16.dp)
|
||||
) {
|
||||
|
||||
Text(
|
||||
text = stringResource(id = commonR.string.connect_to_home_assistant),
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
OnboardingHeaderView(
|
||||
icon = if (onboardingViewModel.deviceIsWatch) {
|
||||
CommunityMaterial.Icon3.cmd_watch
|
||||
} else if (LocalConfiguration.current.screenWidthDp.dp >= 600.dp) {
|
||||
CommunityMaterial.Icon3.cmd_tablet
|
||||
} else {
|
||||
CommunityMaterial.Icon.cmd_cellphone
|
||||
},
|
||||
title = stringResource(id = commonR.string.connect_to_home_assistant)
|
||||
)
|
||||
|
||||
TextField(
|
||||
|
|
|
@ -14,9 +14,11 @@ import androidx.compose.ui.ExperimentalComposeUiApi
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import io.homeassistant.companion.android.onboarding.OnboardingHeaderView
|
||||
import io.homeassistant.companion.android.onboarding.OnboardingViewModel
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
||||
|
@ -31,21 +33,20 @@ fun ManualSetupView(
|
|||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(20.dp)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
|
||||
Text(
|
||||
text = stringResource(commonR.string.manual_title),
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
OnboardingHeaderView(
|
||||
icon = CommunityMaterial.Icon3.cmd_web,
|
||||
title = stringResource(id = commonR.string.manual_title)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = stringResource(id = commonR.string.manual_desc),
|
||||
fontWeight = FontWeight.Light,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(20.dp)
|
||||
.padding(bottom = 16.dp)
|
||||
)
|
||||
|
||||
TextField(
|
||||
|
@ -68,7 +69,7 @@ fun ManualSetupView(
|
|||
onClick = connectedClicked,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(10.dp)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Text(stringResource(commonR.string.connect))
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.Spacer
|
|||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.Button
|
||||
|
@ -14,13 +13,10 @@ import androidx.compose.material.Icon
|
|||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Notifications
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
@ -29,6 +25,7 @@ import com.google.android.material.composethemeadapter.MdcTheme
|
|||
import com.mikepenz.iconics.compose.Image
|
||||
import com.mikepenz.iconics.typeface.IIcon
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import io.homeassistant.companion.android.onboarding.OnboardingHeaderView
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
||||
@Composable
|
||||
|
@ -46,23 +43,11 @@ fun NotificationPermissionView(
|
|||
modifier = Modifier
|
||||
.verticalScroll(scrollState)
|
||||
.fillMaxWidth()
|
||||
.padding(top = 32.dp)
|
||||
.weight(1f)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Notifications,
|
||||
contentDescription = null,
|
||||
tint = colorResource(id = commonR.color.colorAccent),
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = commonR.string.notifications),
|
||||
style = MaterialTheme.typography.h5,
|
||||
modifier = Modifier
|
||||
.padding(vertical = 16.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
OnboardingHeaderView(
|
||||
icon = CommunityMaterial.Icon.cmd_bell_outline,
|
||||
title = stringResource(id = commonR.string.notifications)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = commonR.string.onboarding_notifications_subtitle),
|
||||
|
|
|
@ -333,9 +333,9 @@
|
|||
<string name="manage_wear_device">Manage device %1$s</string>
|
||||
<string name="manage_widgets_summary">Edit your widgets, adding/deleting can only be done from the home screen</string>
|
||||
<string name="manage_widgets">Manage Widgets</string>
|
||||
<string name="manual_desc">Enter the URL of your Home Assistant server. Make sure the URL includes the protocol and port. For example:\n\nhttp://homeassistant.local:8123 or \nhttps://example.duckdns.org.</string>
|
||||
<string name="manual_desc">Enter the URL of your Home Assistant server. Make sure it includes the protocol and port. For example:\n\nhttp://homeassistant.local:8123 or \nhttps://example.duckdns.org.</string>
|
||||
<string name="manual_setup">Enter address manually</string>
|
||||
<string name="manual_title">What is your Home Assistant URL?</string>
|
||||
<string name="manual_title">What is your Home Assistant address?</string>
|
||||
<string name="map">Map</string>
|
||||
<string name="maximum">Maximum</string>
|
||||
<string name="media_player">Media player</string>
|
||||
|
@ -457,7 +457,7 @@
|
|||
<string name="security">Security</string>
|
||||
<string name="select">Select</string>
|
||||
<string name="select_entity_to_display">Select Entity to display</string>
|
||||
<string name="select_instance">Select the instance you would like to connect to:</string>
|
||||
<string name="select_instance">Select your Home Assistant server</string>
|
||||
<string name="sensor_description_active_notification_count">Total count of active notifications that are visible to the user including silent, persistent and the Sensor Worker notifications.</string>
|
||||
<string name="sensor_description_app_importance">If the app is in the foreground, background or any other state it can be.</string>
|
||||
<string name="sensor_description_app_inactive">Whether the app is currently considered inactive by the system</string>
|
||||
|
@ -792,7 +792,6 @@
|
|||
<string name="welcome_hass_desc">This app connects to your Home Assistant server and allows integrating data about you and your phone.\n\nHome Assistant is free and open source home automation software with a focus on local control and privacy.</string>
|
||||
<string name="welcome_hass">Welcome to Home Assistant Companion!</string>
|
||||
<string name="what_is_this_crash">Unable to load Home Assistant home page, do you have a browser installed?</string>
|
||||
<string name="what_is_this">What is this?</string>
|
||||
<string name="widget_attribute_separator_label">Separator between attributes:</string>
|
||||
<string name="widget_background_type_label">Widget theme:</string>
|
||||
<string name="widget_background_type_daynight">Light/dark theme</string>
|
||||
|
|
Loading…
Reference in a new issue