Merge branch 'master' into ep/debug-reconnect
This commit is contained in:
@@ -28,7 +28,9 @@ struct FramedItemView: View {
|
||||
@State var metaColor = Color.secondary
|
||||
@State var showFullScreenImage = false
|
||||
@Binding var allowMenu: Bool
|
||||
|
||||
@State private var showSecrets = false
|
||||
@State private var showQuoteSecrets = false
|
||||
|
||||
@Binding var audioPlayer: AudioPlayer?
|
||||
@Binding var playbackState: VoiceMessagePlaybackState
|
||||
@Binding var playbackTime: TimeInterval?
|
||||
@@ -252,10 +254,12 @@ struct FramedItemView: View {
|
||||
}
|
||||
|
||||
private func ciQuotedMsgTextView(_ qi: CIQuote, lines: Int) -> some View {
|
||||
MsgContentView(chat: chat, text: qi.text, formattedText: qi.formattedText)
|
||||
.lineLimit(lines)
|
||||
.font(.subheadline)
|
||||
.padding(.bottom, 6)
|
||||
toggleSecrets(qi.formattedText, $showQuoteSecrets,
|
||||
MsgContentView(chat: chat, text: qi.text, formattedText: qi.formattedText, showSecrets: showQuoteSecrets)
|
||||
.lineLimit(lines)
|
||||
.font(.subheadline)
|
||||
.padding(.bottom, 6)
|
||||
)
|
||||
}
|
||||
|
||||
private func ciQuoteIconView(_ image: String) -> some View {
|
||||
@@ -278,13 +282,15 @@ struct FramedItemView: View {
|
||||
@ViewBuilder private func ciMsgContentView(_ ci: ChatItem) -> some View {
|
||||
let text = ci.meta.isLive ? ci.content.msgContent?.text ?? ci.text : ci.text
|
||||
let rtl = isRightToLeft(text)
|
||||
let v = MsgContentView(
|
||||
let ft = text == "" ? [] : ci.formattedText
|
||||
let v = toggleSecrets(ft, $showSecrets, MsgContentView(
|
||||
chat: chat,
|
||||
text: text,
|
||||
formattedText: text == "" ? [] : ci.formattedText,
|
||||
formattedText: ft,
|
||||
meta: ci.meta,
|
||||
rightToLeft: rtl
|
||||
)
|
||||
rightToLeft: rtl,
|
||||
showSecrets: showSecrets
|
||||
))
|
||||
.multilineTextAlignment(rtl ? .trailing : .leading)
|
||||
.padding(.vertical, 6)
|
||||
.padding(.horizontal, 12)
|
||||
@@ -298,7 +304,7 @@ struct FramedItemView: View {
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ViewBuilder private func ciFileView(_ ci: ChatItem, _ text: String) -> some View {
|
||||
CIFileView(file: chatItem.file, edited: chatItem.meta.itemEdited)
|
||||
.overlay(DetermineWidth())
|
||||
@@ -318,6 +324,14 @@ struct FramedItemView: View {
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder func toggleSecrets<V: View>(_ ft: [FormattedText]?, _ showSecrets: Binding<Bool>, _ v: V) -> some View {
|
||||
if let ft = ft, ft.contains(where: { $0.isSecret }) {
|
||||
v.onTapGesture { showSecrets.wrappedValue.toggle() }
|
||||
} else {
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
func isRightToLeft(_ s: String) -> Bool {
|
||||
if let lang = CFStringTokenizerCopyBestStringLanguage(s as CFString, CFRange(location: 0, length: min(s.count, 80))) {
|
||||
return NSLocale.characterDirection(forLanguage: lang as String) == .rightToLeft
|
||||
|
||||
@@ -31,6 +31,7 @@ struct MsgContentView: View {
|
||||
var sender: String? = nil
|
||||
var meta: CIMeta? = nil
|
||||
var rightToLeft = false
|
||||
var showSecrets: Bool
|
||||
@State private var typingIdx = 0
|
||||
@State private var timer: Timer?
|
||||
|
||||
@@ -62,7 +63,7 @@ struct MsgContentView: View {
|
||||
}
|
||||
|
||||
private func msgContentView() -> Text {
|
||||
var v = messageText(text, formattedText, sender)
|
||||
var v = messageText(text, formattedText, sender, showSecrets: showSecrets)
|
||||
if let mt = meta {
|
||||
if mt.isLive {
|
||||
v = v + typingIndicator(mt.recent)
|
||||
@@ -84,14 +85,14 @@ struct MsgContentView: View {
|
||||
}
|
||||
}
|
||||
|
||||
func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: String?, icon: String? = nil, preview: Bool = false) -> Text {
|
||||
func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: String?, icon: String? = nil, preview: Bool = false, showSecrets: Bool) -> Text {
|
||||
let s = text
|
||||
var res: Text
|
||||
if let ft = formattedText, ft.count > 0 && ft.count <= 200 {
|
||||
res = formatText(ft[0], preview)
|
||||
res = formatText(ft[0], preview, showSecret: showSecrets)
|
||||
var i = 1
|
||||
while i < ft.count {
|
||||
res = res + formatText(ft[i], preview)
|
||||
res = res + formatText(ft[i], preview, showSecret: showSecrets)
|
||||
i = i + 1
|
||||
}
|
||||
} else {
|
||||
@@ -110,7 +111,7 @@ func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: St
|
||||
}
|
||||
}
|
||||
|
||||
private func formatText(_ ft: FormattedText, _ preview: Bool) -> Text {
|
||||
private func formatText(_ ft: FormattedText, _ preview: Bool, showSecret: Bool) -> Text {
|
||||
let t = ft.text
|
||||
if let f = ft.format {
|
||||
switch (f) {
|
||||
@@ -118,7 +119,13 @@ private func formatText(_ ft: FormattedText, _ preview: Bool) -> Text {
|
||||
case .italic: return Text(t).italic()
|
||||
case .strikeThrough: return Text(t).strikethrough()
|
||||
case .snippet: return Text(t).font(.body.monospaced())
|
||||
case .secret: return Text(t).foregroundColor(.clear).underline(color: .primary)
|
||||
case .secret: return
|
||||
showSecret
|
||||
? Text(t)
|
||||
: Text(AttributedString(t, attributes: AttributeContainer([
|
||||
.foregroundColor: UIColor.clear as Any,
|
||||
.backgroundColor: UIColor.secondarySystemFill as Any
|
||||
])))
|
||||
case let .colored(color): return Text(t).foregroundColor(color.uiColor)
|
||||
case .uri: return linkText(t, t, preview, prefix: "")
|
||||
case let .simplexLink(linkType, simplexUri, smpHosts):
|
||||
@@ -156,7 +163,8 @@ struct MsgContentView_Previews: PreviewProvider {
|
||||
text: chatItem.text,
|
||||
formattedText: chatItem.formattedText,
|
||||
sender: chatItem.memberDisplayName,
|
||||
meta: chatItem.meta
|
||||
meta: chatItem.meta,
|
||||
showSecrets: false
|
||||
)
|
||||
.environmentObject(Chat.sampleData)
|
||||
}
|
||||
|
||||
@@ -168,7 +168,6 @@ struct ChatItemInfoView: View {
|
||||
@ViewBuilder private func itemVersionView(_ itemVersion: ChatItemVersion, _ maxWidth: CGFloat, current: Bool) -> some View {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
textBubble(itemVersion.msgContent.text, itemVersion.formattedText, nil)
|
||||
.allowsHitTesting(false)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 6)
|
||||
.background(chatItemFrameColor(ci, colorScheme))
|
||||
@@ -198,7 +197,7 @@ struct ChatItemInfoView: View {
|
||||
|
||||
@ViewBuilder private func textBubble(_ text: String, _ formattedText: [FormattedText]?, _ sender: String? = nil) -> some View {
|
||||
if text != "" {
|
||||
messageText(text, formattedText, sender)
|
||||
TextBubble(text: text, formattedText: formattedText, sender: sender)
|
||||
} else {
|
||||
Text("no text")
|
||||
.italic()
|
||||
@@ -206,6 +205,17 @@ struct ChatItemInfoView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private struct TextBubble: View {
|
||||
var text: String
|
||||
var formattedText: [FormattedText]?
|
||||
var sender: String? = nil
|
||||
@State private var showSecrets = false
|
||||
|
||||
var body: some View {
|
||||
toggleSecrets(formattedText, $showSecrets, messageText(text, formattedText, sender, showSecrets: showSecrets))
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder private func quoteTab(_ qi: CIQuote) -> some View {
|
||||
GeometryReader { g in
|
||||
let maxWidth = (g.size.width - 32) * 0.84
|
||||
@@ -227,7 +237,6 @@ struct ChatItemInfoView: View {
|
||||
@ViewBuilder private func quotedMsgView(_ qi: CIQuote, _ maxWidth: CGFloat) -> some View {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
textBubble(qi.text, qi.formattedText, qi.getSender(nil))
|
||||
.allowsHitTesting(false)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 6)
|
||||
.background(quotedMsgFrameColor(qi, colorScheme))
|
||||
|
||||
@@ -51,7 +51,8 @@ struct ContextItemView: View {
|
||||
MsgContentView(
|
||||
chat: chat,
|
||||
text: contextItem.text,
|
||||
formattedText: contextItem.formattedText
|
||||
formattedText: contextItem.formattedText,
|
||||
showSecrets: false
|
||||
)
|
||||
.multilineTextAlignment(isRightToLeft(contextItem.text) ? .trailing : .leading)
|
||||
.lineLimit(lines)
|
||||
|
||||
@@ -53,8 +53,7 @@ struct GroupWelcomeView: View {
|
||||
}
|
||||
|
||||
private func textPreview() -> some View {
|
||||
messageText(welcomeText, parseSimpleXMarkdown(welcomeText), nil)
|
||||
.allowsHitTesting(false)
|
||||
messageText(welcomeText, parseSimpleXMarkdown(welcomeText), nil, showSecrets: false)
|
||||
.frame(minHeight: 140, alignment: .topLeading)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ struct ChatPreviewView: View {
|
||||
let msg = draft.message
|
||||
return image("rectangle.and.pencil.and.ellipsis", color: .accentColor)
|
||||
+ attachment()
|
||||
+ messageText(msg, parseSimpleXMarkdown(msg), nil, preview: true)
|
||||
+ messageText(msg, parseSimpleXMarkdown(msg), nil, preview: true, showSecrets: false)
|
||||
|
||||
func image(_ s: String, color: Color = Color(uiColor: .tertiaryLabel)) -> Text {
|
||||
Text(Image(systemName: s)).foregroundColor(color) + Text(" ")
|
||||
@@ -169,7 +169,7 @@ struct ChatPreviewView: View {
|
||||
func chatItemPreview(_ cItem: ChatItem) -> Text {
|
||||
let itemText = cItem.meta.itemDeleted == nil ? cItem.text : NSLocalizedString("marked deleted", comment: "marked deleted chat item preview text")
|
||||
let itemFormattedText = cItem.meta.itemDeleted == nil ? cItem.formattedText : nil
|
||||
return messageText(itemText, itemFormattedText, cItem.memberDisplayName, icon: attachment(), preview: true)
|
||||
return messageText(itemText, itemFormattedText, cItem.memberDisplayName, icon: attachment(), preview: true, showSecrets: false)
|
||||
|
||||
func attachment() -> String? {
|
||||
switch cItem.content.msgContent {
|
||||
|
||||
@@ -42,11 +42,11 @@
|
||||
5C3F1D562842B68D00EC8A82 /* IntegrityErrorItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C3F1D552842B68D00EC8A82 /* IntegrityErrorItemView.swift */; };
|
||||
5C3F1D58284363C400EC8A82 /* PrivacySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C3F1D57284363C400EC8A82 /* PrivacySettings.swift */; };
|
||||
5C4B3B0A285FB130003915F2 /* DatabaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4B3B09285FB130003915F2 /* DatabaseView.swift */; };
|
||||
5C4E80DA2B3CCD090080FAE2 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E80D52B3CCD090080FAE2 /* libgmp.a */; };
|
||||
5C4E80DB2B3CCD090080FAE2 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E80D62B3CCD090080FAE2 /* libffi.a */; };
|
||||
5C4E80DC2B3CCD090080FAE2 /* libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E80D72B3CCD090080FAE2 /* libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5.a */; };
|
||||
5C4E80DD2B3CCD090080FAE2 /* libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E80D82B3CCD090080FAE2 /* libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5-ghc9.6.3.a */; };
|
||||
5C4E80DE2B3CCD090080FAE2 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E80D92B3CCD090080FAE2 /* libgmpxx.a */; };
|
||||
5C4E80E42B40A96C0080FAE2 /* libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E80DF2B40A96C0080FAE2 /* libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ.a */; };
|
||||
5C4E80E52B40A96C0080FAE2 /* libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E80E02B40A96C0080FAE2 /* libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ-ghc9.6.3.a */; };
|
||||
5C4E80E62B40A96C0080FAE2 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E80E12B40A96C0080FAE2 /* libgmp.a */; };
|
||||
5C4E80E72B40A96C0080FAE2 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E80E22B40A96C0080FAE2 /* libgmpxx.a */; };
|
||||
5C4E80E82B40A96C0080FAE2 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E80E32B40A96C0080FAE2 /* libffi.a */; };
|
||||
5C5346A827B59A6A004DF848 /* ChatHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5346A727B59A6A004DF848 /* ChatHelp.swift */; };
|
||||
5C55A91F283AD0E400C4E99E /* CallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C55A91E283AD0E400C4E99E /* CallManager.swift */; };
|
||||
5C55A921283CCCB700C4E99E /* IncomingCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C55A920283CCCB700C4E99E /* IncomingCallView.swift */; };
|
||||
@@ -173,11 +173,6 @@
|
||||
646BB38E283FDB6D001CE359 /* LocalAuthenticationUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 646BB38D283FDB6D001CE359 /* LocalAuthenticationUtils.swift */; };
|
||||
647F090E288EA27B00644C40 /* GroupMemberInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 647F090D288EA27B00644C40 /* GroupMemberInfoView.swift */; };
|
||||
648010AB281ADD15009009B9 /* CIFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648010AA281ADD15009009B9 /* CIFileView.swift */; };
|
||||
64863B9B2B3C536500714A11 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64863B962B3C536500714A11 /* libgmpxx.a */; };
|
||||
64863B9C2B3C536500714A11 /* libHSsimplex-chat-5.4.2.0-1dXNnkvLJVS8FSAgswHDGD-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64863B972B3C536500714A11 /* libHSsimplex-chat-5.4.2.0-1dXNnkvLJVS8FSAgswHDGD-ghc9.6.3.a */; };
|
||||
64863B9D2B3C536500714A11 /* libHSsimplex-chat-5.4.2.0-1dXNnkvLJVS8FSAgswHDGD.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64863B982B3C536500714A11 /* libHSsimplex-chat-5.4.2.0-1dXNnkvLJVS8FSAgswHDGD.a */; };
|
||||
64863B9E2B3C536500714A11 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64863B992B3C536500714A11 /* libgmp.a */; };
|
||||
64863B9F2B3C536500714A11 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64863B9A2B3C536500714A11 /* libffi.a */; };
|
||||
649BCDA0280460FD00C3A862 /* ComposeImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCD9F280460FD00C3A862 /* ComposeImageView.swift */; };
|
||||
649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCDA12805D6EF00C3A862 /* CIImageView.swift */; };
|
||||
64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */; };
|
||||
@@ -294,11 +289,11 @@
|
||||
5C3F1D57284363C400EC8A82 /* PrivacySettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacySettings.swift; sourceTree = "<group>"; };
|
||||
5C422A7C27A9A6FA0097A1E1 /* SimpleX (iOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "SimpleX (iOS).entitlements"; sourceTree = "<group>"; };
|
||||
5C4B3B09285FB130003915F2 /* DatabaseView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseView.swift; sourceTree = "<group>"; };
|
||||
5C4E80D52B3CCD090080FAE2 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
||||
5C4E80D62B3CCD090080FAE2 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
|
||||
5C4E80D72B3CCD090080FAE2 /* libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5.a"; sourceTree = "<group>"; };
|
||||
5C4E80D82B3CCD090080FAE2 /* libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
5C4E80D92B3CCD090080FAE2 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
||||
5C4E80DF2B40A96C0080FAE2 /* libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ.a"; sourceTree = "<group>"; };
|
||||
5C4E80E02B40A96C0080FAE2 /* libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
5C4E80E12B40A96C0080FAE2 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
||||
5C4E80E22B40A96C0080FAE2 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
||||
5C4E80E32B40A96C0080FAE2 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
|
||||
5C5346A727B59A6A004DF848 /* ChatHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatHelp.swift; sourceTree = "<group>"; };
|
||||
5C55A91E283AD0E400C4E99E /* CallManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallManager.swift; sourceTree = "<group>"; };
|
||||
5C55A920283CCCB700C4E99E /* IncomingCallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncomingCallView.swift; sourceTree = "<group>"; };
|
||||
@@ -461,11 +456,6 @@
|
||||
646BB38D283FDB6D001CE359 /* LocalAuthenticationUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAuthenticationUtils.swift; sourceTree = "<group>"; };
|
||||
647F090D288EA27B00644C40 /* GroupMemberInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupMemberInfoView.swift; sourceTree = "<group>"; };
|
||||
648010AA281ADD15009009B9 /* CIFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIFileView.swift; sourceTree = "<group>"; };
|
||||
64863B962B3C536500714A11 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
||||
64863B972B3C536500714A11 /* libHSsimplex-chat-5.4.2.0-1dXNnkvLJVS8FSAgswHDGD-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.2.0-1dXNnkvLJVS8FSAgswHDGD-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
64863B982B3C536500714A11 /* libHSsimplex-chat-5.4.2.0-1dXNnkvLJVS8FSAgswHDGD.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.2.0-1dXNnkvLJVS8FSAgswHDGD.a"; sourceTree = "<group>"; };
|
||||
64863B992B3C536500714A11 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
||||
64863B9A2B3C536500714A11 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
|
||||
6493D667280ED77F007A76FB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
649BCD9F280460FD00C3A862 /* ComposeImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeImageView.swift; sourceTree = "<group>"; };
|
||||
649BCDA12805D6EF00C3A862 /* CIImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIImageView.swift; sourceTree = "<group>"; };
|
||||
@@ -521,13 +511,13 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
5C4E80DD2B3CCD090080FAE2 /* libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5-ghc9.6.3.a in Frameworks */,
|
||||
5C4E80E72B40A96C0080FAE2 /* libgmpxx.a in Frameworks */,
|
||||
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
|
||||
5C4E80DA2B3CCD090080FAE2 /* libgmp.a in Frameworks */,
|
||||
5C4E80DC2B3CCD090080FAE2 /* libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5.a in Frameworks */,
|
||||
5C4E80E62B40A96C0080FAE2 /* libgmp.a in Frameworks */,
|
||||
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
|
||||
5C4E80DB2B3CCD090080FAE2 /* libffi.a in Frameworks */,
|
||||
5C4E80DE2B3CCD090080FAE2 /* libgmpxx.a in Frameworks */,
|
||||
5C4E80E82B40A96C0080FAE2 /* libffi.a in Frameworks */,
|
||||
5C4E80E52B40A96C0080FAE2 /* libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ-ghc9.6.3.a in Frameworks */,
|
||||
5C4E80E42B40A96C0080FAE2 /* libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -589,11 +579,11 @@
|
||||
5C764E5C279C70B7000C6508 /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5C4E80D62B3CCD090080FAE2 /* libffi.a */,
|
||||
5C4E80D52B3CCD090080FAE2 /* libgmp.a */,
|
||||
5C4E80D92B3CCD090080FAE2 /* libgmpxx.a */,
|
||||
5C4E80D82B3CCD090080FAE2 /* libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5-ghc9.6.3.a */,
|
||||
5C4E80D72B3CCD090080FAE2 /* libHSsimplex-chat-5.4.2.1-FP1oxJSttEYhorN1FRfI5.a */,
|
||||
5C4E80E32B40A96C0080FAE2 /* libffi.a */,
|
||||
5C4E80E12B40A96C0080FAE2 /* libgmp.a */,
|
||||
5C4E80E22B40A96C0080FAE2 /* libgmpxx.a */,
|
||||
5C4E80E02B40A96C0080FAE2 /* libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ-ghc9.6.3.a */,
|
||||
5C4E80DF2B40A96C0080FAE2 /* libHSsimplex-chat-5.5.0.0-FwZXD1cMpkc1VLQMq43OyQ.a */,
|
||||
);
|
||||
path = Libraries;
|
||||
sourceTree = "<group>";
|
||||
@@ -1512,7 +1502,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 186;
|
||||
CURRENT_PROJECT_VERSION = 187;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -1534,7 +1524,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.4.2;
|
||||
MARKETING_VERSION = 5.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
|
||||
PRODUCT_NAME = SimpleX;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -1555,7 +1545,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 186;
|
||||
CURRENT_PROJECT_VERSION = 187;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -1577,7 +1567,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.4.2;
|
||||
MARKETING_VERSION = 5.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
|
||||
PRODUCT_NAME = SimpleX;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -1636,7 +1626,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 186;
|
||||
CURRENT_PROJECT_VERSION = 187;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -1649,7 +1639,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.4.2;
|
||||
MARKETING_VERSION = 5.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
@@ -1668,7 +1658,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 186;
|
||||
CURRENT_PROJECT_VERSION = 187;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -1681,7 +1671,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 5.4.2;
|
||||
MARKETING_VERSION = 5.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
@@ -1700,7 +1690,7 @@
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 186;
|
||||
CURRENT_PROJECT_VERSION = 187;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
@@ -1724,7 +1714,7 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Libraries/sim",
|
||||
);
|
||||
MARKETING_VERSION = 5.4.2;
|
||||
MARKETING_VERSION = 5.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SDKROOT = iphoneos;
|
||||
@@ -1746,7 +1736,7 @@
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 186;
|
||||
CURRENT_PROJECT_VERSION = 187;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
@@ -1770,7 +1760,7 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Libraries/sim",
|
||||
);
|
||||
MARKETING_VERSION = 5.4.2;
|
||||
MARKETING_VERSION = 5.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SDKROOT = iphoneos;
|
||||
|
||||
@@ -3131,6 +3131,10 @@ extension MsgContent: Encodable {
|
||||
public struct FormattedText: Decodable {
|
||||
public var text: String
|
||||
public var format: Format?
|
||||
|
||||
public var isSecret: Bool {
|
||||
if case .secret = format { true } else { false }
|
||||
}
|
||||
}
|
||||
|
||||
public enum Format: Decodable, Equatable {
|
||||
|
||||
@@ -53,6 +53,7 @@ fun ChatItemInfoView(chatModel: ChatModel, ci: ChatItem, ciInfo: ChatItemInfo, d
|
||||
text, if (text.isEmpty()) emptyList() else formattedText,
|
||||
sender = sender,
|
||||
senderBold = true,
|
||||
toggleSecrets = true,
|
||||
linkMode = SimplexLinkMode.DESCRIPTION, uriHandler = uriHandler,
|
||||
onLinkLongClick = { showMenu.value = true }
|
||||
)
|
||||
|
||||
@@ -34,6 +34,7 @@ fun ContextItemView(
|
||||
fun msgContentView(lines: Int) {
|
||||
MarkdownText(
|
||||
contextItem.text, contextItem.formattedText,
|
||||
toggleSecrets = false,
|
||||
maxLines = lines,
|
||||
linkMode = SimplexLinkMode.DESCRIPTION,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
|
||||
@@ -15,6 +15,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import dev.icerock.moko.resources.compose.painterResource
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
@@ -119,13 +120,15 @@ private fun GroupWelcomeLayout(
|
||||
|
||||
@Composable
|
||||
private fun TextPreview(text: String, linkMode: SimplexLinkMode, markdown: Boolean = true) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
Column {
|
||||
SelectionContainer(Modifier.fillMaxWidth()) {
|
||||
MarkdownText(
|
||||
text,
|
||||
formattedText = if (markdown) remember(text) { parseToMarkdown(text) } else null,
|
||||
toggleSecrets = false,
|
||||
modifier = Modifier.fillMaxHeight().padding(horizontal = DEFAULT_PADDING),
|
||||
linkMode = linkMode,
|
||||
linkMode = linkMode, uriHandler = uriHandler,
|
||||
style = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.onBackground, lineHeight = 22.sp)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ fun FramedItemView(
|
||||
MarkdownText(
|
||||
qi.text,
|
||||
qi.formattedText,
|
||||
toggleSecrets = true,
|
||||
maxLines = lines,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = TextStyle(fontSize = 15.sp, color = MaterialTheme.colors.onSurface),
|
||||
@@ -288,7 +289,7 @@ fun CIMarkdownText(
|
||||
Box(Modifier.padding(vertical = 6.dp, horizontal = 12.dp)) {
|
||||
val text = if (ci.meta.isLive) ci.content.msgContent?.text ?: ci.text else ci.text
|
||||
MarkdownText(
|
||||
text, if (text.isEmpty()) emptyList() else ci.formattedText,
|
||||
text, if (text.isEmpty()) emptyList() else ci.formattedText, toggleSecrets = true,
|
||||
meta = ci.meta, chatTTL = chatTTL, linkMode = linkMode,
|
||||
uriHandler = uriHandler, senderBold = true, onLinkLongClick = onLinkLongClick
|
||||
)
|
||||
|
||||
@@ -60,6 +60,7 @@ fun MarkdownText (
|
||||
sender: String? = null,
|
||||
meta: CIMeta? = null,
|
||||
chatTTL: Int? = null,
|
||||
toggleSecrets: Boolean,
|
||||
style: TextStyle = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.onSurface, lineHeight = 22.sp),
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
overflow: TextOverflow = TextOverflow.Clip,
|
||||
@@ -89,6 +90,7 @@ fun MarkdownText (
|
||||
) {
|
||||
var timer: Job? by remember { mutableStateOf(null) }
|
||||
var typingIdx by rememberSaveable { mutableStateOf(0) }
|
||||
val showSecrets = remember { mutableStateMapOf<String, Boolean>() }
|
||||
fun stopTyping() {
|
||||
timer?.cancel()
|
||||
timer = null
|
||||
@@ -127,15 +129,22 @@ fun MarkdownText (
|
||||
}
|
||||
Text(annotatedText, style = style, modifier = modifier, maxLines = maxLines, overflow = overflow, inlineContent = inlineContent ?: mapOf())
|
||||
} else {
|
||||
var hasLinks = false
|
||||
var hasAnnotations = false
|
||||
val annotatedText = buildAnnotatedString {
|
||||
appendSender(this, sender, senderBold)
|
||||
for (ft in formattedText) {
|
||||
for ((i, ft) in formattedText.withIndex()) {
|
||||
if (ft.format == null) append(ft.text)
|
||||
else {
|
||||
else if (toggleSecrets && ft.format is Format.Secret) {
|
||||
val ftStyle = ft.format.style
|
||||
hasAnnotations = true
|
||||
val key = i.toString()
|
||||
withAnnotation(tag = "SECRET", annotation = key) {
|
||||
if (showSecrets[key] == true) append(ft.text) else withStyle(ftStyle) { append(ft.text) }
|
||||
}
|
||||
} else {
|
||||
val link = ft.link(linkMode)
|
||||
if (link != null) {
|
||||
hasLinks = true
|
||||
hasAnnotations = true
|
||||
val ftStyle = ft.format.style
|
||||
withAnnotation(tag = if (ft.format is Format.SimplexLink) "SIMPLEX_URL" else "URL", annotation = link) {
|
||||
withStyle(ftStyle) { append(ft.viewText(linkMode)) }
|
||||
@@ -153,7 +162,7 @@ fun MarkdownText (
|
||||
withStyle(reserveTimestampStyle) { append("\n" + metaText) }
|
||||
else */if (meta != null) withStyle(reserveTimestampStyle) { append(reserve) }
|
||||
}
|
||||
if (hasLinks && uriHandler != null) {
|
||||
if (hasAnnotations && uriHandler != null) {
|
||||
val icon = remember { mutableStateOf(PointerIcon.Default) }
|
||||
ClickableText(annotatedText, style = style, modifier = modifier.pointerHoverIcon(icon.value), maxLines = maxLines, overflow = overflow,
|
||||
onLongClick = { offset ->
|
||||
@@ -177,12 +186,20 @@ fun MarkdownText (
|
||||
.firstOrNull()?.let { annotation ->
|
||||
uriHandler.openVerifiedSimplexUri(annotation.item)
|
||||
}
|
||||
annotatedText.getStringAnnotations(tag = "SECRET", start = offset, end = offset)
|
||||
.firstOrNull()?.let { annotation ->
|
||||
val key = annotation.item
|
||||
showSecrets[key] = !(showSecrets[key] ?: false)
|
||||
}
|
||||
},
|
||||
onHover = { offset ->
|
||||
icon.value = annotatedText.getStringAnnotations(tag = "URL", start = offset, end = offset)
|
||||
.firstOrNull()?.let {
|
||||
PointerIcon.Hand
|
||||
} ?: annotatedText.getStringAnnotations(tag = "SIMPLEX_URL", start = offset, end = offset)
|
||||
.firstOrNull()?.let {
|
||||
PointerIcon.Hand
|
||||
} ?: annotatedText.getStringAnnotations(tag = "SECRET", start = offset, end = offset)
|
||||
.firstOrNull()?.let {
|
||||
PointerIcon.Hand
|
||||
} ?: PointerIcon.Default
|
||||
|
||||
@@ -173,6 +173,7 @@ fun ChatPreviewView(
|
||||
cInfo is ChatInfo.Group && !ci.chatDir.sent -> ci.memberDisplayName
|
||||
else -> null
|
||||
},
|
||||
toggleSecrets = false,
|
||||
linkMode = linkMode,
|
||||
senderBold = true,
|
||||
maxLines = 2,
|
||||
|
||||
@@ -78,17 +78,6 @@ fun ReadableText(text: String, textAlign: TextAlign = TextAlign.Start, padding:
|
||||
Text(text, modifier = Modifier.padding(padding), textAlign = textAlign, lineHeight = 22.sp)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ReadableMarkdownText(text: String, textAlign: TextAlign = TextAlign.Start, padding: PaddingValues = PaddingValues(bottom = 12.dp)) {
|
||||
MarkdownText(
|
||||
text,
|
||||
formattedText = remember(text) { parseToMarkdown(text) },
|
||||
modifier = Modifier.padding(padding),
|
||||
style = TextStyle(textAlign = textAlign, lineHeight = 22.sp, fontSize = 16.sp),
|
||||
linkMode = ChatController.appPrefs.simplexLinkMode.get(),
|
||||
)
|
||||
}
|
||||
|
||||
@Preview/*(
|
||||
uiMode = Configuration.UI_MODE_NIGHT_YES,
|
||||
showBackground = true,
|
||||
|
||||
@@ -25,11 +25,11 @@ android.nonTransitiveRClass=true
|
||||
android.enableJetifier=true
|
||||
kotlin.mpp.androidSourceSetLayoutVersion=2
|
||||
|
||||
android.version_name=5.4.2
|
||||
android.version_code=166
|
||||
android.version_name=5.5-beta.0
|
||||
android.version_code=168
|
||||
|
||||
desktop.version_name=5.4.2
|
||||
desktop.version_code=20
|
||||
desktop.version_name=5.5-beta.0
|
||||
desktop.version_code=21
|
||||
|
||||
kotlin.version=1.8.20
|
||||
gradle.plugin.version=7.4.2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: simplex-chat
|
||||
version: 5.4.2.1
|
||||
version: 5.5.0.0
|
||||
#synopsis:
|
||||
#description:
|
||||
homepage: https://github.com/simplex-chat/simplex-chat#readme
|
||||
|
||||
@@ -5,7 +5,7 @@ cabal-version: 1.12
|
||||
-- see: https://github.com/sol/hpack
|
||||
|
||||
name: simplex-chat
|
||||
version: 5.4.2.1
|
||||
version: 5.5.0.0
|
||||
category: Web, System, Services, Cryptography
|
||||
homepage: https://github.com/simplex-chat/simplex-chat#readme
|
||||
author: simplex.chat
|
||||
|
||||
Reference in New Issue
Block a user