/* * Copyright (c) 2010-2023 Belledonne Communications SARL. * * This file is part of Linphone * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ // swiftlint:disable line_length import SwiftUI import UniformTypeIdentifiers struct HistoryContactFragment: View { @State private var orientation = UIDevice.current.orientation @ObservedObject var contactsManager = ContactsManager.shared @ObservedObject private var telecomManager = TelecomManager.shared @ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared @ObservedObject var contactAvatarModel: ContactAvatarModel @ObservedObject var historyViewModel: HistoryViewModel @ObservedObject var historyListViewModel: HistoryListViewModel @ObservedObject var contactViewModel: ContactViewModel @ObservedObject var editContactViewModel: EditContactViewModel @State var isMenuOpen = false @Binding var isShowDeleteAllHistoryPopup: Bool @Binding var isShowEditContactFragment: Bool @Binding var indexPage: Int var body: some View { NavigationView { VStack(spacing: 1) { Rectangle() .foregroundColor(Color.orangeMain500) .edgesIgnoringSafeArea(.top) .frame(height: 0) HStack { if !(orientation == .landscapeLeft || orientation == .landscapeRight || UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height) { Image("caret-left") .renderingMode(.template) .resizable() .foregroundStyle(Color.orangeMain500) .frame(width: 25, height: 25, alignment: .leading) .padding(.all, 10) .padding(.top, 2) .padding(.leading, -10) .onTapGesture { withAnimation { historyViewModel.displayedCall = nil } } } Text("Call history") .default_text_style_orange_800(styleSize: 20) Spacer() Menu { let fromAddressFriend = historyViewModel.displayedCall != nil ? contactsManager.getFriendWithAddress(address: historyViewModel.displayedCall!.fromAddress!) : nil let toAddressFriend = historyViewModel.displayedCall != nil ? contactsManager.getFriendWithAddress(address: historyViewModel.displayedCall!.toAddress!) : nil let addressFriend = historyViewModel.displayedCall != nil ? (historyViewModel.displayedCall!.dir == .Incoming ? fromAddressFriend : toAddressFriend) : nil Button { isMenuOpen = false if contactsManager.getFriendWithAddress( address: historyViewModel.displayedCall != nil && historyViewModel.displayedCall!.dir == .Outgoing ? historyViewModel.displayedCall!.toAddress! : historyViewModel.displayedCall!.fromAddress! ) != nil { let addressCall = historyViewModel.displayedCall != nil && historyViewModel.displayedCall!.dir == .Outgoing ? historyViewModel.displayedCall!.toAddress! : historyViewModel.displayedCall!.fromAddress! let friendIndex = contactsManager.lastSearch.firstIndex( where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressCall.asStringUriOnly()})}) if friendIndex != nil { withAnimation { historyViewModel.displayedCall = nil indexPage = 0 contactViewModel.indexDisplayedFriend = friendIndex } } } else { let addressCall = historyViewModel.displayedCall != nil && historyViewModel.displayedCall!.dir == .Outgoing ? historyViewModel.displayedCall!.toAddress! : historyViewModel.displayedCall!.fromAddress! withAnimation { historyViewModel.displayedCall = nil indexPage = 0 isShowEditContactFragment.toggle() editContactViewModel.sipAddresses.removeAll() editContactViewModel.sipAddresses.append(String(addressCall.asStringUriOnly().dropFirst(4))) editContactViewModel.sipAddresses.append("") } } } label: { HStack { Text(addressFriend != nil ? "See contact" : "Add to contacts") Spacer() Image(addressFriend != nil ? "user-circle" : "plus-circle") .resizable() .frame(width: 25, height: 25, alignment: .leading) .padding(.all, 10) } } Button { isMenuOpen = false if historyViewModel.displayedCall != nil && historyViewModel.displayedCall!.dir == .Outgoing { UIPasteboard.general.setValue( historyViewModel.displayedCall!.toAddress!.asStringUriOnly().dropFirst(4), forPasteboardType: UTType.plainText.identifier ) } else { UIPasteboard.general.setValue( historyViewModel.displayedCall!.fromAddress!.asStringUriOnly().dropFirst(4), forPasteboardType: UTType.plainText.identifier ) } ToastViewModel.shared.toastMessage = "Success_copied_into_clipboard" ToastViewModel.shared.displayToast.toggle() } label: { HStack { Text("Copy SIP address") Spacer() Image("copy") .resizable() .frame(width: 25, height: 25, alignment: .leading) .padding(.all, 10) } } Button(role: .destructive) { isMenuOpen = false if historyViewModel.displayedCall != nil && historyViewModel.displayedCall!.dir == .Outgoing { historyListViewModel.callLogsAddressToDelete = historyViewModel.displayedCall!.toAddress!.asStringUriOnly() } else { historyListViewModel.callLogsAddressToDelete = historyViewModel.displayedCall!.fromAddress!.asStringUriOnly() } isShowDeleteAllHistoryPopup.toggle() } label: { HStack { Text("Delete history") Spacer() Image("trash-simple-red") .resizable() .frame(width: 25, height: 25, alignment: .leading) .padding(.all, 10) } } } label: { Image("dots-three-vertical") .renderingMode(.template) .resizable() .foregroundStyle(Color.orangeMain500) .frame(width: 25, height: 25, alignment: .leading) .padding(.all, 10) } .padding(.leading) .onTapGesture { isMenuOpen = true } } .frame(maxWidth: .infinity) .frame(height: 50) .padding(.horizontal) .padding(.bottom, 4) .background(.white) ScrollView { VStack(spacing: 0) { VStack(spacing: 0) { if #unavailable(iOS 16.0) { Rectangle() .foregroundColor(Color.gray100) .frame(height: 7) } VStack(spacing: 0) { let fromAddressFriend = historyViewModel.displayedCall != nil ? contactsManager.getFriendWithAddress(address: historyViewModel.displayedCall!.fromAddress!) : nil let toAddressFriend = historyViewModel.displayedCall != nil ? contactsManager.getFriendWithAddress(address: historyViewModel.displayedCall!.toAddress!) : nil let addressFriend = historyViewModel.displayedCall != nil ? (historyViewModel.displayedCall!.dir == .Incoming ? fromAddressFriend : toAddressFriend) : nil if historyViewModel.displayedCall != nil && addressFriend != nil && addressFriend!.photo != nil && !addressFriend!.photo!.isEmpty { Avatar(contactAvatarModel: contactAvatarModel, avatarSize: 100) } else if historyViewModel.displayedCall != nil { if historyViewModel.displayedCall!.dir == .Outgoing && historyViewModel.displayedCall!.toAddress != nil { if historyViewModel.displayedCall!.toAddress!.displayName != nil { Image(uiImage: contactsManager.textToImage( firstName: historyViewModel.displayedCall!.toAddress!.displayName!, lastName: historyViewModel.displayedCall!.toAddress!.displayName!.components(separatedBy: " ").count > 1 ? historyViewModel.displayedCall!.toAddress!.displayName!.components(separatedBy: " ")[1] : "")) .resizable() .frame(width: 100, height: 100) .clipShape(Circle()) Text(historyViewModel.displayedCall!.toAddress!.displayName!) .foregroundStyle(Color.grayMain2c700) .multilineTextAlignment(.center) .default_text_style(styleSize: 14) .frame(maxWidth: .infinity) .padding(.top, 10) Text(historyViewModel.displayedCall!.toAddress!.asStringUriOnly()) .foregroundStyle(Color.grayMain2c700) .multilineTextAlignment(.center) .default_text_style(styleSize: 14) .frame(maxWidth: .infinity) .padding(.top, 5) Text("") .multilineTextAlignment(.center) .default_text_style_300(styleSize: 12) .frame(maxWidth: .infinity) .frame(height: 20) } else { Image(uiImage: contactsManager.textToImage( firstName: historyViewModel.displayedCall!.toAddress!.username ?? "Username Error", lastName: historyViewModel.displayedCall!.toAddress!.username!.components(separatedBy: " ").count > 1 ? historyViewModel.displayedCall!.toAddress!.username!.components(separatedBy: " ")[1] : "")) .resizable() .frame(width: 100, height: 100) .clipShape(Circle()) Text(historyViewModel.displayedCall!.toAddress!.username ?? "Username Error") .foregroundStyle(Color.grayMain2c700) .multilineTextAlignment(.center) .default_text_style(styleSize: 14) .frame(maxWidth: .infinity) .padding(.top, 10) Text(historyViewModel.displayedCall!.toAddress!.asStringUriOnly()) .foregroundStyle(Color.grayMain2c700) .multilineTextAlignment(.center) .default_text_style(styleSize: 14) .frame(maxWidth: .infinity) .padding(.top, 5) Text("") .multilineTextAlignment(.center) .default_text_style_300(styleSize: 12) .frame(maxWidth: .infinity) .frame(height: 20) } } else if historyViewModel.displayedCall!.fromAddress != nil { if historyViewModel.displayedCall!.fromAddress!.displayName != nil { Image(uiImage: contactsManager.textToImage( firstName: historyViewModel.displayedCall!.fromAddress!.displayName!, lastName: historyViewModel.displayedCall!.fromAddress!.displayName!.components(separatedBy: " ").count > 1 ? historyViewModel.displayedCall!.fromAddress!.displayName!.components(separatedBy: " ")[1] : "")) .resizable() .frame(width: 100, height: 100) .clipShape(Circle()) Text(historyViewModel.displayedCall!.fromAddress!.displayName!) .foregroundStyle(Color.grayMain2c700) .multilineTextAlignment(.center) .default_text_style(styleSize: 14) .frame(maxWidth: .infinity) .padding(.top, 10) Text(historyViewModel.displayedCall!.fromAddress!.asStringUriOnly()) .foregroundStyle(Color.grayMain2c700) .multilineTextAlignment(.center) .default_text_style(styleSize: 14) .frame(maxWidth: .infinity) .padding(.top, 5) Text("") .multilineTextAlignment(.center) .default_text_style_300(styleSize: 12) .frame(maxWidth: .infinity) .frame(height: 20) } else { Image(uiImage: contactsManager.textToImage( firstName: historyViewModel.displayedCall!.fromAddress!.username ?? "Username Error", lastName: historyViewModel.displayedCall!.fromAddress!.username!.components(separatedBy: " ").count > 1 ? historyViewModel.displayedCall!.fromAddress!.username!.components(separatedBy: " ")[1] : "")) .resizable() .frame(width: 100, height: 100) .clipShape(Circle()) Text(historyViewModel.displayedCall!.fromAddress!.username ?? "Username Error") .foregroundStyle(Color.grayMain2c700) .multilineTextAlignment(.center) .default_text_style(styleSize: 14) .frame(maxWidth: .infinity) .padding(.top, 10) Text(historyViewModel.displayedCall!.fromAddress!.asStringUriOnly()) .foregroundStyle(Color.grayMain2c700) .multilineTextAlignment(.center) .default_text_style(styleSize: 14) .frame(maxWidth: .infinity) .padding(.top, 5) Text("") .multilineTextAlignment(.center) .default_text_style_300(styleSize: 12) .frame(maxWidth: .infinity) .frame(height: 20) } } } if historyViewModel.displayedCall != nil && addressFriend != nil && addressFriend!.name != nil { Text((addressFriend!.name)!) .foregroundStyle(Color.grayMain2c700) .multilineTextAlignment(.center) .default_text_style(styleSize: 14) .frame(maxWidth: .infinity) .padding(.top, 10) if historyViewModel.displayedCall!.dir == .Outgoing && historyViewModel.displayedCall!.toAddress != nil { Text(historyViewModel.displayedCall!.toAddress!.asStringUriOnly()) .foregroundStyle(Color.grayMain2c700) .multilineTextAlignment(.center) .default_text_style(styleSize: 14) .frame(maxWidth: .infinity) .padding(.top, 5) } else if historyViewModel.displayedCall!.fromAddress != nil { Text(historyViewModel.displayedCall!.fromAddress!.asStringUriOnly()) .foregroundStyle(Color.grayMain2c700) .multilineTextAlignment(.center) .default_text_style(styleSize: 14) .frame(maxWidth: .infinity) .padding(.top, 5) } Text(contactAvatarModel.lastPresenceInfo) .foregroundStyle(contactAvatarModel.lastPresenceInfo == "Online" ? Color.greenSuccess500 : Color.orangeWarning600) .multilineTextAlignment(.center) .default_text_style_300(styleSize: 12) .frame(maxWidth: .infinity) .frame(height: 20) .padding(.top, 5) } } .frame(minHeight: 150) .frame(maxWidth: .infinity) .padding(.top, 10) .padding(.bottom, 2) .background(Color.gray100) HStack { Spacer() Button(action: { if historyViewModel.displayedCall!.dir == .Outgoing && historyViewModel.displayedCall!.toAddress != nil { telecomManager.doCallWithCore( addr: historyViewModel.displayedCall!.toAddress!, isVideo: false ) } else if historyViewModel.displayedCall!.dir == .Incoming && historyViewModel.displayedCall!.fromAddress != nil { telecomManager.doCallWithCore( addr: historyViewModel.displayedCall!.fromAddress!, isVideo: false ) } }, label: { VStack { HStack(alignment: .center) { Image("phone") .renderingMode(.template) .resizable() .foregroundStyle(Color.grayMain2c600) .frame(width: 25, height: 25) } .padding(16) .background(Color.grayMain2c200) .cornerRadius(40) Text("Appel") .default_text_style(styleSize: 14) .frame(minWidth: 80) } }) Spacer() Button(action: { }, label: { VStack { HStack(alignment: .center) { Image("chat-teardrop-text") .renderingMode(.template) .resizable() //.foregroundStyle(Color.grayMain2c600) .foregroundStyle(Color.grayMain2c300) .frame(width: 25, height: 25) .onTapGesture { withAnimation { } } } .padding(16) .background(Color.grayMain2c200) .cornerRadius(40) Text("Message") .default_text_style(styleSize: 14) .frame(minWidth: 80) } }) Spacer() Button(action: { if historyViewModel.displayedCall!.dir == .Outgoing && historyViewModel.displayedCall!.toAddress != nil { telecomManager.doCallWithCore( addr: historyViewModel.displayedCall!.toAddress!, isVideo: true ) } else if historyViewModel.displayedCall!.dir == .Incoming && historyViewModel.displayedCall!.fromAddress != nil { telecomManager.doCallWithCore( addr: historyViewModel.displayedCall!.fromAddress!, isVideo: true ) } }, label: { VStack { HStack(alignment: .center) { Image("video-camera") .renderingMode(.template) .resizable() .foregroundStyle(Color.grayMain2c600) .frame(width: 25, height: 25) } .padding(16) .background(Color.grayMain2c200) .cornerRadius(40) Text("Video Call") .default_text_style(styleSize: 14) .frame(minWidth: 80) } }) Spacer() } .padding(.top, 20) .padding(.bottom, 10) .frame(maxWidth: .infinity) .background(Color.gray100) VStack(spacing: 0) { let addressFriend = historyViewModel.displayedCall != nil ? (historyViewModel.displayedCall!.dir == .Incoming ? historyViewModel.displayedCall!.fromAddress!.asStringUriOnly() : historyViewModel.displayedCall!.toAddress!.asStringUriOnly()) : nil let callLogsFilter = historyListViewModel.callLogs.filter({ $0.dir == .Incoming ? $0.fromAddress!.asStringUriOnly() == addressFriend : $0.toAddress!.asStringUriOnly() == addressFriend }) ForEach(0..