Prevent editing when contact is read-only (LDAP contacts)

This commit is contained in:
Benoit Martins 2025-10-28 16:13:57 +01:00
parent 9559701a5e
commit aefa334038
7 changed files with 188 additions and 179 deletions

View file

@ -211,33 +211,11 @@ struct ContactInnerActionsFragment: View {
.background(Color.gray100)
VStack(spacing: 0) {
if !contactAvatarModel.editable {
Button {
actionEditButton()
} label: {
HStack {
Image("pencil-simple")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.grayMain2c600)
.frame(width: 25, height: 25)
.padding(.all, 10)
Text("contact_details_edit")
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1)
.fixedSize(horizontal: false, vertical: true)
Spacer()
}
.padding(.vertical, 15)
.padding(.horizontal, 20)
}
} else {
NavigationLink(destination: EditContactFragment(
contactAvatarModel: contactAvatarModel,
isShowEditContactFragment: $isShowEditContactFragmentInContactDetails,
isShowDismissPopup: $isShowDismissPopup)) {
if !contactAvatarModel.isReadOnly {
if !contactAvatarModel.editable {
Button {
actionEditButton()
} label: {
HStack {
Image("pencil-simple")
.renderingMode(.template)
@ -255,47 +233,71 @@ struct ContactInnerActionsFragment: View {
}
.padding(.vertical, 15)
.padding(.horizontal, 20)
}
} else {
NavigationLink(destination: EditContactFragment(
contactAvatarModel: contactAvatarModel,
isShowEditContactFragment: $isShowEditContactFragmentInContactDetails,
isShowDismissPopup: $isShowDismissPopup)) {
HStack {
Image("pencil-simple")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.grayMain2c600)
.frame(width: 25, height: 25)
.padding(.all, 10)
Text("contact_details_edit")
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1)
.fixedSize(horizontal: false, vertical: true)
Spacer()
}
.padding(.vertical, 15)
.padding(.horizontal, 20)
}
.simultaneousGesture(
TapGesture().onEnded {
isShowEditContactFragmentInContactDetails = true
}
)
}
VStack {
Divider()
}
.padding(.horizontal)
Button {
contactsListViewModel.toggleStarredSelectedFriend()
} label: {
HStack {
Image(contactAvatarModel.starred == true ? "heart-fill" : "heart")
.renderingMode(.template)
.resizable()
.foregroundStyle(contactAvatarModel.starred == true ? Color.redDanger500 : Color.grayMain2c500)
.frame(width: 25, height: 25)
.padding(.all, 10)
Text(contactAvatarModel.starred == true
? "contact_details_remove_from_favourites"
: "contact_details_add_to_favourites")
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1)
.fixedSize(horizontal: false, vertical: true)
Spacer()
}
.padding(.vertical, 15)
.padding(.horizontal, 20)
VStack {
Divider()
}
.padding(.horizontal)
Button {
contactsListViewModel.toggleStarredSelectedFriend()
} label: {
HStack {
Image(contactAvatarModel.starred == true ? "heart-fill" : "heart")
.renderingMode(.template)
.resizable()
.foregroundStyle(contactAvatarModel.starred == true ? Color.redDanger500 : Color.grayMain2c500)
.frame(width: 25, height: 25)
.padding(.all, 10)
Text(contactAvatarModel.starred == true
? "contact_details_remove_from_favourites"
: "contact_details_add_to_favourites")
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1)
.fixedSize(horizontal: false, vertical: true)
Spacer()
}
.padding(.vertical, 15)
.padding(.horizontal, 20)
}
VStack {
Divider()
}
.padding(.horizontal)
}
VStack {
Divider()
}
.padding(.horizontal)
Button {
showShareSheet.toggle()
} label: {
@ -318,32 +320,34 @@ struct ContactInnerActionsFragment: View {
.padding(.horizontal, 20)
}
VStack {
Divider()
}
.padding(.horizontal)
Button {
isShowDeletePopup.toggle()
} label: {
HStack {
Image("trash-simple")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.redDanger500)
.frame(width: 25, height: 25)
.padding(.all, 10)
Text("contact_details_delete")
.foregroundStyle(Color.redDanger500)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1)
.fixedSize(horizontal: false, vertical: true)
Spacer()
if !contactAvatarModel.isReadOnly {
VStack {
Divider()
}
.padding(.horizontal)
Button {
isShowDeletePopup.toggle()
} label: {
HStack {
Image("trash-simple")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.redDanger500)
.frame(width: 25, height: 25)
.padding(.all, 10)
Text("contact_details_delete")
.foregroundStyle(Color.redDanger500)
.default_text_style(styleSize: 14)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(1)
.fixedSize(horizontal: false, vertical: true)
Spacer()
}
.padding(.vertical, 15)
.padding(.horizontal, 20)
}
.padding(.vertical, 15)
.padding(.horizontal, 20)
}
}
.background(.white)

View file

@ -72,24 +72,11 @@ struct ContactInnerFragment: View {
Spacer()
if !contactAvatarModel.editable {
Button(action: {
print("nativeUrinativeUri 00 \(contactAvatarModel.nativeUri)")
editNativeContact()
}, label: {
Image("pencil-simple")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.orangeMain500)
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
.padding(.top, 2)
})
} else {
NavigationLink(destination: EditContactFragment(
contactAvatarModel: contactAvatarModel,
isShowEditContactFragment: $isShowEditContactFragmentInContactDetails,
isShowDismissPopup: $isShowDismissPopup)) {
if !contactAvatarModel.isReadOnly {
if !contactAvatarModel.editable {
Button(action: {
editNativeContact()
}, label: {
Image("pencil-simple")
.renderingMode(.template)
.resizable()
@ -97,13 +84,26 @@ struct ContactInnerFragment: View {
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
.padding(.top, 2)
}
.simultaneousGesture(
TapGesture().onEnded {
print("nativeUrinativeUri 11 \(contactAvatarModel.nativeUri)")
isShowEditContactFragmentInContactDetails = true
})
} else {
NavigationLink(destination: EditContactFragment(
contactAvatarModel: contactAvatarModel,
isShowEditContactFragment: $isShowEditContactFragmentInContactDetails,
isShowDismissPopup: $isShowDismissPopup)) {
Image("pencil-simple")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.orangeMain500)
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
.padding(.top, 2)
}
)
.simultaneousGesture(
TapGesture().onEnded {
isShowEditContactFragmentInContactDetails = true
}
)
}
}
}
.frame(maxWidth: .infinity)

View file

@ -52,7 +52,6 @@ struct ContactListBottomSheet: View {
.padding(.trailing)
}
Spacer()
Button {
UIPasteboard.general.setValue(
contactsListViewModel.stringToCopy.prefix(4) == "sip:"

View file

@ -41,7 +41,7 @@ struct ContactsFragment: View {
showingSheet: $showingSheet,
showShareSheet: $showShareSheet
)
.presentationDetents([.fraction(0.3)])
.presentationDetents(contactsListViewModel.selectedFriend?.isReadOnly == true ? [.fraction(0.1)] : [.fraction(0.3)])
}
.sheet(isPresented: $showShareSheet) {
ShareSheet(friendToShare: contactsListViewModel.selectedFriendToShare!)

View file

@ -55,49 +55,51 @@ struct ContactsListBottomSheet: View {
.padding(.trailing)
}
Spacer()
Button {
self.contactsListViewModel.toggleStarredSelectedFriend()
if !contactsListViewModel.selectedFriend!.isReadOnly {
Spacer()
if #available(iOS 16.0, *) {
if idiom != .pad {
showingSheet.toggle()
Button {
self.contactsListViewModel.toggleStarredSelectedFriend()
if #available(iOS 16.0, *) {
if idiom != .pad {
showingSheet.toggle()
} else {
showingSheet.toggle()
dismiss()
}
} else {
showingSheet.toggle()
dismiss()
dismiss()
}
} else {
showingSheet.toggle()
dismiss()
} label: {
HStack {
Image(contactsListViewModel.selectedFriend != nil && contactsListViewModel.selectedFriend!.starred == true ? "heart-fill" : "heart")
.renderingMode(.template)
.resizable()
.foregroundStyle(
contactsListViewModel.selectedFriend != nil && contactsListViewModel.selectedFriend!.starred == true
? Color.redDanger500
: Color.grayMain2c500
)
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
Text(contactsListViewModel.selectedFriend != nil && contactsListViewModel.selectedFriend!.starred == true
? "contact_details_remove_from_favourites"
: "contact_details_add_to_favourites")
.default_text_style(styleSize: 16)
Spacer()
}
.frame(maxHeight: .infinity)
}
} label: {
HStack {
Image(contactsListViewModel.selectedFriend != nil && contactsListViewModel.selectedFriend!.starred == true ? "heart-fill" : "heart")
.renderingMode(.template)
.resizable()
.foregroundStyle(
contactsListViewModel.selectedFriend != nil && contactsListViewModel.selectedFriend!.starred == true
? Color.redDanger500
: Color.grayMain2c500
)
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
Text(contactsListViewModel.selectedFriend != nil && contactsListViewModel.selectedFriend!.starred == true
? "contact_details_remove_from_favourites"
: "contact_details_add_to_favourites")
.default_text_style(styleSize: 16)
Spacer()
.padding(.horizontal, 30)
.background(Color.gray100)
VStack {
Divider()
}
.frame(maxHeight: .infinity)
.frame(maxWidth: .infinity)
}
.padding(.horizontal, 30)
.background(Color.gray100)
VStack {
Divider()
}
.frame(maxWidth: .infinity)
Button {
if #available(iOS 16.0, *) {
@ -135,45 +137,46 @@ struct ContactsListBottomSheet: View {
.padding(.horizontal, 30)
.background(Color.gray100)
VStack {
Divider()
}
.frame(maxWidth: .infinity)
Button {
if contactsListViewModel.selectedFriend != nil {
isShowDeletePopup.toggle()
if !contactsListViewModel.selectedFriend!.isReadOnly {
VStack {
Divider()
}
.frame(maxWidth: .infinity)
if #available(iOS 16.0, *) {
if idiom != .pad {
showingSheet.toggle()
Button {
if contactsListViewModel.selectedFriend != nil {
isShowDeletePopup.toggle()
}
if #available(iOS 16.0, *) {
if idiom != .pad {
showingSheet.toggle()
} else {
showingSheet.toggle()
dismiss()
}
} else {
showingSheet.toggle()
dismiss()
}
} else {
showingSheet.toggle()
dismiss()
} label: {
HStack {
Image("trash-simple")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.redDanger500)
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
Text("contact_details_delete")
.foregroundStyle(Color.redDanger500)
.default_text_style(styleSize: 16)
Spacer()
}
.frame(maxHeight: .infinity)
}
} label: {
HStack {
Image("trash-simple")
.renderingMode(.template)
.resizable()
.foregroundStyle(Color.redDanger500)
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
Text("contact_details_delete")
.foregroundStyle(Color.redDanger500)
.default_text_style(styleSize: 16)
Spacer()
}
.frame(maxHeight: .infinity)
.padding(.horizontal, 30)
.background(Color.gray100)
}
.padding(.horizontal, 30)
.background(Color.gray100)
}
.background(Color.gray100)
.frame(maxWidth: .infinity)

View file

@ -33,6 +33,7 @@ class ContactAvatarModel: ObservableObject, Identifiable {
var nativeUri: String = ""
var editable: Bool = true
var isReadOnly: Bool = false
var withPresence: Bool?
@Published var starred: Bool = false
@ -72,6 +73,7 @@ class ContactAvatarModel: ObservableObject, Identifiable {
}
let nativeUriTmp = friend?.nativeUri ?? ""
let editableTmp = friend?.friendList?.type == .CardDAV || nativeUriTmp.isEmpty
let isReadOnlyTmp = (friend?.isReadOnly == true) || (friend?.inList() == false)
let withPresenceTmp = withPresence
let starredTmp = friend?.starred ?? false
let vcardTmp = friend?.vcard ?? nil
@ -117,6 +119,7 @@ class ContactAvatarModel: ObservableObject, Identifiable {
self.phoneNumbersWithLabel = phoneNumbersWithLabelTmp
self.nativeUri = nativeUriTmp
self.editable = editableTmp
self.isReadOnly = isReadOnlyTmp
self.withPresence = withPresenceTmp
self.starred = starredTmp
self.vcard = vcardTmp

View file

@ -150,8 +150,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-protobuf.git",
"state" : {
"revision" : "c6fe6442e6a64250495669325044052e113e990c",
"version" : "1.32.0"
"revision" : "97bb244f7a575a419ebc8f3c2d33f2feb9c8f7f2",
"version" : "1.33.1"
}
}
],