mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 02:58:07 +00:00
Add conversations list
This commit is contained in:
parent
60d128f4f2
commit
dc84803a17
17 changed files with 787 additions and 80 deletions
|
|
@ -19,6 +19,7 @@
|
|||
D70C93DE2AC2D0F60063CA3B /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */; };
|
||||
D717071E2AC5922E0037746F /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717071D2AC5922E0037746F /* ColorExtension.swift */; };
|
||||
D71707202AC5989C0037746F /* TextExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717071F2AC5989C0037746F /* TextExtension.swift */; };
|
||||
D7173EBE2B7A5C0A00BCC481 /* LinphoneUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7173EBD2B7A5C0A00BCC481 /* LinphoneUtils.swift */; };
|
||||
D719ABB72ABC67BF00B41C10 /* LinphoneApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D719ABB62ABC67BF00B41C10 /* LinphoneApp.swift */; };
|
||||
D719ABB92ABC67BF00B41C10 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D719ABB82ABC67BF00B41C10 /* ContentView.swift */; };
|
||||
D719ABBB2ABC67BF00B41C10 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D719ABBA2ABC67BF00B41C10 /* Assets.xcassets */; };
|
||||
|
|
@ -80,6 +81,10 @@
|
|||
D7C3650E2AF15BF200FE6142 /* PhotoPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C3650D2AF15BF200FE6142 /* PhotoPicker.swift */; };
|
||||
D7C48DF42AFA66F900D938CB /* EditContactController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C48DF32AFA66F900D938CB /* EditContactController.swift */; };
|
||||
D7C48DF62AFCDF4700D938CB /* ContactInnerActionsFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C48DF52AFCDF4700D938CB /* ContactInnerActionsFragment.swift */; };
|
||||
D7CEE0352B7A210300FD79B7 /* ConversationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7CEE0342B7A210300FD79B7 /* ConversationsView.swift */; };
|
||||
D7CEE0382B7A214F00FD79B7 /* ConversationsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7CEE0372B7A214F00FD79B7 /* ConversationsListViewModel.swift */; };
|
||||
D7CEE03B2B7A234200FD79B7 /* ConversationsFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7CEE03A2B7A234200FD79B7 /* ConversationsFragment.swift */; };
|
||||
D7CEE03D2B7A23B200FD79B7 /* ConversationsListFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7CEE03C2B7A23B200FD79B7 /* ConversationsListFragment.swift */; };
|
||||
D7D1698C2AE66FA500109A5C /* MagicSearchSingleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7D1698B2AE66FA500109A5C /* MagicSearchSingleton.swift */; };
|
||||
D7D24D132AC1B4E800C6F35B /* NotoSans-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D7D24D0D2AC1B4E800C6F35B /* NotoSans-Medium.ttf */; };
|
||||
D7D24D142AC1B4E800C6F35B /* NotoSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D7D24D0E2AC1B4E800C6F35B /* NotoSans-Regular.ttf */; };
|
||||
|
|
@ -112,6 +117,7 @@
|
|||
D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
|
||||
D717071D2AC5922E0037746F /* ColorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorExtension.swift; sourceTree = "<group>"; };
|
||||
D717071F2AC5989C0037746F /* TextExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextExtension.swift; sourceTree = "<group>"; };
|
||||
D7173EBD2B7A5C0A00BCC481 /* LinphoneUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinphoneUtils.swift; sourceTree = "<group>"; };
|
||||
D719ABB32ABC67BF00B41C10 /* Linphone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Linphone.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D719ABB62ABC67BF00B41C10 /* LinphoneApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinphoneApp.swift; sourceTree = "<group>"; };
|
||||
D719ABB82ABC67BF00B41C10 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -176,6 +182,10 @@
|
|||
D7C3650D2AF15BF200FE6142 /* PhotoPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPicker.swift; sourceTree = "<group>"; };
|
||||
D7C48DF32AFA66F900D938CB /* EditContactController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditContactController.swift; sourceTree = "<group>"; };
|
||||
D7C48DF52AFCDF4700D938CB /* ContactInnerActionsFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactInnerActionsFragment.swift; sourceTree = "<group>"; };
|
||||
D7CEE0342B7A210300FD79B7 /* ConversationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationsView.swift; sourceTree = "<group>"; };
|
||||
D7CEE0372B7A214F00FD79B7 /* ConversationsListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationsListViewModel.swift; sourceTree = "<group>"; };
|
||||
D7CEE03A2B7A234200FD79B7 /* ConversationsFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationsFragment.swift; sourceTree = "<group>"; };
|
||||
D7CEE03C2B7A23B200FD79B7 /* ConversationsListFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationsListFragment.swift; sourceTree = "<group>"; };
|
||||
D7D1698B2AE66FA500109A5C /* MagicSearchSingleton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MagicSearchSingleton.swift; sourceTree = "<group>"; };
|
||||
D7D24D0D2AC1B4E800C6F35B /* NotoSans-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NotoSans-Medium.ttf"; sourceTree = "<group>"; };
|
||||
D7D24D0E2AC1B4E800C6F35B /* NotoSans-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NotoSans-Regular.ttf"; sourceTree = "<group>"; };
|
||||
|
|
@ -248,6 +258,7 @@
|
|||
D7C3650D2AF15BF200FE6142 /* PhotoPicker.swift */,
|
||||
D732A9082AFD235500DB42BA /* ShareSheetController.swift */,
|
||||
D7B99E9A2B29F7C200BE7BF2 /* ActivityIndicator.swift */,
|
||||
D7173EBD2B7A5C0A00BCC481 /* LinphoneUtils.swift */,
|
||||
);
|
||||
path = Utils;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -313,6 +324,7 @@
|
|||
D719ABC62ABC6F0200B41C10 /* Main */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D7CEE0332B7A20A400FD79B7 /* Conversations */,
|
||||
D7A03FBB2ACC2D850081A588 /* Contacts */,
|
||||
D74C9CFD2ACAEC150021626A /* Fragments */,
|
||||
D7A03FBE2ACC2E010081A588 /* History */,
|
||||
|
|
@ -518,6 +530,33 @@
|
|||
path = ViewModel;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D7CEE0332B7A20A400FD79B7 /* Conversations */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D7CEE0392B7A232200FD79B7 /* Fragments */,
|
||||
D7CEE0362B7A212C00FD79B7 /* ViewModel */,
|
||||
D7CEE0342B7A210300FD79B7 /* ConversationsView.swift */,
|
||||
);
|
||||
path = Conversations;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D7CEE0362B7A212C00FD79B7 /* ViewModel */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D7CEE0372B7A214F00FD79B7 /* ConversationsListViewModel.swift */,
|
||||
);
|
||||
path = ViewModel;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D7CEE0392B7A232200FD79B7 /* Fragments */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D7CEE03A2B7A234200FD79B7 /* ConversationsFragment.swift */,
|
||||
D7CEE03C2B7A23B200FD79B7 /* ConversationsListFragment.swift */,
|
||||
);
|
||||
path = Fragments;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D7D24D0C2AC1B4C700C6F35B /* Fonts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -676,6 +715,7 @@
|
|||
files = (
|
||||
D7C3650E2AF15BF200FE6142 /* PhotoPicker.swift in Sources */,
|
||||
D7ADF6002AFE356400212231 /* Avatar.swift in Sources */,
|
||||
D7CEE03B2B7A234200FD79B7 /* ConversationsFragment.swift in Sources */,
|
||||
D71707202AC5989C0037746F /* TextExtension.swift in Sources */,
|
||||
66C491F92B24D25B00CEA16D /* ConfigExtension.swift in Sources */,
|
||||
D719ABB92ABC67BF00B41C10 /* ContentView.swift in Sources */,
|
||||
|
|
@ -722,8 +762,10 @@
|
|||
D7A03FC62ACC458A0081A588 /* SplashScreen.swift in Sources */,
|
||||
D7A03FC02ACC2E390081A588 /* HistoryView.swift in Sources */,
|
||||
D748BF2E2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift in Sources */,
|
||||
D7173EBE2B7A5C0A00BCC481 /* LinphoneUtils.swift in Sources */,
|
||||
66C492012B24DB6900CEA16D /* Log.swift in Sources */,
|
||||
D748BF2C2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift in Sources */,
|
||||
D7CEE0382B7A214F00FD79B7 /* ConversationsListViewModel.swift in Sources */,
|
||||
D74C9CF82ACACECE0021626A /* WelcomePage1Fragment.swift in Sources */,
|
||||
D7E6D0552AEBFCCE00A57AAF /* ContactsInnerFragment.swift in Sources */,
|
||||
D732A9092AFD235500DB42BA /* ShareSheetController.swift in Sources */,
|
||||
|
|
@ -740,9 +782,11 @@
|
|||
D726E43F2B19E56F0083C415 /* StartCallViewModel.swift in Sources */,
|
||||
D7D1698C2AE66FA500109A5C /* MagicSearchSingleton.swift in Sources */,
|
||||
D72250692ADFBF2D008FB426 /* SideMenu.swift in Sources */,
|
||||
D7CEE0352B7A210300FD79B7 /* ConversationsView.swift in Sources */,
|
||||
D717071E2AC5922E0037746F /* ColorExtension.swift in Sources */,
|
||||
D78290B82ADD3910004AA85C /* ContactsFragment.swift in Sources */,
|
||||
D7DA67642ACCB31700E95002 /* ProfileModeFragment.swift in Sources */,
|
||||
D7CEE03D2B7A23B200FD79B7 /* ConversationsListFragment.swift in Sources */,
|
||||
D74C9CFC2ACACF370021626A /* WelcomePage3Fragment.swift in Sources */,
|
||||
D719ABCC2ABC769C00B41C10 /* AssistantView.swift in Sources */,
|
||||
D7C365082AEFAB7F00FE6142 /* ContactListBottomSheet.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -135,10 +135,12 @@ final class CoreContext: ObservableObject {
|
|||
self.mCore.removeLinphoneSpec(spec: "conference")
|
||||
Log.info("Removing spec 'ephemeral' from core for this version")
|
||||
self.mCore.removeLinphoneSpec(spec: "ephemeral")
|
||||
/*
|
||||
Log.info("Removing spec 'groupchat' from core for this version")
|
||||
self.mCore.removeLinphoneSpec(spec: "groupchat")
|
||||
Log.info("Removing spec 'lime' from core for this version")
|
||||
self.mCore.removeLinphoneSpec(spec: "lime")
|
||||
*/
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ struct LinphoneApp: App {
|
|||
@State private var historyListViewModel: HistoryListViewModel?
|
||||
@State private var startCallViewModel: StartCallViewModel?
|
||||
@State private var callViewModel: CallViewModel?
|
||||
@State private var conversationsListViewModel: ConversationsListViewModel?
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
|
|
@ -72,7 +73,8 @@ struct LinphoneApp: App {
|
|||
historyViewModel: historyViewModel!,
|
||||
historyListViewModel: historyListViewModel!,
|
||||
startCallViewModel: startCallViewModel!,
|
||||
callViewModel: callViewModel!
|
||||
callViewModel: callViewModel!,
|
||||
conversationsListViewModel: conversationsListViewModel!
|
||||
)
|
||||
} else {
|
||||
SplashScreen()
|
||||
|
|
@ -86,6 +88,7 @@ struct LinphoneApp: App {
|
|||
historyListViewModel = HistoryListViewModel()
|
||||
startCallViewModel = StartCallViewModel()
|
||||
callViewModel = CallViewModel()
|
||||
conversationsListViewModel = ConversationsListViewModel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,6 +250,9 @@
|
|||
},
|
||||
"Continue" : {
|
||||
|
||||
},
|
||||
"Conversations" : {
|
||||
|
||||
},
|
||||
"Copy address" : {
|
||||
|
||||
|
|
@ -424,6 +427,9 @@
|
|||
},
|
||||
"No contacts for the moment..." : {
|
||||
|
||||
},
|
||||
"No conversation for the moment..." : {
|
||||
|
||||
},
|
||||
"Not account yet?" : {
|
||||
|
||||
|
|
|
|||
|
|
@ -99,10 +99,10 @@ class AccountLoginViewModel: ObservableObject {
|
|||
accountParams.pushNotificationConfig?.provider = "apns" + pushEnvironment
|
||||
|
||||
// Temporary disable these features are they are not used for 6.0 first version
|
||||
accountParams.conferenceFactoryUri = nil
|
||||
accountParams.conferenceFactoryAddress = nil
|
||||
//accountParams.conferenceFactoryUri = nil
|
||||
//accountParams.conferenceFactoryAddress = nil
|
||||
accountParams.audioVideoConferenceFactoryAddress = nil
|
||||
accountParams.limeServerUrl = nil
|
||||
//accountParams.limeServerUrl = nil
|
||||
|
||||
// Now that our AccountParams is configured, we can create the Account object
|
||||
let account = try core.createAccount(params: accountParams)
|
||||
|
|
|
|||
|
|
@ -230,11 +230,11 @@ struct CallsListFragment: View {
|
|||
|
||||
if addressFriend != nil && addressFriend!.photo != nil && !addressFriend!.photo!.isEmpty {
|
||||
if contactAvatarModel != nil {
|
||||
Avatar(contactAvatarModel: contactAvatarModel!, avatarSize: 45)
|
||||
Avatar(contactAvatarModel: contactAvatarModel!, avatarSize: 50)
|
||||
} else {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 45, height: 45)
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
} else {
|
||||
|
|
@ -245,7 +245,7 @@ struct CallsListFragment: View {
|
|||
? callViewModel.calls[index].callLog!.remoteAddress!.displayName!.components(separatedBy: " ")[1]
|
||||
: ""))
|
||||
.resizable()
|
||||
.frame(width: 45, height: 45)
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(Circle())
|
||||
|
||||
} else {
|
||||
|
|
@ -255,7 +255,7 @@ struct CallsListFragment: View {
|
|||
? callViewModel.calls[index].callLog!.remoteAddress!.username!.components(separatedBy: " ")[1]
|
||||
: ""))
|
||||
.resizable()
|
||||
.frame(width: 45, height: 45)
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,11 +65,11 @@ struct ContactsListFragment: View {
|
|||
if index < contactsManager.avatarListModel.count
|
||||
&& contactsManager.avatarListModel[index].friend!.photo != nil
|
||||
&& !contactsManager.avatarListModel[index].friend!.photo!.isEmpty {
|
||||
Avatar(contactAvatarModel: contactsManager.avatarListModel[index], avatarSize: 45)
|
||||
Avatar(contactAvatarModel: contactsManager.avatarListModel[index], avatarSize: 50)
|
||||
} else {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 45, height: 45)
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
Text((contactsManager.lastSearch[index].friend?.name)!)
|
||||
|
|
|
|||
|
|
@ -38,11 +38,11 @@ struct FavoriteContactsListFragment: View {
|
|||
VStack {
|
||||
if contactsManager.lastSearch[index].friend!.photo != nil
|
||||
&& !contactsManager.lastSearch[index].friend!.photo!.isEmpty {
|
||||
Avatar(contactAvatarModel: contactsManager.avatarListModel[index], avatarSize: 45)
|
||||
Avatar(contactAvatarModel: contactsManager.avatarListModel[index], avatarSize: 50)
|
||||
} else {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 45, height: 45)
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
Text((contactsManager.lastSearch[index].friend?.name)!)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ struct ContentView: View {
|
|||
@ObservedObject var historyListViewModel: HistoryListViewModel
|
||||
@ObservedObject var startCallViewModel: StartCallViewModel
|
||||
@ObservedObject var callViewModel: CallViewModel
|
||||
@ObservedObject var conversationsListViewModel: ConversationsListViewModel
|
||||
|
||||
@State var index = 0
|
||||
@State private var orientation = UIDevice.current.orientation
|
||||
|
|
@ -128,6 +129,53 @@ struct ContentView: View {
|
|||
})
|
||||
|
||||
Spacer()
|
||||
|
||||
ZStack {
|
||||
if conversationsListViewModel.unreadMessages > 0 {
|
||||
VStack {
|
||||
HStack {
|
||||
Text(
|
||||
conversationsListViewModel.unreadMessages < 99
|
||||
? String(conversationsListViewModel.unreadMessages)
|
||||
: "99+"
|
||||
)
|
||||
.foregroundStyle(.white)
|
||||
.default_text_style(styleSize: 10)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.frame(width: 18, height: 18)
|
||||
.background(Color.redDanger500)
|
||||
.cornerRadius(50)
|
||||
}
|
||||
.padding(.bottom, 30)
|
||||
.padding(.leading, 30)
|
||||
}
|
||||
|
||||
Button(action: {
|
||||
self.index = 2
|
||||
historyViewModel.displayedCall = nil
|
||||
contactViewModel.indexDisplayedFriend = nil
|
||||
}, label: {
|
||||
VStack {
|
||||
Image("chat-teardrop-text")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(self.index == 2 ? Color.orangeMain500 : Color.grayMain2c600)
|
||||
.frame(width: 25, height: 25)
|
||||
|
||||
if self.index == 2 {
|
||||
Text("Conversations")
|
||||
.default_text_style_700(styleSize: 10)
|
||||
} else {
|
||||
Text("Conversations")
|
||||
.default_text_style(styleSize: 10)
|
||||
}
|
||||
}
|
||||
})
|
||||
.padding(.top)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.frame(width: 75)
|
||||
|
|
@ -148,7 +196,7 @@ struct ContentView: View {
|
|||
openMenu()
|
||||
}
|
||||
|
||||
Text(index == 0 ? "Contacts" : "Calls")
|
||||
Text(index == 0 ? "Contacts" : (index == 1 ? "Calls" : "Conversations"))
|
||||
.default_text_style_white_800(styleSize: 20)
|
||||
.padding(.leading, 10)
|
||||
|
||||
|
|
@ -166,72 +214,75 @@ struct ContentView: View {
|
|||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
}
|
||||
.padding(.trailing, index == 2 ? 10 : 0)
|
||||
|
||||
Menu {
|
||||
if index == 0 {
|
||||
Button {
|
||||
contactViewModel.indexDisplayedFriend = nil
|
||||
isMenuOpen = false
|
||||
magicSearch.allContact = true
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("See all")
|
||||
Spacer()
|
||||
if magicSearch.allContact {
|
||||
Image("green-check")
|
||||
if index != 2 {
|
||||
Menu {
|
||||
if index == 0 {
|
||||
Button {
|
||||
contactViewModel.indexDisplayedFriend = nil
|
||||
isMenuOpen = false
|
||||
magicSearch.allContact = true
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("See all")
|
||||
Spacer()
|
||||
if magicSearch.allContact {
|
||||
Image("green-check")
|
||||
.resizable()
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
contactViewModel.indexDisplayedFriend = nil
|
||||
isMenuOpen = false
|
||||
magicSearch.allContact = false
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("See Linphone contact")
|
||||
Spacer()
|
||||
if !magicSearch.allContact {
|
||||
Image("green-check")
|
||||
.resizable()
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Button(role: .destructive) {
|
||||
isMenuOpen = false
|
||||
isShowDeleteAllHistoryPopup.toggle()
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Delete all history")
|
||||
Spacer()
|
||||
Image("trash-simple-red")
|
||||
.resizable()
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
contactViewModel.indexDisplayedFriend = nil
|
||||
isMenuOpen = false
|
||||
magicSearch.allContact = false
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("See Linphone contact")
|
||||
Spacer()
|
||||
if !magicSearch.allContact {
|
||||
Image("green-check")
|
||||
.resizable()
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Button(role: .destructive) {
|
||||
isMenuOpen = false
|
||||
isShowDeleteAllHistoryPopup.toggle()
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Delete all history")
|
||||
Spacer()
|
||||
Image("trash-simple-red")
|
||||
.resizable()
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Image(index == 0 ? "funnel" : "dots-three-vertical")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(.white)
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
}
|
||||
.padding(.trailing, 10)
|
||||
.onTapGesture {
|
||||
isMenuOpen = true
|
||||
}
|
||||
} label: {
|
||||
Image(index == 0 ? "funnel" : "dots-three-vertical")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(.white)
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
}
|
||||
.padding(.trailing, 10)
|
||||
.onTapGesture {
|
||||
isMenuOpen = true
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
|
|
@ -254,8 +305,10 @@ struct ContentView: View {
|
|||
magicSearch.currentFilter = ""
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} else {
|
||||
} else if index == 1 {
|
||||
historyListViewModel.resetFilterCallLogs()
|
||||
} else {
|
||||
//TODO Conversations List reset
|
||||
}
|
||||
} label: {
|
||||
Image("caret-left")
|
||||
|
|
@ -293,8 +346,10 @@ struct ContentView: View {
|
|||
magicSearch.currentFilter = newValue
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} else {
|
||||
} else if index == 1 {
|
||||
historyListViewModel.filterCallLogs(filter: text)
|
||||
} else {
|
||||
//TODO Conversations List Filter
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -317,9 +372,15 @@ struct ContentView: View {
|
|||
self.focusedField = true
|
||||
}
|
||||
.onChange(of: text) { newValue in
|
||||
magicSearch.currentFilter = newValue
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
if index == 0 {
|
||||
magicSearch.currentFilter = newValue
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} else if index == 1 {
|
||||
historyListViewModel.filterCallLogs(filter: text)
|
||||
} else {
|
||||
//TODO Conversations List Filter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -360,6 +421,8 @@ struct ContentView: View {
|
|||
isShowStartCallFragment: $isShowStartCallFragment,
|
||||
isShowEditContactFragment: $isShowEditContactFragment
|
||||
)
|
||||
} else if self.index == 2 {
|
||||
ConversationsView(conversationsListViewModel: conversationsListViewModel)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth:
|
||||
|
|
@ -408,6 +471,7 @@ struct ContentView: View {
|
|||
}
|
||||
})
|
||||
.padding(.top)
|
||||
.frame(width: 100)
|
||||
|
||||
Spacer()
|
||||
|
||||
|
|
@ -431,6 +495,56 @@ struct ContentView: View {
|
|||
}
|
||||
})
|
||||
.padding(.top)
|
||||
.frame(width: 100)
|
||||
|
||||
Spacer()
|
||||
|
||||
ZStack {
|
||||
if conversationsListViewModel.unreadMessages > 0 {
|
||||
VStack {
|
||||
HStack {
|
||||
Text(
|
||||
conversationsListViewModel.unreadMessages < 99
|
||||
? String(conversationsListViewModel.unreadMessages)
|
||||
: "99+"
|
||||
)
|
||||
.foregroundStyle(.white)
|
||||
.default_text_style(styleSize: 10)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.frame(width: 18, height: 18)
|
||||
.background(Color.redDanger500)
|
||||
.cornerRadius(50)
|
||||
}
|
||||
.padding(.bottom, 30)
|
||||
.padding(.leading, 30)
|
||||
}
|
||||
|
||||
Button(action: {
|
||||
self.index = 2
|
||||
historyViewModel.displayedCall = nil
|
||||
contactViewModel.indexDisplayedFriend = nil
|
||||
}, label: {
|
||||
VStack {
|
||||
Image("chat-teardrop-text")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(self.index == 2 ? Color.orangeMain500 : Color.grayMain2c600)
|
||||
.frame(width: 25, height: 25)
|
||||
|
||||
if self.index == 2 {
|
||||
Text("Conversations")
|
||||
.default_text_style_700(styleSize: 10)
|
||||
} else {
|
||||
Text("Conversations")
|
||||
.default_text_style(styleSize: 10)
|
||||
}
|
||||
}
|
||||
})
|
||||
.padding(.top)
|
||||
.frame(width: 100)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
|
|
@ -491,6 +605,11 @@ struct ContentView: View {
|
|||
.background(Color.gray100)
|
||||
.ignoresSafeArea(.keyboard)
|
||||
}
|
||||
} else if self.index == 2 {
|
||||
ConversationsView(conversationsListViewModel: conversationsListViewModel)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color.gray100)
|
||||
.ignoresSafeArea(.keyboard)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
|
|
@ -745,7 +864,8 @@ struct ContentView: View {
|
|||
historyViewModel: HistoryViewModel(),
|
||||
historyListViewModel: HistoryListViewModel(),
|
||||
startCallViewModel: StartCallViewModel(),
|
||||
callViewModel: CallViewModel()
|
||||
callViewModel: CallViewModel(),
|
||||
conversationsListViewModel: ConversationsListViewModel()
|
||||
)
|
||||
}
|
||||
// swiftlint:enable type_body_length
|
||||
|
|
|
|||
51
Linphone/UI/Main/Conversations/ConversationsView.swift
Normal file
51
Linphone/UI/Main/Conversations/ConversationsView.swift
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* 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 SwiftUI
|
||||
|
||||
struct ConversationsView: View {
|
||||
|
||||
@ObservedObject var conversationsListViewModel: ConversationsListViewModel
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
ConversationsFragment(conversationsListViewModel: conversationsListViewModel)
|
||||
|
||||
Button {
|
||||
} label: {
|
||||
Image("plus-circle")
|
||||
.renderingMode(.template)
|
||||
.foregroundStyle(.white)
|
||||
.padding()
|
||||
.background(Color.orangeMain500)
|
||||
.clipShape(Circle())
|
||||
.shadow(color: .black.opacity(0.2), radius: 4)
|
||||
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
.navigationViewStyle(.stack)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ConversationsListFragment(conversationsListViewModel: ConversationsListViewModel())
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* 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 SwiftUI
|
||||
|
||||
struct ConversationsFragment: View {
|
||||
|
||||
@ObservedObject var conversationsListViewModel: ConversationsListViewModel
|
||||
|
||||
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
if #available(iOS 16.0, *), idiom != .pad {
|
||||
ConversationsListFragment(conversationsListViewModel: conversationsListViewModel)
|
||||
/*
|
||||
.sheet(isPresented: $showingSheet) {
|
||||
HistoryListBottomSheet(
|
||||
historyViewModel: historyViewModel,
|
||||
contactViewModel: contactViewModel,
|
||||
editContactViewModel: editContactViewModel,
|
||||
historyListViewModel: historyListViewModel,
|
||||
showingSheet: $showingSheet,
|
||||
index: $index,
|
||||
isShowEditContactFragment: $isShowEditContactFragment
|
||||
)
|
||||
.presentationDetents([.fraction(0.2)])
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
ConversationsListFragment(conversationsListViewModel: conversationsListViewModel)
|
||||
/*
|
||||
.halfSheet(showSheet: $showingSheet) {
|
||||
HistoryListBottomSheet(
|
||||
historyViewModel: historyViewModel,
|
||||
contactViewModel: contactViewModel,
|
||||
editContactViewModel: editContactViewModel,
|
||||
historyListViewModel: historyListViewModel,
|
||||
showingSheet: $showingSheet,
|
||||
index: $index,
|
||||
isShowEditContactFragment: $isShowEditContactFragment
|
||||
)
|
||||
} onDismiss: {}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ConversationsFragment(conversationsListViewModel: ConversationsListViewModel())
|
||||
}
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* 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 SwiftUI
|
||||
import linphonesw
|
||||
|
||||
struct ConversationsListFragment: View {
|
||||
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
|
||||
@ObservedObject var conversationsListViewModel: ConversationsListViewModel
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
List {
|
||||
ForEach(0..<conversationsListViewModel.conversationsList.count, id: \.self) { index in
|
||||
HStack {
|
||||
let addressFriend =
|
||||
(conversationsListViewModel.conversationsList[index].participants.first != nil && conversationsListViewModel.conversationsList[index].participants.first!.address != nil)
|
||||
? contactsManager.getFriendWithAddress(address: conversationsListViewModel.conversationsList[index].participants.first!.address!)
|
||||
: nil
|
||||
HStack {
|
||||
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, withPresence: false)
|
||||
|
||||
|
||||
if LinphoneUtils.isChatRoomAGroup(chatRoom: conversationsListViewModel.conversationsList[index]) {
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: conversationsListViewModel.conversationsList[index].subject!,
|
||||
lastName: conversationsListViewModel.conversationsList[index].subject!.components(separatedBy: " ").count > 1
|
||||
? conversationsListViewModel.conversationsList[index].subject!.components(separatedBy: " ")[1]
|
||||
: ""))
|
||||
.resizable()
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(Circle())
|
||||
} else 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())
|
||||
}
|
||||
} else {
|
||||
if conversationsListViewModel.conversationsList[index].participants.first != nil
|
||||
&& conversationsListViewModel.conversationsList[index].participants.first!.address != nil {
|
||||
if conversationsListViewModel.conversationsList[index].participants.first!.address!.displayName != nil {
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: conversationsListViewModel.conversationsList[index].participants.first!.address!.displayName!,
|
||||
lastName: conversationsListViewModel.conversationsList[index].participants.first!.address!.displayName!.components(separatedBy: " ").count > 1
|
||||
? conversationsListViewModel.conversationsList[index].participants.first!.address!.displayName!.components(separatedBy: " ")[1]
|
||||
: ""))
|
||||
.resizable()
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(Circle())
|
||||
|
||||
} else {
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: conversationsListViewModel.conversationsList[index].participants.first!.address!.username ?? "Username Error",
|
||||
lastName: conversationsListViewModel.conversationsList[index].participants.first!.address!.username!.components(separatedBy: " ").count > 1
|
||||
? conversationsListViewModel.conversationsList[index].participants.first!.address!.username!.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(spacing: 0) {
|
||||
Spacer()
|
||||
|
||||
if LinphoneUtils.isChatRoomAGroup(chatRoom: conversationsListViewModel.conversationsList[index]) {
|
||||
Text(conversationsListViewModel.conversationsList[index].subject ?? "No Subject")
|
||||
.foregroundStyle(Color.grayMain2c800)
|
||||
.if(conversationsListViewModel.conversationsList[index].unreadMessagesCount > 0) { view in
|
||||
view.default_text_style_700(styleSize: 14)
|
||||
}
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
} else if addressFriend != nil {
|
||||
Text(addressFriend!.name!)
|
||||
.foregroundStyle(Color.grayMain2c800)
|
||||
.if(conversationsListViewModel.conversationsList[index].unreadMessagesCount > 0) { view in
|
||||
view.default_text_style_700(styleSize: 14)
|
||||
}
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
} else {
|
||||
if conversationsListViewModel.conversationsList[index].participants.first != nil && conversationsListViewModel.conversationsList[index].participants.first!.address != nil {
|
||||
Text(conversationsListViewModel.conversationsList[index].participants.first!.address!.displayName != nil
|
||||
? conversationsListViewModel.conversationsList[index].participants.first!.address!.displayName!
|
||||
: conversationsListViewModel.conversationsList[index].participants.first!.address!.username!)
|
||||
.foregroundStyle(Color.grayMain2c800)
|
||||
.if(conversationsListViewModel.conversationsList[index].unreadMessagesCount > 0) { view in
|
||||
view.default_text_style_700(styleSize: 14)
|
||||
}
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
}
|
||||
}
|
||||
|
||||
let text = conversationsListViewModel.conversationsList[index].lastMessageInHistory?.contents.first(where: {$0.isText == true})?.utf8Text ?? ""
|
||||
|
||||
Text(text)
|
||||
.foregroundStyle(Color.grayMain2c400)
|
||||
.if(conversationsListViewModel.conversationsList[index].unreadMessagesCount > 0) { view in
|
||||
view.default_text_style_700(styleSize: 14)
|
||||
}
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
VStack(alignment: .trailing, spacing: 0) {
|
||||
Spacer()
|
||||
|
||||
HStack {
|
||||
if conversationsListViewModel.conversationsList[index].currentParams != nil
|
||||
&& !conversationsListViewModel.conversationsList[index].currentParams!.encryptionEnabled {
|
||||
Image("warning-circle")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.redDanger500)
|
||||
.frame(width: 18, height: 18, alignment: .trailing)
|
||||
}
|
||||
|
||||
if conversationsListViewModel.conversationsList[index].lastMessageInHistory != nil {
|
||||
Text(conversationsListViewModel.getCallTime(startDate: conversationsListViewModel.conversationsList[index].lastMessageInHistory!.time))
|
||||
.foregroundStyle(Color.grayMain2c400)
|
||||
.default_text_style(styleSize: 14)
|
||||
.lineLimit(1)
|
||||
} else {
|
||||
Text(conversationsListViewModel.getCallTime(startDate: conversationsListViewModel.conversationsList[index].lastUpdateTime))
|
||||
.foregroundStyle(Color.grayMain2c400)
|
||||
.default_text_style(styleSize: 14)
|
||||
.lineLimit(1)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
HStack {
|
||||
if conversationsListViewModel.conversationsList[index].lastMessageInHistory != nil
|
||||
&& conversationsListViewModel.conversationsList[index].lastMessageInHistory!.isOutgoing == true {
|
||||
let imageName = LinphoneUtils.getChatIconState(chatState: conversationsListViewModel.conversationsList[index].lastMessageInHistory!.state)
|
||||
Image(imageName)
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.orangeMain500)
|
||||
.frame(width: 18, height: 18, alignment: .trailing)
|
||||
}
|
||||
|
||||
if conversationsListViewModel.conversationsList[index].unreadMessagesCount > 0 {
|
||||
HStack {
|
||||
Text(
|
||||
conversationsListViewModel.conversationsList[index].unreadMessagesCount < 99
|
||||
? String(conversationsListViewModel.conversationsList[index].unreadMessagesCount)
|
||||
: "99+"
|
||||
)
|
||||
.foregroundStyle(.white)
|
||||
.default_text_style(styleSize: 10)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.frame(width: 18, height: 18)
|
||||
.background(Color.redDanger500)
|
||||
.cornerRadius(50)
|
||||
}
|
||||
|
||||
if !(conversationsListViewModel.conversationsList[index].lastMessageInHistory != nil
|
||||
&& conversationsListViewModel.conversationsList[index].lastMessageInHistory!.isOutgoing == true)
|
||||
&& conversationsListViewModel.conversationsList[index].unreadMessagesCount == 0 {
|
||||
Text("")
|
||||
.frame(width: 18, height: 18, alignment: .trailing)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.trailing, 10)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.borderless)
|
||||
.listRowInsets(EdgeInsets(top: 6, leading: 20, bottom: 6, trailing: 20))
|
||||
.listRowSeparator(.hidden)
|
||||
.background(.white)
|
||||
.onTapGesture {
|
||||
}
|
||||
.onLongPressGesture(minimumDuration: 0.2) {
|
||||
}
|
||||
}
|
||||
}
|
||||
.listStyle(.plain)
|
||||
.overlay(
|
||||
VStack {
|
||||
if conversationsListViewModel.conversationsList.isEmpty {
|
||||
Spacer()
|
||||
Image("illus-belledonne")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.clipped()
|
||||
.padding(.all)
|
||||
Text("No conversation for the moment...")
|
||||
.default_text_style_800(styleSize: 16)
|
||||
Spacer()
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.padding(.all)
|
||||
)
|
||||
}
|
||||
.navigationTitle("")
|
||||
.navigationBarHidden(true)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ConversationsListFragment(conversationsListViewModel: ConversationsListViewModel())
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* 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 ConversationsListViewModel: ObservableObject {
|
||||
|
||||
private var coreContext = CoreContext.shared
|
||||
|
||||
@Published var conversationsList: [ChatRoom] = []
|
||||
@Published var unreadMessages: Int = 0
|
||||
|
||||
init() {
|
||||
computeChatRoomsList(filter: "")
|
||||
updateUnreadMessagesCount()
|
||||
}
|
||||
|
||||
func computeChatRoomsList(filter: String) {
|
||||
coreContext.doOnCoreQueue { core in
|
||||
let account = core.defaultAccount
|
||||
let chatRooms = account?.chatRooms != nil ? account!.chatRooms : core.chatRooms
|
||||
|
||||
chatRooms.forEach { chatRoom in
|
||||
//let disabledBecauseNotSecured = (account?.isInSecureMode() == true && !chatRoom.hasCapability) ? Capabilities.Encrypted.toInt() : 0
|
||||
|
||||
if filter.isEmpty {
|
||||
//val model = ConversationModel(chatRoom, disabledBecauseNotSecured)
|
||||
self.conversationsList.append(chatRoom)
|
||||
}
|
||||
/*
|
||||
else {
|
||||
val participants = chatRoom.participants
|
||||
val found = participants.find {
|
||||
// Search in address but also in contact name if exists
|
||||
val model =
|
||||
coreContext.contactsManager.getContactAvatarModelForAddress(it.address)
|
||||
model.contactName?.contains(
|
||||
filter,
|
||||
ignoreCase = true
|
||||
) == true || it.address.asStringUriOnly().contains(
|
||||
filter,
|
||||
ignoreCase = true
|
||||
)
|
||||
}
|
||||
if (
|
||||
found != null ||
|
||||
chatRoom.peerAddress.asStringUriOnly().contains(filter, ignoreCase = true) ||
|
||||
chatRoom.subject.orEmpty().contains(filter, ignoreCase = true)
|
||||
) {
|
||||
val model = ConversationModel(chatRoom, disabledBecauseNotSecured)
|
||||
list.add(model)
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getCallTime(startDate: time_t) -> String {
|
||||
let timeInterval = TimeInterval(startDate)
|
||||
|
||||
let myNSDate = Date(timeIntervalSince1970: timeInterval)
|
||||
|
||||
if Calendar.current.isDateInToday(myNSDate) {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = Locale.current.identifier == "fr_FR" ? "HH:mm" : "h:mm a"
|
||||
return formatter.string(from: myNSDate)
|
||||
} else if Calendar.current.isDateInYesterday(myNSDate) {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = Locale.current.identifier == "fr_FR" ? "HH:mm" : "h:mm a"
|
||||
return "Yesterday"
|
||||
} else if Calendar.current.isDate(myNSDate, equalTo: .now, toGranularity: .year) {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = Locale.current.identifier == "fr_FR" ? "dd/MM" : "MM/dd"
|
||||
return formatter.string(from: myNSDate)
|
||||
} else {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = Locale.current.identifier == "fr_FR" ? "dd/MM/yy" : "MM/dd/yy"
|
||||
return formatter.string(from: myNSDate)
|
||||
}
|
||||
}
|
||||
|
||||
func updateUnreadMessagesCount() {
|
||||
coreContext.doOnCoreQueue { core in
|
||||
let account = core.defaultAccount
|
||||
if account != nil {
|
||||
let count = account?.unreadChatMessageCount != nil ? account!.unreadChatMessageCount : core.unreadChatMessageCount
|
||||
self.unreadMessages = count
|
||||
} else {
|
||||
self.unreadMessages = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ struct HistoryListFragment: View {
|
|||
|
||||
if addressFriend != nil && addressFriend!.photo != nil && !addressFriend!.photo!.isEmpty {
|
||||
if contactAvatarModel != nil {
|
||||
Avatar(contactAvatarModel: contactAvatarModel!, avatarSize: 45)
|
||||
Avatar(contactAvatarModel: contactAvatarModel!, avatarSize: 50)
|
||||
} else {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class HistoryListViewModel: ObservableObject {
|
|||
|
||||
var callLogsAddressToDelete = ""
|
||||
var callLogSubscription: AnyCancellable?
|
||||
|
||||
init() {
|
||||
computeCallLogsList()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ struct Avatar: View {
|
|||
Image(contactAvatarModel.presenceStatus == .Online ? "presence-online" : "presence-busy")
|
||||
.resizable()
|
||||
.frame(width: avatarSize/4, height: avatarSize/4)
|
||||
.padding(.trailing, avatarSize == 45 ? 1 : 3)
|
||||
.padding(.bottom, avatarSize == 45 ? 1 : 3)
|
||||
.padding(.trailing, avatarSize == 50 ? 1 : 3)
|
||||
.padding(.bottom, avatarSize == 50 ? 1 : 3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
46
Linphone/Utils/LinphoneUtils.swift
Normal file
46
Linphone/Utils/LinphoneUtils.swift
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* 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 LinphoneUtils: NSObject {
|
||||
public class func isChatRoomAGroup(chatRoom: ChatRoom) -> Bool {
|
||||
let oneToOne = chatRoom.hasCapability(mask: ChatRoom.Capabilities.OneToOne.rawValue)
|
||||
let conference = chatRoom.hasCapability(mask: ChatRoom.Capabilities.Conference.rawValue)
|
||||
return !oneToOne && conference
|
||||
}
|
||||
|
||||
public class func getChatIconState(chatState: ChatMessage.State) -> String {
|
||||
return switch chatState {
|
||||
case ChatMessage.State.Displayed, ChatMessage.State.FileTransferDone:
|
||||
"checks"
|
||||
case ChatMessage.State.DeliveredToUser:
|
||||
"check"
|
||||
case ChatMessage.State.Delivered:
|
||||
"envelope-simple"
|
||||
case ChatMessage.State.NotDelivered, ChatMessage.State.FileTransferError:
|
||||
"warning-circle"
|
||||
case ChatMessage.State.InProgress, ChatMessage.State.FileTransferInProgress:
|
||||
"animated-in-progress"
|
||||
default:
|
||||
"animated-in-progress"
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue