Add "Encrypted Conversation" banner in chatrooms

This commit is contained in:
Benoit Martins 2025-07-31 17:42:28 +02:00
parent 64a3876a95
commit c6d58693eb
9 changed files with 114 additions and 1 deletions

View file

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "lock-simple-bold.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M208,76H180V56A52,52,0,0,0,76,56V76H48A20,20,0,0,0,28,96V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V96A20,20,0,0,0,208,76ZM100,56a28,28,0,0,1,56,0V76H100ZM204,204H52V100H204Z"></path></svg>

After

Width:  |  Height:  |  Size: 299 B

View file

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "lock-simple.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Z"></path></svg>

After

Width:  |  Height:  |  Size: 299 B

View file

@ -414,6 +414,8 @@
"conversation_composing_label_multiple" = "%@ píšou…";
"conversation_composing_label_single" = "%@ píše…";
"conversation_end_to_end_encrypted_bottom_sheet_link" = "https://linphone.org/en/features/#security";
"conversation_end_to_end_encrypted_event_title" = "Koncově šifrovaná konverzace";
"conversation_end_to_end_encrypted_event_subtitle" = "Zprávy v této konverzaci jsou koncově šifrovány. Dešifrovat je může pouze váš protějšek.";
"conversation_event_device_added" = "Nové zařízení pro %@";
"conversation_event_participant_added" = "%@ se připojil";
"conversation_event_subject_changed" = "Nový předmět: %@";

View file

@ -201,6 +201,8 @@
"conversation_dialog_set_subject" = "Set conversation subject";
"conversation_dialog_subject_hint" = "Conversation subject";
"conversation_end_to_end_encrypted_bottom_sheet_link" = "https://linphone.org/en/features/#security";
"conversation_end_to_end_encrypted_event_title" = "End-to-end encrypted conversation";
"conversation_end_to_end_encrypted_event_subtitle" = "Messages in this conversation are e2e encrypted. Only your correspondent can decrypt them.";
"conversation_ephemeral_messages_duration_disabled" = "Disabled";
"conversation_ephemeral_messages_duration_multiple_days" = "%d days";
"conversation_ephemeral_messages_duration_one_day" = "1 day";

View file

@ -201,6 +201,8 @@
"conversation_dialog_set_subject" = "Nommer la conversation";
"conversation_dialog_subject_hint" = "Nom de la conversation";
"conversation_end_to_end_encrypted_bottom_sheet_link" = "https://linphone.org/en/features/#security";
"conversation_end_to_end_encrypted_event_title" = "Conversation chiffrée de bout en bout";
"conversation_end_to_end_encrypted_event_subtitle" = "Les messages de cette conversation sont chiffrés de bout en bout. Seul votre correspondant peut les déchiffrer.";
"conversation_ephemeral_messages_duration_disabled" = "Désactiver";
"conversation_ephemeral_messages_duration_multiple_days" = "%d jours";
"conversation_ephemeral_messages_duration_one_day" = "1 jour";

View file

@ -424,6 +424,8 @@
"conversation_composing_label_multiple" = "%@ скомпоновано…";
"conversation_composing_label_single" = "%@ скомпоновано…";
"conversation_end_to_end_encrypted_bottom_sheet_link" = "https://linphone.org/en/features/#security";
"conversation_end_to_end_encrypted_event_title" = "Наскрізне шифрування розмови";
"conversation_end_to_end_encrypted_event_subtitle" = "Повідомлення в цій розмові зашифровані за методом електронного шифрування (e2e). Розшифрувати їх може лише ваш співрозмовник.";
"conversation_event_admin_set" = "%@ є адміном";
"conversation_event_admin_unset" = "%@ більше не є адміном";
"conversation_event_ephemeral_messages_lifetime_changed" = "Термін дії тимчасових повідомлень тепер %@";

View file

@ -135,6 +135,13 @@ struct UIList: UIViewRepresentable {
tableView.backgroundColor = UIColor(.white)
tableView.scrollsToTop = true
if SharedMainViewModel.shared.displayedConversation != nil && SharedMainViewModel.shared.displayedConversation!.encryptionEnabled {
let footerView = Self.makeFooterView()
footerView.frame = CGRect(x: 0, y: 0, width: tableView.bounds.width, height: 120)
footerView.transform = CGAffineTransformMakeScale(1, -1)
tableView.tableFooterView = footerView
}
// Create the floating UIButton
let button = FloatingButton(frame: CGRect(x: 0, y: 0, width: 60, height: 60))
button.translatesAutoresizingMaskIntoConstraints = false
@ -172,6 +179,47 @@ struct UIList: UIViewRepresentable {
return containerView
}
static func makeFooterView() -> UIView {
let host = UIHostingController(
rootView:
VStack {
HStack {
Image("lock-simple-bold")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.blueInfo500)
.frame(width: 25, height: 25)
.padding(10)
VStack(spacing: 5) {
Text("conversation_end_to_end_encrypted_event_title")
.foregroundStyle(Color.blueInfo500)
.default_text_style_700(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.multilineTextAlignment(.leading)
Text("conversation_end_to_end_encrypted_event_subtitle")
.foregroundStyle(Color.gray400)
.default_text_style(styleSize: 12)
.frame(maxWidth: .infinity, alignment: .leading)
.multilineTextAlignment(.leading)
}
}
.padding(10)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.inset(by: 0.5)
.stroke(Color.blueInfo500, lineWidth: 0.5)
)
.padding(10)
}
.frame(height: 120)
)
host.view.backgroundColor = .clear
return host.view
}
// func updateUIView(_ tableView: UITableView, context: Context) {
func updateUIView(_ uiView: UIView, context: Context) {
if let button = uiView.viewWithTag(102) as? FloatingButton {
@ -422,10 +470,11 @@ struct UIList: UIViewRepresentable {
}
func progressView(_ section: Int) -> UIView? {
if section > parent.conversationViewModel.conversationMessagesSection.count
if section < parent.conversationViewModel.conversationMessagesSection.count
&& parent.conversationViewModel.conversationMessagesSection[section].rows.count < parent.conversationViewModel.displayedConversationHistorySize {
let header = UIHostingController(rootView:
ProgressView()
.frame(height: 50)
.frame(idealWidth: .infinity, maxWidth: .infinity, alignment: .center)
).view
header?.backgroundColor = UIColor(.white)
@ -516,6 +565,18 @@ struct UIList: UIViewRepresentable {
return configuration
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
if section == tableView.numberOfSections - 1 {
let contentHeight = tableView.contentSize.height
let tableHeight = tableView.frame.height
let progressViewDisplayed = section < parent.conversationViewModel.conversationMessagesSection.count
&& parent.conversationViewModel.conversationMessagesSection[section].rows.count < parent.conversationViewModel.displayedConversationHistorySize
let extraSpace = max(progressViewDisplayed ? 50 : 0, tableHeight - contentHeight - 20)
return extraSpace
}
return 0
}
}
}