mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-06-28 20:29:53 +00:00
improve text message view (#276)
* show text and time on the same line * convert emails and phones to links
This commit is contained in:
parent
8efb8b2f86
commit
7883ca7657
5 changed files with 54 additions and 20 deletions
|
@ -201,6 +201,8 @@ func chatRecvMsg() throws -> ChatResponse {
|
|||
}
|
||||
|
||||
func apiGetActiveUser() throws -> User? {
|
||||
let _ = getChatCtrl()
|
||||
sleep(1)
|
||||
let r = try chatSendCmd(.showActiveUser)
|
||||
switch r {
|
||||
case let .activeUser(user): return user
|
||||
|
|
|
@ -24,3 +24,7 @@ for match in matches {
|
|||
let url = input[range]
|
||||
print(url)
|
||||
}
|
||||
|
||||
let r = try! NSRegularExpression(pattern: "^\\+?[0-9\\.\\(\\)\\-]{7,20}$")
|
||||
|
||||
print(r.firstMatch(in: "+44(0)7448-736-790", options: [], range: NSRange(location: 0, length: "+44(0)7448-736-790".count)) == nil)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
version = "3.0">
|
||||
<TimelineItems>
|
||||
<LoggerValueHistoryTimelineItem
|
||||
documentLocation = "file:///Users/evgeny/opensource/simplex-chat/simplex-chat/apps/ios/Shared/MyPlayground.playground#CharacterRangeLen=88&CharacterRangeLoc=91&EndingColumnNumber=0&EndingLineNumber=7&StartingColumnNumber=3&StartingLineNumber=6&Timestamp=665788560.47885"
|
||||
documentLocation = "file:///Users/evgeny/opensource/simplex-chat/simplex-chat/apps/ios/Shared/MyPlayground.playground#CharacterRangeLen=88&CharacterRangeLoc=91&EndingColumnNumber=0&EndingLineNumber=7&StartingColumnNumber=3&StartingLineNumber=6&Timestamp=665873333.107271"
|
||||
selectedRepresentationIndex = "0"
|
||||
shouldTrackSuperviewWidth = "NO">
|
||||
</LoggerValueHistoryTimelineItem>
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
|
||||
import SwiftUI
|
||||
|
||||
private let emailRegex = try! NSRegularExpression(pattern: "^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$", options: .caseInsensitive)
|
||||
|
||||
private let phoneRegex = try! NSRegularExpression(pattern: "^\\+?[0-9\\.\\(\\)\\-]{7,20}$")
|
||||
|
||||
struct TextItemView: View {
|
||||
var chatItem: ChatItem
|
||||
var width: CGFloat
|
||||
|
@ -17,22 +21,25 @@ struct TextItemView: View {
|
|||
let sent = chatItem.chatDir.sent
|
||||
let minWidth = min(200, width)
|
||||
let maxWidth = min(300, width * 0.78)
|
||||
return VStack {
|
||||
messageText(chatItem.content.text, sent: sent)
|
||||
.padding(.top, 8)
|
||||
let meta = getDateFormatter().string(from: chatItem.meta.itemTs)
|
||||
|
||||
return ZStack(alignment: .bottomTrailing) {
|
||||
(messageText(chatItem.content.text, sent: sent) + reserveSpaceForMeta(meta))
|
||||
.padding(.top, 6)
|
||||
.padding(.bottom, 7)
|
||||
.padding(.horizontal, 12)
|
||||
.frame(minWidth: minWidth, maxWidth: maxWidth, alignment: .leading)
|
||||
.foregroundColor(sent ? .white : .primary)
|
||||
.textSelection(.enabled)
|
||||
Text(getDateFormatter().string(from: chatItem.meta.itemTs))
|
||||
Text(meta)
|
||||
.font(.caption)
|
||||
.foregroundColor(sent ? .white : .secondary)
|
||||
.padding(.bottom, 8)
|
||||
.foregroundColor(sent ? Color(uiColor: .secondarySystemBackground) : .secondary)
|
||||
.padding(.bottom, 4)
|
||||
.padding(.horizontal, 12)
|
||||
.frame(minWidth: minWidth, maxWidth: maxWidth, alignment: .trailing)
|
||||
.frame(minWidth: minWidth, maxWidth: maxWidth, alignment: .bottomTrailing)
|
||||
}
|
||||
.background(sent ? .blue : Color(uiColor: .tertiarySystemGroupedBackground))
|
||||
.cornerRadius(10)
|
||||
.cornerRadius(18)
|
||||
.padding(.horizontal)
|
||||
.frame(
|
||||
minWidth: 200,
|
||||
|
@ -43,7 +50,7 @@ struct TextItemView: View {
|
|||
)
|
||||
}
|
||||
|
||||
private func messageText(_ s: String, sent: Bool = false) -> Text {
|
||||
private func messageText(_ s: String, sent: Bool) -> Text {
|
||||
if s == "" { return Text("") }
|
||||
let parts = s.split(separator: " ")
|
||||
var res = wordToText(parts[0], sent)
|
||||
|
@ -55,14 +62,22 @@ struct TextItemView: View {
|
|||
return res
|
||||
}
|
||||
|
||||
private func reserveSpaceForMeta(_ meta: String) -> Text {
|
||||
Text(AttributedString(" \(meta)", attributes: AttributeContainer([
|
||||
.font: UIFont.preferredFont(forTextStyle: .caption1) as Any,
|
||||
.foregroundColor: UIColor.clear as Any,
|
||||
])))
|
||||
}
|
||||
|
||||
private func wordToText(_ s: String.SubSequence, _ sent: Bool) -> Text {
|
||||
let str = String(s)
|
||||
switch true {
|
||||
case s.starts(with: "http://") || s.starts(with: "https://"):
|
||||
let str = String(s)
|
||||
return Text(AttributedString(str, attributes: AttributeContainer([
|
||||
.link: NSURL(string: str) as Any,
|
||||
.foregroundColor: (sent ? UIColor.white : nil) as Any
|
||||
]))).underline()
|
||||
return linkText(str, prefix: "", sent: sent)
|
||||
case match(str, emailRegex):
|
||||
return linkText(str, prefix: "mailto:", sent: sent)
|
||||
case match(str, phoneRegex):
|
||||
return linkText(str, prefix: "tel:", sent: sent)
|
||||
default:
|
||||
if (s.count > 1) {
|
||||
switch true {
|
||||
|
@ -78,6 +93,17 @@ struct TextItemView: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func match(_ s: String, _ regex: NSRegularExpression) -> Bool {
|
||||
regex.firstMatch(in: s, options: [], range: NSRange(location: 0, length: s.count)) != nil
|
||||
}
|
||||
|
||||
private func linkText(_ s: String, prefix: String, sent: Bool) -> Text {
|
||||
Text(AttributedString(s, attributes: AttributeContainer([
|
||||
.link: NSURL(string: prefix + s) as Any,
|
||||
.foregroundColor: (sent ? UIColor.white : nil) as Any
|
||||
]))).underline()
|
||||
}
|
||||
|
||||
private func mdText(_ s: String.SubSequence) -> Text {
|
||||
Text(s[s.index(s.startIndex, offsetBy: 1)..<s.index(s.endIndex, offsetBy: -1)])
|
||||
}
|
||||
|
@ -88,8 +114,10 @@ struct TextItemView_Previews: PreviewProvider {
|
|||
Group{
|
||||
TextItemView(chatItem: chatItemSample(1, .directSnd, .now, "hello"), width: 360)
|
||||
TextItemView(chatItem: chatItemSample(2, .directSnd, .now, "https://simplex.chat"), width: 360)
|
||||
TextItemView(chatItem: chatItemSample(2, .directRcv, .now, "hello there too"), width: 360)
|
||||
TextItemView(chatItem: chatItemSample(2, .directRcv, .now, "hello there too!!! this covers -"), width: 360)
|
||||
TextItemView(chatItem: chatItemSample(2, .directRcv, .now, "hello there too!!! this text has the time on the same line "), width: 360)
|
||||
TextItemView(chatItem: chatItemSample(2, .directRcv, .now, "https://simplex.chat"), width: 360)
|
||||
TextItemView(chatItem: chatItemSample(2, .directRcv, .now, "chaT@simplex.chat"), width: 360)
|
||||
}
|
||||
.previewLayout(.fixed(width: 360, height: 70))
|
||||
}
|
||||
|
|
|
@ -763,7 +763,7 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
CURRENT_PROJECT_VERSION = 4;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
|
@ -783,7 +783,7 @@
|
|||
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/Libraries";
|
||||
"LIBRARY_SEARCH_PATHS[sdk=iphoneos*]" = "$(PROJECT_DIR)/Libraries/ios";
|
||||
"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = "$(PROJECT_DIR)/Libraries/sim";
|
||||
MARKETING_VERSION = 0.2.0;
|
||||
MARKETING_VERSION = 0.2.1;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
|
||||
PRODUCT_NAME = SimpleX;
|
||||
SDKROOT = iphoneos;
|
||||
|
@ -803,7 +803,7 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
CURRENT_PROJECT_VERSION = 4;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
|
@ -823,7 +823,7 @@
|
|||
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/Libraries";
|
||||
"LIBRARY_SEARCH_PATHS[sdk=iphoneos*]" = "$(PROJECT_DIR)/Libraries/ios";
|
||||
"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = "$(PROJECT_DIR)/Libraries/sim";
|
||||
MARKETING_VERSION = 0.2.0;
|
||||
MARKETING_VERSION = 0.2.1;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
|
||||
PRODUCT_NAME = SimpleX;
|
||||
SDKROOT = iphoneos;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue