fix markdown type for Colored, add types/parsing for formatted text to iOS/android (#358)

This commit is contained in:
Evgeny Poberezkin
2022-02-23 08:45:49 +00:00
committed by GitHub
parent fb76917ec3
commit 8f21453e82
8 changed files with 98 additions and 31 deletions

View File

@@ -436,7 +436,8 @@ class AChatItem (
data class ChatItem (
val chatDir: CIDirection,
val meta: CIMeta,
val content: CIContent
val content: CIContent,
val formattedText: List<FormattedText>? = null
) {
val id: Long get() = meta.itemId
val timestampText: String get() = meta.timestampText
@@ -567,6 +568,33 @@ sealed class MsgContent {
}
@Serializable
class RcvFileTransfer {
class FormattedText(val text: String, val format: Format? = null)
@Serializable
sealed class Format {
@Serializable @SerialName("bold") class Bold: Format()
@Serializable @SerialName("italic") class Italic: Format()
@Serializable @SerialName("underline") class Underline: Format()
@Serializable @SerialName("strikeThrough") class StrikeThrough: Format()
@Serializable @SerialName("snippet") class Snippet: Format()
@Serializable @SerialName("secret") class Secret: Format()
@Serializable @SerialName("colored") class Colored(val formatColor: FormatColor): Format()
@Serializable @SerialName("uri") class Uri: Format()
@Serializable @SerialName("email") class Email: Format()
@Serializable @SerialName("phone") class Phone: Format()
}
@Serializable
enum class FormatColor(val color: String) {
Red("red"),
Green("green"),
Blue("blue"),
Yellow("yellow"),
Cyan("cyan"),
Magenta("magenta"),
Black("black"),
White("white")
}
@Serializable
class RcvFileTransfer

View File

@@ -69,14 +69,13 @@ fun ChatPreviewView(chat: Chat, goToChat: () -> Unit) {
Text(
if (n < 1000) "$n" else "${n / 1000}k",
color = MaterialTheme.colors.onPrimary,
style = MaterialTheme.typography.body2,
fontSize = 14.sp,
modifier = Modifier
.background(MaterialTheme.colors.primary, shape = CircleShape)
.align(Alignment.End)
.badgeLayout()
.padding(horizontal = 4.dp)
.padding(vertical = 2.dp)
.padding(horizontal = 3.dp)
.padding(vertical = 1.dp)
)
}
}
@@ -97,7 +96,7 @@ fun ChatPreviewViewExample() {
Clock.System.now(),
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
)),
chatStats = Chat.ChatStats()
chatStats = Chat.ChatStats(unreadCount = 3)
),
goToChat = {}
)

View File

@@ -512,6 +512,7 @@ struct ChatItem: Identifiable, Decodable {
var chatDir: CIDirection
var meta: CIMeta
var content: CIContent
var formattedText: [FormattedText]?
var id: Int64 { get { meta.itemId } }
@@ -657,3 +658,34 @@ extension MsgContent: Decodable {
}
}
}
struct FormattedText: Decodable {
var text: String
var format: Format?
}
enum Format: Decodable {
case bold
case italic
case underline
case strikeThrough
case snippet
case secret
case colored(formatColor: FormatColor)
case uri
case email
case phone
}
enum FormatColor: Decodable {
case red
case green
case blue
case yellow
case cyan
case magenta
case black
case white
// TODO custom decoding, it won't parse as is
}

View File

