ios: fix message view updates (refactor model to make it shallow) (#254)
This commit is contained in:
committed by
GitHub
parent
1d1ba8607e
commit
7ce305e16f
@@ -25,8 +25,7 @@ struct ContentView: View {
|
||||
}
|
||||
|
||||
do {
|
||||
let chats = try apiGetChats()
|
||||
chatModel.chatPreviews = chats
|
||||
chatModel.chats = try apiGetChats()
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
|
||||
@@ -12,29 +12,76 @@ import SwiftUI
|
||||
|
||||
final class ChatModel: ObservableObject {
|
||||
@Published var currentUser: User?
|
||||
@Published var chats: Dictionary<String, Chat> = [:]
|
||||
@Published var chatPreviews: [Chat] = []
|
||||
// list of chat "previews"
|
||||
@Published var chats: [Chat] = []
|
||||
// current chat
|
||||
@Published var chatId: String?
|
||||
@Published var chatItems: [ChatItem] = []
|
||||
// items in the terminal view
|
||||
@Published var terminalItems: [TerminalItem] = []
|
||||
@Published var userAddress: String?
|
||||
@Published var appOpenUrl: URL?
|
||||
@Published var connectViaUrl = false
|
||||
|
||||
func hasChat(_ id: String) -> Bool {
|
||||
chats.first(where: { $0.id == id }) != nil
|
||||
}
|
||||
|
||||
func getChat(_ id: String) -> Chat? {
|
||||
chats.first(where: { $0.id == id })
|
||||
}
|
||||
|
||||
func addChat(_ chat: Chat) {
|
||||
chats.insert(chat, at: 0)
|
||||
}
|
||||
|
||||
func updateChatInfo(_ cInfo: ChatInfo) {
|
||||
if let ix = chats.firstIndex(where: { $0.id == cInfo.id }) {
|
||||
chats[ix].chatInfo = cInfo
|
||||
}
|
||||
}
|
||||
|
||||
func replaceChat(_ id: String, _ chat: Chat) {
|
||||
if let ix = chats.firstIndex(where: { $0.id == id }) {
|
||||
chats[ix] = chat
|
||||
} else {
|
||||
// invalid state, correcting
|
||||
chats.insert(chat, at: 0)
|
||||
}
|
||||
}
|
||||
|
||||
func addChatItem(_ cInfo: ChatInfo, _ cItem: ChatItem) {
|
||||
if let ix = chats.firstIndex(where: { $0.id == cInfo.id }) {
|
||||
chats[ix].chatItems = [cItem]
|
||||
if chatId != cInfo.id {
|
||||
let chat = chats.remove(at: ix)
|
||||
chats.insert(chat, at: 0)
|
||||
}
|
||||
}
|
||||
if chatId == cInfo.id {
|
||||
chatItems.append(cItem)
|
||||
}
|
||||
}
|
||||
|
||||
func removeChat(_ id: String) {
|
||||
chats.removeAll(where: { $0.id == id })
|
||||
}
|
||||
}
|
||||
|
||||
class User: Decodable {
|
||||
struct User: Decodable {
|
||||
var userId: Int64
|
||||
var userContactId: Int64
|
||||
var localDisplayName: ContactName
|
||||
var profile: Profile
|
||||
var activeUser: Bool
|
||||
|
||||
internal init(userId: Int64, userContactId: Int64, localDisplayName: ContactName, profile: Profile, activeUser: Bool) {
|
||||
self.userId = userId
|
||||
self.userContactId = userContactId
|
||||
self.localDisplayName = localDisplayName
|
||||
self.profile = profile
|
||||
self.activeUser = activeUser
|
||||
}
|
||||
// internal init(userId: Int64, userContactId: Int64, localDisplayName: ContactName, profile: Profile, activeUser: Bool) {
|
||||
// self.userId = userId
|
||||
// self.userContactId = userContactId
|
||||
// self.localDisplayName = localDisplayName
|
||||
// self.profile = profile
|
||||
// self.activeUser = activeUser
|
||||
// }
|
||||
}
|
||||
|
||||
let sampleUser = User(
|
||||
@@ -103,9 +150,9 @@ enum ChatInfo: Identifiable, Decodable {
|
||||
var apiId: Int64 {
|
||||
get {
|
||||
switch self {
|
||||
case let .direct(contact): return contact.contactId
|
||||
case let .group(groupInfo): return groupInfo.groupId
|
||||
case let .contactRequest(contactRequest): return contactRequest.contactRequestId
|
||||
case let .direct(contact): return contact.apiId
|
||||
case let .group(groupInfo): return groupInfo.apiId
|
||||
case let .contactRequest(contactRequest): return contactRequest.apiId
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,11 +164,16 @@ let sampleGroupChatInfo = ChatInfo.group(groupInfo: sampleGroupInfo)
|
||||
|
||||
let sampleContactRequestChatInfo = ChatInfo.contactRequest(contactRequest: sampleContactRequest)
|
||||
|
||||
class Chat: Decodable, Identifiable {
|
||||
var chatInfo: ChatInfo
|
||||
var chatItems: [ChatItem]
|
||||
final class Chat: ObservableObject, Identifiable {
|
||||
@Published var chatInfo: ChatInfo
|
||||
@Published var chatItems: [ChatItem]
|
||||
|
||||
init(chatInfo: ChatInfo, chatItems: [ChatItem]) {
|
||||
init(_ cData: ChatData) {
|
||||
self.chatInfo = cData.chatInfo
|
||||
self.chatItems = cData.chatItems
|
||||
}
|
||||
|
||||
init(chatInfo: ChatInfo, chatItems: [ChatItem] = []) {
|
||||
self.chatInfo = chatInfo
|
||||
self.chatItems = chatItems
|
||||
}
|
||||
@@ -129,6 +181,13 @@ class Chat: Decodable, Identifiable {
|
||||
var id: String { get { chatInfo.id } }
|
||||
}
|
||||
|
||||
struct ChatData: Decodable, Identifiable {
|
||||
var chatInfo: ChatInfo
|
||||
var chatItems: [ChatItem]
|
||||
|
||||
var id: String { get { chatInfo.id } }
|
||||
}
|
||||
|
||||
struct Contact: Identifiable, Decodable {
|
||||
var contactId: Int64
|
||||
var localDisplayName: ContactName
|
||||
@@ -137,7 +196,7 @@ struct Contact: Identifiable, Decodable {
|
||||
var viaGroup: Int64?
|
||||
|
||||
var id: String { get { "@\(contactId)" } }
|
||||
|
||||
var apiId: Int64 { get { contactId } }
|
||||
var connected: Bool { get { activeConn.connStatus == "ready" || activeConn.connStatus == "snd-ready" } }
|
||||
}
|
||||
|
||||
@@ -160,6 +219,8 @@ struct UserContactRequest: Decodable {
|
||||
var profile: Profile
|
||||
|
||||
var id: String { get { "<@\(contactRequestId)" } }
|
||||
|
||||
var apiId: Int64 { get { contactRequestId } }
|
||||
}
|
||||
|
||||
let sampleContactRequest = UserContactRequest(
|
||||
@@ -174,6 +235,8 @@ struct GroupInfo: Identifiable, Decodable {
|
||||
var groupProfile: GroupProfile
|
||||
|
||||
var id: String { get { "#\(groupId)" } }
|
||||
|
||||
var apiId: Int64 { get { groupId } }
|
||||
}
|
||||
|
||||
let sampleGroupInfo = GroupInfo(
|
||||
|
||||
@@ -69,8 +69,8 @@ struct APIResponse: Decodable {
|
||||
|
||||
enum ChatResponse: Decodable, Error {
|
||||
case response(type: String, json: String)
|
||||
case apiChats(chats: [Chat])
|
||||
case apiChat(chat: Chat)
|
||||
case apiChats(chats: [ChatData])
|
||||
case apiChat(chat: ChatData)
|
||||
case invitation(connReqInvitation: String)
|
||||
case sentConfirmation
|
||||
case sentInvitation
|
||||
@@ -210,13 +210,13 @@ func chatRecvMsg() throws -> ChatResponse {
|
||||
|
||||
func apiGetChats() throws -> [Chat] {
|
||||
let r = try chatSendCmd(.apiGetChats)
|
||||
if case let .apiChats(chats) = r { return chats }
|
||||
if case let .apiChats(chats) = r { return chats.map { Chat.init($0) } }
|
||||
throw r
|
||||
}
|
||||
|
||||
func apiGetChat(type: ChatType, id: Int64) throws -> Chat {
|
||||
let r = try chatSendCmd(.apiGetChat(type: type, id: id))
|
||||
if case let .apiChat(chat) = r { return chat }
|
||||
if case let .apiChat(chat) = r { return Chat.init(chat) }
|
||||
throw r
|
||||
}
|
||||
|
||||
@@ -296,27 +296,19 @@ func processReceivedMsg(_ chatModel: ChatModel, _ res: ChatResponse) {
|
||||
chatModel.terminalItems.append(.resp(Date.now, res))
|
||||
switch res {
|
||||
case let .contactConnected(contact):
|
||||
if let chat = chatModel.chats[contact.id] {
|
||||
chat.chatInfo = ChatInfo.direct(contact: contact)
|
||||
let cInfo = ChatInfo.direct(contact: contact)
|
||||
if chatModel.hasChat(contact.id) {
|
||||
chatModel.updateChatInfo(cInfo)
|
||||
} else {
|
||||
let chat = Chat(chatInfo: ChatInfo.direct(contact: contact), chatItems: [])
|
||||
chatModel.chats[contact.id] = chat
|
||||
chatModel.chatPreviews.insert(chat, at: 0)
|
||||
chatModel.addChat(Chat(chatInfo: cInfo, chatItems: []))
|
||||
}
|
||||
case let .receivedContactRequest(contactRequest):
|
||||
let chat = Chat(chatInfo: ChatInfo.contactRequest(contactRequest: contactRequest), chatItems: [])
|
||||
chatModel.chats[contactRequest.id] = chat
|
||||
chatModel.chatPreviews.insert(chat, at: 0)
|
||||
chatModel.addChat(Chat(
|
||||
chatInfo: ChatInfo.contactRequest(contactRequest: contactRequest),
|
||||
chatItems: []
|
||||
))
|
||||
case let .newChatItem(aChatItem):
|
||||
let ci = aChatItem.chatInfo
|
||||
let chat = chatModel.chats[ci.id] ?? Chat(chatInfo: ci, chatItems: [])
|
||||
chatModel.chats[ci.id] = chat
|
||||
chat.chatItems.append(aChatItem.chatItem)
|
||||
if let cp = chatModel.chatPreviews.first(where: { $0.id == ci.id } ) {
|
||||
cp.chatItems = [aChatItem.chatItem]
|
||||
} else {
|
||||
chatModel.chatPreviews.insert(Chat(chatInfo: ci, chatItems: [aChatItem.chatItem]), at: 0)
|
||||
}
|
||||
chatModel.addChatItem(aChatItem.chatInfo, aChatItem.chatItem)
|
||||
default:
|
||||
print("unsupported response: ", res.responseType)
|
||||
}
|
||||
|
||||
@@ -10,9 +10,7 @@ import SwiftUI
|
||||
|
||||
struct ChatListNavLink: View {
|
||||
@EnvironmentObject var chatModel: ChatModel
|
||||
|
||||
@Binding var chatId: String?
|
||||
@State var chatPreview: Chat
|
||||
@State var chat: Chat
|
||||
var width: CGFloat
|
||||
|
||||
@State private var showDeleteContactAlert = false
|
||||
@@ -24,7 +22,7 @@ struct ChatListNavLink: View {
|
||||
@State private var alertContactRequest: UserContactRequest?
|
||||
|
||||
var body: some View {
|
||||
switch chatPreview.chatInfo {
|
||||
switch chat.chatInfo {
|
||||
case let .direct(contact):
|
||||
contactNavLink(contact)
|
||||
case let .group(groupInfo):
|
||||
@@ -36,15 +34,15 @@ struct ChatListNavLink: View {
|
||||
|
||||
private func chatView() -> some View {
|
||||
ChatView(
|
||||
chatId: $chatId,
|
||||
chatInfo: chatPreview.chatInfo,
|
||||
chatInfo: chat.chatInfo,
|
||||
width: width
|
||||
)
|
||||
.onAppear {
|
||||
do {
|
||||
let ci = chatPreview.chatInfo
|
||||
let chat = try apiGetChat(type: ci.chatType, id: ci.apiId)
|
||||
chatModel.chats[ci.id] = chat
|
||||
let cInfo = chat.chatInfo
|
||||
let chat = try apiGetChat(type: cInfo.chatType, id: cInfo.apiId)
|
||||
chatModel.updateChatInfo(chat.chatInfo)
|
||||
chatModel.chatItems = chat.chatItems
|
||||
} catch {
|
||||
print("apiGetChatItems", error)
|
||||
}
|
||||
@@ -53,10 +51,10 @@ struct ChatListNavLink: View {
|
||||
|
||||
private func contactNavLink(_ contact: Contact) -> some View {
|
||||
NavigationLink(
|
||||
tag: chatPreview.chatInfo.id,
|
||||
selection: $chatId,
|
||||
tag: chat.chatInfo.id,
|
||||
selection: $chatModel.chatId,
|
||||
destination: { chatView() },
|
||||
label: { ChatPreviewView(chatPreview: chatPreview) }
|
||||
label: { ChatPreviewView(chat: chat) }
|
||||
)
|
||||
.disabled(!contact.connected)
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
|
||||
@@ -75,10 +73,10 @@ struct ChatListNavLink: View {
|
||||
|
||||
private func groupNavLink(_ groupInfo: GroupInfo) -> some View {
|
||||
NavigationLink(
|
||||
tag: chatPreview.chatInfo.id,
|
||||
selection: $chatId,
|
||||
tag: chat.chatInfo.id,
|
||||
selection: $chatModel.chatId,
|
||||
destination: { chatView() },
|
||||
label: { ChatPreviewView(chatPreview: chatPreview) }
|
||||
label: { ChatPreviewView(chat: chat) }
|
||||
)
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
|
||||
Button(role: .destructive) {
|
||||
@@ -95,7 +93,7 @@ struct ChatListNavLink: View {
|
||||
}
|
||||
|
||||
private func contactRequestNavLink(_ contactRequest: UserContactRequest) -> some View {
|
||||
ChatPreviewView(chatPreview: chatPreview)
|
||||
ChatPreviewView(chat: chat)
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
|
||||
Button { acceptContactRequest(contactRequest) }
|
||||
label: { Label("Accept", systemImage: "checkmark") }
|
||||
@@ -125,9 +123,8 @@ struct ChatListNavLink: View {
|
||||
message: Text("Contact and all messages will be deleted"),
|
||||
primaryButton: .destructive(Text("Delete")) {
|
||||
do {
|
||||
try apiDeleteChat(type: .direct, id: contact.contactId)
|
||||
chatModel.chats.removeValue(forKey: contact.id)
|
||||
chatModel.chatPreviews.removeAll(where: { $0.id == contact.id })
|
||||
try apiDeleteChat(type: .direct, id: contact.apiId)
|
||||
chatModel.removeChat(contact.id)
|
||||
} catch let error {
|
||||
print("Error: \(error)")
|
||||
}
|
||||
@@ -160,15 +157,9 @@ struct ChatListNavLink: View {
|
||||
|
||||
private func acceptContactRequest(_ contactRequest: UserContactRequest) {
|
||||
do {
|
||||
let contact = try apiAcceptContactRequest(contactReqId: contactRequest.contactRequestId)
|
||||
chatModel.chats.removeValue(forKey: contactRequest.id)
|
||||
let contact = try apiAcceptContactRequest(contactReqId: contactRequest.apiId)
|
||||
let chat = Chat(chatInfo: ChatInfo.direct(contact: contact), chatItems: [])
|
||||
chatModel.chats[contact.id] = chat
|
||||
if let i = chatModel.chatPreviews.firstIndex(where: { $0.id == contactRequest.id }) {
|
||||
chatModel.chatPreviews[i] = chat
|
||||
} else {
|
||||
chatModel.chatPreviews.insert(chat, at: 0)
|
||||
}
|
||||
chatModel.replaceChat(contactRequest.id, chat)
|
||||
} catch let error {
|
||||
print("Error: \(error)")
|
||||
}
|
||||
@@ -176,9 +167,8 @@ struct ChatListNavLink: View {
|
||||
|
||||
private func rejectContactRequest(_ contactRequest: UserContactRequest) {
|
||||
do {
|
||||
try apiRejectContactRequest(contactReqId: contactRequest.contactRequestId)
|
||||
chatModel.chats.removeValue(forKey: contactRequest.id)
|
||||
chatModel.chatPreviews.removeAll(where: { $0.id == contactRequest.id })
|
||||
try apiRejectContactRequest(contactReqId: contactRequest.apiId)
|
||||
chatModel.removeChat(contactRequest.id)
|
||||
} catch let error {
|
||||
print("Error: \(error)")
|
||||
}
|
||||
@@ -189,15 +179,15 @@ struct ChatListNavLink_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
@State var chatId: String? = "@1"
|
||||
return Group {
|
||||
ChatListNavLink(chatId: $chatId, chatPreview: Chat(
|
||||
ChatListNavLink(chat: Chat(
|
||||
chatInfo: sampleDirectChatInfo,
|
||||
chatItems: [chatItemSample(1, .directSnd, Date.now, "hello")]
|
||||
), width: 300)
|
||||
ChatListNavLink(chatId: $chatId, chatPreview: Chat(
|
||||
ChatListNavLink(chat: Chat(
|
||||
chatInfo: sampleDirectChatInfo,
|
||||
chatItems: [chatItemSample(1, .directSnd, Date.now, "hello")]
|
||||
), width: 300)
|
||||
ChatListNavLink(chatId: $chatId, chatPreview: Chat(
|
||||
ChatListNavLink(chat: Chat(
|
||||
chatInfo: sampleContactRequestChatInfo,
|
||||
chatItems: []
|
||||
), width: 300)
|
||||
|
||||
@@ -10,7 +10,6 @@ import SwiftUI
|
||||
|
||||
struct ChatListView: View {
|
||||
@EnvironmentObject var chatModel: ChatModel
|
||||
@State private var chatId: String?
|
||||
@State private var connectAlert = false
|
||||
@State private var connectError: Error?
|
||||
|
||||
@@ -34,10 +33,9 @@ struct ChatListView: View {
|
||||
Text("Terminal")
|
||||
}
|
||||
|
||||
ForEach(chatModel.chatPreviews) { chatPreview in
|
||||
ForEach(chatModel.chats) { chat in
|
||||
ChatListNavLink(
|
||||
chatId: $chatId,
|
||||
chatPreview: chatPreview,
|
||||
chat: chat,
|
||||
width: geometry.size.width
|
||||
)
|
||||
}
|
||||
@@ -95,7 +93,7 @@ struct ChatListView: View {
|
||||
struct ChatListView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let chatModel = ChatModel()
|
||||
chatModel.chatPreviews = [
|
||||
chatModel.chats = [
|
||||
Chat(
|
||||
chatInfo: sampleDirectChatInfo,
|
||||
chatItems: [chatItemSample(1, .directSnd, Date.now, "hello")]
|
||||
|
||||
@@ -9,21 +9,21 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ChatPreviewView: View {
|
||||
var chatPreview: Chat
|
||||
|
||||
@ObservedObject var chat: Chat
|
||||
|
||||
var body: some View {
|
||||
let ci = chatPreview.chatItems.last
|
||||
let cItem = chat.chatItems.last
|
||||
return VStack(spacing: 4) {
|
||||
HStack(alignment: .top) {
|
||||
Text(chatPreview.chatInfo.localDisplayName)
|
||||
Text(chat.chatInfo.localDisplayName)
|
||||
.font(.title3)
|
||||
.fontWeight(.bold)
|
||||
.padding(.leading, 8)
|
||||
.padding(.top, 4)
|
||||
.frame(maxHeight: .infinity, alignment: .topLeading)
|
||||
Spacer()
|
||||
if let ci = ci {
|
||||
Text(getDateFormatter().string(from: ci.meta.itemTs))
|
||||
if let cItem = cItem {
|
||||
Text(getDateFormatter().string(from: cItem.meta.itemTs))
|
||||
.font(.subheadline)
|
||||
.padding(.trailing, 8)
|
||||
.padding(.top, 4)
|
||||
@@ -31,8 +31,8 @@ struct ChatPreviewView: View {
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
if let ci = ci {
|
||||
Text(ci.content.text)
|
||||
if let cItem = cItem {
|
||||
Text(cItem.content.text)
|
||||
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 44, maxHeight: 44, alignment: .topLeading)
|
||||
.padding([.leading, .trailing], 8)
|
||||
.padding(.bottom, 4)
|
||||
@@ -52,15 +52,15 @@ struct ChatPreviewView: View {
|
||||
struct ChatPreviewView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
Group{
|
||||
ChatPreviewView(chatPreview: Chat(
|
||||
ChatPreviewView(chat: Chat(
|
||||
chatInfo: sampleDirectChatInfo,
|
||||
chatItems: []
|
||||
))
|
||||
ChatPreviewView(chatPreview: Chat(
|
||||
ChatPreviewView(chat: Chat(
|
||||
chatInfo: sampleDirectChatInfo,
|
||||
chatItems: [chatItemSample(1, .directSnd, Date.now, "hello")]
|
||||
))
|
||||
ChatPreviewView(chatPreview: Chat(
|
||||
ChatPreviewView(chat: Chat(
|
||||
chatInfo: sampleGroupChatInfo,
|
||||
chatItems: [chatItemSample(1, .directSnd, Date.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.")]
|
||||
))
|
||||
|
||||
@@ -10,23 +10,18 @@ import SwiftUI
|
||||
|
||||
struct ChatView: View {
|
||||
@EnvironmentObject var chatModel: ChatModel
|
||||
@Binding var chatId: String?
|
||||
var chatInfo: ChatInfo
|
||||
var width: CGFloat
|
||||
@State private var inProgress: Bool = false
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
if let chat: Chat = chatModel.chats[chatInfo.id] {
|
||||
ScrollView {
|
||||
LazyVStack(spacing: 5) {
|
||||
ForEach(chat.chatItems) {
|
||||
ChatItemView(chatItem: $0)
|
||||
}
|
||||
ScrollView {
|
||||
LazyVStack(spacing: 5) {
|
||||
ForEach(chatModel.chatItems) {
|
||||
ChatItemView(chatItem: $0)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("unexpected: chat not found...")
|
||||
}
|
||||
|
||||
Spacer(minLength: 0)
|
||||
@@ -35,7 +30,9 @@ struct ChatView: View {
|
||||
}
|
||||
.toolbar {
|
||||
HStack {
|
||||
Button { chatId = nil } label: { Image(systemName: "chevron.backward") }
|
||||
Button { chatModel.chatId = nil } label: {
|
||||
Image(systemName: "chevron.backward")
|
||||
}
|
||||
Spacer()
|
||||
Text(chatInfo.localDisplayName)
|
||||
.font(.title3)
|
||||
@@ -52,9 +49,7 @@ struct ChatView: View {
|
||||
func sendMessage(_ msg: String) {
|
||||
do {
|
||||
let chatItem = try apiSendMessage(type: chatInfo.chatType, id: chatInfo.apiId, msg: .text(msg))
|
||||
let chat = chatModel.chats[chatInfo.id] ?? Chat(chatInfo: chatInfo, chatItems: [])
|
||||
chatModel.chats[chatInfo.id] = chat
|
||||
chat.chatItems.append(chatItem)
|
||||
chatModel.addChatItem(chatInfo, chatItem)
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
@@ -63,23 +58,18 @@ struct ChatView: View {
|
||||
|
||||
struct ChatView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
@State var chatId: String? = "@1"
|
||||
let chatModel = ChatModel()
|
||||
chatModel.chats = [
|
||||
"@1": Chat(
|
||||
chatInfo: sampleDirectChatInfo,
|
||||
chatItems: [
|
||||
chatItemSample(1, .directSnd, Date.now, "hello"),
|
||||
chatItemSample(2, .directRcv, Date.now, "hi"),
|
||||
chatItemSample(3, .directRcv, Date.now, "hi there"),
|
||||
chatItemSample(4, .directRcv, Date.now, "hello again"),
|
||||
chatItemSample(5, .directSnd, Date.now, "hi there!!!"),
|
||||
chatItemSample(6, .directSnd, Date.now, "how are you?"),
|
||||
chatItemSample(7, .directSnd, Date.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.")
|
||||
]
|
||||
)
|
||||
chatModel.chatId = "@1"
|
||||
chatModel.chatItems = [
|
||||
chatItemSample(1, .directSnd, Date.now, "hello"),
|
||||
chatItemSample(2, .directRcv, Date.now, "hi"),
|
||||
chatItemSample(3, .directRcv, Date.now, "hi there"),
|
||||
chatItemSample(4, .directRcv, Date.now, "hello again"),
|
||||
chatItemSample(5, .directSnd, Date.now, "hi there!!!"),
|
||||
chatItemSample(6, .directSnd, Date.now, "how are you?"),
|
||||
chatItemSample(7, .directSnd, Date.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(chatId: $chatId, chatInfo: sampleDirectChatInfo, width: 300)
|
||||
return ChatView(chatInfo: sampleDirectChatInfo, width: 300)
|
||||
.environmentObject(chatModel)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ChatListToolbar: View {
|
||||
@EnvironmentObject var chatModel: ChatModel
|
||||
var width: CGFloat
|
||||
|
||||
var body: some View {
|
||||
@@ -28,15 +27,7 @@ struct ChatListToolbar: View {
|
||||
|
||||
struct ChatListToolbar_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let chatModel = ChatModel()
|
||||
chatModel.chats = [
|
||||
"@1": Chat(
|
||||
chatInfo: sampleDirectChatInfo,
|
||||
chatItems: [chatItemSample(1, .directSnd, Date.now, "hello")]
|
||||
)
|
||||
]
|
||||
return ChatListToolbar(width: 300)
|
||||
.previewLayout(.fixed(width: 300, height: 70))
|
||||
.environmentObject(chatModel)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ struct UserProfile: View {
|
||||
.padding(.bottom)
|
||||
HStack(spacing: 20) {
|
||||
Button("Cancel") { editProfile = false }
|
||||
Button("Save (and notify contacts)") { saveProfile(user) }
|
||||
Button("Save (and notify contacts)") { saveProfile() }
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, minHeight: 120, alignment: .leading)
|
||||
@@ -63,10 +63,10 @@ struct UserProfile: View {
|
||||
.padding()
|
||||
}
|
||||
|
||||
func saveProfile(_ user: User) {
|
||||
func saveProfile() {
|
||||
do {
|
||||
if let newProfile = try apiUpdateProfile(profile: profile) {
|
||||
user.profile = newProfile
|
||||
chatModel.currentUser?.profile = newProfile
|
||||
profile = newProfile
|
||||
}
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user