Skip to content

Commit 08d1919

Browse files
committed
don't crash when user opens a URI without having a browser installed (fixes #6798)
1 parent 79a7f85 commit 08d1919

File tree

7 files changed

+36
-15
lines changed

7 files changed

+36
-15
lines changed

app/src/androidMain/kotlin/de/westnordost/streetcomplete/screens/about/AboutScreen.kt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import de.westnordost.streetcomplete.ui.common.settings.PreferenceCategory
3535
import de.westnordost.streetcomplete.util.ktx.displayLanguage
3636
import org.jetbrains.compose.resources.stringResource
3737
import androidx.compose.ui.tooling.preview.Preview
38+
import de.westnordost.streetcomplete.ui.ktx.tryOpenUri
3839

3940
@Composable
4041
fun AboutScreen(
@@ -80,7 +81,7 @@ fun AboutScreen(
8081

8182
Preference(
8283
name = stringResource(Res.string.about_title_license),
83-
onClick = { uriHandler.openUri("https://www.gnu.org/licenses/gpl-3.0.html") },
84+
onClick = { uriHandler.tryOpenUri("https://www.gnu.org/licenses/gpl-3.0.html") },
8485
) {
8586
Text("GPLv3")
8687
OpenInBrowserIcon()
@@ -100,12 +101,12 @@ fun AboutScreen(
100101

101102
Preference(
102103
name = stringResource(Res.string.about_title_faq),
103-
onClick = { uriHandler.openUri("https://wiki.openstreetmap.org/wiki/StreetComplete/FAQ") },
104+
onClick = { uriHandler.tryOpenUri("https://wiki.openstreetmap.org/wiki/StreetComplete/FAQ") },
104105
) { OpenInBrowserIcon() }
105106

106107
Preference(
107108
name = stringResource(Res.string.about_title_report_error),
108-
onClick = { uriHandler.openUri("https://github.com/streetcomplete/StreetComplete/issues") },
109+
onClick = { uriHandler.tryOpenUri("https://github.com/streetcomplete/StreetComplete/issues") },
109110
) { OpenInBrowserIcon() }
110111

111112
Preference(
@@ -125,7 +126,7 @@ fun AboutScreen(
125126

126127
Preference(
127128
name = stringResource(Res.string.about_title_translate),
128-
onClick = { uriHandler.openUri("https://poeditor.com/join/project/IE4GC127Ki") },
129+
onClick = { uriHandler.tryOpenUri("https://poeditor.com/join/project/IE4GC127Ki") },
129130
description = stringResource(
130131
Res.string.about_description_translate,
131132
Locale.current.displayLanguage ?: Locale.current.language,
@@ -135,7 +136,7 @@ fun AboutScreen(
135136

136137
Preference(
137138
name = stringResource(Res.string.about_title_repository),
138-
onClick = { uriHandler.openUri("https://github.com/streetcomplete/StreetComplete") },
139+
onClick = { uriHandler.tryOpenUri("https://github.com/streetcomplete/StreetComplete") },
139140
) { OpenInBrowserIcon() }
140141
}
141142

@@ -144,13 +145,13 @@ fun AboutScreen(
144145
if (context.isInstalledViaGooglePlay()) {
145146
Preference(
146147
name = stringResource(Res.string.about_title_rate),
147-
onClick = { uriHandler.openUri("market://details?id=${context.packageName}") },
148+
onClick = { uriHandler.tryOpenUri("market://details?id=${context.packageName}") },
148149
) { OpenInBrowserIcon() }
149150
}
150151

151152
Preference(
152153
name = stringResource(Res.string.about_title_feedback),
153-
onClick = { uriHandler.openUri("https://github.com/streetcomplete/StreetComplete/discussions") },
154+
onClick = { uriHandler.tryOpenUri("https://github.com/streetcomplete/StreetComplete/discussions") },
154155
) { OpenInBrowserIcon() }
155156
}
156157
}
@@ -162,7 +163,7 @@ fun AboutScreen(
162163
} else {
163164
DonationsDialog(
164165
onDismissRequest = { showDonateDialog = false },
165-
onClickLink = { uriHandler.openUri(it) }
166+
onClickLink = { uriHandler.tryOpenUri(it) }
166167
)
167168
}
168169
}

app/src/androidMain/kotlin/de/westnordost/streetcomplete/screens/main/messages/MessageDialog.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import androidx.compose.ui.platform.LocalUriHandler
66
import de.westnordost.streetcomplete.data.messages.Message
77
import de.westnordost.streetcomplete.screens.settings.SettingsActivity
88
import de.westnordost.streetcomplete.screens.user.achievements.AchievementDialog
9+
import de.westnordost.streetcomplete.ui.ktx.tryOpenUri
910
import kotlin.reflect.KClass
1011

1112
/** Dialog that shows a Message */
@@ -47,7 +48,7 @@ fun MessageDialog(
4748
unreadMessageCount = message.unreadMessages,
4849
onDismissRequest = onDismissRequest,
4950
onClickOpenMessages = {
50-
uriHandler.openUri("https://www.openstreetmap.org/messages/inbox")
51+
uriHandler.tryOpenUri("https://www.openstreetmap.org/messages/inbox")
5152
}
5253
)
5354
}
@@ -59,7 +60,7 @@ fun MessageDialog(
5960
onClickOpenWeeklyOsm = {
6061
// note that weeklyOSM website is smart enough to show the site in the user
6162
// preferred language
62-
uriHandler.openUri("https://www.weeklyosm.eu")
63+
uriHandler.tryOpenUri("https://www.weeklyosm.eu")
6364
},
6465
onToggleDontNotifyAgain = { dontNotifyAgain ->
6566
onToggleDontNotifyAgain(Message.NewWeeklyOsm::class, dontNotifyAgain)
@@ -71,7 +72,7 @@ fun MessageDialog(
7172
CalendarEventDialog(
7273
event = message.event,
7374
onDismissRequest = onDismissRequest,
74-
onClickOpenEvent = { uriHandler.openUri(message.event.url) },
75+
onClickOpenEvent = { uriHandler.tryOpenUri(message.event.url) },
7576
onToggleDontNotifyAgain = { dontNotifyAgain ->
7677
onToggleDontNotifyAgain(Message.NewCalendarEvent::class, dontNotifyAgain)
7778
}

app/src/androidMain/kotlin/de/westnordost/streetcomplete/screens/user/edits/EditTypeDialog.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import de.westnordost.streetcomplete.ui.common.OpenInBrowserIcon
3232
import de.westnordost.streetcomplete.ui.theme.headlineSmall
3333
import org.jetbrains.compose.resources.stringResource
3434
import androidx.compose.ui.tooling.preview.Preview
35+
import de.westnordost.streetcomplete.ui.ktx.tryOpenUri
3536

3637
/** Shows the details for a certain quest type in a custom dialog. */
3738
@Composable
@@ -91,7 +92,7 @@ private fun EditTypeDetails(
9192

9293
editType.wikiLink?.let { wikiLink ->
9394
OutlinedButton(
94-
onClick = { uriHandler.openUri("https://wiki.openstreetmap.org/wiki/$wikiLink") }
95+
onClick = { uriHandler.tryOpenUri("https://wiki.openstreetmap.org/wiki/$wikiLink") }
9596
) {
9697
OpenInBrowserIcon()
9798
Text(

app/src/commonMain/kotlin/de/westnordost/streetcomplete/screens/user/edits/CountryDialog.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import de.westnordost.streetcomplete.util.ktx.displayRegion
3131
import de.westnordost.streetcomplete.util.ktx.getDisplayRegion
3232
import org.jetbrains.compose.resources.stringResource
3333
import androidx.compose.ui.tooling.preview.Preview
34+
import de.westnordost.streetcomplete.ui.ktx.tryOpenUri
3435

3536
/** Shows the details for a certain country as a dialog. */
3637
@Composable
@@ -112,7 +113,7 @@ private fun CountryInfoDetails(
112113
onClick = {
113114
val britishCountryName = countryLocale.getDisplayRegion(Locale("en-GB"))
114115
if (britishCountryName != null) {
115-
uriHandler.openUri("https://wiki.openstreetmap.org/wiki/$britishCountryName")
116+
uriHandler.tryOpenUri("https://wiki.openstreetmap.org/wiki/$britishCountryName")
116117
}
117118
}
118119
) {

app/src/commonMain/kotlin/de/westnordost/streetcomplete/screens/user/links/LinkRow.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import org.jetbrains.compose.resources.StringResource
2525
import org.jetbrains.compose.resources.painterResource
2626
import org.jetbrains.compose.resources.stringResource
2727
import androidx.compose.ui.tooling.preview.Preview
28+
import de.westnordost.streetcomplete.ui.ktx.tryOpenUri
2829

2930
/** Display a single link category from the link collection */
3031
@Composable
@@ -58,7 +59,7 @@ fun LinkRow(link: Link, modifier: Modifier = Modifier) {
5859
val uriHandler = LocalUriHandler.current
5960
Row(
6061
modifier = modifier
61-
.clickable { uriHandler.openUri(link.url) }
62+
.clickable { uriHandler.tryOpenUri(link.url) }
6263
.padding(8.dp),
6364
horizontalArrangement = Arrangement.spacedBy(8.dp),
6465
) {

app/src/commonMain/kotlin/de/westnordost/streetcomplete/screens/user/profile/ProfileScreen.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import androidx.compose.ui.unit.dp
3939
import androidx.compose.ui.unit.sp
4040
import de.westnordost.streetcomplete.resources.*
4141
import de.westnordost.streetcomplete.ui.ktx.toDp
42+
import de.westnordost.streetcomplete.ui.ktx.tryOpenUri
4243
import de.westnordost.streetcomplete.ui.theme.headlineLarge
4344
import de.westnordost.streetcomplete.ui.theme.titleLarge
4445
import de.westnordost.streetcomplete.util.image.fileBitmapPainter
@@ -116,7 +117,7 @@ fun ProfileScreen(viewModel: ProfileViewModel) {
116117
) {
117118
val uriHandler = LocalUriHandler.current
118119
Button(onClick = {
119-
uriHandler.openUri("https://www.openstreetmap.org/user/" + viewModel.userName.value)
120+
uriHandler.tryOpenUri("https://www.openstreetmap.org/user/" + viewModel.userName.value)
120121
}) {
121122
Icon(painterResource(Res.drawable.ic_open_in_browser_24), null)
122123
Spacer(Modifier.width(8.dp))
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package de.westnordost.streetcomplete.ui.ktx
2+
3+
import androidx.compose.ui.platform.UriHandler
4+
5+
/**
6+
* Try to open given URL in browser. Returns `false` if given [uri] is invalid and/or can't be
7+
* handled by the system (e.g. if no browser is installed).
8+
*/
9+
fun UriHandler.tryOpenUri(uri: String): Boolean =
10+
try {
11+
openUri(uri)
12+
return true
13+
} catch (e: IllegalArgumentException) {
14+
return false
15+
}

0 commit comments

Comments
 (0)