Add Meeting invite

This commit is contained in:
Benoit Martins 2024-10-16 17:10:54 +02:00
parent 27e0757c5f
commit 3203cb3ccc
9 changed files with 206 additions and 30 deletions

View file

@ -1303,6 +1303,40 @@
}
}
},
"conversation_message_meeting_cancelled_label" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Meeting has been cancelled!"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "La réunion a été annulée"
}
}
}
},
"conversation_message_meeting_updated_label" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Meeting has been updated"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "La réunion a été mise à jour"
}
}
}
},
"conversation_reply_to_message_title" : {
"extractionState" : "manual",
"localizations" : {
@ -1384,6 +1418,9 @@
},
"Deny all" : {
},
"Description" : {
},
"Dialer" : {
@ -1818,8 +1855,22 @@
"Meeting added to iPhone calendar" : {
},
"Meeting invite !!" : {
"meeting_waiting_room_join" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Join"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Rejoindre"
}
}
}
},
"Meetings" : {
@ -2238,9 +2289,6 @@
}
}
}
},
"Rejoindre" : {
},
"Remove from favourites" : {

View file

@ -171,8 +171,12 @@ class TelecomManager: ObservableObject {
do {
let meetingAddress = try Factory.Instance.createAddress(addr: address.asStringUriOnly())
meetingWaitingRoomDisplayed = true
meetingWaitingRoomSelected = meetingAddress
DispatchQueue.main.async {
withAnimation {
self.meetingWaitingRoomDisplayed = true
self.meetingWaitingRoomSelected = meetingAddress
}
}
} catch {}
} else {
doCallWithCore(

View file

@ -335,7 +335,7 @@ struct MeetingWaitingRoomFragment: View {
Button(action: {
meetingWaitingRoomViewModel.joinMeeting()
}, label: {
Text("Rejoindre")
Text("meeting_waiting_room_join")
.default_text_style_white_600(styleSize: 20)
.frame(height: 35)
.frame(maxWidth: .infinity)
@ -356,7 +356,7 @@ struct MeetingWaitingRoomFragment: View {
Button(action: {
meetingWaitingRoomViewModel.joinMeeting()
}, label: {
Text("Rejoindre")
Text("meeting_waiting_room_join")
.default_text_style_white_600(styleSize: 20)
.frame(height: 35)
.frame(maxWidth: .infinity)

View file

@ -43,7 +43,7 @@ struct ChatBubbleView: View {
HStack {
if eventLogMessage.eventModel.eventLogType == .ConferenceChatMessage {
VStack {
if !eventLogMessage.message.text.isEmpty || !eventLogMessage.message.attachments.isEmpty {
if !eventLogMessage.message.text.isEmpty || !eventLogMessage.message.attachments.isEmpty || eventLogMessage.message.isIcalendar {
HStack(alignment: .top, content: {
if eventLogMessage.message.isOutgoing {
Spacer()
@ -159,7 +159,7 @@ struct ChatBubbleView: View {
VStack(alignment: eventLogMessage.message.isOutgoing ? .trailing : .leading) {
VStack(alignment: eventLogMessage.message.isOutgoing ? .trailing : .leading) {
if !eventLogMessage.message.attachments.isEmpty {
if !eventLogMessage.message.attachments.isEmpty && !eventLogMessage.message.isIcalendar {
messageAttachments()
}
@ -169,20 +169,129 @@ struct ChatBubbleView: View {
.default_text_style(styleSize: 14)
}
if eventLogMessage.message.isIcalendar {
VStack{
if eventLogMessage.message.isIcalendar && eventLogMessage.message.messageConferenceInfo != nil {
VStack(spacing: 0) {
VStack {
if eventLogMessage.message.messageConferenceInfo!.meetingState != .new {
if eventLogMessage.message.messageConferenceInfo!.meetingState == .updated {
Text("conversation_message_meeting_updated_label")
.foregroundStyle(Color.orangeWarning600)
.default_text_style_600(styleSize: 12)
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.bottom, 5)
} else {
Text("conversation_message_meeting_cancelled_label")
.foregroundStyle(Color.redDanger500)
.default_text_style_600(styleSize: 12)
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.bottom, 5)
}
}
HStack {
VStack(spacing: 0) {
Text(eventLogMessage.message.messageConferenceInfo!.meetingDay)
.default_text_style(styleSize: 16)
Text(eventLogMessage.message.messageConferenceInfo!.meetingDayNumber)
.foregroundStyle(.white)
.default_text_style_800(styleSize: 18)
.lineLimit(1)
.frame(width: 30, height: 30, alignment: .center)
.background(Color.orangeMain500)
.clipShape(Circle())
}
.padding(.all, 10)
.frame(width: 70, height: 70)
.background(.white)
.cornerRadius(15)
.shadow(color: .black.opacity(0.1), radius: 15)
VStack {
HStack {
Image("video-conference")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.grayMain2c600)
.frame(width: 25, height: 25)
Text(eventLogMessage.message.messageConferenceInfo!.meetingSubject)
.default_text_style_800(styleSize: 15)
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading)
}
.frame(maxWidth: .infinity, alignment: .leading)
Text(eventLogMessage.message.messageConferenceInfo!.meetingDate)
.default_text_style_300(styleSize: 14)
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading)
Text(eventLogMessage.message.messageConferenceInfo!.meetingTime)
.default_text_style_300(styleSize: 14)
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(.leading, 5)
}
.frame(maxWidth: .infinity)
}
.padding(.all, 15)
.frame(maxWidth: .infinity)
.background(Color.gray100)
VStack {
VStack(spacing: 2) {
if !eventLogMessage.message.messageConferenceInfo!.meetingDescription.isEmpty {
Text("Description")
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
Text(eventLogMessage.message.messageConferenceInfo!.meetingDescription)
.default_text_style_300(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
}
if eventLogMessage.message.messageConferenceInfo!.meetingState != .cancelled {
HStack {
Image("users")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.grayMain2c600)
.frame(width: 20, height: 20)
Text(eventLogMessage.message.messageConferenceInfo!.meetingParticipants)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
Button(action: {
conversationViewModel.joinMeetingInvite(addressUri: eventLogMessage.message.messageConferenceInfo!.meetingConferenceUri)
}, label: {
Text("meeting_waiting_room_join")
.default_text_style_white_600(styleSize: 14)
})
.padding(.horizontal, 15)
.padding(.vertical, 10)
.background(Color.orangeMain500)
.cornerRadius(60)
}
.padding(.top, !eventLogMessage.message.messageConferenceInfo!.meetingDescription.isEmpty ? 10 : 0)
}
}
.padding(.all,
eventLogMessage.message.messageConferenceInfo!.meetingState != .cancelled
|| !eventLogMessage.message.messageConferenceInfo!.meetingDescription.isEmpty
? 15
: 0
)
.frame(maxWidth: .infinity)
.background(.white)
}
Text("Meeting invite !!")
.foregroundStyle(Color.grayMain2c500)
.default_text_style(styleSize: 12)
.frame(width: geometryProxy.size.width - 110)
.background(.white)
.cornerRadius(10)
}
HStack(alignment: .center) {

View file

@ -27,7 +27,7 @@ public enum MessageConferenceState: Codable {
public struct MessageConferenceInfo: Codable, Identifiable, Hashable {
public let id: UUID
public let meetingConferenceUri: URL
public let meetingConferenceUri: String
public let meetingSubject: String
public let meetingDescription: String
public let meetingState: MessageConferenceState
@ -37,7 +37,7 @@ public struct MessageConferenceInfo: Codable, Identifiable, Hashable {
public let meetingDayNumber: String
public let meetingParticipants: String
public init(id: UUID, meetingConferenceUri: URL, meetingSubject: String, meetingDescription: String, meetingState: MessageConferenceState, meetingDate: String, meetingTime: String, meetingDay: String, meetingDayNumber: String, meetingParticipants: String) {
public init(id: UUID, meetingConferenceUri: String, meetingSubject: String, meetingDescription: String, meetingState: MessageConferenceState, meetingDate: String, meetingTime: String, meetingDay: String, meetingDayNumber: String, meetingParticipants: String) {
self.id = id
self.meetingConferenceUri = meetingConferenceUri
self.meetingSubject = meetingSubject

View file

@ -1915,7 +1915,7 @@ class ConversationViewModel: ObservableObject {
}
func parseConferenceInvite(content: Content) -> MessageConferenceInfo? {
var meetingConferenceUriTmp: URL?
var meetingConferenceUriTmp: String = ""
var meetingSubjectTmp: String = ""
var meetingDescriptionTmp: String = ""
var meetingStateTmp: MessageConferenceState = .new
@ -1930,7 +1930,7 @@ class ConversationViewModel: ObservableObject {
if let conferenceAddress = conferenceInfo.uri {
let conferenceUri = conferenceAddress.asStringUriOnly()
Log.info("Found conference info with URI [\(conferenceUri)] and subject [\(conferenceInfo.subject ?? "")]")
meetingConferenceUriTmp = URL(string: conferenceAddress.asStringUriOnly())
meetingConferenceUriTmp = conferenceAddress.asStringUriOnly()
meetingSubjectTmp = conferenceInfo.subject ?? ""
meetingDescriptionTmp = conferenceInfo.description ?? ""
@ -1949,7 +1949,7 @@ class ConversationViewModel: ObservableObject {
dateFormatter.dateStyle = .full
dateFormatter.timeStyle = .none
meetingDateTmp = dateFormatter.string(from: dateTmp)
meetingDateTmp = dateFormatter.string(from: dateTmp).capitalized
let timeFormatter = DateFormatter()
timeFormatter.dateFormat = Locale.current.identifier == "fr_FR" ? "HH:mm" : "h:mm a"
@ -1962,14 +1962,14 @@ class ConversationViewModel: ObservableObject {
meetingTimeTmp = "\(timeTmp) - \(endTime)"
meetingDayTmp = dateTmp.formatted(Date.FormatStyle().weekday(.abbreviated)).capitalized
meetingDayNumberTmp = dateTmp.formatted(Date.FormatStyle().day(.twoDigits))
meetingDayNumberTmp = dateTmp.formatted(Date.FormatStyle().day(.defaultDigits))
meetingParticipantsTmp = String(conferenceInfo.participantInfos.count)
meetingParticipantsTmp = String(conferenceInfo.participantInfos.count) + " participant" + (conferenceInfo.participantInfos.count > 1 ? "s" : "")
if meetingConferenceUriTmp != nil {
if !meetingConferenceUriTmp.isEmpty {
return MessageConferenceInfo(
id: UUID(),
meetingConferenceUri: meetingConferenceUriTmp!,
meetingConferenceUri: meetingConferenceUriTmp,
meetingSubject: meetingSubjectTmp,
meetingDescription: meetingDescriptionTmp,
meetingState: meetingStateTmp,
@ -1985,6 +1985,14 @@ class ConversationViewModel: ObservableObject {
return nil
}
func joinMeetingInvite(addressUri: String) {
coreContext.doOnCoreQueue { _ in
if let address = try? Factory.Instance.createAddress(addr: addressUri) {
TelecomManager.shared.doCallOrJoinConf(address: address)
}
}
}
}
// swiftlint:enable line_length
// swiftlint:enable type_body_length

View file

@ -357,7 +357,7 @@ struct HistoryContactFragment: View {
.background(Color.grayMain2c200)
.cornerRadius(40)
Text("Rejoindre")
Text("meeting_waiting_room_join")
.default_text_style(styleSize: 14)
.frame(minWidth: 80)
}

View file

@ -299,8 +299,7 @@ struct MeetingFragment: View {
Spacer()
Button(action: {
TelecomManager.shared.meetingWaitingRoomSelected = try? Factory.Instance.createAddress(addr: meetingViewModel.displayedMeeting?.address ?? "")
TelecomManager.shared.meetingWaitingRoomDisplayed = true
meetingViewModel.joinMeeting(addressUri: meetingViewModel.displayedMeeting?.address ?? "")
}, label: {
Text("Join the meeting now")
.bold()

View file

@ -379,6 +379,14 @@ class MeetingViewModel: ObservableObject {
}
})
}
func joinMeeting(addressUri: String) {
CoreContext.shared.doOnCoreQueue { _ in
if let address = try? Factory.Instance.createAddress(addr: addressUri) {
TelecomManager.shared.doCallOrJoinConf(address: address)
}
}
}
}
// swiftlint:enable type_body_length