Open location links in the browser instead of maps (#357)
Bump to 2.22.1.
This commit is contained in:
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2.22.1] — 2026-10-02
|
||||
|
||||
### Fixed
|
||||
- **Links in an event's location open in the browser.** Tapping a location that holds a URL, such as a video-call link, opened it in a maps app; maps is now only used for plain addresses ([#357]).
|
||||
|
||||
## [2.22.0] — 2026-10-01
|
||||
|
||||
### Added
|
||||
@@ -1817,3 +1822,4 @@ automatically, with zero telemetry and no internet permission.
|
||||
[#322]: https://codeberg.org/jlmakiola/calendula/issues/322
|
||||
[#331]: https://codeberg.org/jlmakiola/calendula/issues/331
|
||||
[#336]: https://codeberg.org/jlmakiola/calendula/issues/336
|
||||
[#357]: https://codeberg.org/jlmakiola/calendula/issues/357
|
||||
|
||||
@@ -28,8 +28,8 @@ android {
|
||||
// which builds this version and then creates the matching vX.Y.Z tag +
|
||||
// release itself (versionCode is pinned to MAJOR*10000 + MINOR*100 +
|
||||
// PATCH from versionName, e.g. 2.7.2 -> 20702). See docs/RELEASING.md.
|
||||
versionCode = 22200
|
||||
versionName = "2.22.0"
|
||||
versionCode = 22201
|
||||
versionName = "2.22.1"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
@@ -534,7 +534,7 @@ private fun EventDetailContent(
|
||||
)
|
||||
}
|
||||
|
||||
// Location (conditional, tap → maps).
|
||||
// Location (conditional, tap → link if it holds a URL, else maps).
|
||||
instance.location?.takeIf { it.isNotBlank() }?.let { location ->
|
||||
val context = LocalContext.current
|
||||
val locationLabel = stringResource(R.string.event_detail_location)
|
||||
@@ -553,7 +553,7 @@ private fun EventDetailContent(
|
||||
label = locationLabel,
|
||||
text = location,
|
||||
copy = copyField,
|
||||
onTap = { openInMaps(context, location) },
|
||||
onTap = { openLocation(context, location) },
|
||||
)
|
||||
.padding(vertical = 2.dp),
|
||||
)
|
||||
@@ -846,19 +846,22 @@ private fun foreignTimeZone(
|
||||
)
|
||||
}
|
||||
|
||||
private val urlRegex = Regex("""https?://\S+""")
|
||||
|
||||
/** Strip trailing punctuation that commonly abuts a URL in prose. */
|
||||
private fun String.trimUrlPunctuation(): String =
|
||||
trimEnd('.', ',', ';', ':', '!', '?', ')', ']', '"', '\'')
|
||||
|
||||
/** Wrap http(s) URLs in [text] as tappable links tinted [linkColor]. */
|
||||
@Composable
|
||||
private fun linkifyUrls(text: String, linkColor: Color): AnnotatedString = remember(text, linkColor) {
|
||||
val regex = Regex("""https?://\S+""")
|
||||
val styles = TextLinkStyles(
|
||||
style = SpanStyle(color = linkColor, textDecoration = TextDecoration.Underline),
|
||||
)
|
||||
buildAnnotatedString {
|
||||
append(text)
|
||||
for (match in regex.findAll(text)) {
|
||||
// Trim trailing punctuation that commonly abuts a URL in prose.
|
||||
val raw = match.value
|
||||
val url = raw.trimEnd('.', ',', ';', ':', '!', '?', ')', ']', '"', '\'')
|
||||
for (match in urlRegex.findAll(text)) {
|
||||
val url = match.value.trimUrlPunctuation()
|
||||
val end = match.range.first + url.length
|
||||
addLink(LinkAnnotation.Url(url, styles), match.range.first, end)
|
||||
}
|
||||
@@ -915,6 +918,20 @@ private fun formatWhen(
|
||||
private fun Instant.toJavaLocalDateTime(zid: ZoneId): java.time.LocalDateTime =
|
||||
java.time.LocalDateTime.ofInstant(java.time.Instant.ofEpochMilli(toEpochMilliseconds()), zid)
|
||||
|
||||
/** Open the first URL in [location] (e.g. a meeting link), otherwise search it in maps. */
|
||||
private fun openLocation(context: Context, location: String) {
|
||||
val url = urlRegex.find(location)?.value?.trimUrlPunctuation()
|
||||
if (url == null) {
|
||||
openInMaps(context, location)
|
||||
return
|
||||
}
|
||||
try {
|
||||
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
// No app handles the link — nothing sensible to do; swallow.
|
||||
}
|
||||
}
|
||||
|
||||
/** Open a maps intent for [query]; fall back to a web maps URL if no app handles geo:. */
|
||||
private fun openInMaps(context: Context, query: String) {
|
||||
val encoded = Uri.encode(query)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Fixed
|
||||
• Links in an event's location open in the browser. Tapping a video-call link in the location opened a maps app instead.
|
||||
Reference in New Issue
Block a user