@@ -13,6 +13,11 @@
5C116CDD27AABE0400E66D01 /* ContactRequestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C116CDB27AABE0400E66D01 /* ContactRequestView.swift */; };
5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1A4C1D27A715B700EAD5AD /* ChatItemView.swift */; };
5C1A4C1F27A715B700EAD5AD /* ChatItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1A4C1D27A715B700EAD5AD /* ChatItemView.swift */; };
5C27CFFE27C61CAB00DD6182 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C27CFF927C61CAB00DD6182 /* libgmp.a */; };
5C27CFFF27C61CAB00DD6182 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C27CFFA27C61CAB00DD6182 /* libgmpxx.a */; };
5C27D00027C61CAB00DD6182 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C27CFFB27C61CAB00DD6182 /* libffi.a */; };
5C27D00127C61CAB00DD6182 /* libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C27CFFC27C61CAB00DD6182 /* libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP-ghc8.10.7.a */; };
5C27D00227C61CAB00DD6182 /* libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C27CFFD27C61CAB00DD6182 /* libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP.a */; };
5C2E260727A2941F00F70299 /* SimpleXAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260627A2941F00F70299 /* SimpleXAPI.swift */; };
5C2E260827A2941F00F70299 /* SimpleXAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260627A2941F00F70299 /* SimpleXAPI.swift */; };
5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260A27A30CFA00F70299 /* ChatListView.swift */; };
@@ -25,11 +30,6 @@
5C35CFC927B2782E00FB6C6D /* BGManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C35CFC727B2782E00FB6C6D /* BGManager.swift */; };
5C35CFCB27B2E91D00FB6C6D /* NtfManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C35CFCA27B2E91D00FB6C6D /* NtfManager.swift */; };
5C35CFCC27B2E91D00FB6C6D /* NtfManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C35CFCA27B2E91D00FB6C6D /* NtfManager.swift */; };
5C499F2D27BAF1E300ECB4C5 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C499F2827BAF1E300ECB4C5 /* libffi.a */; };
5C499F2E27BAF1E300ECB4C5 /* libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C499F2927BAF1E300ECB4C5 /* libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8.a */; };
5C499F2F27BAF1E300ECB4C5 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C499F2A27BAF1E300ECB4C5 /* libgmpxx.a */; };
5C499F3027BAF1E300ECB4C5 /* libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C499F2B27BAF1E300ECB4C5 /* libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8-ghc8.10.7.a */; };
5C499F3127BAF1E300ECB4C5 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C499F2C27BAF1E300ECB4C5 /* libgmp.a */; };
5C5346A827B59A6A004DF848 /* ChatHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5346A727B59A6A004DF848 /* ChatHelp.swift */; };
5C5346A927B59A6A004DF848 /* ChatHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5346A727B59A6A004DF848 /* ChatHelp.swift */; };
5C6AD81327A834E300348BD7 /* NewChatButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C6AD81227A834E300348BD7 /* NewChatButton.swift */; };
@@ -118,6 +118,11 @@
5C063D2627A4564100AEC577 /* ChatPreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatPreviewView.swift; sourceTree = "<group>"; };
5C116CDB27AABE0400E66D01 /* ContactRequestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactRequestView.swift; sourceTree = "<group>"; };
5C1A4C1D27A715B700EAD5AD /* ChatItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemView.swift; sourceTree = "<group>"; };
5C27CFF927C61CAB00DD6182 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5C27CFFA27C61CAB00DD6182 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5C27CFFB27C61CAB00DD6182 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5C27CFFC27C61CAB00DD6182 /* libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP-ghc8.10.7.a"; sourceTree = "<group>"; };
5C27CFFD27C61CAB00DD6182 /* libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP.a"; sourceTree = "<group>"; };
5C2E260627A2941F00F70299 /* SimpleXAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleXAPI.swift; sourceTree = "<group>"; };
5C2E260927A2C63500F70299 /* MyPlayground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = MyPlayground.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
5C2E260A27A30CFA00F70299 /* ChatListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListView.swift; sourceTree = "<group>"; };
@@ -126,11 +131,6 @@
5C35CFC727B2782E00FB6C6D /* BGManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGManager.swift; sourceTree = "<group>"; };
5C35CFCA27B2E91D00FB6C6D /* NtfManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NtfManager.swift; sourceTree = "<group>"; };
5C422A7C27A9A6FA0097A1E1 /* SimpleX (iOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "SimpleX (iOS).entitlements"; sourceTree = "<group>"; };
5C499F2827BAF1E300ECB4C5 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5C499F2927BAF1E300ECB4C5 /* libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8.a"; sourceTree = "<group>"; };
5C499F2A27BAF1E300ECB4C5 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5C499F2B27BAF1E300ECB4C5 /* libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8-ghc8.10.7.a"; sourceTree = "<group>"; };
5C499F2C27BAF1E300ECB4C5 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5C5346A727B59A6A004DF848 /* ChatHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatHelp.swift; sourceTree = "<group>"; };
5C6AD81227A834E300348BD7 /* NewChatButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewChatButton.swift; sourceTree = "<group>"; };
5C7505A127B65FDB00BE3227 /* CIMetaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIMetaView.swift; sourceTree = "<group>"; };
@@ -178,14 +178,14 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5C499F3027BAF1E300ECB4C5 /* libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8-ghc8.10.7.a in Frameworks */,
5C499F2F27BAF1E300ECB4C5 /* libgmpxx.a in Frameworks */,
5C499F3127BAF1E300ECB4C5 /* libgmp.a in Frameworks */,
5C8F01CD27A6F0D8007D2C8D /* CodeScanner in Frameworks */,
5C499F2E27BAF1E300ECB4C5 /* libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8.a in Frameworks */,
5C27D00027C61CAB00DD6182 /* libffi.a in Frameworks */,
5C27D00227C61CAB00DD6182 /* libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP.a in Frameworks */,
5C27CFFF27C61CAB00DD6182 /* libgmpxx.a in Frameworks */,
5C764E83279C748B000C6508 /* libz.tbd in Frameworks */,
5C27CFFE27C61CAB00DD6182 /* libgmp.a in Frameworks */,
5C764E82279C748B000C6508 /* libiconv.tbd in Frameworks */,
5C499F2D27BAF1E300ECB4C5 /* libffi.a in Frameworks */,
5C27D00127C61CAB00DD6182 /* libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP-ghc8.10.7.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -246,11 +246,11 @@
5C764E5C279C70B7000C6508 /* Libraries */ = {
isa = PBXGroup;
children = (
5C499F2827BAF1E300ECB4C5 /* libffi.a */,
5C499F2C27BAF1E300ECB4C5 /* libgmp.a */,
5C499F2A27BAF1E300ECB4C5 /* libgmpxx.a */,
5C499F2B27BAF1E300ECB4C5 /* libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8-ghc8.10.7.a */,
5C499F2927BAF1E300ECB4C5 /* libHSsimplex-chat-1.2.0-KiHnJvLnz2iELJvTN47xo8.a */,
5C27CFFB27C61CAB00DD6182 /* libffi.a */,
5C27CFF927C61CAB00DD6182 /* libgmp.a */,
5C27CFFA27C61CAB00DD6182 /* libgmpxx.a */,
5C27CFFC27C61CAB00DD6182 /* libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP-ghc8.10.7.a */,
5C27CFFD27C61CAB00DD6182 /* libHSsimplex-chat-1.2.1-GdoRfDZWUHsJU1nzGNbZpP.a */,
);
path = Libraries;
sourceTree = "<group>";

View File

@@ -1295,7 +1295,7 @@ saveChatItem userId cd ci@NewChatItem {itemContent, itemTs, itemText, createdAt}
tz <- liftIO getCurrentTimeZone
ciId <- withStore $ \st -> createNewChatItem st userId cd ci
let ciMeta = mkCIMeta ciId itemText ciStatusNew tz itemTs createdAt
pure $ ChatItem (toCIDirection cd) ciMeta itemContent $ parseMarkdownList itemText
pure $ ChatItem (toCIDirection cd) ciMeta itemContent $ parseMaybeMarkdownList itemText
mkNewChatItem :: forall d. MsgDirectionI d => CIContent d -> MessageId -> UTCTime -> UTCTime -> NewChatItem d
mkNewChatItem itemContent msgId itemTs createdAt =

View File

@@ -14,6 +14,7 @@ import Data.Either (fromRight)
import Data.Functor (($>))
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as M
import Data.Maybe (isNothing)
import Data.String
import Data.Text (Text)
import qualified Data.Text as T
@@ -31,8 +32,10 @@ data Format
| StrikeThrough
| Snippet
| Secret
| Colored FormatColor
| Colored {formatColor :: FormatColor}
| Uri
| Email
| Phone
deriving (Eq, Show, Generic)
colored :: Color -> Format
@@ -127,6 +130,11 @@ colors =
("6", Magenta)
]
parseMaybeMarkdownList :: Text -> Maybe MarkdownList
parseMaybeMarkdownList s =
let m = markdownToList $ parseMarkdown s
in if all (isNothing . format) m then Nothing else Just m
parseMarkdownList :: Text -> MarkdownList
parseMarkdownList = markdownToList . parseMarkdown

