Skip to content

Commit 6cb05f6

Browse files
author
sds100
committed
Merge branch 'feature/10-about-screen' into develop
2 parents 743356e + 7b1864c commit 6cb05f6

5 files changed

Lines changed: 234 additions & 6 deletions

File tree

app/src/main/java/com/mapcode/map/MapScreen.kt

Lines changed: 178 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ import android.Manifest
44
import androidx.annotation.DrawableRes
55
import androidx.compose.foundation.clickable
66
import androidx.compose.foundation.layout.*
7+
import androidx.compose.foundation.rememberScrollState
8+
import androidx.compose.foundation.text.InlineTextContent
79
import androidx.compose.foundation.text.KeyboardActions
810
import androidx.compose.foundation.text.KeyboardOptions
11+
import androidx.compose.foundation.text.appendInlineContent
12+
import androidx.compose.foundation.verticalScroll
913
import androidx.compose.material.*
1014
import androidx.compose.material.icons.Icons
11-
import androidx.compose.material.icons.outlined.Add
12-
import androidx.compose.material.icons.outlined.Clear
13-
import androidx.compose.material.icons.outlined.LocationOn
14-
import androidx.compose.material.icons.outlined.Share
15+
import androidx.compose.material.icons.outlined.*
1516
import androidx.compose.runtime.*
17+
import androidx.compose.runtime.saveable.rememberSaveable
1618
import androidx.compose.ui.Alignment
1719
import androidx.compose.ui.Modifier
1820
import androidx.compose.ui.focus.FocusRequester
@@ -21,21 +23,26 @@ import androidx.compose.ui.focus.onFocusChanged
2123
import androidx.compose.ui.graphics.Color
2224
import androidx.compose.ui.graphics.painter.Painter
2325
import androidx.compose.ui.platform.LocalFocusManager
26+
import androidx.compose.ui.platform.LocalUriHandler
2427
import androidx.compose.ui.res.painterResource
2528
import androidx.compose.ui.res.stringResource
29+
import androidx.compose.ui.text.Placeholder
30+
import androidx.compose.ui.text.PlaceholderVerticalAlign
2631
import androidx.compose.ui.text.SpanStyle
2732
import androidx.compose.ui.text.buildAnnotatedString
2833
import androidx.compose.ui.text.font.FontWeight
2934
import androidx.compose.ui.text.input.ImeAction
3035
import androidx.compose.ui.text.input.KeyboardType
3136
import androidx.compose.ui.tooling.preview.Preview
3237
import androidx.compose.ui.unit.dp
38+
import androidx.compose.ui.window.Dialog
3339
import com.google.accompanist.permissions.ExperimentalPermissionsApi
3440
import com.google.accompanist.permissions.PermissionStatus
3541
import com.google.accompanist.permissions.rememberMultiplePermissionsState
3642
import com.google.android.gms.maps.CameraUpdateFactory
3743
import com.google.android.gms.maps.model.LatLng
3844
import com.google.maps.android.compose.*
45+
import com.mapcode.BuildConfig
3946
import com.mapcode.R
4047
import com.mapcode.theme.Green600
4148
import com.mapcode.theme.MapcodeTheme
@@ -65,6 +72,11 @@ fun MapBox(
6572
) {
6673
val scope: CoroutineScope = rememberCoroutineScope()
6774
val isSatelliteModeEnabled by derivedStateOf { mapProperties.mapType == MapType.HYBRID }
75+
var showAboutDialog by rememberSaveable { mutableStateOf(false) }
76+
77+
if (showAboutDialog) {
78+
AboutDialog(onDismiss = { showAboutDialog = false })
79+
}
6880

6981
Box(modifier) {
7082
if (renderGoogleMaps) {
@@ -106,11 +118,156 @@ fun MapBox(
106118
},
107119
onMyLocationClick = onMyLocationClick,
108120
onExternalMapAppClick = onExternalMapAppClick,
109-
onShareMapcodeClick = onShareMapcodeClick
121+
onShareMapcodeClick = onShareMapcodeClick,
122+
onAboutClick = { showAboutDialog = true }
110123
)
111124
}
112125
}
113126

