Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shortcut path input improvements #3831

Merged
merged 1 commit into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Button
import androidx.compose.material.Divider
import androidx.compose.material.DropdownMenu
Expand All @@ -31,6 +32,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.mikepenz.iconics.compose.IconicsPainter
Expand Down Expand Up @@ -230,6 +233,7 @@ private fun CreateShortcutView(
value = viewModel.shortcuts[i].path.value,
onValueChange = { viewModel.shortcuts[i].path.value = it },
label = { Text(stringResource(id = R.string.lovelace_view_dashboard)) },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done, autoCorrect = false, keyboardType = KeyboardType.Uri),
modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp)
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface WebView {
TIMEOUT
}

fun loadUrl(url: String, keepHistory: Boolean)
fun loadUrl(url: String, keepHistory: Boolean, openInApp: Boolean)

fun setStatusBarAndNavigationBarColor(statusBarColor: Int, navigationBarColor: Int)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1113,11 +1113,20 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
finish()
}

override fun loadUrl(url: String, keepHistory: Boolean) {
loadedUrl = url
clearHistory = !keepHistory
webView.loadUrl(url)
waitForConnection()
override fun loadUrl(url: String, keepHistory: Boolean, openInApp: Boolean) {
if (openInApp) {
loadedUrl = url
clearHistory = !keepHistory
webView.loadUrl(url)
waitForConnection()
} else {
try {
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(browserIntent)
} catch (e: Exception) {
Log.e(TAG, "Unable to view url", e)
}
}
}

override fun setStatusBarAndNavigationBarColor(statusBarColor: Int, navigationBarColor: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import io.homeassistant.companion.android.matter.MatterFrontendCommissioningStat
import io.homeassistant.companion.android.matter.MatterManager
import io.homeassistant.companion.android.thread.ThreadManager
import io.homeassistant.companion.android.util.UrlUtil
import io.homeassistant.companion.android.util.UrlUtil.baseIsEqual
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
Expand Down Expand Up @@ -88,6 +89,7 @@ class WebViewPresenterImpl @Inject constructor(
serverConnectionInfo.isInternal() || (serverConnectionInfo.prioritizeInternal && !DisabledLocationHandler.isLocationEnabled(view as Context))
)
urlForServer = server?.id
val baseUrl = url

if (path != null && !path.startsWith("entityId:")) {
url = UrlUtil.handle(url, path)
Expand All @@ -101,12 +103,13 @@ class WebViewPresenterImpl @Inject constructor(
*/
if (oldUrlForServer != urlForServer || oldUrl?.host != url?.host) {
view.loadUrl(
Uri.parse(url.toString())
url = Uri.parse(url.toString())
.buildUpon()
.appendQueryParameter("external_auth", "1")
.build()
.toString(),
oldUrlForServer == urlForServer
keepHistory = oldUrlForServer == urlForServer,
openInApp = url?.baseIsEqual(baseUrl) ?: false
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package io.homeassistant.companion.android.util

import android.net.Uri
import android.util.Log
import io.homeassistant.companion.android.common.data.MalformedHttpUrlException
import io.homeassistant.companion.android.common.data.authentication.impl.AuthenticationService
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import java.net.URI
import java.net.URL

object UrlUtil {
Expand Down Expand Up @@ -39,15 +41,26 @@ object UrlUtil {
}

fun handle(base: URL?, input: String): URL? {
val asURI = try {
URI(input.removePrefix("homeassistant://navigate/"))
} catch (e: Exception) {
Log.w("UrlUtil", "Invalid input, returning base only")
null
}
return when {
isAbsoluteUrl(input) -> {
URL(input)
asURI == null -> {
base
}
input.startsWith("homeassistant://navigate/") -> {
(base.toString() + input.removePrefix("homeassistant://navigate/")).toHttpUrlOrNull()?.toUrl()
isAbsoluteUrl(input) -> {
asURI.toURL()
}
else -> {
(base.toString() + input.removePrefix("/")).toHttpUrlOrNull()?.toUrl()
else -> { // Input is relative to base URL
val builder = base
?.toHttpUrlOrNull()
?.newBuilder()
if (!asURI.path.isNullOrBlank()) builder?.addPathSegments(asURI.path.trim().removePrefix("/"))
if (!asURI.query.isNullOrBlank()) builder?.query(asURI.query.trim())
builder?.build()?.toUrl()
}
}
}
Expand All @@ -56,6 +69,17 @@ object UrlUtil {
return Regex("^https?://").containsMatchIn(it.toString())
}

/** @return `true` if both URLs have the same 'base': an equal protocol, host, port and userinfo */
fun URL.baseIsEqual(other: URL?): Boolean =
if (other == null) {
false
} else {
host?.lowercase() == other.host?.lowercase() &&
port.let { if (it == -1) defaultPort else it } == other.port.let { if (it == -1) defaultPort else it } &&
protocol?.lowercase() == other.protocol?.lowercase() &&
userInfo == other.userInfo
}

fun splitNfcTagId(it: Uri?): String? {
val matches =
Regex("^https?://www\\.home-assistant\\.io/tag/(.*)").find(
Expand Down