Refactor history views

This commit is contained in:
Benoit Martins 2024-05-27 17:29:03 +02:00
parent 9f3aeb63ac
commit ad701fb952
8 changed files with 536 additions and 739 deletions

View file

@ -86,6 +86,7 @@
D74C9CFC2ACACF370021626A /* WelcomePage3Fragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74C9CFB2ACACF370021626A /* WelcomePage3Fragment.swift */; };
D74C9CFF2ACAEC5E0021626A /* PopupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74C9CFE2ACAEC5E0021626A /* PopupView.swift */; };
D74C9D012ACB098C0021626A /* PermissionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74C9D002ACB098C0021626A /* PermissionManager.swift */; };
D74DA0122C047F0700A8561D /* HistoryModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74DA0112C047F0700A8561D /* HistoryModel.swift */; };
D750D3392AD3E6EE00EC99C5 /* PopupLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D750D3382AD3E6EE00EC99C5 /* PopupLoadingView.swift */; };
D75759322B56D40900E7AC10 /* ZRTPPopup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D75759312B56D40900E7AC10 /* ZRTPPopup.swift */; };
D76005F62B0798B00054B79A /* IntExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D76005F52B0798B00054B79A /* IntExtension.swift */; };
@ -244,6 +245,7 @@
D74C9CFB2ACACF370021626A /* WelcomePage3Fragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomePage3Fragment.swift; sourceTree = "<group>"; };
D74C9CFE2ACAEC5E0021626A /* PopupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopupView.swift; sourceTree = "<group>"; };
D74C9D002ACB098C0021626A /* PermissionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionManager.swift; sourceTree = "<group>"; };
D74DA0112C047F0700A8561D /* HistoryModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryModel.swift; sourceTree = "<group>"; };
D750D3382AD3E6EE00EC99C5 /* PopupLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopupLoadingView.swift; sourceTree = "<group>"; };
D75759312B56D40900E7AC10 /* ZRTPPopup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZRTPPopup.swift; sourceTree = "<group>"; };
D76005F52B0798B00054B79A /* IntExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntExtension.swift; sourceTree = "<group>"; };
@ -595,6 +597,14 @@
path = Fragments;
sourceTree = "<group>";
};
D74DA0102C047EE300A8561D /* Model */ = {
isa = PBXGroup;
children = (
D74DA0112C047F0700A8561D /* HistoryModel.swift */,
);
path = Model;
sourceTree = "<group>";
};
D75759302B56D3CE00E7AC10 /* Fragments */ = {
isa = PBXGroup;
children = (
@ -669,6 +679,7 @@
isa = PBXGroup;
children = (
D72992372ADD7F1C003AF125 /* Fragments */,
D74DA0102C047EE300A8561D /* Model */,
D72250612ADE95E4008FB426 /* ViewModel */,
D7A03FBF2ACC2E390081A588 /* HistoryView.swift */,
);
@ -1047,6 +1058,7 @@
D726E43F2B19E56F0083C415 /* StartCallViewModel.swift in Sources */,
D70A26EE2B7CF60B006CC8FC /* ConversationsListBottomSheet.swift in Sources */,
D7D1698C2AE66FA500109A5C /* MagicSearchSingleton.swift in Sources */,
D74DA0122C047F0700A8561D /* HistoryModel.swift in Sources */,
D72250692ADFBF2D008FB426 /* SideMenu.swift in Sources */,
D7CEE0352B7A210300FD79B7 /* ConversationsView.swift in Sources */,
D717071E2AC5922E0037746F /* ColorExtension.swift in Sources */,

View file

@ -718,21 +718,9 @@ struct ContentView: View {
.background(Color.gray100)
.ignoresSafeArea(.keyboard)
} else if self.index == 1 {
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
let contactAvatarModel = addressFriend != nil
? ContactsManager.shared.avatarListModel.first(where: {
($0.friend!.consolidatedPresence == .Online || $0.friend!.consolidatedPresence == .Busy)
&& $0.friend!.name == addressFriend!.name
&& $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly()
})
: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false)
if contactAvatarModel != nil {
if historyViewModel.displayedCall!.avatarModel != nil {
HistoryContactFragment(
contactAvatarModel: contactAvatarModel!,
contactAvatarModel: historyViewModel.displayedCall!.avatarModel!,
historyViewModel: historyViewModel,
historyListViewModel: historyListViewModel,
contactViewModel: contactViewModel,
@ -984,6 +972,7 @@ struct ContentView: View {
}
.onReceive(pub) { _ in
conversationsListViewModel.refreshContactAvatarModel()
historyListViewModel.refreshHistoryAvatarModel()
}
}
.overlay {

View file

@ -76,551 +76,381 @@ struct HistoryContactFragment: View {
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
if historyViewModel.displayedCallIsConference.isEmpty {
if historyViewModel.displayedCall != nil && !historyViewModel.displayedCall!.isConf {
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!
if historyViewModel.displayedCall != nil && historyViewModel.displayedCall!.addressFriend != nil {
let addressCall = historyViewModel.displayedCall!.addressFriend!.address
let friendIndex = contactsManager.lastSearch.firstIndex(
where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressCall.asStringUriOnly()})})
if friendIndex != nil {
withAnimation {
historyViewModel.displayedCall = nil
indexPage = 0
if addressCall != nil {
let friendIndex = contactsManager.lastSearch.firstIndex(
where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressCall!.asStringUriOnly()})})
if friendIndex != nil {
contactViewModel.indexDisplayedFriend = friendIndex
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(String(historyViewModel.displayedCall?.address.dropFirst(4) ?? ""))
editContactViewModel.sipAddresses.append("")
}
}
} label: {
HStack {
Text(addressFriend != nil ? "See contact" : "Add to contacts")
Text(historyViewModel.displayedCall!.addressFriend != nil ? "See contact" : "Add to contacts")
Spacer()
Image(addressFriend != nil ? "user-circle" : "plus-circle")
Image(historyViewModel.displayedCall!.addressFriend != nil ? "user-circle" : "plus-circle")
.resizable()
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
}
}
}
Button {
isMenuOpen = false
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)
}
if historyViewModel.displayedCall != nil && historyViewModel.displayedCall!.isOutgoing {
UIPasteboard.general.setValue(
historyViewModel.displayedCall!.address.dropFirst(4),
forPasteboardType: UTType.plainText.identifier
)
} else {
UIPasteboard.general.setValue(
historyViewModel.displayedCall!.address.dropFirst(4),
forPasteboardType: UTType.plainText.identifier
)
}
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)
}
}
ToastViewModel.shared.toastMessage = "Success_copied_into_clipboard"
ToastViewModel.shared.displayToast.toggle()
} label: {
Image("dots-three-vertical")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.orangeMain500)
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
HStack {
Text("Copy SIP address")
Spacer()
Image("copy")
.resizable()
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
}
}
.padding(.leading)
.onTapGesture {
isMenuOpen = true
Button(role: .destructive) {
isMenuOpen = false
if historyViewModel.displayedCall != nil && historyViewModel.displayedCall!.isOutgoing {
historyListViewModel.callLogsAddressToDelete = historyViewModel.displayedCall!.address
} else {
historyListViewModel.callLogsAddressToDelete = historyViewModel.displayedCall!.address
}
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) {
if historyViewModel.displayedCall != nil && !historyViewModel.displayedCall!.isConf {
if historyViewModel.displayedCall!.avatarModel != nil {
Avatar(contactAvatarModel: historyViewModel.displayedCall!.avatarModel!, avatarSize: 100)
}
Text(historyViewModel.displayedCall!.addressName)
.foregroundStyle(Color.grayMain2c700)
.multilineTextAlignment(.center)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity)
.padding(.top, 10)
Text(historyViewModel.displayedCall!.address)
.foregroundStyle(Color.grayMain2c700)
.multilineTextAlignment(.center)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity)
.padding(.top, 5)
if historyViewModel.displayedCall!.avatarModel != nil {
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)
} else {
Text("")
.multilineTextAlignment(.center)
.default_text_style_300(styleSize: 12)
.frame(maxWidth: .infinity)
.frame(height: 20)
}
} else {
VStack {
Image("users-three-square")
.renderingMode(.template)
.resizable()
.frame(width: 60, height: 60)
.foregroundStyle(Color.grayMain2c600)
}
.frame(width: 100, height: 100)
.background(Color.grayMain2c200)
.clipShape(Circle())
Text(historyViewModel.displayedCall!.subject)
.foregroundStyle(Color.grayMain2c700)
.multilineTextAlignment(.center)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity)
.padding(.top, 10)
}
}
.frame(minHeight: 150)
.frame(maxWidth: .infinity)
.padding(.top, 10)
.padding(.bottom, 2)
.background(Color.gray100)
HStack {
Spacer()
if historyViewModel.displayedCall != nil && !historyViewModel.displayedCall!.isConf {
Button(action: {
telecomManager.doCallOrJoinConf(address: historyViewModel.displayedCall!.addressLinphone)
}, 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: {
telecomManager.doCallOrJoinConf(address: historyViewModel.displayedCall!.addressLinphone, 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)
}
})
} else {
Button(action: {
withAnimation {
if historyViewModel.displayedCall != nil && historyViewModel.displayedCall!.address.hasPrefix("sip:conference-focus@sip.linphone.org") {
do {
let meetingAddress = try Factory.Instance.createAddress(addr: historyViewModel.displayedCall!.address)
telecomManager.meetingWaitingRoomDisplayed = true
telecomManager.meetingWaitingRoomSelected = meetingAddress
} catch {}
} else {
telecomManager.doCallOrJoinConf(address: historyViewModel.displayedCall!.addressLinphone)
}
}
}, label: {
VStack {
HStack(alignment: .center) {
Image("users-three-square")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.grayMain2c600)
.frame(width: 25, height: 25)
}
.padding(16)
.background(Color.grayMain2c200)
.cornerRadius(40)
Text("Rejoindre")
.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!.address : nil
let callLogsFilter = historyListViewModel.callLogs.filter({ $0.address == addressFriend})
ForEach(0..<callLogsFilter.count, id: \.self) { index in
HStack {
VStack {
Image(historyListViewModel.getCallIconResId(callStatus: callLogsFilter[index].status, isOutgoing: callLogsFilter[index].isOutgoing))
.resizable()
.frame(
width: historyListViewModel.getCallIconResId(
callStatus: callLogsFilter[index].status,
isOutgoing: callLogsFilter[index].isOutgoing
).contains("rejected") ? 12 : 8,
height: historyListViewModel.getCallIconResId(
callStatus: callLogsFilter[index].status,
isOutgoing: callLogsFilter[index].isOutgoing
).contains("rejected") ? 6 : 8)
.padding(.top, 6)
Spacer()
}
VStack {
Text(historyListViewModel.getCallText(
callStatus: callLogsFilter[index].status,
isOutgoing: callLogsFilter[index].isOutgoing)
)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
Text(historyListViewModel.getCallTime(startDate: callLogsFilter[index].startDate))
.foregroundStyle(
callLogsFilter[index].status != .Success
? Color.redDanger500
: Color.grayMain2c600
)
.default_text_style_300(styleSize: 12)
.frame(maxWidth: .infinity, alignment: .leading)
}
VStack {
Spacer()
Text(callLogsFilter[index].duration.convertDurationToString())
.default_text_style_300(styleSize: 12)
Spacer()
}
}
.padding(.vertical, 15)
.padding(.horizontal, 20)
.frame(maxHeight: 65)
}
}
.background(.white)
.cornerRadius(15)
.padding(.all)
}
.frame(maxWidth: sharedMainViewModel.maxWidth)
}
.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) {
if historyViewModel.displayedCallIsConference.isEmpty {
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)
}
} else {
VStack {
Image("users-three-square")
.renderingMode(.template)
.resizable()
.frame(width: 60, height: 60)
.foregroundStyle(Color.grayMain2c600)
}
.frame(width: 100, height: 100)
.background(Color.grayMain2c200)
.clipShape(Circle())
Text(historyViewModel.displayedCallIsConference ?? "")
.foregroundStyle(Color.grayMain2c700)
.multilineTextAlignment(.center)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity)
.padding(.top, 10)
}
}
.frame(minHeight: 150)
.frame(maxWidth: .infinity)
.padding(.top, 10)
.padding(.bottom, 2)
.background(Color.gray100)
HStack {
Spacer()
if historyViewModel.displayedCallIsConference.isEmpty {
Button(action: {
if historyViewModel.displayedCall!.dir == .Outgoing && historyViewModel.displayedCall!.toAddress != nil {
telecomManager.doCallOrJoinConf(address: historyViewModel.displayedCall!.toAddress!)
} else if historyViewModel.displayedCall!.dir == .Incoming && historyViewModel.displayedCall!.fromAddress != nil {
telecomManager.doCallOrJoinConf(address: historyViewModel.displayedCall!.fromAddress!)
}
}, 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.doCallOrJoinConf(address: historyViewModel.displayedCall!.toAddress!, isVideo: true)
} else if historyViewModel.displayedCall!.dir == .Incoming && historyViewModel.displayedCall!.fromAddress != nil {
telecomManager.doCallOrJoinConf(address: 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)
}
})
} else {
Button(action: {
withAnimation {
if historyViewModel.displayedCall!.dir == .Outgoing && historyViewModel.displayedCall!.toAddress != nil {
if historyViewModel.displayedCall!.toAddress!.asStringUriOnly().hasPrefix("sip:conference-focus@sip.linphone.org") {
do {
let meetingAddress = try Factory.Instance.createAddress(addr: historyViewModel.displayedCall!.toAddress!.asStringUriOnly())
telecomManager.meetingWaitingRoomDisplayed = true
telecomManager.meetingWaitingRoomSelected = meetingAddress
} catch {}
} else {
telecomManager.doCallOrJoinConf(address: historyViewModel.displayedCall!.toAddress!)
}
} else if historyViewModel.displayedCall!.fromAddress != nil {
if historyViewModel.displayedCall!.fromAddress!.asStringUriOnly().hasPrefix("sip:conference-focus@sip.linphone.org") {
do {
let meetingAddress = try Factory.Instance.createAddress(addr: historyViewModel.displayedCall!.fromAddress!.asStringUriOnly())
telecomManager.meetingWaitingRoomDisplayed = true
telecomManager.meetingWaitingRoomSelected = meetingAddress
} catch {}
} else {
telecomManager.doCallOrJoinConf(address: historyViewModel.displayedCall!.fromAddress!)
}
}
}
}, label: {
VStack {
HStack(alignment: .center) {
Image("users-three-square")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.grayMain2c600)
.frame(width: 25, height: 25)
}
.padding(16)
.background(Color.grayMain2c200)
.cornerRadius(40)
Text("Rejoindre")
.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..<callLogsFilter.count, id: \.self) { index in
HStack {
VStack {
Image(historyListViewModel.getCallIconResId(callStatus: callLogsFilter[index].status, callDir: callLogsFilter[index].dir))
.resizable()
.frame(
width: historyListViewModel.getCallIconResId(
callStatus: callLogsFilter[index].status,
callDir: callLogsFilter[index].dir
).contains("rejected") ? 12 : 8,
height: historyListViewModel.getCallIconResId(
callStatus: callLogsFilter[index].status,
callDir: callLogsFilter[index].dir
).contains("rejected") ? 6 : 8)
.padding(.top, 6)
Spacer()
}
VStack {
Text(historyListViewModel.getCallText(
callStatus: callLogsFilter[index].status,
callDir: callLogsFilter[index].dir)
)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
Text(historyListViewModel.getCallTime(startDate: callLogsFilter[index].startDate))
.foregroundStyle(
callLogsFilter[index].status != .Success
? Color.redDanger500
: Color.grayMain2c600
)
.default_text_style_300(styleSize: 12)
.frame(maxWidth: .infinity, alignment: .leading)
}
VStack {
Spacer()
Text(callLogsFilter[index].duration.convertDurationToString())
.default_text_style_300(styleSize: 12)
Spacer()
}
}
.padding(.vertical, 15)
.padding(.horizontal, 20)
.frame(maxHeight: 65)
}
}
.background(.white)
.cornerRadius(15)
.padding(.all)
}
.frame(maxWidth: sharedMainViewModel.maxWidth)
}
.frame(maxWidth: .infinity)
.padding(.top, 2)
}
.background(Color.gray100)
}
.background(.white)
.navigationBarHidden(true)
.onRotate { newOrientation in
orientation = newOrientation
.padding(.top, 2)
}
.background(Color.gray100)
}
.background(.white)
.navigationBarHidden(true)
.onRotate { newOrientation in
orientation = newOrientation
}
}
}
.navigationViewStyle(.stack)
}