View File

@@ -78,7 +78,7 @@ data ChatItem (c :: ChatType) (d :: MsgDirection) = ChatItem
{ chatDir :: CIDirection c d,
meta :: CIMeta d,
content :: CIContent d,
formattedText :: [FormattedText]
formattedText :: Maybe [FormattedText]
}
deriving (Show, Generic)

View File

@@ -2709,7 +2709,7 @@ toDirectChatItem tz (itemId, itemTs, itemContent, itemText, itemStatus, createdA
_ -> badItem
where
cItem :: MsgDirectionI d => SMsgDirection d -> CIDirection c d -> CIStatus d -> CIContent d -> CChatItem c
cItem d cid ciStatus ciContent = CChatItem d (ChatItem cid (ciMeta ciStatus) ciContent $ parseMarkdownList itemText)
cItem d cid ciStatus ciContent = CChatItem d (ChatItem cid (ciMeta ciStatus) ciContent $ parseMaybeMarkdownList itemText)
badItem = Left $ SEBadChatItem itemId
ciMeta :: CIStatus d -> CIMeta d
ciMeta status = mkCIMeta itemId itemText status tz itemTs createdAt
@@ -2732,7 +2732,7 @@ toGroupChatItem tz userContactId ((itemId, itemTs, itemContent, itemText, itemSt
_ -> badItem
where
cItem :: MsgDirectionI d => SMsgDirection d -> CIDirection c d -> CIStatus d -> CIContent d -> CChatItem c
cItem d cid ciStatus ciContent = CChatItem d (ChatItem cid (ciMeta ciStatus) ciContent $ parseMarkdownList itemText)
cItem d cid ciStatus ciContent = CChatItem d (ChatItem cid (ciMeta ciStatus) ciContent $ parseMaybeMarkdownList itemText)
badItem = Left $ SEBadChatItem itemId
ciMeta :: CIStatus d -> CIMeta d
ciMeta status = mkCIMeta itemId itemText status tz itemTs createdAt