Android compose navigation (#316)
* initial rough ideas * refactor and put in high level navigation * refactor Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
This commit is contained in:
117
apps/android/.idea/codeStyles/Project.xml
generated
Normal file
117
apps/android/.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,117 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
5
apps/android/.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
apps/android/.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
||||
2
apps/android/.idea/deploymentTargetDropDown.xml
generated
2
apps/android/.idea/deploymentTargetDropDown.xml
generated
@@ -12,6 +12,6 @@
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</runningDeviceTargetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2022-02-16T16:12:41.610721Z" />
|
||||
<timeTargetWasSelectedWithDropDown value="2022-02-16T17:42:43.145045Z" />
|
||||
</component>
|
||||
</project>
|
||||
2
apps/android/.idea/misc.xml
generated
2
apps/android/.idea/misc.xml
generated
@@ -7,6 +7,8 @@
|
||||
<entry key="../../../../../../../layout/compose-model-1644941851914.xml" value="0.28378378378378377" />
|
||||
<entry key="../../../../../../../layout/compose-model-1644956742665.xml" value="1.0" />
|
||||
<entry key="../../../../../../../layout/compose-model-1644963789622.xml" value="0.8420454545454545" />
|
||||
<entry key="../../../../../../../layout/compose-model-1645006324692.xml" value="0.36363636363636365" />
|
||||
<entry key="../../../../../../../layout/compose-model-1645006342272.xml" value="0.36363636363636365" />
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
|
||||
@@ -73,4 +73,5 @@ dependencies {
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
|
||||
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
|
||||
implementation "androidx.navigation:navigation-compose:2.4.1"
|
||||
}
|
||||
|
||||
@@ -8,11 +8,9 @@ import androidx.activity.viewModels
|
||||
import androidx.compose.runtime.Composable
|
||||
import chat.simplex.app.ui.theme.SimpleXTheme
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import chat.simplex.app.model.*
|
||||
import chat.simplex.app.views.TerminalView
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.json.*
|
||||
import kotlinx.serialization.modules.*
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
|
||||
|
||||
class MainActivity: ComponentActivity() {
|
||||
@@ -21,7 +19,7 @@ class MainActivity: ComponentActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
SimpleXTheme {
|
||||
MainPage(viewModel)
|
||||
Navigation(viewModel = viewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +30,21 @@ class SimplexViewModel(application: Application) : AndroidViewModel(application)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MainPage(vm: SimplexViewModel) {
|
||||
TerminalView(vm.chatModel)
|
||||
fun Navigation(viewModel: SimplexViewModel) {
|
||||
val navController = rememberNavController()
|
||||
|
||||
NavHost(navController=navController, startDestination=Pages.Home.route){
|
||||
composable(route=Pages.Home.route){
|
||||
MainPage(vm = viewModel)
|
||||
}
|
||||
// composable(route=Pages.Welcome.route){
|
||||
// WelcomeView(vm.)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Pages(val route: String) {
|
||||
object Home : Pages("home")
|
||||
object Terminal : Pages("terminal")
|
||||
object Welcome : Pages("welcome")
|
||||
}
|
||||
|
||||
10
apps/android/app/src/main/java/chat/simplex/app/MainPage.kt
Normal file
10
apps/android/app/src/main/java/chat/simplex/app/MainPage.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
package chat.simplex.app
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import chat.simplex.app.views.TerminalPage
|
||||
|
||||
@Composable
|
||||
fun MainPage(vm: SimplexViewModel) {
|
||||
|
||||
TerminalPage(vm.chatModel)
|
||||
}
|
||||
@@ -3,20 +3,41 @@ package chat.simplex.app.views
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.text.ClickableText
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import chat.simplex.app.model.CC
|
||||
import chat.simplex.app.model.ChatModel
|
||||
import chat.simplex.app.model.TerminalItem
|
||||
import androidx.navigation.*
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import chat.simplex.app.model.*
|
||||
import chat.simplex.app.ui.theme.SimpleXTheme
|
||||
import chat.simplex.app.views.chat.SendMsgView
|
||||
|
||||
|
||||
@Composable
|
||||
fun TerminalView(chatModel: ChatModel) {
|
||||
fun TerminalPage(chatModel: ChatModel) {
|
||||
val navController = rememberNavController()
|
||||
NavHost(navController = navController, startDestination = "terminalView"){
|
||||
composable("terminalView") { TerminalView(chatModel, navController) }
|
||||
composable(
|
||||
"details" + "/{_details}",
|
||||
arguments=listOf(
|
||||
navArgument("_details"){
|
||||
type = NavType.StringType
|
||||
}
|
||||
)
|
||||
) { entry -> DetailView( entry.arguments?.getString("_details"), navController)}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TerminalView(chatModel: ChatModel, navController: NavController) {
|
||||
Column {
|
||||
TerminalLog(chatModel.terminalItems)
|
||||
TerminalLog(chatModel.terminalItems, navController)
|
||||
SendMsgView(sendMessage = { cmd ->
|
||||
chatModel.controller.sendCmd(CC.Console(cmd))
|
||||
})
|
||||
@@ -24,18 +45,26 @@ fun TerminalView(chatModel: ChatModel) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TerminalLog(terminalItems: List<TerminalItem>) {
|
||||
fun TerminalLog(terminalItems: List<TerminalItem>, navController: NavController) {
|
||||
LazyColumn {
|
||||
items(terminalItems) { item ->
|
||||
Text(item.label)
|
||||
ClickableText(
|
||||
AnnotatedString(item.label),
|
||||
onClick={navController.navigate("details/${item.details}")}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreviewSendMsgView() {
|
||||
SimpleXTheme {
|
||||
TerminalView(chatModel = ChatModel.sampleData)
|
||||
fun DetailView(details: String?, navController: NavController){
|
||||
Column {
|
||||
Text("$details")
|
||||
|
||||
Button(
|
||||
onClick={navController.popBackStack()}
|
||||
)
|
||||
{Text("Back")}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package chat.simplex.app.views
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import chat.simplex.app.R
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextField
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.NavController
|
||||
|
||||
@Composable
|
||||
fun WelcomeView(createUser: (data: String) -> String, navController: NavController) {
|
||||
Column {
|
||||
Image(
|
||||
painter=painterResource(R.drawable.logo), contentDescription = "Simplex Logo",
|
||||
)
|
||||
Text("You control your chat!")
|
||||
Text("The messaging and application platform protecting your privacy and security.")
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Text("We don't store any of your contacts or messages (once delivered) on the servers.")
|
||||
Spacer(Modifier.height(24.dp))
|
||||
CreateProfilePanel(createUser, navController)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CreateProfilePanel(createUser: (data: String) -> String, navController: NavController) {
|
||||
var displayName by remember { mutableStateOf("") }
|
||||
var fullName by remember { mutableStateOf("") }
|
||||
|
||||
Column {
|
||||
Text("Create profile")
|
||||
Text("Your profile is stored on your device and shared only with your contacts.")
|
||||
Text("Display Name")
|
||||
TextField(value = displayName, onValueChange = { displayName = it }, modifier = Modifier.height(30.dp))
|
||||
Text("Full Name (Optional)")
|
||||
TextField(value = fullName, onValueChange = { fullName = it }, modifier = Modifier.height(30.dp))
|
||||
Button(onClick={
|
||||
createUser("{\"displayName\": $displayName, \"fullName\": $fullName}")
|
||||
navController.navigate("home") { popUpTo("home") { inclusive = true }}
|
||||
}) { Text("Create")}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package chat.simplex.app.views.usersettings
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import chat.simplex.app.model.Profile
|
||||
|
||||
//@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun SettingsView(profile: Profile) {
|
||||
Column() {
|
||||
Text("Your Settings")
|
||||
Spacer(Modifier.height(4.dp))
|
||||
Text("YOU", style= MaterialTheme.typography.h4)
|
||||
Button(
|
||||
onClick = { println(profile.displayName) }
|
||||
) {
|
||||
Text(profile.displayName)
|
||||
}
|
||||
Button(
|
||||
onClick = { println(profile.hashCode()) }
|
||||
) {
|
||||
Text("Your SimpleX contact address", style= MaterialTheme.typography.body1)
|
||||
}
|
||||
Spacer(Modifier.height(10.dp))
|
||||
Text("HELP", style= MaterialTheme.typography.h4)
|
||||
Button(
|
||||
onClick = { println("navigate to help") }
|
||||
) {
|
||||
Text("How to use SimpleX Chat")
|
||||
}
|
||||
Button(
|
||||
onClick = { println("start help chat") }
|
||||
) {
|
||||
Text("Get help & advice via chat")
|
||||
}
|
||||
Button(
|
||||
onClick = { println("navigate to email") }
|
||||
) {
|
||||
Text("Ask questions via email")
|
||||
}
|
||||
Spacer(Modifier.height(10.dp))
|
||||
Text("DEVELOP", style= MaterialTheme.typography.h4)
|
||||
Button(
|
||||
onClick = { println("navigate to console") }
|
||||
) {
|
||||
Text("Chat console")
|
||||
}
|
||||
Button(
|
||||
onClick = { println("navigate to github") }
|
||||
) {
|
||||
Text("Install SimpleX for terminal")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
apps/android/app/src/main/res/drawable/logo.png
Normal file
BIN
apps/android/app/src/main/res/drawable/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Reference in New Issue
Block a user