View file

@ -77,40 +77,28 @@ struct HistoryListBottomSheet: View {
index = 0
if contactsManager.getFriendWithAddress(
address: historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.dir == .Outgoing
? historyViewModel.selectedCall!.toAddress!
: historyViewModel.selectedCall!.fromAddress!
) != nil {
let addressCall = historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.dir == .Outgoing
? historyViewModel.selectedCall!.toAddress!
: historyViewModel.selectedCall!.fromAddress!
if historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.addressFriend != nil {
let addressCall = historyViewModel.selectedCall!.address
let friendIndex = contactsManager.lastSearch.firstIndex(where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressCall.asStringUriOnly()})})
let friendIndex = contactsManager.lastSearch.firstIndex(where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressCall})})
if friendIndex != nil {
withAnimation {
contactViewModel.indexDisplayedFriend = friendIndex
}
}
} else {
let addressCall = historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.dir == .Outgoing
? historyViewModel.selectedCall!.toAddress!
: historyViewModel.selectedCall!.fromAddress!
} else if historyViewModel.selectedCall != nil {
let addressCall = historyViewModel.selectedCall!.address
withAnimation {
isShowEditContactFragment.toggle()
editContactViewModel.sipAddresses.removeAll()
editContactViewModel.sipAddresses.append(String(addressCall.asStringUriOnly().dropFirst(4)))
editContactViewModel.sipAddresses.append(String(addressCall.dropFirst(4)))
editContactViewModel.sipAddresses.append("")
}
}
} label: {
HStack {
if contactsManager.getFriendWithAddress(
address: historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.dir == .Outgoing
? historyViewModel.selectedCall!.toAddress!
: historyViewModel.selectedCall!.fromAddress!
) != nil {
if historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.addressFriend != nil {
Image("user-circle")
.renderingMode(.template)
.resizable()
@ -143,14 +131,14 @@ struct HistoryListBottomSheet: View {
.frame(maxWidth: .infinity)
Button {
if historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.dir == .Outgoing {
if historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.isOutgoing {
UIPasteboard.general.setValue(
historyViewModel.selectedCall!.toAddress!.asStringUriOnly().dropFirst(4),
historyViewModel.selectedCall!.address.dropFirst(4),
forPasteboardType: UTType.plainText.identifier
)
} else {
UIPasteboard.general.setValue(
historyViewModel.selectedCall!.fromAddress!.asStringUriOnly().dropFirst(4),
historyViewModel.selectedCall!.address.dropFirst(4),
forPasteboardType: UTType.plainText.identifier
)
}
@ -193,11 +181,8 @@ struct HistoryListBottomSheet: View {
.frame(maxWidth: .infinity)
Button {
CoreContext.shared.doOnCoreQueue { core in
if historyViewModel.selectedCall != nil {
core.removeCallLog(callLog: historyViewModel.selectedCall!)
historyListViewModel.removeCallLog(callLog: historyViewModel.selectedCall!)
}
if historyViewModel.selectedCall != nil {
historyListViewModel.removeCallLog(historyModel: historyViewModel.selectedCall!)
}
if #available(iOS 16.0, *) {

View file

@ -38,97 +38,30 @@ struct HistoryListFragment: View {
ForEach(0..<historyListViewModel.callLogs.count, id: \.self) { index in
HStack {
HStack {
if historyListViewModel.callLogsIsConference[index].isEmpty {
let fromAddressFriend = contactsManager.getFriendWithAddress(address: historyListViewModel.callLogs[index].fromAddress!)
let toAddressFriend = contactsManager.getFriendWithAddress(address: historyListViewModel.callLogs[index].toAddress!)
let addressFriend = historyListViewModel.callLogs[index].dir == .Incoming ? fromAddressFriend : toAddressFriend
let contactAvatarModel = addressFriend != nil
? ContactsManager.shared.avatarListModel.first(where: {
($0.friend!.consolidatedPresence == .Online || $0.friend!.consolidatedPresence == .Busy)
&& $0.friend!.name == addressFriend!.name
&& $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly()
})
: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false)
if addressFriend != nil && addressFriend!.photo != nil && !addressFriend!.photo!.isEmpty {
if contactAvatarModel != nil {
Avatar(contactAvatarModel: contactAvatarModel!, avatarSize: 50)
} else {
Image("profil-picture-default")
.resizable()
.frame(width: 50, height: 50)
.clipShape(Circle())
}
if !historyListViewModel.callLogs[index].isConf {
if historyListViewModel.callLogs[index].avatarModel != nil {
Avatar(contactAvatarModel: historyListViewModel.callLogs[index].avatarModel!, avatarSize: 50)
} else {
if historyListViewModel.callLogs[index].dir == .Outgoing && historyListViewModel.callLogs[index].toAddress != nil {
if historyListViewModel.callLogs[index].toAddress!.displayName != nil {
Image(uiImage: contactsManager.textToImage(
firstName: historyListViewModel.callLogs[index].toAddress!.displayName!,
lastName: historyListViewModel.callLogs[index].toAddress!.displayName!.components(separatedBy: " ").count > 1
? historyListViewModel.callLogs[index].toAddress!.displayName!.components(separatedBy: " ")[1]
: ""))
.resizable()
.frame(width: 50, height: 50)
.clipShape(Circle())
} else if historyListViewModel.callLogs[index].toAddress!.username != nil {
Image(uiImage: contactsManager.textToImage(
firstName: historyListViewModel.callLogs[index].toAddress!.username!,
lastName: historyListViewModel.callLogs[index].toAddress!.username!.components(separatedBy: " ").count > 1
? historyListViewModel.callLogs[index].toAddress!.username!.components(separatedBy: " ")[1]
: ""))
.resizable()
.frame(width: 50, height: 50)
.clipShape(Circle())
} else {
VStack {
Image("users-three-square")
.renderingMode(.template)
.resizable()
.frame(width: 28, height: 28)
.foregroundStyle(Color.grayMain2c600)
}
.frame(width: 50, height: 50)
.background(Color.grayMain2c200)
.clipShape(Circle())
}
} else if historyListViewModel.callLogs[index].fromAddress != nil {
if historyListViewModel.callLogs[index].fromAddress!.displayName != nil {
Image(uiImage: contactsManager.textToImage(
firstName: historyListViewModel.callLogs[index].fromAddress!.displayName!,
lastName: historyListViewModel.callLogs[index].fromAddress!.displayName!.components(separatedBy: " ").count > 1
? historyListViewModel.callLogs[index].fromAddress!.displayName!.components(separatedBy: " ")[1]
: ""))
.resizable()
.frame(width: 50, height: 50)
.clipShape(Circle())
} else if historyListViewModel.callLogs[index].fromAddress!.username != nil {
Image(uiImage: contactsManager.textToImage(
firstName: historyListViewModel.callLogs[index].fromAddress!.username!,
lastName: historyListViewModel.callLogs[index].fromAddress!.username!.components(separatedBy: " ").count > 1
? historyListViewModel.callLogs[index].fromAddress!.username!.components(separatedBy: " ")[1]
: ""))
.resizable()
.frame(width: 50, height: 50)
.clipShape(Circle())
} else {
VStack {
Image("users-three-square")
.renderingMode(.template)
.resizable()
.frame(width: 28, height: 28)
.foregroundStyle(Color.grayMain2c600)
}
.frame(width: 50, height: 50)
.background(Color.grayMain2c200)
.clipShape(Circle())
}
if !historyListViewModel.callLogs[index].addressName.isEmpty {
Image(uiImage: contactsManager.textToImage(
firstName: historyListViewModel.callLogs[index].addressName,
lastName: historyListViewModel.callLogs[index].addressName.components(separatedBy: " ").count > 1
? historyListViewModel.callLogs[index].addressName.components(separatedBy: " ")[1]
: ""))
.resizable()
.frame(width: 50, height: 50)
.clipShape(Circle())
} else {
Image("profil-picture-default")
.resizable()
.frame(width: 50, height: 50)
.clipShape(Circle())
VStack {
Image("profil-picture-default")
.renderingMode(.template)
.resizable()
.frame(width: 28, height: 28)
.foregroundStyle(Color.grayMain2c600)
}
.frame(width: 50, height: 50)
.background(Color.grayMain2c200)
.clipShape(Circle())
}
}
} else {
@ -146,47 +79,24 @@ struct HistoryListFragment: View {
VStack(spacing: 0) {
Spacer()
if historyListViewModel.callLogsIsConference[index].isEmpty {
let fromAddressFriend = contactsManager.getFriendWithAddress(address: historyListViewModel.callLogs[index].fromAddress!)
let toAddressFriend = contactsManager.getFriendWithAddress(address: historyListViewModel.callLogs[index].toAddress!)
let addressFriend = historyListViewModel.callLogs[index].dir == .Incoming ? fromAddressFriend : toAddressFriend
if addressFriend != nil {
Text(addressFriend!.name!)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1)
} else {
if historyListViewModel.callLogs[index].dir == .Outgoing && historyListViewModel.callLogs[index].toAddress != nil {
Text(historyListViewModel.callLogs[index].toAddress!.displayName != nil
? historyListViewModel.callLogs[index].toAddress!.displayName!
: historyListViewModel.callLogs[index].toAddress!.username ?? "")
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1)
} else if historyListViewModel.callLogs[index].fromAddress != nil {
Text(historyListViewModel.callLogs[index].fromAddress!.displayName != nil
? historyListViewModel.callLogs[index].fromAddress!.displayName!
: historyListViewModel.callLogs[index].fromAddress!.username ?? "")
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1)
}
}
if !historyListViewModel.callLogs[index].isConf {
Text(historyListViewModel.callLogs[index].addressName)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1)
} else {
Text(historyListViewModel.callLogsIsConference[index])
Text(historyListViewModel.callLogs[index].subject)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1)
}
HStack {
Image(historyListViewModel.getCallIconResId(callStatus: historyListViewModel.callLogs[index].status, callDir: historyListViewModel.callLogs[index].dir))
Image(historyListViewModel.getCallIconResId(callStatus: historyListViewModel.callLogs[index].status, isOutgoing: historyListViewModel.callLogs[index].isOutgoing))
.resizable()
.frame(
width: historyListViewModel.getCallIconResId(callStatus: historyListViewModel.callLogs[index].status, callDir: historyListViewModel.callLogs[index].dir).contains("rejected") ? 12 : 8,
height: historyListViewModel.getCallIconResId(callStatus: historyListViewModel.callLogs[index].status, callDir: historyListViewModel.callLogs[index].dir).contains("rejected") ? 6 : 8)
width: historyListViewModel.getCallIconResId(callStatus: historyListViewModel.callLogs[index].status, isOutgoing: historyListViewModel.callLogs[index].isOutgoing).contains("rejected") ? 12 : 8,
height: historyListViewModel.getCallIconResId(callStatus: historyListViewModel.callLogs[index].status, isOutgoing: historyListViewModel.callLogs[index].isOutgoing).contains("rejected") ? 6 : 8)
Text(historyListViewModel.getCallTime(startDate: historyListViewModel.callLogs[index].startDate))
.default_text_style_300(styleSize: 12)
.frame(maxWidth: .infinity, alignment: .leading)
@ -197,7 +107,7 @@ struct HistoryListFragment: View {
Spacer()
}
if historyListViewModel.callLogsIsConference[index].isEmpty {
if !historyListViewModel.callLogs[index].isConf {
Image("phone")
.resizable()
.frame(width: 25, height: 25)
@ -223,7 +133,6 @@ struct HistoryListFragment: View {
.onTapGesture {
withAnimation {
historyViewModel.displayedCall = historyListViewModel.callLogs[index]
historyViewModel.getConferenceSubject()
}
}
.onLongPressGesture(minimumDuration: 0.2) {
@ -256,11 +165,7 @@ struct HistoryListFragment: View {
}
func doCall(index: Int) {
if historyListViewModel.callLogs[index].dir == .Outgoing && historyListViewModel.callLogs[index].toAddress != nil {
telecomManager.doCallOrJoinConf(address: historyListViewModel.callLogs[index].toAddress!)
} else if historyListViewModel.callLogs[index].fromAddress != nil {
telecomManager.doCallOrJoinConf(address: historyListViewModel.callLogs[index].fromAddress!)
}
telecomManager.doCallOrJoinConf(address: historyListViewModel.callLogs[index].addressLinphone)
}
}

View file

@ -0,0 +1,99 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
import Foundation
import linphonesw
class HistoryModel: ObservableObject {
private var coreContext = CoreContext.shared
static let TAG = "[History Model]"
let callLog: CallLog
let id: String
@Published var subject: String
@Published var isConf: Bool
@Published var addressLinphone: Address
@Published var address: String
@Published var addressName: String
@Published var isOutgoing: Bool
@Published var status: Call.Status
@Published var startDate: time_t
@Published var duration: Int
@Published var addressFriend: Friend? = nil
@Published var avatarModel: ContactAvatarModel? = nil
init(callLog: CallLog) {
self.callLog = callLog
self.id = callLog.callId ?? ""
self.subject = callLog.conferenceInfo != nil && callLog.conferenceInfo!.subject != nil ? callLog.conferenceInfo!.subject! : ""
self.isConf = callLog.conferenceInfo != nil
let addressLinphoneTmp = callLog.dir == .Outgoing && callLog.toAddress != nil ? callLog.toAddress! : callLog.fromAddress!
self.addressLinphone = addressLinphoneTmp
//let addressLinphone = callLog.dir == .Outgoing && callLog.toAddress != nil ? callLog.toAddress! : callLog.fromAddress!
self.address = addressLinphoneTmp.asStringUriOnly()
let addressNameTmp = callLog.conferenceInfo != nil && callLog.conferenceInfo!.subject != nil
? callLog.conferenceInfo!.subject!
: (addressLinphoneTmp.username != nil ? addressLinphoneTmp.username ?? "" : addressLinphoneTmp.displayName ?? "")
self.addressName = addressNameTmp
self.isOutgoing = callLog.dir == .Outgoing
self.status = callLog.status
self.startDate = callLog.startDate
self.duration = callLog.duration
refreshAvatarModel()
}
func refreshAvatarModel() {
coreContext.doOnCoreQueue { _ in
let addressFriendTmp = ContactsManager.shared.getFriendWithAddress(address: self.callLog.dir == .Outgoing ? self.callLog.toAddress! : self.callLog.fromAddress!)
if addressFriendTmp != nil {
self.addressFriend = addressFriendTmp
let addressNameTmp = self.addressName
let avatarModelTmp = addressFriendTmp != nil
? ContactsManager.shared.avatarListModel.first(where: {
$0.friend!.name == addressFriendTmp!.name
&& $0.friend!.address!.asStringUriOnly() == addressFriendTmp!.address!.asStringUriOnly()
}) ?? ContactAvatarModel(friend: nil, name: self.addressName, address: self.address, withPresence: false)
: ContactAvatarModel(friend: nil, name: self.addressName, address: self.address, withPresence: false)
DispatchQueue.main.async {
self.addressFriend = addressFriendTmp
self.addressName = addressFriendTmp!.name ?? addressNameTmp
self.avatarModel = avatarModelTmp
}
} else {
DispatchQueue.main.async {
self.avatarModel = ContactAvatarModel(friend: nil, name: self.addressName, address: self.address, withPresence: false)
}
}
}
}
}

View file

@ -24,9 +24,8 @@ class HistoryListViewModel: ObservableObject {
private var coreContext = CoreContext.shared
@Published var callLogs: [CallLog] = []
@Published var callLogsIsConference: [String] = []
var callLogsTmp: [CallLog] = []
@Published var callLogs: [HistoryModel] = []
var callLogsTmp: [HistoryModel] = []
var callLogsAddressToDelete = ""
var callLogSubscription: AnyCancellable?
@ -43,14 +42,13 @@ class HistoryListViewModel: ObservableObject {
let account = core.defaultAccount
let logs = account?.callLogs != nil ? account!.callLogs : core.callLogs
var callLogsBis: [CallLog] = []
var callLogsIsConferenceBis: [String] = []
var callLogsTmpBis: [CallLog] = []
var callLogsBis: [HistoryModel] = []
var callLogsTmpBis: [HistoryModel] = []
logs.forEach { log in
callLogsBis.append(log)
callLogsIsConferenceBis.append(log.conferenceInfo != nil && log.conferenceInfo!.subject != nil ? log.conferenceInfo!.subject! : "")
callLogsTmpBis.append(log)
let history = HistoryModel(callLog: log)
callLogsBis.append(history)
callLogsTmpBis.append(history)
}
DispatchQueue.main.async {
@ -58,7 +56,6 @@ class HistoryListViewModel: ObservableObject {
self.callLogsTmp.removeAll()
self.callLogs = callLogsBis
self.callLogsIsConference = callLogsIsConferenceBis
self.callLogsTmp = callLogsTmpBis
}
@ -66,14 +63,13 @@ class HistoryListViewModel: ObservableObject {
let account = core.defaultAccount
let logs = account?.callLogs != nil ? account!.callLogs : core.callLogs
var callLogsBis: [CallLog] = []
var callLogsIsConferenceBis: [String] = []
var callLogsTmpBis: [CallLog] = []
var callLogsBis: [HistoryModel] = []
var callLogsTmpBis: [HistoryModel] = []
logs.forEach { log in
callLogsBis.append(log)
callLogsIsConferenceBis.append(log.conferenceInfo != nil && log.conferenceInfo!.subject != nil ? log.conferenceInfo!.subject! : "")
callLogsTmpBis.append(log)
let history = HistoryModel(callLog: log)
callLogsBis.append(history)
callLogsTmpBis.append(history)
}
DispatchQueue.main.async {
@ -81,7 +77,6 @@ class HistoryListViewModel: ObservableObject {
self.callLogsTmp.removeAll()
self.callLogs = callLogsBis
self.callLogsIsConference = callLogsIsConferenceBis
self.callLogsTmp = callLogsTmpBis
}
@ -123,24 +118,24 @@ class HistoryListViewModel: ObservableObject {
}
}
func getCallIconResId(callStatus: Call.Status, callDir: Call.Dir) -> String {
func getCallIconResId(callStatus: Call.Status, isOutgoing: Bool) -> String {
switch callStatus {
case Call.Status.Missed:
if callDir == .Outgoing {
if isOutgoing {
"outgoing-call-missed"
} else {
"incoming-call-missed"
}
case Call.Status.Success:
if callDir == .Outgoing {
if isOutgoing {
"outgoing-call"
} else {
"incoming-call"
}
default:
if callDir == .Outgoing {
if isOutgoing {
"outgoing-call-rejected"
} else {
"incoming-call-rejected"
@ -148,24 +143,24 @@ class HistoryListViewModel: ObservableObject {
}
}
func getCallText(callStatus: Call.Status, callDir: Call.Dir) -> String {
func getCallText(callStatus: Call.Status, isOutgoing: Bool) -> String {
switch callStatus {
case Call.Status.Missed:
if callDir == .Outgoing {
if isOutgoing {
"Outgoing Call"
} else {
"Missed Call"
}
case Call.Status.Success:
if callDir == .Outgoing {
if isOutgoing {
"Outgoing Call"
} else {
"Incoming Call"
}
default:
if callDir == .Outgoing {
if isOutgoing {
"Outgoing Call"
} else {
"Incoming Call"
@ -200,18 +195,8 @@ class HistoryListViewModel: ObservableObject {
func filterCallLogs(filter: String) {
callLogs.removeAll()
callLogsTmp.forEach { callLog in
if callLog.dir == .Outgoing && callLog.toAddress != nil {
if callLog.toAddress!.username != nil && callLog.toAddress!.username!.contains(filter) {
callLogs.append(callLog)
} else if callLog.toAddress!.displayName != nil && callLog.toAddress!.displayName!.contains(filter) {
callLogs.append(callLog)
}
} else if callLog.fromAddress != nil {
if callLog.fromAddress!.username != nil && callLog.fromAddress!.username!.contains(filter) {
callLogs.append(callLog)
} else if callLog.fromAddress!.displayName != nil && callLog.fromAddress!.displayName!.contains(filter) {
callLogs.append(callLog)
}
if callLog.addressName.contains(filter) {
callLogs.append(callLog)
}
}
}
@ -242,20 +227,26 @@ class HistoryListViewModel: ObservableObject {
}
func removeCallLogsWithAddress() {
self.callLogs.filter { $0.toAddress!.asStringUriOnly() == callLogsAddressToDelete || $0.fromAddress!.asStringUriOnly() == callLogsAddressToDelete }.forEach { callLog in
removeCallLog(callLog: callLog)
coreContext.doOnCoreQueue { core in
core.removeCallLog(callLog: callLog)
}
self.callLogs.filter { $0.address == callLogsAddressToDelete || $0.address == callLogsAddressToDelete }.forEach { historyModel in
removeCallLog(historyModel: historyModel)
}
}
func removeCallLog(callLog: CallLog) {
let index = self.callLogs.firstIndex(where: {$0.callId == callLog.callId})
func removeCallLog(historyModel: HistoryModel) {
let index = self.callLogs.firstIndex(where: {$0.id == historyModel.id})
self.callLogs.remove(at: index!)
let indexTmp = self.callLogsTmp.firstIndex(where: {$0.callId == callLog.callId})
let indexTmp = self.callLogsTmp.firstIndex(where: {$0.id == historyModel.id})
self.callLogsTmp.remove(at: indexTmp!)
coreContext.doOnCoreQueue { core in
core.removeCallLog(callLog: historyModel.callLog)
}
}
func refreshHistoryAvatarModel() {
callLogs.forEach { historyModel in
historyModel.refreshAvatarModel()
}
}
}

View file

@ -22,23 +22,9 @@ import linphonesw
class HistoryViewModel: ObservableObject {
@Published var displayedCall: CallLog?
@Published var displayedCallIsConference: String = ""
@Published var displayedCall: HistoryModel?
var selectedCall: CallLog?
var selectedCall: HistoryModel?
init() {}
func getConferenceSubject() {
CoreContext.shared.doOnCoreQueue { core in
var displayedCallIsConferenceTmp = ""
if self.displayedCall?.conferenceInfo != nil {
displayedCallIsConferenceTmp = self.displayedCall?.conferenceInfo?.subject ?? ""
}
DispatchQueue.main.async {
self.displayedCallIsConference = displayedCallIsConferenceTmp
}
}
}
}