@ -216,521 +216,523 @@ class ThreadSettingsViewModel: SessionTableViewModel, NavigationItemSource, Navi
disappearingMessagesConfig : disappearingMessagesConfig
disappearingMessagesConfig : disappearingMessagesConfig
)
)
}
}
. mapWithPrevious { [ weak self , dependencies ] previous , current -> [ SectionModel ] in
. compactMapWithPrevious { [ weak self ] prev , current -> [ SectionModel ] ? in self ? . content ( prev , current ) }
// I f w e d o n ' t g e t a ` S e s s i o n T h r e a d V i e w M o d e l ` t h e n i t m e a n s t h e t h r e a d w a s p r o b a b l y d e l e t e d
// s o d i s m i s s t h e s c r e e n
private func content ( _ previous : State ? , _ current : State ) -> [ SectionModel ] {
guard let threadViewModel : SessionThreadViewModel = current . threadViewModel else {
// I f w e d o n ' t g e t a ` S e s s i o n T h r e a d V i e w M o d e l ` t h e n i t m e a n s t h e t h r e a d w a s p r o b a b l y d e l e t e d
self ? . dismissScreen ( type : . popToRoot )
// s o d i s m i s s t h e s c r e e n
return [ ]
guard let threadViewModel : SessionThreadViewModel = current . threadViewModel else {
}
self . dismissScreen ( type : . popToRoot )
return [ ]
let currentUserIsClosedGroupMember : Bool = (
}
(
threadViewModel . threadVariant = = . legacyGroup ||
let currentUserIsClosedGroupMember : Bool = (
threadViewModel . threadVariant = = . group
(
) &&
threadViewModel . threadVariant = = . legacyGroup ||
threadViewModel . currentUserIsClosedGroupMember = = true
threadViewModel . threadVariant = = . group
)
) &&
let currentUserIsClosedGroupAdmin : Bool = (
threadViewModel . currentUserIsClosedGroupMember = = true
(
)
threadViewModel . threadVariant = = . legacyGroup ||
let currentUserIsClosedGroupAdmin : Bool = (
threadViewModel . threadVariant = = . group
(
) &&
threadViewModel . threadVariant = = . legacyGroup ||
threadViewModel . currentUserIsClosedGroupAdmin = = true
threadViewModel . threadVariant = = . group
)
) &&
let editIcon : UIImage ? = UIImage ( named : " icon_edit " )
threadViewModel . currentUserIsClosedGroupAdmin = = true
)
return [
let editIcon : UIImage ? = UIImage ( named : " icon_edit " )
SectionModel (
model : . conversationInfo ,
return [
elements : [
SectionModel (
SessionCell . Info (
model : . conversationInfo ,
id : . avatar ,
elements : [
accessory : . profile (
SessionCell . Info (
id : threadViewModel . id ,
id : . avatar ,
size : . hero ,
accessory : . profile (
threadVariant : threadViewModel . threadVariant ,
id : threadViewModel . id ,
customImageData : threadViewModel . openGroupProfilePictureData ,
size : . hero ,
profile : threadViewModel . profile ,
threadVariant : threadViewModel . threadVariant ,
profileIcon : . none ,
customImageData : threadViewModel . openGroupProfilePictureData ,
additionalProfile : threadViewModel . additionalProfile ,
profile : threadViewModel . profile ,
additionalProfileIcon : . none ,
profileIcon : . none ,
accessibility : nil
additionalProfile : threadViewModel . additionalProfile ,
) ,
additionalProfileIcon : . none ,
styling : SessionCell . StyleInfo (
accessibility : nil
alignment : . centerHugging ,
) ,
customPadding : SessionCell . Padding ( bottom : Values . smallSpacing ) ,
styling : SessionCell . StyleInfo (
backgroundStyle : . noBackground
alignment : . centerHugging ,
customPadding : SessionCell . Padding ( bottom : Values . smallSpacing ) ,
backgroundStyle : . noBackground
) ,
onTap : { [ weak self ] in self ? . viewProfilePicture ( threadViewModel : threadViewModel ) }
) ,
SessionCell . Info (
id : . nickname ,
leftAccessory : ( threadViewModel . threadVariant != . contact ? nil :
. icon (
editIcon ? . withRenderingMode ( . alwaysTemplate ) ,
size : . fit ,
customTint : . textSecondary
)
) ,
title : SessionCell . TextInfo (
threadViewModel . displayName ,
font : . titleLarge ,
alignment : . center ,
editingPlaceholder : " CONTACT_NICKNAME_PLACEHOLDER " . localized ( ) ,
interaction : ( threadViewModel . threadVariant = = . contact ? . editable : . none )
) ,
styling : SessionCell . StyleInfo (
alignment : . centerHugging ,
customPadding : SessionCell . Padding (
top : Values . smallSpacing ,
trailing : ( threadViewModel . threadVariant != . contact ?
nil :
- ( ( ( editIcon ? . size . width ? ? 0 ) + ( Values . smallSpacing * 2 ) ) / 2 )
) ,
bottom : ( threadViewModel . threadVariant != . contact ?
nil :
Values . smallSpacing
) ,
interItem : 0
) ,
) ,
onTap : { self ? . viewProfilePicture ( threadViewModel : threadViewModel ) }
backgroundStyle: . noBackground
) ,
) ,
accessibility : Accessibility (
identifier : " Username " ,
label : threadViewModel . displayName
) ,
onTap : { [ weak self ] in
self ? . textChanged ( self ? . oldDisplayName , for : . nickname )
self ? . setIsEditing ( true )
}
) ,
( threadViewModel . threadVariant != . contact ? nil :
SessionCell . Info (
SessionCell . Info (
id : . nickname ,
id : . sessionId ,
leftAccessory : ( threadViewModel . threadVariant != . contact ? nil :
subtitle : SessionCell . TextInfo (
. icon (
threadViewModel . id ,
editIcon ? . withRenderingMode ( . alwaysTemplate ) ,
font : . monoSmall ,
size : . fit ,
customTint : . textSecondary
)
) ,
title : SessionCell . TextInfo (
threadViewModel . displayName ,
font : . titleLarge ,
alignment : . center ,
alignment : . center ,
editingPlaceholder : " CONTACT_NICKNAME_PLACEHOLDER " . localized ( ) ,
interaction : . copy
interaction : ( threadViewModel . threadVariant = = . contact ? . editable : . none )
) ,
) ,
styling : SessionCell . StyleInfo (
styling : SessionCell . StyleInfo (
alignment : . centerHugging ,
customPadding : SessionCell . Padding (
customPadding : SessionCell . Padding (
top : Values . smallSpacing ,
top : Values . smallSpacing ,
trailing : ( threadViewModel . threadVariant != . contact ?
bottom : Values . largeSpacing
nil :
- ( ( ( editIcon ? . size . width ? ? 0 ) + ( Values . smallSpacing * 2 ) ) / 2 )
) ,
bottom : ( threadViewModel . threadVariant != . contact ?
nil :
Values . smallSpacing
) ,
interItem : 0
) ,
) ,
backgroundStyle : . noBackground
backgroundStyle : . noBackground
) ,
) ,
accessibility : Accessibility (
accessibility : Accessibility (
identifier : " Username " ,
identifier : " Session ID " ,
label : threadViewModel . displayName
label : threadViewModel . id
)
)
)
] . compactMap { $0 }
) ,
SectionModel (
model : . content ,
elements : [
( threadViewModel . threadVariant = = . legacyGroup || threadViewModel . threadVariant = = . group ? nil :
SessionCell . Info (
id : . copyThreadId ,
leftAccessory : . icon (
UIImage ( named : " ic_copy " ) ?
. withRenderingMode ( . alwaysTemplate )
) ,
) ,
onTap : {
title : ( threadViewModel . threadVariant = = . community ?
self ? . textChanged ( self ? . oldDisplayName , for : . nickname )
" COPY_GROUP_URL " . localized ( ) :
self ? . setIsEditing ( true )
" vc_conversation_settings_copy_session_id_button_title " . localized ( )
) ,
accessibility : Accessibility (
identifier : " \( ThreadSettingsViewModel . self ) .copy_thread_id " ,
label : " Copy Session ID "
) ,
onTap : { [ weak self ] in
switch threadViewModel . threadVariant {
case . contact , . legacyGroup , . group :
UIPasteboard . general . string = threadViewModel . threadId
case . community :
guard
let server : String = threadViewModel . openGroupServer ,
let roomToken : String = threadViewModel . openGroupRoomToken ,
let publicKey : String = threadViewModel . openGroupPublicKey
else { return }
UIPasteboard . general . string = LibSession . communityUrlFor (
server : server ,
roomToken : roomToken ,
publicKey : publicKey
)
}
self ? . showToast (
text : " copied " . localized ( ) ,
backgroundColor : . backgroundSecondary
)
}
}
) ,
)
) ,
( threadViewModel . threadVariant != . contact ? nil :
SessionCell . Info (
SessionCell . Info (
id : . allMedia ,
id : . sessionId ,
leftAccessory : . icon (
subtitle : SessionCell . TextInfo (
UIImage ( named : " actionsheet_camera_roll_black " ) ?
threadViewModel . id ,
. withRenderingMode ( . alwaysTemplate )
font : . monoSmall ,
) ,
alignment : . center ,
title : MediaStrings . allMedia ,
interaction : . copy
accessibility : Accessibility (
) ,
identifier : " \( ThreadSettingsViewModel . self ) .all_media " ,
styling : SessionCell . StyleInfo (
label : " All media "
customPadding : SessionCell . Padding (
) ,
top : Values . smallSpacing ,
onTap : { [ weak self ] in
bottom : Values . largeSpacing
self ? . transitionToScreen (
) ,
MediaGalleryViewModel . createAllMediaViewController (
backgroundStyle : . noBackground
threadId : threadViewModel . threadId ,
) ,
threadVariant : threadViewModel . threadVariant ,
accessibility : Accessibility (
focusedAttachmentId : nil
identifier : " Session ID " ,
label : threadViewModel . id
)
)
)
)
)
}
] . compactMap { $0 }
) ,
) ,
SectionModel (
model : . content ,
elements : [
( threadViewModel . threadVariant = = . legacyGroup || threadViewModel . threadVariant = = . group ? nil :
SessionCell . Info (
id : . copyThreadId ,
leftAccessory : . icon (
UIImage ( named : " ic_copy " ) ?
. withRenderingMode ( . alwaysTemplate )
) ,
title : ( threadViewModel . threadVariant = = . community ?
" COPY_GROUP_URL " . localized ( ) :
" vc_conversation_settings_copy_session_id_button_title " . localized ( )
) ,
accessibility : Accessibility (
identifier : " \( ThreadSettingsViewModel . self ) .copy_thread_id " ,
label : " Copy Session ID "
) ,
onTap : {
switch threadViewModel . threadVariant {
case . contact , . legacyGroup , . group :
UIPasteboard . general . string = threadViewModel . threadId
case . community :
SessionCell . Info (
guard
id : . searchConversation ,
let server : String = threadViewModel . openGroupServer ,
leftAccessory : . icon (
let roomToken : String = threadViewModel . openGroupRoomToken ,
UIImage ( named : " conversation_settings_search " ) ?
let publicKey : String = threadViewModel . openGroupPublicKey
. withRenderingMode ( . alwaysTemplate )
else { return }
) ,
title : " CONVERSATION_SETTINGS_SEARCH " . localized ( ) ,
accessibility : Accessibility (
identifier : " \( ThreadSettingsViewModel . self ) .search " ,
label : " Search "
) ,
onTap : { [ weak self ] in
self ? . didTriggerSearch ( )
}
) ,
UIPasteboard . general . string = LibSession . communityUrlFor (
( threadViewModel . threadVariant != . community ? nil :
server : server ,
SessionCell . Info (
roomToken : roomToken ,
id : . addToOpenGroup ,
publicKey : publicKey
leftAccessory : . icon (
)
UIImage ( named : " ic_plus_24 " ) ?
. withRenderingMode ( . alwaysTemplate )
) ,
title : " vc_conversation_settings_invite_button_title " . localized ( ) ,
accessibility : Accessibility (
identifier : " \( ThreadSettingsViewModel . self ) .add_to_open_group "
) ,
onTap : { [ weak self ] in
self ? . transitionToScreen (
UserSelectionVC (
with : " vc_conversation_settings_invite_button_title " . localized ( ) ,
excluding : Set ( )
) { [ weak self ] selectedUsers in
self ? . addUsersToOpenGoup (
threadViewModel : threadViewModel ,
selectedUsers : selectedUsers
)
}
}
)
}
)
) ,
self ? . showToast (
( threadViewModel . threadVariant = = . community || threadViewModel . threadIsBlocked = = true ? nil :
text : " copied " . localized ( ) ,
SessionCell . Info (
backgroundColor : . backgroundSecondary
id : . disappearingMessages ,
leftAccessory : . icon (
UIImage ( systemName : " timer " ) ?
. withRenderingMode ( . alwaysTemplate )
) ,
title : " DISAPPEARING_MESSAGES " . localized ( ) ,
subtitle : {
guard current . disappearingMessagesConfig . isEnabled else {
return " DISAPPEARING_MESSAGES_SUBTITLE_OFF " . localized ( )
}
guard Features . useNewDisappearingMessagesConfig else {
return String (
format : " DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER_LEGACY " . localized ( ) ,
current . disappearingMessagesConfig . durationString
)
)
}
}
)
) ,
return String (
format : ( current . disappearingMessagesConfig . type = = . disappearAfterRead ?
" DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER_READ " . localized ( ) :
" DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER_SEND " . localized ( )
) ,
current . disappearingMessagesConfig . durationString
)
} ( ) ,
accessibility : Accessibility (
identifier : " Disappearing messages " ,
label : " \( ThreadSettingsViewModel . self ) .disappearing_messages "
) ,
onTap : { [ weak self ] in
self ? . transitionToScreen (
SessionTableViewController (
viewModel : ThreadDisappearingMessagesSettingsViewModel (
threadId : threadViewModel . threadId ,
threadVariant : threadViewModel . threadVariant ,
currentUserIsClosedGroupMember : threadViewModel . currentUserIsClosedGroupMember ,
currentUserIsClosedGroupAdmin : threadViewModel . currentUserIsClosedGroupAdmin ,
config : current . disappearingMessagesConfig
)
)
)
}
)
) ,
( ! currentUserIsClosedGroupMember ? nil :
SessionCell . Info (
SessionCell . Info (
id : . allMedia ,
id : . editGroup ,
leftAccessory : . icon (
leftAccessory : . icon (
UIImage ( named : " actionsheet_camera_roll_black " ) ?
UIImage ( named : " table_ic_group_edit " ) ?
. withRenderingMode ( . alwaysTemplate )
. withRenderingMode ( . alwaysTemplate )
) ,
) ,
title : MediaStrings . allMedia ,
title : " EDIT_GROUP_ACTION " . localized ( ) ,
accessibility : Accessibility (
accessibility : Accessibility (
identifier : " \( ThreadSettingsViewModel . self ) .all_media " ,
identifier : " Edit group " ,
label : " All media "
label : " Edit group "
) ,
) ,
onTap : { [ weak self ] in
onTap : { [ weak self ] in
self ? . transitionToScreen (
self ? . transitionToScreen (
MediaGalleryViewModel . createAllMediaViewController (
EditClosedGroupVC (
threadId : threadViewModel . threadId ,
threadId : threadViewModel . threadId ,
threadVariant : threadViewModel . threadVariant ,
threadVariant : threadViewModel . threadVariant
focusedAttachmentId : nil
)
)
)
)
}
}
) ,
)
) ,
( ! currentUserIsClosedGroupMember ? nil :
SessionCell . Info (
SessionCell . Info (
id : . searchConversation ,
id : . leaveGroup ,
leftAccessory : . icon (
leftAccessory : . icon (
UIImage ( named : " conversation_settings_search " ) ?
UIImage ( named : " table_ic_group_leave " ) ?
. withRenderingMode ( . alwaysTemplate )
. withRenderingMode ( . alwaysTemplate )
) ,
) ,
title : " CONVERSATION_SETTINGS_SEARCH " . localized ( ) ,
title : " LEAVE_GROUP_ACTION " . localized ( ) ,
accessibility : Accessibility (
accessibility : Accessibility (
identifier : " \( ThreadSettingsViewModel . self ) .search " ,
identifier : " Leave group " ,
label : " Search "
label : " Leave group "
) ,
) ,
onTap : { [ weak self ] in
confirmationInfo : ConfirmationModal . Info (
self ? . didTriggerSearch ( )
title : " leave_group_confirmation_alert_title " . localized ( ) ,
}
body : . attributedText ( {
) ,
if currentUserIsClosedGroupAdmin {
return NSAttributedString ( string : " admin_group_leave_warning " . localized ( ) )
( threadViewModel . threadVariant != . community ? nil :
SessionCell . Info (
id : . addToOpenGroup ,
leftAccessory : . icon (
UIImage ( named : " ic_plus_24 " ) ?
. withRenderingMode ( . alwaysTemplate )
) ,
title : " vc_conversation_settings_invite_button_title " . localized ( ) ,
accessibility : Accessibility (
identifier : " \( ThreadSettingsViewModel . self ) .add_to_open_group "
) ,
onTap : { [ weak self ] in
self ? . transitionToScreen (
UserSelectionVC (
with : " vc_conversation_settings_invite_button_title " . localized ( ) ,
excluding : Set ( )
) { [ weak self ] selectedUsers in
self ? . addUsersToOpenGoup (
threadViewModel : threadViewModel ,
selectedUsers : selectedUsers
)
}
)
}
)
) ,
( threadViewModel . threadVariant = = . community || threadViewModel . threadIsBlocked = = true ? nil :
SessionCell . Info (
id : . disappearingMessages ,
leftAccessory : . icon (
UIImage ( systemName : " timer " ) ?
. withRenderingMode ( . alwaysTemplate )
) ,
title : " DISAPPEARING_MESSAGES " . localized ( ) ,
subtitle : {
guard current . disappearingMessagesConfig . isEnabled else {
return " DISAPPEARING_MESSAGES_SUBTITLE_OFF " . localized ( )
}
guard Features . useNewDisappearingMessagesConfig else {
return String (
format : " DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER_LEGACY " . localized ( ) ,
current . disappearingMessagesConfig . durationString
)
}
}
return String (
let mutableAttributedString = NSMutableAttributedString (
format : ( current . disappearingMessagesConfig . type = = . disappearAfterRead ?
string : String (
" DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER_READ " . localized ( ) :
format : " leave_community_confirmation_alert_message " . localized ( ) ,
" DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER_SEND " . localized ( )
threadViewModel . displayName
) ,
current . disappearingMessagesConfig . durationString
)
} ( ) ,
accessibility : Accessibility (
identifier : " Disappearing messages " ,
label : " \( ThreadSettingsViewModel . self ) .disappearing_messages "
) ,
onTap : { [ weak self ] in
self ? . transitionToScreen (
SessionTableViewController (
viewModel : ThreadDisappearingMessagesSettingsViewModel (
threadId : threadViewModel . threadId ,
threadVariant : threadViewModel . threadVariant ,
currentUserIsClosedGroupMember : threadViewModel . currentUserIsClosedGroupMember ,
currentUserIsClosedGroupAdmin : threadViewModel . currentUserIsClosedGroupAdmin ,
config : current . disappearingMessagesConfig
)
)
)
)
)
}
mutableAttributedString . addAttribute (
)
. font ,
) ,
value : UIFont . boldSystemFont ( ofSize : Values . smallFontSize ) ,
range : ( mutableAttributedString . string as NSString ) . range ( of : threadViewModel . displayName )
( ! currentUserIsClosedGroupMember ? nil :
)
SessionCell . Info (
return mutableAttributedString
id : . editGroup ,
} ( ) ) ,
leftAccessory : . icon (
confirmTitle : " LEAVE_BUTTON_TITLE " . localized ( ) ,
UIImage ( named : " table_ic_group_edit " ) ?
confirmStyle : . danger ,
. withRenderingMode ( . alwaysTemplate )
cancelStyle : . alert_text
) ,
) ,
title : " EDIT_GROUP_ACTION " . localized ( ) ,
onTap : { [ dependencies ] in
accessibility : Accessibility (
dependencies . storage . write { db in
identifier : " Edit group " ,
try SessionThread . deleteOrLeave (
label : " Edit group "
db ,
) ,
threadId : threadViewModel . threadId ,
onTap : { [ weak self ] in
threadVariant : threadViewModel . threadVariant ,
self ? . transitionToScreen (
groupLeaveType : . standard ,
EditClosedGroupVC (
calledFromConfigHandling : false
threadId : threadViewModel . threadId ,
threadVariant : threadViewModel . threadVariant
)
)
)
}
}
)
}
) ,
)
) ,
( ! currentUserIsClosedGroupMember ? nil :
SessionCell . Info (
( threadViewModel . threadIsNoteToSelf ? nil :
id : . leaveGroup ,
SessionCell . Info (
leftAccessory : . icon (
id : . notificationSound ,
UIImage ( named : " table_ic_group_leave " ) ?
leftAccessory : . icon (
. withRenderingMode ( . alwaysTemplate )
UIImage ( named : " table_ic_notification_sound " ) ?
) ,
. withRenderingMode ( . alwaysTemplate )
title : " LEAVE_GROUP_ACTION " . localized ( ) ,
) ,
accessibility : Accessibility (
title : " SETTINGS_ITEM_NOTIFICATION_SOUND " . localized ( ) ,
identifier : " Leave group " ,
rightAccessory : . dropDown (
label : " Leave group "
. dynamicString { current . notificationSound . displayName }
) ,
) ,
confirmationInfo : ConfirmationModal . Info (
onTap : { [ weak self ] in
title : " leave_group_confirmation_alert_title " . localized ( ) ,
self ? . transitionToScreen (
body : . attributedText ( {
SessionTableViewController (
if currentUserIsClosedGroupAdmin {
viewModel : NotificationSoundViewModel ( threadId : threadViewModel . threadId )
return NSAttributedString ( string : " admin_group_leave_warning " . localized ( ) )
)
}
)
}
let mutableAttributedString = NSMutableAttributedString (
)
string : String (
) ,
format : " leave_community_confirmation_alert_message " . localized ( ) ,
threadViewModel . displayName
( threadViewModel . threadVariant = = . contact ? nil :
)
SessionCell . Info (
)
id : . notificationMentionsOnly ,
mutableAttributedString . addAttribute (
leftAccessory : . icon (
. font ,
UIImage ( named : " NotifyMentions " ) ?
value : UIFont . boldSystemFont ( ofSize : Values . smallFontSize ) ,
. withRenderingMode ( . alwaysTemplate )
range : ( mutableAttributedString . string as NSString ) . range ( of : threadViewModel . displayName )
) ,
)
title : " vc_conversation_settings_notify_for_mentions_only_title " . localized ( ) ,
return mutableAttributedString
subtitle : " vc_conversation_settings_notify_for_mentions_only_explanation " . localized ( ) ,
} ( ) ) ,
rightAccessory : . toggle (
confirmTitle : " LEAVE_BUTTON_TITLE " . localized ( ) ,
. boolValue (
confirmStyle : . danger ,
threadViewModel . threadOnlyNotifyForMentions = = true ,
cancelStyle : . alert_text
oldValue : ( ( previous ? . threadViewModel ? ? threadViewModel ) . threadOnlyNotifyForMentions = = true )
) ,
)
onTap : { [ weak self ] in
) ,
dependencies . storage . write { db in
isEnabled : (
try SessionThread . deleteOrLeave (
(
threadViewModel . threadVariant != . legacyGroup &&
threadViewModel . threadVariant != . group
) ||
currentUserIsClosedGroupMember
) ,
accessibility : Accessibility (
identifier : " Mentions only notification setting " ,
label : " Mentions only "
) ,
onTap : { [ dependencies ] in
let newValue : Bool = ! ( threadViewModel . threadOnlyNotifyForMentions = = true )
dependencies . storage . writeAsync { db in
try SessionThread
. filter ( id : threadViewModel . threadId )
. updateAll (
db ,
db ,
threadId : threadViewModel . threadId ,
SessionThread . Columns . onlyNotifyForMentions
threadVariant : threadViewModel . threadVariant ,
. set ( to : newValue )
groupLeaveType : . standard ,
calledFromConfigHandling : false
)
)
}
}
)
) ,
( threadViewModel . threadIsNoteToSelf ? nil :
SessionCell . Info (
id : . notificationSound ,
leftAccessory : . icon (
UIImage ( named : " table_ic_notification_sound " ) ?
. withRenderingMode ( . alwaysTemplate )
) ,
title : " SETTINGS_ITEM_NOTIFICATION_SOUND " . localized ( ) ,
rightAccessory : . dropDown (
. dynamicString { current . notificationSound . displayName }
) ,
onTap : { [ weak self ] in
self ? . transitionToScreen (
SessionTableViewController (
viewModel : NotificationSoundViewModel ( threadId : threadViewModel . threadId )
)
)
}
}
)
}
) ,
)
) ,
( threadViewModel . threadVariant = = . contact ? nil :
SessionCell . Info (
( threadViewModel . threadIsNoteToSelf ? nil :
id : . notificationMentionsOnly ,
SessionCell . Info (
leftAccessory : . icon (
id : . notificationMute ,
UIImage ( named : " NotifyMentions " ) ?
leftAccessory : . icon (
. withRenderingMode ( . alwaysTemplate )
UIImage ( named : " Mute " ) ?
) ,
. withRenderingMode ( . alwaysTemplate )
title : " vc_conversation_settings_notify_for_mentions_only_title " . localized ( ) ,
) ,
subtitle : " vc_conversation_settings_notify_for_mentions_only_explanation " . localized ( ) ,
title : " CONVERSATION_SETTINGS_MUTE_LABEL " . localized ( ) ,
rightAccessory : . toggle (
rightAccessory : . toggle (
. boolValue (
. boolValue (
threadViewModel . threadOnlyNotifyForMentions = = true ,
threadViewModel . threadMutedUntilTimestamp != nil ,
oldValue : ( ( previous ? . threadViewModel ? ? threadViewModel ) . threadOnlyNotifyForMentions = = true )
oldValue : ( ( previous ? . threadViewModel ? ? threadViewModel ) . threadMutedUntilTimestamp != nil )
)
)
) ,
) ,
isEnabled : (
isEnabled : (
(
(
threadViewModel . threadVariant != . legacyGroup &&
threadViewModel . threadVariant != . legacyGroup &&
threadViewModel . threadVariant != . group
threadViewModel . threadVariant != . group
) ||
) ||
currentUserIsClosedGroupMember
currentUserIsClosedGroupMember
) ,
) ,
accessibility : Accessibility (
accessibility : Accessibility (
identifier : " Mentions only notification setting " ,
identifier : " \( ThreadSettingsViewModel . self ) .mute " ,
label : " Mentions only "
label : " Mute notifications "
) ,
) ,
onTap : {
onTap : { [ dependencies ] in
let newValue : Bool = ! ( threadViewModel . threadOnlyNotifyForMentions = = true )
dependencies . storage . writeAsync { db in
let currentValue : TimeInterval ? = try SessionThread
. filter ( id : threadViewModel . threadId )
. select ( . mutedUntilTimestamp )
. asRequest ( of : TimeInterval . self )
. fetchOne ( db )
dependencies . storage . writeAsync { db in
try SessionThread
try SessionThread
. filter ( id : threadViewModel . threadId )
. filter ( id : threadViewModel . threadId )
. updateAll (
. updateAll (
db ,
db ,
SessionThread . Columns . mutedUntilTimestamp . set (
SessionThread . Columns . onlyNotifyForMentions
to : ( currentValue = = nil ?
. set ( to : newValue )
Date . distantFuture . timeIntervalSince1970 :
)
nil
}
}
)
) ,
( threadViewModel . threadIsNoteToSelf ? nil :
SessionCell . Info (
id : . notificationMute ,
leftAccessory : . icon (
UIImage ( named : " Mute " ) ?
. withRenderingMode ( . alwaysTemplate )
) ,
title : " CONVERSATION_SETTINGS_MUTE_LABEL " . localized ( ) ,
rightAccessory : . toggle (
. boolValue (
threadViewModel . threadMutedUntilTimestamp != nil ,
oldValue : ( ( previous ? . threadViewModel ? ? threadViewModel ) . threadMutedUntilTimestamp != nil )
)
) ,
isEnabled : (
(
threadViewModel . threadVariant != . legacyGroup &&
threadViewModel . threadVariant != . group
) ||
currentUserIsClosedGroupMember
) ,
accessibility : Accessibility (
identifier : " \( ThreadSettingsViewModel . self ) .mute " ,
label : " Mute notifications "
) ,
onTap : {
dependencies . storage . writeAsync { db in
let currentValue : TimeInterval ? = try SessionThread
. filter ( id : threadViewModel . threadId )
. select ( . mutedUntilTimestamp )
. asRequest ( of : TimeInterval . self )
. fetchOne ( db )
try SessionThread
. filter ( id : threadViewModel . threadId )
. updateAll (
db ,
SessionThread . Columns . mutedUntilTimestamp . set (
to : ( currentValue = = nil ?
Date . distantFuture . timeIntervalSince1970 :
nil
)
)
)
)
)
}
)
}
}
)
}
) ,
)
) ,
( threadViewModel . threadIsNoteToSelf || threadViewModel . threadVariant != . contact ? nil :
SessionCell . Info (
( threadViewModel . threadIsNoteToSelf || threadViewModel . threadVariant != . contact ? nil :
id : . blockUser ,
SessionCell . Info (
leftAccessory : . icon (
id : . blockUser ,
UIImage ( named : " table_ic_block " ) ?
leftAccessory : . icon (
. withRenderingMode ( . alwaysTemplate )
UIImage ( named : " table_ic_block " ) ?
) ,
. withRenderingMode ( . alwaysTemplate )
title : " CONVERSATION_SETTINGS_BLOCK_THIS_USER " . localized ( ) ,
) ,
rightAccessory : . toggle (
title : " CONVERSATION_SETTINGS_BLOCK_THIS_USER " . localized ( ) ,
. boolValue (
rightAccessory : . toggle (
threadViewModel . threadIsBlocked = = true ,
. boolValue (
oldValue : ( ( previous ? . threadViewModel ? ? threadViewModel ) . threadIsBlocked = = true )
threadViewModel . threadIsBlocked = = true ,
)
oldValue : ( ( previous ? . threadViewModel ? ? threadViewModel ) . threadIsBlocked = = true )
) ,
)
accessibility : Accessibility (
) ,
identifier : " \( ThreadSettingsViewModel . self ) .block " ,
accessibility : Accessibility (
label : " Block "
identifier : " \( ThreadSettingsViewModel . self ) .block " ,
) ,
label : " Block "
confirmationInfo : ConfirmationModal . Info (
) ,
title : {
confirmationInfo : ConfirmationModal . Info (
guard threadViewModel . threadIsBlocked = = true else {
title : {
return String (
guard threadViewModel . threadIsBlocked = = true else {
format : " BLOCK_LIST_BLOCK_USER_TITLE_FORMAT " . localized ( ) ,
threadViewModel . displayName
)
}
return String (
return String (
format : " BLOCK_LIST_ UN BLOCK_TITLE_FORMAT" . localized ( ) ,
format : " BLOCK_LIST_BLOCK_USER_TITLE_FORMAT " . localized ( ) ,
threadViewModel . displayName
threadViewModel . displayName
)
)
} ( ) ,
}
body : ( threadViewModel . threadIsBlocked = = true ? . none :
. text ( " BLOCK_USER_BEHAVIOR_EXPLANATION " . localized ( ) )
) ,
confirmTitle : ( threadViewModel . threadIsBlocked = = true ?
" BLOCK_LIST_UNBLOCK_BUTTON " . localized ( ) :
" BLOCK_LIST_BLOCK_BUTTON " . localized ( )
) ,
confirmAccessibility : Accessibility ( identifier : " Confirm block " ) ,
confirmStyle : . danger ,
cancelStyle : . alert_text
) ,
onTap : {
let isBlocked : Bool = ( threadViewModel . threadIsBlocked = = true )
self ? . updateBlockedState (
return String (
from : isBlocked ,
format : " BLOCK_LIST_UNBLOCK_TITLE_FORMAT " . localized ( ) ,
isBlocked : ! isBlocked ,
threadViewModel . displayName
threadId : threadViewModel . threadId ,
displayName : threadViewModel . displayName
)
)
}
} ( ) ,
)
body : ( threadViewModel . threadIsBlocked = = true ? . none :
. text ( " BLOCK_USER_BEHAVIOR_EXPLANATION " . localized ( ) )
) ,
confirmTitle : ( threadViewModel . threadIsBlocked = = true ?
" BLOCK_LIST_UNBLOCK_BUTTON " . localized ( ) :
" BLOCK_LIST_BLOCK_BUTTON " . localized ( )
) ,
confirmAccessibility : Accessibility ( identifier : " Confirm block " ) ,
confirmStyle : . danger ,
cancelStyle : . alert_text
) ,
onTap : { [ weak self ] in
let isBlocked : Bool = ( threadViewModel . threadIsBlocked = = true )
self ? . updateBlockedState (
from : isBlocked ,
isBlocked : ! isBlocked ,
threadId : threadViewModel . threadId ,
displayName : threadViewModel . displayName
)
}
)
)
] . compactMap { $0 }
)
)
] . compactMap { $0 }
]
)
}
]
}
// MARK: - F u n c t i o n s
// MARK: - F u n c t i o n s