From f9c495a5962a646ff5e95f631b4248c0199a6ab9 Mon Sep 17 00:00:00 2001 From: Efim Poberezkin <8711996+efim-poberezkin@users.noreply.github.com> Date: Tue, 22 Feb 2022 23:38:47 +0400 Subject: [PATCH] android: help view (#351) * android: help view * chats loaded * remove comment --- .../java/chat/simplex/app/MainActivity.kt | 10 +- .../java/chat/simplex/app/model/ChatModel.kt | 1 + .../java/chat/simplex/app/model/SimpleXAPI.kt | 1 + .../app/views/chatlist/ChatHelpView.kt | 170 ++++++++++++++++++ .../app/views/chatlist/ChatListView.kt | 58 +++++- .../simplex/app/views/newchat/NewChatSheet.kt | 4 +- .../app/views/usersettings/HelpView.kt | 64 +++++++ .../app/views/usersettings/SettingsView.kt | 17 +- 8 files changed, 302 insertions(+), 23 deletions(-) create mode 100644 apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt create mode 100644 apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt diff --git a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt b/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt index 083405159b..337d8237e1 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt @@ -21,7 +21,7 @@ import chat.simplex.app.views.chat.ChatView import chat.simplex.app.views.chatlist.ChatListView import chat.simplex.app.views.helpers.withApi import chat.simplex.app.views.newchat.* -import chat.simplex.app.views.usersettings.SettingsView +import chat.simplex.app.views.usersettings.HelpView import chat.simplex.app.views.usersettings.UserProfileView import com.google.accompanist.insets.ExperimentalAnimatedInsets import com.google.accompanist.permissions.ExperimentalPermissionsApi @@ -108,12 +108,12 @@ fun Navigation(chatModel: ChatModel) { } ) ) { entry -> DetailView(entry.arguments!!.getLong("identifier"), chatModel.terminalItems, nav) } - composable(route = Pages.Settings.route) { - SettingsView(chatModel, nav) - } composable(route = Pages.UserProfile.route) { UserProfileView(chatModel, nav) } + composable(route = Pages.Help.route) { + HelpView(chatModel, nav) + } } val am = chatModel.alertManager if (am.presentAlert.value) am.alertView.value?.invoke() @@ -130,8 +130,8 @@ sealed class Pages(val route: String) { object AddContact: Pages("add_contact") object Connect: Pages("connect") object ChatInfo: Pages("chat_info") - object Settings: Pages("settings") object UserProfile: Pages("user_profile") + object Help: Pages("help") } @DelicateCoroutinesApi diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt index 63c36affa2..fa78a9a418 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt @@ -12,6 +12,7 @@ class ChatModel(val controller: ChatController, val alertManager: SimplexApp.Ale var currentUser = mutableStateOf(null) var userCreated = mutableStateOf(null) var chats = mutableStateListOf() + var chatsLoaded = mutableStateOf(null) var chatId = mutableStateOf(null) var chatItems = mutableStateListOf() diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt index bfb255dad4..a1c790134b 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt @@ -24,6 +24,7 @@ open class ChatController(val ctrl: ChatCtrl, val alertManager: SimplexApp.Alert try { apiStartChat() chatModel.chats.addAll(apiGetChats()) + chatModel.chatsLoaded.value = true startReceiver() Log.d("SIMPLEX", "started chat") } catch(e: Error) { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt new file mode 100644 index 0000000000..8fb912c6d5 --- /dev/null +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt @@ -0,0 +1,170 @@ +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.* +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.PersonAdd +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.text.* +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import chat.simplex.app.ui.theme.SimpleXTheme +import chat.simplex.app.views.usersettings.simplexTeamUri + +@Composable +fun ChatHelpView(addContact: () -> Unit, doAddContact: Boolean) { + Column( + Modifier + .fillMaxWidth() + .background(MaterialTheme.colors.background), + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + val uriHandler = LocalUriHandler.current + + Text( + "Thank you for installing SimpleX Chat!", + color = MaterialTheme.colors.onBackground + ) + Text( + buildAnnotatedString { + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground)) { + append("You can ") + } + withStyle(SpanStyle(color = MaterialTheme.colors.primary)) { + append("connect to SimpleX team") + } + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground)) { + append(".") + } + }, + modifier = Modifier + .clickable(onClick = { uriHandler.openUri(simplexTeamUri) }) + ) + + Column( + Modifier.padding(top = 24.dp), + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Text( + "To start a new chat", + color = MaterialTheme.colors.onBackground, + style = MaterialTheme.typography.h2 + ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + "Tap button", + color = MaterialTheme.colors.onBackground + ) + Icon( + Icons.Outlined.PersonAdd, + "Add Contact", + modifier = if (doAddContact) Modifier.clickable(onClick = addContact) else Modifier, + tint = MaterialTheme.colors.onBackground, + ) + Text( + "above, then:", + color = MaterialTheme.colors.onBackground + ) + } + Text( + buildAnnotatedString { + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground, fontWeight = FontWeight.Bold)) { + append("Add new contact") + } + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground)) { + append(": to create your one-time QR Code for your contact.") + } + } + ) + Text( + buildAnnotatedString { + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground, fontWeight = FontWeight.Bold)) { + append("Scan QR code") + } + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground)) { + append(": to connect to your contact who shows QR code to you.") + } + } + ) + } + + Column( + Modifier.padding(top = 24.dp), + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + Text( + "To connect via link", + color = MaterialTheme.colors.onBackground, + style = MaterialTheme.typography.h2 + ) + Text( + "If you received SimpleX Chat invitation link you can open it in your browser:", + color = MaterialTheme.colors.onBackground + ) + Text( + buildAnnotatedString { + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground)) { + append("\uD83D\uDCBB desktop: scan displayed QR code from the app, via ") + } + withStyle( + SpanStyle(color = MaterialTheme.colors.onBackground, fontWeight = FontWeight.Bold) + ) { + append("Scan QR code") + } + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground)) { + append(".") + } + } + ) + Text( + buildAnnotatedString { + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground)) { + append("\uD83D\uDCF1 mobile: tap ") + } + withStyle( + SpanStyle(color = MaterialTheme.colors.onBackground, fontWeight = FontWeight.Bold) + ) { + append("Open in mobile app") + } + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground)) { + append(", then tap ") + } + withStyle( + SpanStyle(color = MaterialTheme.colors.onBackground, fontWeight = FontWeight.Bold) + ) { + append("Connect") + } + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground)) { + append(" in the app.") + } + } + ) + } + } +} + +@Preview(showBackground = true) +@Preview( + uiMode = Configuration.UI_MODE_NIGHT_YES, + showBackground = true, + name = "Dark Mode" +) +@Composable +fun PreviewChatHelpLayout() { + SimpleXTheme { + ChatHelpView({}, false) + } +} diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt index bd8c40a0fe..ba35676549 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt @@ -21,6 +21,7 @@ import androidx.navigation.NavOptions import chat.simplex.app.Pages import chat.simplex.app.model.Chat import chat.simplex.app.model.ChatModel +import chat.simplex.app.views.chat.ChatHelpView import chat.simplex.app.views.helpers.withApi import chat.simplex.app.views.newchat.NewChatSheet import chat.simplex.app.views.usersettings.SettingsView @@ -31,7 +32,7 @@ import kotlinx.coroutines.* class ScaffoldController(val state: BottomSheetScaffoldState, val scope: CoroutineScope) { fun expand() = scope.launch { state.bottomSheetState.expand() } fun collapse() = scope.launch { state.bottomSheetState.collapse() } - fun toggle() = scope.launch { + fun toggleSheet() = scope.launch { val s = state.bottomSheetState if (s.isExpanded) s.collapse() else s.expand() } @@ -61,10 +62,7 @@ fun ChatListView(chatModel: ChatModel, nav: NavController) { BottomSheetScaffold( scaffoldState = scaffoldCtrl.state, topBar = { - ChatListToolbar( - scaffoldCtrl, - settings = { scaffoldCtrl.toggleDrawer() } - ) + ChatListToolbar(scaffoldCtrl) }, drawerContent = { SettingsView(chatModel, nav) @@ -79,7 +77,15 @@ fun ChatListView(chatModel: ChatModel, nav: NavController) { .fillMaxSize() .background(MaterialTheme.colors.background) ) { - ChatList(chatModel, nav) + when (chatModel.chatsLoaded.value) { + true -> if (chatModel.chats.isNotEmpty()) { + ChatList(chatModel, nav) + } else { + val user = chatModel.currentUser.value + Help(scaffoldCtrl, displayName = user?.profile?.displayName) + } + else -> ChatList(chatModel, nav) + } } if (scaffoldCtrl.state.bottomSheetState.isExpanded) { Surface( @@ -94,7 +100,41 @@ fun ChatListView(chatModel: ChatModel, nav: NavController) { @ExperimentalMaterialApi @Composable -fun ChatListToolbar(newChatSheetCtrl: ScaffoldController, settings: () -> Unit) { +fun Help(scaffoldCtrl: ScaffoldController, displayName: String?) { + Column( + Modifier + .fillMaxWidth() + .padding(8.dp) + ) { + Text( + text = if (displayName != null) "Welcome ${displayName}!" else "Welcome!", + Modifier.padding(bottom = 24.dp), + style = MaterialTheme.typography.h1, + color = MaterialTheme.colors.onBackground + ) + ChatHelpView({ scaffoldCtrl.toggleSheet() }, true) + Row( + Modifier.padding(top = 30.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + "This text is available in settings", + color = MaterialTheme.colors.onBackground + ) + Icon( + Icons.Outlined.Settings, + "Settings", + tint = MaterialTheme.colors.onBackground, + modifier = Modifier.clickable(onClick = { scaffoldCtrl.toggleDrawer() }) + ) + } + } +} + +@ExperimentalMaterialApi +@Composable +fun ChatListToolbar(scaffoldCtrl: ScaffoldController) { Row( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, @@ -103,7 +143,7 @@ fun ChatListToolbar(newChatSheetCtrl: ScaffoldController, settings: () -> Unit) .padding(horizontal = 8.dp) .height(60.dp) ) { - IconButton(onClick = settings) { + IconButton(onClick = { scaffoldCtrl.toggleDrawer() }) { Icon( Icons.Outlined.Settings, "Settings", @@ -117,7 +157,7 @@ fun ChatListToolbar(newChatSheetCtrl: ScaffoldController, settings: () -> Unit) fontWeight = FontWeight.Bold, modifier = Modifier.padding(5.dp) ) - IconButton(onClick = { newChatSheetCtrl.toggle() }) { + IconButton(onClick = { scaffoldCtrl.toggleSheet() }) { Icon( Icons.Outlined.PersonAdd, "Add Contact", diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt index b4f8094224..64db15a0cf 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.unit.dp import androidx.navigation.NavController import chat.simplex.app.Pages import chat.simplex.app.model.ChatModel -import chat.simplex.app.ui.theme.DarkGray +import chat.simplex.app.ui.theme.HighOrLowlight import chat.simplex.app.ui.theme.SimpleXTheme import chat.simplex.app.views.chatlist.ScaffoldController import chat.simplex.app.views.helpers.withApi @@ -91,7 +91,7 @@ fun ActionButton(text: String, comment: String, icon: ImageVector, disabled: Boo .padding(horizontal = 8.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - val tint = if (disabled) DarkGray else MaterialTheme.colors.primary + val tint = if (disabled) HighOrLowlight else MaterialTheme.colors.primary Icon(icon, text, tint = tint, modifier = Modifier diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt new file mode 100644 index 0000000000..b882cca8b1 --- /dev/null +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt @@ -0,0 +1,64 @@ +package chat.simplex.app.views.usersettings + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import chat.simplex.app.model.ChatModel +import chat.simplex.app.ui.theme.SimpleXTheme +import chat.simplex.app.views.chat.ChatHelpView +import chat.simplex.app.views.helpers.CloseSheetBar + +@Composable +fun HelpView(chatModel: ChatModel, nav: NavController) { + val user = chatModel.currentUser.value + if (user != null) { + HelpLayout( + displayName = user.profile.displayName, + back = { nav.popBackStack() } + ) + } +} + +@Composable +fun HelpLayout(displayName: String, back: () -> Unit) { + Column( + modifier = Modifier + .fillMaxSize() + .background(MaterialTheme.colors.background) + .padding(horizontal = 8.dp), + horizontalAlignment = Alignment.Start + ) { + CloseSheetBar(back) + Text( + "Welcome $displayName!", + Modifier.padding(bottom = 24.dp), + style = MaterialTheme.typography.h1, + color = MaterialTheme.colors.onBackground + ) + ChatHelpView({}, false) + } +} + +@Preview(showBackground = true) +@Preview( + uiMode = Configuration.UI_MODE_NIGHT_YES, + showBackground = true, + name = "Dark Mode" +) +@Composable +fun PreviewHelpView() { + SimpleXTheme { + HelpLayout( + displayName = "Alice", + back = {} + ) + } +} diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt index a44c3b9664..aff3dea986 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt @@ -11,6 +11,7 @@ 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.* import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp @@ -111,7 +112,7 @@ fun SettingsLayout( color = MaterialTheme.colors.onBackground ) }, - func = { println("navigate to help") } + func = { navigate(Pages.Help.route) } ) Divider(Modifier.padding(horizontal = 8.dp)) SettingsSectionView( @@ -172,12 +173,14 @@ fun SettingsLayout( ) Spacer(Modifier.padding(horizontal = 4.dp)) Text( - "Install ", - color = MaterialTheme.colors.onBackground - ) - Text( - "SimpleX Chat for terminal", - color = MaterialTheme.colors.primary + buildAnnotatedString { + withStyle(SpanStyle(color = MaterialTheme.colors.onBackground)) { + append("Install ") + } + withStyle(SpanStyle(color = MaterialTheme.colors.primary)) { + append("SimpleX Chat for terminal") + } + } ) }, func = { uriHandler.openUri("https://github.com/simplex-chat/simplex-chat") }