updated text items (#278)

* updated text items

* update version

* fix JSON parsing in CIDirection, refactor data samples

* show group member in received messages and chat preview

* use profile displayName instead of localDisplayName, do not show fullName if it is the same as displayName
This commit is contained in:
Evgeny Poberezkin 2022-02-08 09:19:25 +00:00 committed by GitHub
parent 855881094b
commit b3a4c21c4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 245 additions and 151 deletions

View File

@ -1,6 +1,15 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "1.000",
"green" : "0.533",
"red" : "0.000"
}
},
"idiom" : "universal"
}
],

View File

@ -115,15 +115,15 @@ struct User: Decodable {
// self.profile = profile
// self.activeUser = activeUser
// }
}
let sampleUser = User(
userId: 1,
userContactId: 1,
localDisplayName: "alice",
profile: sampleProfile,
activeUser: true
)
static let sampleData = User(
userId: 1,
userContactId: 1,
localDisplayName: "alice",
profile: Profile.sampleData,
activeUser: true
)
}
typealias ContactName = String
@ -132,12 +132,12 @@ typealias GroupName = String
struct Profile: Codable {
var displayName: String
var fullName: String
}
let sampleProfile = Profile(
displayName: "alice",
fullName: "Alice"
)
static let sampleData = Profile(
displayName: "alice",
fullName: "Alice"
)
}
enum ChatType: String {
case direct = "@"
@ -160,6 +160,16 @@ enum ChatInfo: Identifiable, Decodable {
}
}
var displayName: String {
get {
switch self {
case let .direct(contact): return contact.profile.displayName
case let .group(groupInfo): return groupInfo.groupProfile.displayName
case let .contactRequest(contactRequest): return contactRequest.profile.displayName
}
}
}
var fullName: String {
get {
switch self {
@ -171,7 +181,7 @@ enum ChatInfo: Identifiable, Decodable {
}
var chatViewName: String {
get { localDisplayName + (fullName == "" || fullName == localDisplayName ? "" : " / \(fullName)") }
get { displayName + (fullName == "" || fullName == displayName ? "" : " / \(fullName)") }
}
var id: String {
@ -211,14 +221,20 @@ enum ChatInfo: Identifiable, Decodable {
case let .contactRequest(contactRequest): return contactRequest.createdAt
}
}
struct SampleData {
var direct: ChatInfo
var group: ChatInfo
var contactRequest: ChatInfo
}
static var sampleData: ChatInfo.SampleData = SampleData(
direct: ChatInfo.direct(contact: Contact.sampleData),
group: ChatInfo.group(groupInfo: GroupInfo.sampleData),
contactRequest: ChatInfo.contactRequest(contactRequest: UserContactRequest.sampleData)
)
}
let sampleDirectChatInfo = ChatInfo.direct(contact: sampleContact)
let sampleGroupChatInfo = ChatInfo.group(groupInfo: sampleGroupInfo)
let sampleContactRequestChatInfo = ChatInfo.contactRequest(contactRequest: sampleContactRequest)
final class Chat: ObservableObject, Identifiable {
@Published var chatInfo: ChatInfo
@Published var chatItems: [ChatItem]
@ -297,21 +313,21 @@ struct Contact: Identifiable, Decodable {
var id: String { get { "@\(contactId)" } }
var apiId: Int64 { get { contactId } }
var ready: Bool { get { activeConn.connStatus == "ready" || activeConn.connStatus == "snd-ready" } }
}
let sampleContact = Contact(
contactId: 1,
localDisplayName: "alice",
profile: sampleProfile,
activeConn: sampleConnection,
createdAt: .now
)
static let sampleData = Contact(
contactId: 1,
localDisplayName: "alice",
profile: Profile.sampleData,
activeConn: Connection.sampleData,
createdAt: .now
)
}
struct Connection: Decodable {
var connStatus: String
}
let sampleConnection = Connection(connStatus: "ready")
static let sampleData = Connection(connStatus: "ready")
}
struct UserContactRequest: Decodable {
var contactRequestId: Int64
@ -322,14 +338,14 @@ struct UserContactRequest: Decodable {
var id: String { get { "<@\(contactRequestId)" } }
var apiId: Int64 { get { contactRequestId } }
}
let sampleContactRequest = UserContactRequest(
contactRequestId: 1,
localDisplayName: "alice",
profile: sampleProfile,
createdAt: .now
)
static let sampleData = UserContactRequest(
contactRequestId: 1,
localDisplayName: "alice",
profile: Profile.sampleData,
createdAt: .now
)
}
struct GroupInfo: Identifiable, Decodable {
var groupId: Int64
@ -340,27 +356,44 @@ struct GroupInfo: Identifiable, Decodable {
var id: String { get { "#\(groupId)" } }
var apiId: Int64 { get { groupId } }
}
let sampleGroupInfo = GroupInfo(
groupId: 1,
localDisplayName: "team",
groupProfile: sampleGroupProfile,
createdAt: .now
)
static let sampleData = GroupInfo(
groupId: 1,
localDisplayName: "team",
groupProfile: GroupProfile.sampleData,
createdAt: .now
)
}
struct GroupProfile: Codable {
var displayName: String
var fullName: String
static let sampleData = GroupProfile(
displayName: "team",
fullName: "My Team"
)
}
let sampleGroupProfile = GroupProfile(
displayName: "team",
fullName: "My Team"
)
struct GroupMember: Decodable {
var groupMemberId: Int64
var memberId: String
// var memberRole: GroupMemberRole
// var memberCategory: GroupMemberCategory
// var memberStatus: GroupMemberStatus
// var invitedBy: InvitedBy
var localDisplayName: ContactName
var memberProfile: Profile
var memberContactId: Int64?
// var activeConn: Connection?
static let sampleData = GroupMember(
groupMemberId: 1,
memberId: "abcd",
localDisplayName: "alice",
memberProfile: Profile.sampleData,
memberContactId: 1
)
}
struct AChatItem: Decodable {
@ -374,21 +407,21 @@ struct ChatItem: Identifiable, Decodable {
var content: CIContent
var id: Int64 { get { meta.itemId } }
}
func chatItemSample(_ id: Int64, _ dir: CIDirection, _ ts: Date, _ text: String) -> ChatItem {
ChatItem(
chatDir: dir,
meta: ciMetaSample(id, ts, text),
content: .sndMsgContent(msgContent: .text(text))
)
static func getSample (_ id: Int64, _ dir: CIDirection, _ ts: Date, _ text: String) -> ChatItem {
ChatItem(
chatDir: dir,
meta: CIMeta.getSample(id, ts, text),
content: .sndMsgContent(msgContent: .text(text))
)
}
}
enum CIDirection: Decodable {
case directSnd
case directRcv
case groupSnd
case groupRcv(GroupMember)
case groupRcv(groupMember: GroupMember)
var sent: Bool {
get {
@ -407,6 +440,15 @@ struct CIMeta: Decodable {
var itemTs: Date
var itemText: String
var createdAt: Date
static func getSample(_ id: Int64, _ ts: Date, _ text: String) -> CIMeta {
CIMeta(
itemId: id,
itemTs: ts,
itemText: text,
createdAt: ts
)
}
}
enum CIStatus: Decodable {
@ -418,15 +460,6 @@ enum CIStatus: Decodable {
case rcvRead
}
func ciMetaSample(_ id: Int64, _ ts: Date, _ text: String) -> CIMeta {
CIMeta(
itemId: id,
itemTs: ts,
itemText: text,
createdAt: ts
)
}
enum CIContent: Decodable {
case sndMsgContent(msgContent: MsgContent)
case rcvMsgContent(msgContent: MsgContent)

View File

@ -90,10 +90,8 @@ struct ChatInfoView: View {
}
struct ChatInfoView_Previews: PreviewProvider {
var chatInfo = sampleDirectChatInfo
static var previews: some View {
@State var showChatInfo = true
return ChatInfoView(chat: Chat(chatInfo: sampleDirectChatInfo, chatItems: []), showChatInfo: $showChatInfo)
return ChatInfoView(chat: Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: []), showChatInfo: $showChatInfo)
}
}

View File

@ -35,8 +35,8 @@ struct EmojiItemView: View {
struct EmojiItemView_Previews: PreviewProvider {
static var previews: some View {
Group{
EmojiItemView(chatItem: chatItemSample(1, .directSnd, .now, "🙂"))
EmojiItemView(chatItem: chatItemSample(2, .directRcv, .now, "👍"))
EmojiItemView(chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂"))
EmojiItemView(chatItem: ChatItem.getSample(2, .directRcv, .now, "👍"))
}
.previewLayout(.fixed(width: 360, height: 70))
}

View File

@ -12,54 +12,73 @@ private let emailRegex = try! NSRegularExpression(pattern: "^[a-z0-9.!#$%&'*+/=?
private let phoneRegex = try! NSRegularExpression(pattern: "^\\+?[0-9\\.\\(\\)\\-]{7,20}$")
private let sentColorLigth = Color(.sRGB, red: 0.27, green: 0.72, blue: 1, opacity: 0.12)
private let sentColorDark = Color(.sRGB, red: 0.27, green: 0.72, blue: 1, opacity: 0.17)
private let linkColor = UIColor(red: 0, green: 0.533, blue: 1, alpha: 1)
struct TextItemView: View {
@Environment(\.colorScheme) var colorScheme
var chatItem: ChatItem
var width: CGFloat
private let codeFont = Font.custom("Courier", size: UIFont.preferredFont(forTextStyle: .body).pointSize)
var body: some View {
let sent = chatItem.chatDir.sent
let minWidth = min(200, width)
let maxWidth = min(300, width * 0.78)
// let minWidth = min(200, width)
let maxWidth = width * 0.78
let meta = getDateFormatter().string(from: chatItem.meta.itemTs)
return ZStack(alignment: .bottomTrailing) {
(messageText(chatItem.content.text, sent: sent) + reserveSpaceForMeta(meta))
(messageText(chatItem) + reserveSpaceForMeta(meta))
.padding(.top, 6)
.padding(.bottom, 7)
.padding(.horizontal, 12)
.frame(minWidth: minWidth, maxWidth: maxWidth, alignment: .leading)
.foregroundColor(sent ? .white : .primary)
.frame(minWidth: 0, alignment: .leading)
// .foregroundColor(sent ? .white : .primary)
.textSelection(.enabled)
Text(meta)
.font(.caption)
.foregroundColor(sent ? Color(uiColor: .secondarySystemBackground) : .secondary)
.foregroundColor(.secondary)
// .foregroundColor(sent ? Color(uiColor: .secondarySystemBackground) : .secondary)
.padding(.bottom, 4)
.padding(.horizontal, 12)
.frame(minWidth: minWidth, maxWidth: maxWidth, alignment: .bottomTrailing)
}
.background(sent ? .blue : Color(uiColor: .tertiarySystemGroupedBackground))
// .background(sent ? .blue : Color(uiColor: .tertiarySystemGroupedBackground))
.background(
sent
? (colorScheme == .light ? sentColorLigth : sentColorDark)
: Color(uiColor: .tertiarySystemGroupedBackground)
)
.cornerRadius(18)
.padding(.horizontal)
.frame(
minWidth: 200,
maxWidth: .infinity,
minHeight: 0,
maxWidth: maxWidth,
maxHeight: .infinity,
alignment: sent ? .trailing : .leading
)
}
private func messageText(_ s: String, sent: Bool) -> Text {
if s == "" { return Text("") }
let parts = s.split(separator: " ")
var res = wordToText(parts[0], sent)
var i = 1
while i < parts.count {
res = res + Text(" ") + wordToText(parts[i], sent)
i = i + 1
private func messageText(_ chatItem: ChatItem) -> Text {
let s = chatItem.content.text
var res: Text
if s == "" {
res = Text("")
} else {
let parts = s.split(separator: " ")
res = wordToText(parts[0])
var i = 1
while i < parts.count {
res = res + Text(" ") + wordToText(parts[i])
i = i + 1
}
}
if case let .groupRcv(groupMember) = chatItem.chatDir {
let member = Text(groupMember.memberProfile.displayName).font(.headline)
return member + Text(": ") + res
} else {
return res
}
return res
}
private func reserveSpaceForMeta(_ meta: String) -> Text {
@ -69,15 +88,15 @@ struct TextItemView: View {
])))
}
private func wordToText(_ s: String.SubSequence, _ sent: Bool) -> Text {
private func wordToText(_ s: String.SubSequence) -> Text {
let str = String(s)
switch true {
case s.starts(with: "http://") || s.starts(with: "https://"):
return linkText(str, prefix: "", sent: sent)
return linkText(str, prefix: "")
case match(str, emailRegex):
return linkText(str, prefix: "mailto:", sent: sent)
return linkText(str, prefix: "mailto:")
case match(str, phoneRegex):
return linkText(str, prefix: "tel:", sent: sent)
return linkText(str, prefix: "tel:")
default:
if (s.count > 1) {
switch true {
@ -97,10 +116,10 @@ struct TextItemView: View {
regex.firstMatch(in: s, options: [], range: NSRange(location: 0, length: s.count)) != nil
}
private func linkText(_ s: String, prefix: String, sent: Bool) -> Text {
private func linkText(_ s: String, prefix: String) -> Text {
Text(AttributedString(s, attributes: AttributeContainer([
.link: NSURL(string: prefix + s) as Any,
.foregroundColor: (sent ? UIColor.white : nil) as Any
.foregroundColor: linkColor as Any
]))).underline()
}
@ -112,12 +131,13 @@ struct TextItemView: View {
struct TextItemView_Previews: PreviewProvider {
static var previews: some View {
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!!! 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)
TextItemView(chatItem: ChatItem.getSample(1, .directSnd, .now, "hello"), width: 360)
TextItemView(chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello"), width: 360)
TextItemView(chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat"), width: 360)
TextItemView(chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this covers -"), width: 360)
TextItemView(chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this text has the time on the same line "), width: 360)
TextItemView(chatItem: ChatItem.getSample(2, .directRcv, .now, "https://simplex.chat"), width: 360)
TextItemView(chatItem: ChatItem.getSample(2, .directRcv, .now, "chaT@simplex.chat"), width: 360)
}
.previewLayout(.fixed(width: 360, height: 70))
}

View File

@ -34,11 +34,11 @@ func getDateFormatter() -> DateFormatter {
struct ChatItemView_Previews: PreviewProvider {
static var previews: some View {
Group{
ChatItemView(chatItem: chatItemSample(1, .directSnd, .now, "hello"), width: 360)
ChatItemView(chatItem: chatItemSample(2, .directRcv, .now, "hello there too"), width: 360)
ChatItemView(chatItem: chatItemSample(1, .directSnd, .now, "🙂"), width: 360)
ChatItemView(chatItem: chatItemSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂"), width: 360)
ChatItemView(chatItem: chatItemSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂🙂"), width: 360)
ChatItemView(chatItem: ChatItem.getSample(1, .directSnd, .now, "hello"), width: 360)
ChatItemView(chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too"), width: 360)
ChatItemView(chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂"), width: 360)
ChatItemView(chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂"), width: 360)
ChatItemView(chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂🙂"), width: 360)
}
.previewLayout(.fixed(width: 360, height: 70))
}

View File

@ -8,20 +8,27 @@
import SwiftUI
private let chatImageColorLight = Color(red: 0.9, green: 0.9, blue: 0.9)
private let chatImageColorDark = Color(red: 0.2, green: 0.2, blue: 0.2 )
struct ChatView: View {
@EnvironmentObject var chatModel: ChatModel
@Environment(\.colorScheme) var colorScheme
@ObservedObject var chat: Chat
@State private var inProgress: Bool = false
@State private var showChatInfo = false
var body: some View {
VStack {
let cInfo = chat.chatInfo
return VStack {
GeometryReader { g in
ScrollViewReader { proxy in
ScrollView {
VStack(spacing: 5) {
ForEach(chatModel.chatItems, id: \.id) {
ChatItemView(chatItem: $0, width: g.size.width)
.frame(minWidth: 0, maxWidth: .infinity, alignment: $0.chatDir.sent ? .trailing : .leading)
}
.onAppear { scrollToBottom(proxy) }
.onChange(of: chatModel.chatItems.count) { _ in scrollToBottom(proxy) }
@ -37,7 +44,7 @@ struct ChatView: View {
SendMessageView(sendMessage: sendMessage, inProgress: inProgress)
}
.navigationTitle(chat.chatInfo.chatViewName)
.navigationTitle(cInfo.chatViewName)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
@ -53,12 +60,19 @@ struct ChatView: View {
showChatInfo = true
} label: {
HStack {
ChatInfoImage(chat: chat)
.frame(width: 32, height: 32)
.padding(.trailing, 4)
ChatInfoImage(
chat: chat,
color: colorScheme == .dark
? chatImageColorDark
: chatImageColorLight
)
.frame(width: 32, height: 32)
.padding(.trailing, 4)
VStack {
Text(chat.chatInfo.localDisplayName).font(.headline)
Text(chat.chatInfo.fullName).font(.subheadline)
Text(cInfo.displayName).font(.headline)
if cInfo.fullName != "" && cInfo.displayName != cInfo.fullName {
Text(cInfo.fullName).font(.subheadline)
}
}
}
.foregroundColor(.primary)
@ -94,16 +108,16 @@ struct ChatView_Previews: PreviewProvider {
let chatModel = ChatModel()
chatModel.chatId = "@1"
chatModel.chatItems = [
chatItemSample(1, .directSnd, .now, "hello"),
chatItemSample(2, .directRcv, .now, "hi"),
chatItemSample(3, .directRcv, .now, "hi there"),
chatItemSample(4, .directRcv, .now, "hello again"),
chatItemSample(5, .directSnd, .now, "hi there!!!"),
chatItemSample(6, .directSnd, .now, "how are you?"),
chatItemSample(7, .directSnd, .now, "👍👍👍👍"),
chatItemSample(8, .directSnd, .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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
ChatItem.getSample(1, .directSnd, .now, "hello"),
ChatItem.getSample(2, .directRcv, .now, "hi"),
ChatItem.getSample(3, .directRcv, .now, "hi there"),
ChatItem.getSample(4, .directRcv, .now, "hello again"),
ChatItem.getSample(5, .directSnd, .now, "hi there!!!"),
ChatItem.getSample(6, .directSnd, .now, "how are you?"),
ChatItem.getSample(7, .directSnd, .now, "👍👍👍👍"),
ChatItem.getSample(8, .directSnd, .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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
]
return ChatView(chat: Chat(chatInfo: sampleDirectChatInfo, chatItems: []))
return ChatView(chat: Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: []))
.environmentObject(chatModel)
}
}

View File

@ -175,15 +175,15 @@ struct ChatListNavLink_Previews: PreviewProvider {
@State var chatId: String? = "@1"
return Group {
ChatListNavLink(chat: Chat(
chatInfo: sampleDirectChatInfo,
chatItems: [chatItemSample(1, .directSnd, .now, "hello")]
chatInfo: ChatInfo.sampleData.direct,
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")]
))
ChatListNavLink(chat: Chat(
chatInfo: sampleDirectChatInfo,
chatItems: [chatItemSample(1, .directSnd, .now, "hello")]
chatInfo: ChatInfo.sampleData.direct,
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")]
))
ChatListNavLink(chat: Chat(
chatInfo: sampleContactRequestChatInfo,
chatInfo: ChatInfo.sampleData.contactRequest,
chatItems: []
))
}

View File

@ -91,20 +91,20 @@ struct ChatListView_Previews: PreviewProvider {
let chatModel = ChatModel()
chatModel.chats = [
Chat(
chatInfo: sampleDirectChatInfo,
chatItems: [chatItemSample(1, .directSnd, .now, "hello")]
chatInfo: ChatInfo.sampleData.direct,
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")]
),
Chat(
chatInfo: sampleGroupChatInfo,
chatItems: [chatItemSample(1, .directSnd, .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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")]
chatInfo: ChatInfo.sampleData.group,
chatItems: [ChatItem.getSample(1, .directSnd, .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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")]
),
Chat(
chatInfo: sampleContactRequestChatInfo,
chatInfo: ChatInfo.sampleData.contactRequest,
chatItems: []
)
]
return ChatListView(user: sampleUser)
return ChatListView(user: User.sampleData)
.environmentObject(chatModel)
}
}

View File

@ -46,7 +46,7 @@ struct ChatPreviewView: View {
.padding(.horizontal, 8)
if let cItem = cItem {
Text(cItem.content.text)
Text(chatItemText(cItem))
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 44, maxHeight: 44, alignment: .topLeading)
.padding([.leading, .trailing], 8)
.padding(.bottom, 4)
@ -60,22 +60,30 @@ struct ChatPreviewView: View {
}
}
}
private func chatItemText(_ cItem: ChatItem) -> String {
let t = cItem.content.text
if case let .groupRcv(groupMember) = cItem.chatDir {
return groupMember.memberProfile.displayName + ": " + t
}
return t
}
}
struct ChatPreviewView_Previews: PreviewProvider {
static var previews: some View {
Group{
ChatPreviewView(chat: Chat(
chatInfo: sampleDirectChatInfo,
chatInfo: ChatInfo.sampleData.direct,
chatItems: []
))
ChatPreviewView(chat: Chat(
chatInfo: sampleDirectChatInfo,
chatItems: [chatItemSample(1, .directSnd, .now, "hello")]
chatInfo: ChatInfo.sampleData.direct,
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")]
))
ChatPreviewView(chat: Chat(
chatInfo: sampleGroupChatInfo,
chatItems: [chatItemSample(1, .directSnd, .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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")]
chatInfo: ChatInfo.sampleData.group,
chatItems: [ChatItem.getSample(1, .directSnd, .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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")]
))
}
.previewLayout(.fixed(width: 360, height: 78))

View File

@ -47,7 +47,7 @@ struct ContactRequestView: View {
struct ContactRequestView_Previews: PreviewProvider {
static var previews: some View {
ContactRequestView(contactRequest: sampleContactRequest)
ContactRequestView(contactRequest: UserContactRequest.sampleData)
.previewLayout(.fixed(width: 360, height: 80))
}
}

View File

@ -10,6 +10,7 @@ import SwiftUI
struct ChatInfoImage: View {
@ObservedObject var chat: Chat
var color = Color(uiColor: .tertiarySystemGroupedBackground)
var body: some View {
var iconName: String
@ -21,13 +22,16 @@ struct ChatInfoImage: View {
return Image(systemName: iconName)
.resizable()
.foregroundColor(Color(uiColor: .secondarySystemBackground))
.foregroundColor(color)
}
}
struct ChatInfoImage_Previews: PreviewProvider {
static var previews: some View {
ChatInfoImage(chat: Chat(chatInfo: sampleDirectChatInfo, chatItems: []))
.previewLayout(.fixed(width: 63, height: 63))
ChatInfoImage(
chat: Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: [])
, color: Color(red: 0.9, green: 0.9, blue: 0.9)
)
.previewLayout(.fixed(width: 63, height: 63))
}
}

View File

@ -64,7 +64,7 @@ struct SettingsView: View {
struct SettingsView_Previews: PreviewProvider {
static var previews: some View {
let chatModel = ChatModel()
chatModel.currentUser = sampleUser
chatModel.currentUser = User.sampleData
return SettingsView()
.environmentObject(chatModel)
}

View File

@ -77,7 +77,7 @@ struct UserProfile: View {
struct UserProfile_Previews: PreviewProvider {
static var previews: some View {
let chatModel = ChatModel()
chatModel.currentUser = sampleUser
chatModel.currentUser = User.sampleData
return UserProfile()
.environmentObject(chatModel)
}

View File

@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>chat.simplex.app.receive</string>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
@ -15,5 +19,9 @@
</array>
</dict>
</array>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
</dict>
</plist>

View File

@ -763,7 +763,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 4;
CURRENT_PROJECT_VERSION = 5;
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.1;
MARKETING_VERSION = 0.2.2;
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 = 4;
CURRENT_PROJECT_VERSION = 5;
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.1;
MARKETING_VERSION = 0.2.2;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;