127+
@Composable
128+
fun ScrollableDialog(onDismiss: () -> Unit, title: String, buttonText: String, content: @Composable () -> Unit) {
129+
Dialog(onDismissRequest = onDismiss) {
130+
Surface(color = MaterialTheme.colors.surface, shape = MaterialTheme.shapes.medium) {
131+
Column(verticalArrangement = Arrangement.SpaceBetween) {
132+
Text(
133+
modifier = Modifier
134+
.align(Alignment.Start)
135+
.height(64.dp)
136+
.wrapContentSize()
137+
.padding(start = 24.dp, end = 24.dp),
138+
text = title,
139+
style = MaterialTheme.typography.h6
140+
)
141+
Divider(Modifier.height(1.dp))
142+
Box(
143+
Modifier
144+
.weight(1f, fill = false)
145+
.verticalScroll(rememberScrollState())
146+
.padding(start = 24.dp, end = 24.dp, top = 8.dp, bottom = 8.dp)
147+
) {
148+
content()
149+
}
150+
Divider(Modifier.height(1.dp))
151+
TextButton(
152+
modifier = Modifier
153+
.align(Alignment.End)
154+
.padding(8.dp),
155+
onClick = onDismiss
156+
) {
157+
Text(buttonText)
158+
}
159+
}
160+
}
161+
}
162+
}
163+
164+
@Composable
165+
fun AboutDialog(onDismiss: () -> Unit = {}) {
166+
val uriHandler = LocalUriHandler.current
167+
val websiteUrl = stringResource(R.string.website_url)
168+
val sourceCodeUrl = stringResource(R.string.source_code_url)
169+
170+
ScrollableDialog(
171+
onDismiss = onDismiss, title = stringResource(R.string.about_dialog_title, BuildConfig.VERSION_NAME),
172+
buttonText = stringResource(R.string.close_dialog_button)
173+
) {
174+
Column {
175+
val dialogTextStyle = MaterialTheme.typography.body1
176+
val inlineContent = mapOf(
177+
"share_icon" to InlineTextContent(
178+
Placeholder(
179+
width = dialogTextStyle.fontSize,
180+
height = dialogTextStyle.fontSize,
181+
placeholderVerticalAlign = PlaceholderVerticalAlign.Center
182+
)
183+
) {
184+
Icon(Icons.Outlined.Share, "")
185+
},
186+
"directions_icon" to InlineTextContent(
187+
Placeholder(
188+
width = dialogTextStyle.fontSize,
189+
height = dialogTextStyle.fontSize,
190+
placeholderVerticalAlign = PlaceholderVerticalAlign.Center
191+
)
192+
) {
193+
Icon(
194+
painter = painterResource(R.drawable.ic_outline_directions_24),
195+
contentDescription = ""
196+
)
197+
},
198+
)
199+
200+
val aboutString = buildAnnotatedString {
201+
pushStyle(dialogTextStyle.toSpanStyle())
202+
203+
append(stringResource(R.string.copyright_welcome))
204+
append("\n\n")
205+
206+
pushStyle(MaterialTheme.typography.subtitle2.toSpanStyle())
207+
append(stringResource(R.string.how_to_use_header))
208+
pop()
209+
210+
append("\n\n")
211+
append(stringResource(R.string.how_to_use_address))
212+
append("\n\n")
213+
append(stringResource(R.string.how_to_use_territory))
214+
215+
append("\n\n")
216+
append(stringResource(R.string.how_to_use_share_1))
217+
appendInlineContent("share_icon")
218+
append(stringResource(R.string.how_to_use_share_2))
219+
220+
append("\n\n")
221+
append(stringResource(R.string.how_to_use_directions_1))
222+
appendInlineContent("directions_icon")
223+
append(stringResource(R.string.how_to_use_directions_2))
224+
225+
append("\n\n")
226+
append(stringResource(R.string.visit_website_notice))
227+
228+
pop()
229+
}
230+
231+
Text(text = aboutString, inlineContent = inlineContent)
232+
Spacer(Modifier.height(8.dp))
233+
DialogContentButton(
234+
icon = painterResource(R.drawable.web),
235+
text = stringResource(R.string.website_button)
236+
) {
237+
uriHandler.openUri(websiteUrl)
238+
}
239+
DialogContentButton(
240+
icon = painterResource(R.drawable.ic_outline_article_24),
241+
text = stringResource(R.string.changelog_button)
242+
) {
243+
}
244+
DialogContentButton(
245+
icon = painterResource(R.drawable.ic_outline_code_24),
246+
text = stringResource(R.string.source_code_button)
247+
) {
248+
uriHandler.openUri(sourceCodeUrl)
249+
}
250+
}
251+
}
252+
}
253+
254+
@Composable
255+
fun DialogContentButton(icon: Painter, text: String, onClick: () -> Unit) {
256+
OutlinedButton(onClick = onClick) {
257+
Icon(icon, contentDescription = null)
258+
Spacer(modifier = Modifier.width(8.dp))
259+
Text(text)
260+
}
261+
}
262+
263+
@Preview(heightDp = 500)
264+
@Composable
265+
fun AboutDialogPreview() {
266+
MapcodeTheme {
267+
AboutDialog()
268+
}
269+
}
270+
114271
@Composable
115272
fun greyButtonColors(): ButtonColors {
116273
return ButtonDefaults.buttonColors(backgroundColor = Color.LightGray, contentColor = Color.DarkGray)
@@ -125,7 +282,8 @@ fun MapControls(
125282
onZoomOutClick: () -> Unit = {},
126283
onMyLocationClick: () -> Unit = {},
127284
onExternalMapAppClick: () -> Unit = {},
128-
onShareMapcodeClick: () -> Unit = {}
285+
onShareMapcodeClick: () -> Unit = {},
286+
onAboutClick: () -> Unit = {}
129287
) {
130288
val greenButtonColors = ButtonDefaults.buttonColors(backgroundColor = Green600, contentColor = Color.White)
131289
val satelliteButtonColors: ButtonColors = if (isSatelliteModeEnabled) {
@@ -141,6 +299,20 @@ fun MapControls(
141299
}
142300

143301
Row(modifier) {
302+
Button(
303+
modifier = Modifier
304+
.size(48.dp)
305+
.align(Alignment.Bottom),
306+
onClick = onAboutClick,
307+
contentPadding = PaddingValues(8.dp),
308+
colors = greyButtonColors()
309+
) {
310+
Icon(
311+
imageVector = Icons.Outlined.Info,
312+
contentDescription = stringResource(R.string.about_content_description)
313+
)
314+
}
315+
Spacer(Modifier.width(8.dp))
144316
Button(
145317
modifier = Modifier
146318
.size(48.dp)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:autoMirrored="true"
5+
android:tint="#000000"
6+
android:viewportWidth="24"
7+
android:viewportHeight="24">
8+
<path
9+
android:fillColor="@android:color/white"
10+
android:pathData="M19,5v14H5V5H19M19,3H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3L19,3z" />
11+
<path
12+
android:fillColor="@android:color/white"
13+
android:pathData="M14,17H7v-2h7V17zM17,13H7v-2h10V13zM17,9H7V7h10V9z" />
14+
</vector>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:tint="#000000"
5+
android:viewportWidth="24"
6+
android:viewportHeight="24">
7+
<path
8+
android:fillColor="@android:color/white"
9+
android:pathData="M9.4,16.6L4.8,12l4.6,-4.6L8,6l-6,6 6,6 1.4,-1.4zM14.6,16.6l4.6,-4.6 -4.6,-4.6L16,6l6,6 -6,6 -1.4,-1.4z" />
10+
</vector>

app/src/main/res/drawable/web.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!-- drawable/web.xml -->
2+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
android:width="24dp"
5+
android:height="24dp"
6+
android:viewportWidth="24"
7+
android:viewportHeight="24">
8+
<path
9+
android:fillColor="#000"
10+
android:pathData="M16.36,14C16.44,13.34 16.5,12.68 16.5,12C16.5,11.32 16.44,10.66 16.36,10H19.74C19.9,10.64 20,11.31 20,12C20,12.69 19.9,13.36 19.74,14M14.59,19.56C15.19,18.45 15.65,17.25 15.97,16H18.92C17.96,17.65 16.43,18.93 14.59,19.56M14.34,14H9.66C9.56,13.34 9.5,12.68 9.5,12C9.5,11.32 9.56,10.65 9.66,10H14.34C14.43,10.65 14.5,11.32 14.5,12C14.5,12.68 14.43,13.34 14.34,14M12,19.96C11.17,18.76 10.5,17.43 10.09,16H13.91C13.5,17.43 12.83,18.76 12,19.96M8,8H5.08C6.03,6.34 7.57,5.06 9.4,4.44C8.8,5.55 8.35,6.75 8,8M5.08,16H8C8.35,17.25 8.8,18.45 9.4,19.56C7.57,18.93 6.03,17.65 5.08,16M4.26,14C4.1,13.36 4,12.69 4,12C4,11.31 4.1,10.64 4.26,10H7.64C7.56,10.66 7.5,11.32 7.5,12C7.5,12.68 7.56,13.34 7.64,14M12,4.03C12.83,5.23 13.5,6.57 13.91,8H10.09C10.5,6.57 11.17,5.23 12,4.03M18.92,8H15.97C15.65,6.75 15.19,5.55 14.59,4.44C16.43,5.07 17.96,6.34 18.92,8M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z"
11+
tools:ignore="VectorPath" />
12+
</vector>

app/src/main/res/values/strings.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,25 @@
2424
<string name="cant_find_my_location_snackbar">Can\'t find location. Is your GPS turned on?</string>
2525
<string name="no_map_app_installed_error">You have no map app installed to open this in.</string>
2626
<string name="share_mapcode_content_description">Share mapcode</string>
27+
<string name="about_content_description">About this app</string>
28+
<string name="about_dialog_title">About Mapcode %s</string>
29+
<string name="close_dialog_button">Close</string>
30+
<string name="website_button">Website</string>
31+
<string name="changelog_button">Changelog</string>
32+
<string name="source_code_button">Source code</string>
33+
34+
<string name="copyright_welcome">Copyright © 2022, Mapcode Foundation\n\nWelcome to the official Mapcode app from the Mapcode Foundation!</string>
35+
<string name="how_to_use_header">How to use the app</string>
36+
<string name="how_to_use_address">Enter an address or coordinate to get a mapcode, or move the map around.\n\nEnter a mapcode into the address field to show its location on the map.</string>
37+
<string name="how_to_use_territory">Tap the territory to cycle through the mapcode territories.</string>
38+
<string name="how_to_use_share_1">Tap the mapcode to copy it to the clipboard or tap the share\u0020</string>
39+
<string name="how_to_use_share_2">\u0020button to quickly share it in another app.</string>
40+
<string name="how_to_use_directions_1">Tap on the directions\u0020</string>
41+
<string name="how_to_use_directions_2">\u0020button to navigate to the location in another maps app.</string>
42+
43+
<string name="contact_header">Contact the developer</string>
44+
<string name="visit_website_notice">For questions, or more info in general, please visit our website.</string>
45+
<string name="website_url" translatable="false">https://mapcode.com</string>
46+
<string name="source_code_url" translatable="false">https://github.com/mapcode-foundation/mapcode-android-app</string>
2747
<!-- Map screen -->
2848
</resources>

0 commit comments

Comments
 (0)