android: settings drawer, dark mode user profile view, dark mode previews (#347)

This commit is contained in:
Efim Poberezkin
2022-02-22 17:08:42 +04:00
committed by GitHub
parent 0a6c03079c
commit 353e04bddd
11 changed files with 316 additions and 96 deletions

View File

@@ -3,39 +3,32 @@ package chat.simplex.app.ui.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
private val DarkColorPalette = darkColors(
primary = SimplexBlue,
primaryVariant = SimplexGreen,
secondary = DarkGray,
// background = Color.Black,
// surface = Color.Black
/*
background: Color = Color(0xFF121212),
surface: Color = Color(0xFF121212),
error: Color = Color(0xFFCF6679),
onPrimary: Color = Color.Black,
onSecondary: Color = Color.Black,
onBackground: Color = Color.White,
onSurface: Color = Color.White,
onError: Color = Color.Black
*/
// surface = Color.Black,
// background = Color(0xFF121212),
// surface = Color(0xFF121212),
// error = Color(0xFFCF6679),
// onPrimary = Color.Black,
// onSecondary = Color.Black,
// onBackground = Color.White,
// onSurface = Color.White,
// onError: Color = Color.Black,
)
private val LightColorPalette = lightColors(
primary = SimplexBlue,
primaryVariant = SimplexGreen,
secondary = LightGray,
// background = Color.White,
// surface = Color.White
/* Other default colors to override
surface = Color.White,
onPrimary = Color.White,
onSecondary = Color.Black,
onBackground = Color.Black,
onSurface = Color.Black,
*/
// onPrimary = Color.White,
// onSecondary = Color.Black,
// onBackground = Color.Black,
// onSurface = Color.Black,
)
@Composable

View File

@@ -1,6 +1,5 @@
package chat.simplex.app.ui.theme
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily

View File

@@ -1,5 +1,6 @@
package chat.simplex.app.views
import android.content.res.Configuration
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
@@ -92,6 +93,11 @@ fun DetailView(identifier: Long, terminalItems: List<TerminalItem>, navControlle
}
@Preview(showBackground = true)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
@Composable
fun PreviewTerminalLayout() {
SimpleXTheme {

View File

@@ -1,5 +1,6 @@
package chat.simplex.app.views.chat
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
@@ -139,6 +140,11 @@ fun ChatItemsList(chatItems: List<ChatItem>) {
@ExperimentalAnimatedInsets
@Preview(showBackground = true)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
@Composable
fun PreviewChatLayout() {
SimpleXTheme {

View File

@@ -1,5 +1,6 @@
package chat.simplex.app.views.chat
import android.content.res.Configuration
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
@@ -13,13 +14,11 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusState
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.*
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import chat.simplex.app.ui.theme.*
import chat.simplex.app.ui.theme.SimpleXTheme
@Composable
fun SendMsgView(sendMessage: (String) -> Unit) {
@@ -76,6 +75,11 @@ fun SendMsgView(sendMessage: (String) -> Unit) {
}
@Preview(showBackground = true)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
@Composable
fun PreviewSendMsgView() {
SimpleXTheme {

View File

@@ -22,6 +22,7 @@ import chat.simplex.app.model.Chat
import chat.simplex.app.model.ChatModel
import chat.simplex.app.views.helpers.withApi
import chat.simplex.app.views.newchat.NewChatSheet
import chat.simplex.app.views.usersettings.SettingsView
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import kotlinx.coroutines.*
@@ -33,6 +34,12 @@ class ScaffoldController(val state: BottomSheetScaffoldState, val scope: Corouti
val s = state.bottomSheetState
if (s.isExpanded) s.collapse() else s.expand()
}
fun toggleDrawer() = scope.launch {
state.drawerState.apply {
if (isClosed) open() else close()
}
}
}
@ExperimentalMaterialApi
@@ -49,31 +56,37 @@ fun scaffoldController(): ScaffoldController {
@ExperimentalMaterialApi
@Composable
fun ChatListView(chatModel: ChatModel, nav: NavController) {
val newChatCtrl = scaffoldController()
val scaffoldCtrl = scaffoldController()
BottomSheetScaffold(
scaffoldState = newChatCtrl.state,
topBar = { ChatListToolbar(newChatCtrl, settings = { nav.navigate(Pages.Settings.route) }) },
scaffoldState = scaffoldCtrl.state,
topBar = {
ChatListToolbar(
scaffoldCtrl,
settings = { scaffoldCtrl.toggleDrawer() }
)
},
drawerContent = {
SettingsView(chatModel, nav)
},
sheetPeekHeight = 0.dp,
sheetContent = { NewChatSheet(chatModel, newChatCtrl, nav) },
sheetContent = { NewChatSheet(chatModel, scaffoldCtrl, nav) },
sheetShape = RoundedCornerShape(topStart = 18.dp, topEnd = 18.dp),
) {
Box {
Column(
modifier = Modifier
.padding(vertical = 8.dp)
Column(
modifier = Modifier
.padding(vertical = 8.dp)
.fillMaxSize()
.background(MaterialTheme.colors.background)
) {
ChatList(chatModel, nav)
}
if (scaffoldCtrl.state.bottomSheetState.isExpanded) {
Surface(
Modifier
.fillMaxSize()
.background(MaterialTheme.colors.background)
) {
ChatList(chatModel, nav)
}
if (newChatCtrl.state.bottomSheetState.isExpanded) {
Surface(
Modifier
.fillMaxSize()
.clickable { newChatCtrl.collapse() },
color = Color.Black.copy(alpha = 0.12F)
) {}
}
.clickable { scaffoldCtrl.collapse() },
color = Color.Black.copy(alpha = 0.12F)
) {}
}
}
}
@@ -87,7 +100,8 @@ fun ChatListToolbar(newChatSheetCtrl: ScaffoldController, settings: () -> Unit)
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
.height(60.dp)) {
.height(60.dp)
) {
IconButton(onClick = settings) {
Icon(
Icons.Outlined.Settings,
@@ -118,7 +132,7 @@ fun goToChat(chatPreview: Chat, chatModel: ChatModel, navController: NavControll
withApi {
val cInfo = chatPreview.chatInfo
val chat = chatModel.controller.apiGetChat(cInfo.chatType, cInfo.apiId)
if (chat != null ) {
if (chat != null) {
chatModel.chatId.value = cInfo.id
chatModel.chatItems = chat.chatItems.toMutableStateList()
navController.navigate(Pages.Chat.route)
@@ -135,12 +149,10 @@ fun ChatList(chatModel: ChatModel, navController: NavController) {
modifier = Modifier.fillMaxWidth()
) {
items(chatModel.chats) { chat ->
ChatPreviewView(chat) {goToChat(chat, chatModel, navController)}
ChatPreviewView(chat) { goToChat(chat, chatModel, navController) }
}
}
}
//@Preview
//@Composable
//fun PreviewChatListView() {

View File

@@ -1,5 +1,6 @@
package chat.simplex.app.views.helpers
import android.content.res.Configuration
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
@@ -32,6 +33,11 @@ fun CloseSheetBar(close: () -> Unit) {
}
@Preview(showBackground = true)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
@Composable
fun PreviewCloseSheetBar() {
SimpleXTheme {

View File

@@ -1,16 +1,26 @@
package chat.simplex.app.views.usersettings
import android.content.res.Configuration
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import chat.simplex.app.Pages
import chat.simplex.app.R
import chat.simplex.app.model.ChatModel
import chat.simplex.app.model.Profile
import chat.simplex.app.ui.theme.HighOrLowlight
import chat.simplex.app.ui.theme.SimpleXTheme
@Composable
@@ -19,62 +29,190 @@ fun SettingsView(chatModel: ChatModel, nav: NavController) {
if (user != null) {
SettingsLayout(
profile = user.profile,
back = nav::popBackStack,
navigate = nav::navigate
)
}
}
val simplexTeamUri = "simplex:/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D"
val simplexTeamUri =
"simplex:/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D"
@Composable
fun SettingsLayout(
profile: Profile,
back: () -> Unit,
navigate: (String) -> Unit
) {
val uriHandler = LocalUriHandler.current
Column() {
Button(onClick = back) {
Text("Back")
}
Text("Your Settings")
Spacer(Modifier.height(4.dp))
Column(
Modifier
.fillMaxSize()
// .background(MaterialTheme.colors.background)
.padding(8.dp)
) {
Text(
"Your Settings",
style = MaterialTheme.typography.h1,
color = MaterialTheme.colors.onBackground
)
Spacer(Modifier.height(30.dp))
Text("YOU", style = MaterialTheme.typography.h4)
Button(onClick = { navigate(Pages.UserProfile.route) }) {
Text(profile.displayName)
}
SettingsSectionView(
content = {
Icon(
Icons.Outlined.AccountCircle,
contentDescription = "Avatar Placeholder",
tint = MaterialTheme.colors.onBackground,
)
Spacer(Modifier.padding(horizontal = 4.dp))
Column {
Text(
profile.displayName,
style = MaterialTheme.typography.caption,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colors.onBackground
)
Text(
profile.fullName,
color = MaterialTheme.colors.onBackground
)
}
},
func = { navigate(Pages.UserProfile.route) },
height = 60.dp
)
Divider(Modifier.padding(horizontal = 8.dp))
SettingsSectionView(
content = {
Icon(
Icons.Outlined.QrCode,
contentDescription = "Address",
tint = HighOrLowlight,
)
Spacer(Modifier.padding(horizontal = 4.dp))
Text(
"Your SimpleX contact address",
color = HighOrLowlight
)
},
func = { println("navigate to address") }
)
Spacer(Modifier.height(24.dp))
Text("HELP", style = MaterialTheme.typography.h4)
Button(onClick = { println("navigate to help") }) {
Text("How to use SimpleX Chat")
}
Button(onClick = { uriHandler.openUri(simplexTeamUri) }) {
Text("Get help & advice via chat")
}
Button(onClick = { uriHandler.openUri("mailto:chat@simplex.chat") }) {
Text("Ask questions via email")
}
Spacer(Modifier.height(10.dp))
SettingsSectionView(
content = {
Icon(
Icons.Outlined.HelpOutline,
contentDescription = "Help",
tint = MaterialTheme.colors.onBackground,
)
Spacer(Modifier.padding(horizontal = 4.dp))
Text(
"How to use SimpleX Chat",
color = MaterialTheme.colors.onBackground
)
},
func = { println("navigate to help") }
)
Divider(Modifier.padding(horizontal = 8.dp))
SettingsSectionView(
content = {
Icon(
Icons.Outlined.Tag,
contentDescription = "SimpleX Team",
tint = MaterialTheme.colors.onBackground,
)
Spacer(Modifier.padding(horizontal = 4.dp))
Text(
"Get help & advice via chat",
color = MaterialTheme.colors.primary
)
},
func = { uriHandler.openUri(simplexTeamUri) }
)
Divider(Modifier.padding(horizontal = 8.dp))
SettingsSectionView(
content = {
Icon(
Icons.Outlined.Email,
contentDescription = "Email",
tint = MaterialTheme.colors.onBackground,
)
Spacer(Modifier.padding(horizontal = 4.dp))
Text(
"Ask questions via email",
color = MaterialTheme.colors.primary
)
},
func = { uriHandler.openUri("mailto:chat@simplex.chat") }
)
Spacer(Modifier.height(24.dp))
Text("DEVELOP", style = MaterialTheme.typography.h4)
Button(onClick = { navigate(Pages.Terminal.route) }) {
Text("Chat console")
}
Button(onClick = { uriHandler.openUri("https://github.com/simplex-chat/simplex-chat") }) {
Text("Install SimpleX for terminal")
SettingsSectionView(
content = {
Icon(
painter = painterResource(id = R.drawable.ic_outline_terminal),
contentDescription = "Chat console",
tint = MaterialTheme.colors.onBackground,
)
Spacer(Modifier.padding(horizontal = 4.dp))
Text(
"Chat console",
color = MaterialTheme.colors.onBackground
)
},
func = { navigate(Pages.Terminal.route) }
)
Divider(Modifier.padding(horizontal = 8.dp))
SettingsSectionView(
content = {
Icon(
painter = painterResource(id = R.drawable.ic_github),
contentDescription = "GitHub",
tint = MaterialTheme.colors.onBackground,
)
Spacer(Modifier.padding(horizontal = 4.dp))
Text(
"Install ",
color = MaterialTheme.colors.onBackground
)
Text(
"SimpleX Chat for terminal",
color = MaterialTheme.colors.primary
)
},
func = { uriHandler.openUri("https://github.com/simplex-chat/simplex-chat") }
)
}
}
@Composable
fun SettingsSectionView(content: (@Composable () -> Unit), func: () -> Unit, height: Dp = 48.dp) {
Surface(
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = func)
.height(height),
) {
Row(
Modifier.padding(start = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
content.invoke()
}
}
}
@Preview(showBackground = true)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
@Composable
fun PreviewSettingsLayout() {
SimpleXTheme {
SettingsLayout(
profile = Profile.sampleData,
back = {},
navigate = {}
)
}

View File

@@ -1,19 +1,20 @@
package chat.simplex.app.views.usersettings
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import chat.simplex.app.model.ChatModel
import chat.simplex.app.model.Profile
@@ -60,19 +61,23 @@ fun UserProfileLayout(
) {
Column(
modifier = Modifier
.padding(horizontal = 8.dp)
.fillMaxWidth(),
.fillMaxSize()
.background(MaterialTheme.colors.background)
.padding(horizontal = 8.dp),
horizontalAlignment = Alignment.Start
) {
CloseSheetBar(back)
Text("Your chat profile",
Text(
"Your chat profile",
Modifier.padding(bottom = 24.dp),
style = MaterialTheme.typography.h1
style = MaterialTheme.typography.h1,
color = MaterialTheme.colors.onBackground
)
Text(
"Your profile is stored on your device and shared only with your contacts.\n" +
"SimpleX servers cannot see your profile.",
Modifier.padding(bottom = 24.dp)
Modifier.padding(bottom = 24.dp),
color = MaterialTheme.colors.onBackground
)
if (editProfile) {
var displayName by remember { mutableStateOf(profile.displayName) }
@@ -88,7 +93,7 @@ fun UserProfileLayout(
modifier = Modifier
.padding(bottom = 24.dp)
.fillMaxWidth(),
textStyle = TextStyle(fontSize = 16.sp),
textStyle = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.onBackground),
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.None,
autoCorrect = false
@@ -101,7 +106,7 @@ fun UserProfileLayout(
modifier = Modifier
.padding(bottom = 24.dp)
.fillMaxWidth(),
textStyle = TextStyle(fontSize = 16.sp),
textStyle = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.onBackground),
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.None,
autoCorrect = false
@@ -113,7 +118,7 @@ fun UserProfileLayout(
"Cancel",
color = MaterialTheme.colors.primary,
modifier = Modifier
.clickable(onClick = editProfileOff)
.clickable(onClick = editProfileOff),
)
Spacer(Modifier.padding(horizontal = 8.dp))
Text(
@@ -132,21 +137,29 @@ fun UserProfileLayout(
Row(
Modifier.padding(bottom = 24.dp)
) {
Text("Display name:")
Text(
"Display name:",
color = MaterialTheme.colors.onBackground
)
Spacer(Modifier.padding(horizontal = 4.dp))
Text(
profile.displayName,
fontWeight = FontWeight.Bold
fontWeight = FontWeight.Bold,
color = MaterialTheme.colors.onBackground
)
}
Row(
Modifier.padding(bottom = 24.dp)
) {
Text("Full name:")
Text(
"Full name:",
color = MaterialTheme.colors.onBackground
)
Spacer(Modifier.padding(horizontal = 4.dp))
Text(
profile.fullName,
fontWeight = FontWeight.Bold
fontWeight = FontWeight.Bold,
color = MaterialTheme.colors.onBackground
)
}
Text(
@@ -161,6 +174,12 @@ fun UserProfileLayout(
}
@Preview(showBackground = true)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
@Composable
fun PreviewUserProfileLayoutEditOff() {
SimpleXTheme {
@@ -176,6 +195,11 @@ fun PreviewUserProfileLayoutEditOff() {
}
@Preview(showBackground = true)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
@Composable
fun PreviewUserProfileLayoutEditOn() {
SimpleXTheme {

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Android drawable generated by fa5ad-free project:
https://github.com/diwanoczko/fa5ad-free
Resource generated base on Font Awesome 5 Free icons set:
https://fontawesome.com/
All brand icons are trademarks of their respective owners.
Please do not use brand logos for any purpose except to represent the
company, product, or service to which they refer.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="23.25dp"
android:height="24dp"
android:viewportWidth="496"
android:viewportHeight="512">
<path
android:fillColor="#FF000000"
android:pathData="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"
/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M20,4H4C2.89,4 2,4.9 2,6v12c0,1.1 0.89,2 2,2h16c1.1,0 2,-0.9 2,-2V6C22,4.9 21.11,4 20,4zM20,18H4V8h16V18zM18,17h-6v-2h6V17zM7.5,17l-1.41,-1.41L8.67,13l-2.59,-2.59L7.5,9l4,4L7.5,17z"/>
</vector>