android: markdown help (#376)
This commit is contained in:
committed by
GitHub
parent
0389a58f64
commit
ad1612d84a
@@ -122,6 +122,9 @@ fun Navigation(chatModel: ChatModel) {
|
||||
composable(route = Pages.Help.route) {
|
||||
HelpView(chatModel, nav)
|
||||
}
|
||||
composable(route = Pages.Markdown.route) {
|
||||
MarkdownHelpView(nav)
|
||||
}
|
||||
}
|
||||
val am = chatModel.alertManager
|
||||
if (am.presentAlert.value) am.alertView.value?.invoke()
|
||||
@@ -141,6 +144,7 @@ sealed class Pages(val route: String) {
|
||||
object UserProfile: Pages("user_profile")
|
||||
object UserAddress: Pages("user_address")
|
||||
object Help: Pages("help")
|
||||
object Markdown: Pages("markdown")
|
||||
}
|
||||
|
||||
@DelicateCoroutinesApi
|
||||
|
||||
@@ -250,6 +250,13 @@ data class Chat (
|
||||
@Serializable @SerialName("disconnected") class Disconnected: NetworkStatus()
|
||||
@Serializable @SerialName("error") class Error(val error: String): NetworkStatus()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val sampleData = Chat(
|
||||
chatInfo = ChatInfo.Direct.sampleData,
|
||||
chatItems = arrayListOf(ChatItem.getSampleData())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@@ -465,7 +472,13 @@ data class ChatItem (
|
||||
val isRcvNew: Boolean get() = meta.itemStatus is CIStatus.RcvNew
|
||||
|
||||
companion object {
|
||||
fun getSampleData(id: Long, dir: CIDirection, ts: Instant, text: String,status: CIStatus = CIStatus.SndNew()) =
|
||||
fun getSampleData(
|
||||
id: Long = 1,
|
||||
dir: CIDirection = CIDirection.DirectSnd(),
|
||||
ts: Instant = Clock.System.now(),
|
||||
text: String = "hello\nthere",
|
||||
status: CIStatus = CIStatus.SndNew()
|
||||
) =
|
||||
ChatItem(
|
||||
chatDir = dir,
|
||||
meta = CIMeta.getSample(id, ts, text, status),
|
||||
|
||||
@@ -11,6 +11,7 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@@ -66,7 +67,10 @@ fun TerminalLog(terminalItems: List<TerminalItem>, navigate: (String) -> Unit) {
|
||||
items(terminalItems) { item ->
|
||||
Text("${item.date.toString().subSequence(11, 19)} ${item.label}",
|
||||
style = TextStyle(fontFamily = FontFamily.Monospace, fontSize = 18.sp, color = MaterialTheme.colors.primary),
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||
.clickable { navigate("details/${item.id}") })
|
||||
}
|
||||
val len = terminalItems.count()
|
||||
@@ -79,15 +83,17 @@ fun TerminalLog(terminalItems: List<TerminalItem>, navigate: (String) -> Unit) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DetailView(identifier: Long, terminalItems: List<TerminalItem>, navController: NavController){
|
||||
Column(
|
||||
modifier = Modifier.verticalScroll(rememberScrollState())
|
||||
fun DetailView(identifier: Long, terminalItems: List<TerminalItem>, nav: NavController){
|
||||
Surface(
|
||||
Modifier
|
||||
.background(MaterialTheme.colors.background)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
Button(onClick = { navController.popBackStack() }) {
|
||||
Text("Back")
|
||||
}
|
||||
SelectionContainer {
|
||||
Text((terminalItems.firstOrNull { it.id == identifier })?.details ?: "")
|
||||
Column {
|
||||
CloseSheetBar(nav::popBackStack)
|
||||
SelectionContainer(modifier = Modifier.verticalScroll(rememberScrollState())) {
|
||||
Text((terminalItems.firstOrNull { it.id == identifier })?.details ?: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ fun TextItemView(chatItem: ChatItem, uriHandler: UriHandler? = null) {
|
||||
}
|
||||
|
||||
val reserveTimestampStyle = SpanStyle(color = Color.Transparent)
|
||||
val boldFont = SpanStyle(fontWeight = FontWeight.Bold)
|
||||
val boldFont = SpanStyle(fontWeight = FontWeight.Medium)
|
||||
|
||||
fun appendGroupMember(b: AnnotatedString.Builder, chatItem: ChatItem, groupMemberBold: Boolean) {
|
||||
if (chatItem.chatDir is CIDirection.GroupRcv) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package chat.simplex.app.views.chatlist
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
@@ -11,11 +12,13 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.ExperimentalTextApi
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import chat.simplex.app.model.Chat
|
||||
import chat.simplex.app.model.getTimestampText
|
||||
import chat.simplex.app.ui.theme.HighOrLowlight
|
||||
import chat.simplex.app.ui.theme.SimpleXTheme
|
||||
import chat.simplex.app.views.chat.item.MarkdownText
|
||||
import chat.simplex.app.views.helpers.ChatInfoImage
|
||||
import chat.simplex.app.views.helpers.badgeLayout
|
||||
@@ -74,3 +77,17 @@ fun ChatPreviewView(chat: Chat) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalTextApi
|
||||
@Preview(showBackground = true)
|
||||
@Preview(
|
||||
uiMode = Configuration.UI_MODE_NIGHT_YES,
|
||||
showBackground = true,
|
||||
name = "Dark Mode"
|
||||
)
|
||||
@Composable
|
||||
fun PreviewChatPreviewView() {
|
||||
SimpleXTheme {
|
||||
ChatPreviewView(Chat.sampleData)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ fun HelpView(chatModel: ChatModel, nav: NavController) {
|
||||
if (user != null) {
|
||||
HelpLayout(
|
||||
displayName = user.profile.displayName,
|
||||
back = { nav.popBackStack() }
|
||||
back = nav::popBackStack
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
package chat.simplex.app.views.usersettings
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.*
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import chat.simplex.app.model.Format
|
||||
import chat.simplex.app.model.FormatColor
|
||||
import chat.simplex.app.ui.theme.SimpleXTheme
|
||||
import chat.simplex.app.views.helpers.CloseSheetBar
|
||||
|
||||
@Composable
|
||||
fun MarkdownHelpView(nav: NavController) {
|
||||
MarkdownHelpLayout(nav::popBackStack)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MarkdownHelpLayout(back: () -> Unit) {
|
||||
Surface(
|
||||
Modifier
|
||||
.background(MaterialTheme.colors.background)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
Column {
|
||||
CloseSheetBar(back)
|
||||
Column(Modifier.padding(horizontal = 16.dp)) {
|
||||
Text(
|
||||
"How to use markdown",
|
||||
style = MaterialTheme.typography.h1,
|
||||
)
|
||||
Text(
|
||||
"You can use markdown to format messages:",
|
||||
Modifier.padding(vertical = 16.dp)
|
||||
)
|
||||
MdFormat("*bold*", "bold text", Format.Bold())
|
||||
MdFormat("_italic_", "italic text", Format.Italic())
|
||||
MdFormat("~strike~", "strikethrough text", Format.StrikeThrough())
|
||||
MdFormat("`code`", "a = b + c", Format.Snippet())
|
||||
Row {
|
||||
MdSyntax("!1 colored!")
|
||||
Text(buildAnnotatedString {
|
||||
withStyle(Format.Colored(FormatColor.red).style) { append("red text") }
|
||||
append(" (")
|
||||
appendColor(this, "1", FormatColor.red, ", ")
|
||||
appendColor(this, "2", FormatColor.green, ", ")
|
||||
appendColor(this, "3", FormatColor.blue, ", ")
|
||||
appendColor(this, "4", FormatColor.yellow, ", ")
|
||||
appendColor(this, "5", FormatColor.cyan, ", ")
|
||||
appendColor(this, "6", FormatColor.magenta, ")")
|
||||
})
|
||||
}
|
||||
Row {
|
||||
MdSyntax("#secret")
|
||||
SelectionContainer {
|
||||
Text(buildAnnotatedString {
|
||||
withStyle(Format.Secret().style) { append("secret text") }
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MdSyntax(markdown: String) {
|
||||
Text(markdown, Modifier
|
||||
.width(100.dp)
|
||||
.padding(bottom = 4.dp))
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MdFormat(markdown: String, example: String, format: Format) {
|
||||
Row {
|
||||
MdSyntax(markdown)
|
||||
Text(buildAnnotatedString {
|
||||
withStyle(format.style) { append(example) }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun appendColor(b: AnnotatedString.Builder, s: String, c: FormatColor, after: String) {
|
||||
b.withStyle(Format.Colored(c).style) { append(s)}
|
||||
b.append(after)
|
||||
}
|
||||
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Preview(
|
||||
uiMode = Configuration.UI_MODE_NIGHT_YES,
|
||||
showBackground = true,
|
||||
name = "Dark Mode"
|
||||
)
|
||||
@Composable
|
||||
fun PreviewMarkdownHelpView() {
|
||||
SimpleXTheme {
|
||||
MarkdownHelpLayout(back = {})
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
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.material.*
|
||||
@@ -43,26 +44,28 @@ fun SettingsLayout(
|
||||
navigate: (String) -> Unit
|
||||
) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
Column(
|
||||
Surface(
|
||||
Modifier
|
||||
.background(MaterialTheme.colors.background)
|
||||
.fillMaxSize()
|
||||
// .background(MaterialTheme.colors.background)
|
||||
.padding(8.dp)
|
||||
.padding(top = 16.dp)
|
||||
) {
|
||||
Text(
|
||||
"Your Settings",
|
||||
style = MaterialTheme.typography.h1,
|
||||
color = MaterialTheme.colors.onBackground
|
||||
)
|
||||
Spacer(Modifier.height(30.dp))
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.colors.background)
|
||||
.padding(8.dp)
|
||||
.padding(top = 16.dp)
|
||||
) {
|
||||
Text(
|
||||
"Your Settings",
|
||||
style = MaterialTheme.typography.h1,
|
||||
)
|
||||
Spacer(Modifier.height(30.dp))
|
||||
|
||||
SettingsSectionView(
|
||||
content = {
|
||||
SettingsSectionView({ navigate(Pages.UserProfile.route) }, 60.dp) {
|
||||
Icon(
|
||||
Icons.Outlined.AccountCircle,
|
||||
contentDescription = "Avatar Placeholder",
|
||||
tint = MaterialTheme.colors.onBackground,
|
||||
)
|
||||
Spacer(Modifier.padding(horizontal = 4.dp))
|
||||
Column {
|
||||
@@ -70,138 +73,102 @@ fun SettingsLayout(
|
||||
profile.displayName,
|
||||
style = MaterialTheme.typography.caption,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colors.onBackground
|
||||
)
|
||||
Text(
|
||||
profile.fullName,
|
||||
color = MaterialTheme.colors.onBackground
|
||||
)
|
||||
Text(profile.fullName)
|
||||
}
|
||||
},
|
||||
func = { navigate(Pages.UserProfile.route) },
|
||||
height = 60.dp
|
||||
)
|
||||
Divider(Modifier.padding(horizontal = 8.dp))
|
||||
SettingsSectionView(
|
||||
content = {
|
||||
}
|
||||
Divider(Modifier.padding(horizontal = 8.dp))
|
||||
SettingsSectionView({ navigate(Pages.UserAddress.route) }) {
|
||||
Icon(
|
||||
Icons.Outlined.QrCode,
|
||||
contentDescription = "Address",
|
||||
tint = MaterialTheme.colors.onBackground,
|
||||
)
|
||||
Spacer(Modifier.padding(horizontal = 4.dp))
|
||||
Text(
|
||||
"Your SimpleX contact address",
|
||||
color = MaterialTheme.colors.onBackground
|
||||
)
|
||||
},
|
||||
func = { navigate(Pages.UserAddress.route) }
|
||||
)
|
||||
Spacer(Modifier.height(24.dp))
|
||||
Text("Your SimpleX contact address")
|
||||
}
|
||||
Spacer(Modifier.height(24.dp))
|
||||
|
||||
SettingsSectionView(
|
||||
content = {
|
||||
SettingsSectionView({ navigate(Pages.Help.route) }) {
|
||||
Icon(
|
||||
Icons.Outlined.HelpOutline,
|
||||
contentDescription = "Help",
|
||||
tint = MaterialTheme.colors.onBackground,
|
||||
contentDescription = "Chat help",
|
||||
)
|
||||
Spacer(Modifier.padding(horizontal = 4.dp))
|
||||
Text(
|
||||
"How to use SimpleX Chat",
|
||||
color = MaterialTheme.colors.onBackground
|
||||
Text("How to use SimpleX Chat")
|
||||
}
|
||||
SettingsSectionView({ navigate(Pages.Markdown.route) }) {
|
||||
Icon(
|
||||
Icons.Outlined.TextFormat,
|
||||
contentDescription = "Markdown help",
|
||||
)
|
||||
},
|
||||
func = { navigate(Pages.Help.route) }
|
||||
)
|
||||
Divider(Modifier.padding(horizontal = 8.dp))
|
||||
SettingsSectionView(
|
||||
content = {
|
||||
Spacer(Modifier.padding(horizontal = 4.dp))
|
||||
Text("Markdown in messages")
|
||||
}
|
||||
Divider(Modifier.padding(horizontal = 8.dp))
|
||||
SettingsSectionView({ uriHandler.openUri(simplexTeamUri) }) {
|
||||
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 = {
|
||||
}
|
||||
Divider(Modifier.padding(horizontal = 8.dp))
|
||||
SettingsSectionView({ uriHandler.openUri("mailto:chat@simplex.chat") }) {
|
||||
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))
|
||||
}
|
||||
Spacer(Modifier.height(24.dp))
|
||||
|
||||
SettingsSectionView(
|
||||
content = {
|
||||
SettingsSectionView({ navigate(Pages.Terminal.route) }) {
|
||||
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 = {
|
||||
Text("Chat console")
|
||||
}
|
||||
Divider(Modifier.padding(horizontal = 8.dp))
|
||||
SettingsSectionView({ uriHandler.openUri("https://github.com/simplex-chat/simplex-chat") }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_github),
|
||||
contentDescription = "GitHub",
|
||||
tint = MaterialTheme.colors.onBackground,
|
||||
)
|
||||
Spacer(Modifier.padding(horizontal = 4.dp))
|
||||
Text(
|
||||
buildAnnotatedString {
|
||||
withStyle(SpanStyle(color = MaterialTheme.colors.onBackground)) {
|
||||
append("Install ")
|
||||
}
|
||||
append("Install ")
|
||||
withStyle(SpanStyle(color = MaterialTheme.colors.primary)) {
|
||||
append("SimpleX Chat for terminal")
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
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
|
||||
fun SettingsSectionView(func: () -> Unit, height: Dp = 48.dp, content: (@Composable () -> Unit)) {
|
||||
Row(
|
||||
Modifier
|
||||
.padding(start = 8.dp)
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = func)
|
||||
.height(height),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Row(
|
||||
Modifier.padding(start = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
content.invoke()
|
||||
}
|
||||
content.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user