From 1f2ff1270af5919faac37d1dde2caa76d4db6698 Mon Sep 17 00:00:00 2001 From: Shunmugaraj Date: Thu, 27 Oct 2022 09:38:38 +0300 Subject: [PATCH 1/3] store the m.room.custom.policy with key incognito with value incognito.enabled. Filter the events from displaying. Added settings for room admin to enable the incognito mode. --- Riot/Assets/en.lproj/Untranslated.strings | 1 + Riot/Categories/MXRoom+Riot.h | 4 ++ Riot/Categories/MXRoom+Riot.m | 13 ++++ Riot/Generated/UntranslatedStrings.swift | 4 ++ .../Models/Room/MXKRoomBubbleComponent.m | 22 ++++++ .../Settings/RoomSettingsViewController.m | 69 ++++++++++++++++++- 6 files changed, 112 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/en.lproj/Untranslated.strings b/Riot/Assets/en.lproj/Untranslated.strings index 6d9320f4a1..5851b411e0 100644 --- a/Riot/Assets/en.lproj/Untranslated.strings +++ b/Riot/Assets/en.lproj/Untranslated.strings @@ -20,3 +20,4 @@ "image_picker_action_files" = "Choose from files"; "voice_broadcast_in_timeline_title" = "Voice broadcast detected (under active development)"; +"room_settings_advanced_incognito_title" = "Enable Incognito Mode"; diff --git a/Riot/Categories/MXRoom+Riot.h b/Riot/Categories/MXRoom+Riot.h index e57cd21a2f..6a64263df9 100644 --- a/Riot/Categories/MXRoom+Riot.h +++ b/Riot/Categories/MXRoom+Riot.h @@ -84,4 +84,8 @@ */ - (void)encryptionTrustLevelForUserId:(NSString*)userId onComplete:(void (^)(UserEncryptionTrustLevel userEncryptionTrustLevel))onComplete; +// Returns bool value if the room incognito mode enabled by admin. + ++ (BOOL)isRoomIncognitoEnabled:(MXRoomState*)roomState; + @end diff --git a/Riot/Categories/MXRoom+Riot.m b/Riot/Categories/MXRoom+Riot.m index 8012215974..5d6e5a60c0 100644 --- a/Riot/Categories/MXRoom+Riot.m +++ b/Riot/Categories/MXRoom+Riot.m @@ -657,4 +657,17 @@ - (id)notificationCenterDidUpdateObserver return objc_getAssociatedObject(self, @selector(notificationCenterDidUpdateObserver)); } ++ (BOOL)isRoomIncognitoEnabled:(MXRoomState*)roomState { + + NSPredicate *customPolicy = [NSPredicate predicateWithFormat:@"type like %@", @"m.room.custom.policy"]; + NSArray *events = [roomState.stateEvents filteredArrayUsingPredicate:customPolicy]; + NSArray *sortedArray = [events sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { + return [[obj1 valueForKey:@"originServerTs"] compare:[obj2 valueForKey:@"originServerTs"]]; + }]; + MXEvent *event = sortedArray.lastObject; + NSString *incognitoMode = [[event wireContent] + valueForKey:@"incognito"]; + return [incognitoMode isEqualToString:@"incognito.enabled"]; +} + @end diff --git a/Riot/Generated/UntranslatedStrings.swift b/Riot/Generated/UntranslatedStrings.swift index 1f417c7701..e01288c389 100644 --- a/Riot/Generated/UntranslatedStrings.swift +++ b/Riot/Generated/UntranslatedStrings.swift @@ -14,6 +14,10 @@ public extension VectorL10n { static var imagePickerActionFiles: String { return VectorL10n.tr("Untranslated", "image_picker_action_files") } + /// Enable Incognito Mode + static var roomSettingsAdvancedIncognitoTitle: String { + return VectorL10n.tr("Untranslated", "room_settings_advanced_incognito_title") + } /// Voice broadcast detected (under active development) static var voiceBroadcastInTimelineTitle: String { return VectorL10n.tr("Untranslated", "voice_broadcast_in_timeline_title") diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.m index 6d231262c9..93f50c718d 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.m @@ -19,6 +19,7 @@ #import "MXEvent+MatrixKit.h" #import "MXKSwiftHeader.h" #import +#import "MXRoom+Riot.h" @interface MXKRoomBubbleComponent () @@ -45,6 +46,27 @@ - (instancetype)initWithEvent:(MXEvent*)event andLatestRoomState:latestRoomState error:&error]; + if ([MXRoom isRoomIncognitoEnabled:roomState]) { + NSArray *excludedEvents = @[ + @(MXEventTypeRoomMember), + @(MXEventTypeRoomJoinRules), + @(MXEventTypeRoomPowerLevels), + @(MXEventTypeRoomHistoryVisibility), + @(MXEventTypeRoomRedaction), + @(MXEventTypeRoomThirdPartyInvite)]; + + if ([excludedEvents containsObject:@(event.eventType)]) { + return nil; + } + + if (event.wireEventType == MXEventTypeRoomMember) { + if ([event.wireContent valueForKey:@"membership"]) { + return nil; + } + + } + } + // Store the potential error event.mxkEventFormatterError = error; diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index d042a5f183..30b33a7da5 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -33,6 +33,7 @@ #import "RoomMemberDetailsViewController.h" #import +#import "MXRoom+Riot.h" enum { @@ -82,7 +83,8 @@ ROOM_SETTINGS_ADVANCED_ENCRYPT_TO_VERIFIED, ROOM_SETTINGS_ADVANCED_ENCRYPTION_ENABLED, ROOM_SETTINGS_ADVANCED_ENABLE_ENCRYPTION, - ROOM_SETTINGS_ADVANCED_ENCRYPTION_DISABLED + ROOM_SETTINGS_ADVANCED_ENCRYPTION_DISABLED, + ROOM_SETTINGS_ADVANCED_INCOGNITO }; enum @@ -120,6 +122,9 @@ NSString *const kRoomSettingsAdvancedEnableE2eCellViewIdentifier = @"kRoomSettingsAdvancedEnableE2eCellViewIdentifier"; NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSettingsAdvancedE2eEnabledCellViewIdentifier"; +NSString *const kRoomSettingsAdvancedIncognito = @"kRoomSettingsAdvancedIncognito"; + + @interface RoomSettingsViewController () { // The updated user data @@ -605,6 +610,7 @@ - (void)updateSections Section *sectionAdvanced = [Section sectionWithTag:SECTION_TAG_BANNED_ADVANCED]; [sectionAdvanced addRowWithTag:ROOM_SETTINGS_ADVANCED_ROOM_ID]; + [sectionAdvanced addRowWithTag:ROOM_SETTINGS_ADVANCED_INCOGNITO]; if (mxRoom.mxSession.crypto) { if (mxRoom.summary.isEncrypted) @@ -2018,6 +2024,43 @@ - (IBAction)onSave:(id)sender BOOL blacklistUnverifiedDevices = [((NSNumber*)updatedItemsDict[kRoomSettingsEncryptionBlacklistUnverifiedDevicesKey]) boolValue]; [mxRoom.mxSession.crypto setBlacklistUnverifiedDevicesInRoom:mxRoom.roomId blacklist:blacklistUnverifiedDevices]; } + + if(updatedItemsDict[kRoomSettingsAdvancedIncognito]) { + BOOL enableIncognito = [((NSNumber*)updatedItemsDict[kRoomSettingsAdvancedIncognito]) boolValue]; + + // m.room.custom.policy will be stored with key incognito and value incognito.enabled to enable the incognito mode + [mxRoom sendStateEventOfType:@"m.room.custom.policy" + content:@{@"incognito" : enableIncognito ? @"incognito.enabled" : @"incognito.disabled"} + stateKey:nil + success:^(NSString *eventId) { + if (weakSelf) + { + typeof(self) self = weakSelf; + [self->updatedItemsDict removeObjectForKey:kRoomSettingsAdvancedIncognito]; + [self onSave:nil]; + } + + } failure:^(NSError *error) { + MXLogDebug(@"[RoomSettingsViewController] Update incognito failed"); + if (weakSelf) + { + typeof(self) self = weakSelf; + self->pendingOperation = nil; + + dispatch_async(dispatch_get_main_queue(), ^{ + NSString* message = error.localizedDescription; + if (!message.length) + { + message = @"Failed to update incoginto"; + } + [self onSaveFailed:message withKeys:@[kRoomSettingsAdvancedIncognito]]; + + }); + } + + } + ]; + } } [self getNavigationItem].rightBarButtonItem.enabled = NO; @@ -2798,6 +2841,16 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell.selectionStyle = UITableViewCellSelectionStyleNone; } + else if (row == ROOM_SETTINGS_ADVANCED_INCOGNITO) + { + MXKTableViewCellWithLabelAndSwitch *roomIncognitoModeCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; + [roomIncognitoModeCell.mxkSwitch addTarget:self action:@selector(toggleIncognitoMode:) forControlEvents:UIControlEventValueChanged]; + roomIncognitoModeCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; + roomIncognitoModeCell.mxkSwitch.on = [MXRoom isRoomIncognitoEnabled:mxRoomState]; + roomIncognitoModeCell.mxkLabel.text = [VectorL10n roomSettingsAdvancedIncognitoTitle]; + cell = roomIncognitoModeCell; + cell.userInteractionEnabled = oneSelfPowerLevel == RoomPowerLevelAdmin; + } } // Sanity check @@ -3387,6 +3440,20 @@ - (void)toggleBlacklistUnverifiedDevice:(UISwitch*)theSwitch [self getNavigationItem].rightBarButtonItem.enabled = (updatedItemsDict.count != 0); } +- (void)toggleIncognitoMode:(UISwitch*)theSwitch +{ + + if ([MXRoom isRoomIncognitoEnabled:mxRoomState] != theSwitch.on) + { + updatedItemsDict[kRoomSettingsAdvancedIncognito] = @(theSwitch.on); + } + else + { + [updatedItemsDict removeObjectForKey:kRoomSettingsAdvancedIncognito]; + } + + [self getNavigationItem].rightBarButtonItem.enabled = (updatedItemsDict.count != 0); +} - (void)toggleDirectoryVisibility:(UISwitch*)theSwitch { From 45cbcbb900500e12924e496826bd356cf7a7fa1b Mon Sep 17 00:00:00 2001 From: Shunmugaraj Date: Thu, 27 Oct 2022 09:43:51 +0300 Subject: [PATCH 2/3] Hide read recipients and members list when incognito mode is on. --- Riot/Modules/Room/DataSources/RoomDataSource.m | 2 +- .../Room/Members/RoomParticipantsViewController.m | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 8426238188..0aaa43092d 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -526,7 +526,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N } // Check whether some receipts are found - if (roomMembers.count) + if (roomMembers.count && ![MXRoom isRoomIncognitoEnabled:self.roomState]) { // Define the read receipts container, positioned on the right border of the bubble cell (Note the right margin 6 pts). avatarsContainer = [[MXKReceiptSendersContainer alloc] initWithFrame:CGRectMake(bubbleCell.frame.size.width - PlainRoomCellLayoutConstants.readReceiptsViewWidth + PlainRoomCellLayoutConstants.readReceiptsViewRightMargin, bottomPositionY + PlainRoomCellLayoutConstants.readReceiptsViewTopMargin, PlainRoomCellLayoutConstants.readReceiptsViewWidth, PlainRoomCellLayoutConstants.readReceiptsViewHeight) andMediaManager:self.mxSession.mediaManager]; diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index be8e7ce9fe..f338f8d307 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -28,6 +28,7 @@ #import "ContactTableViewCell.h" #import "RageShakeManager.h" +#import "MXRoom+Riot.h" @interface RoomParticipantsViewController () { @@ -856,7 +857,15 @@ - (void)showDetailFor:(MXRoomMember* _Nonnull)member from:(UIView* _Nullable)sou - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { NSInteger count = 0; - + MXRoomState *roomState = self.mxRoom.dangerousSyncState; + // If the room is incognito mode non admin users can't see the list of members + if([MXRoom isRoomIncognitoEnabled:roomState]) { + MXRoomPowerLevels *powerLevels = [roomState powerLevels]; + NSInteger oneSelfPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mainSession.myUser.userId]; + if(oneSelfPowerLevel < RoomPowerLevelModerator) { + return 0; + } + } participantsSection = invitedSection = -1; if (currentSearchText.length) From 7294f1d04a90814a4da507cb6c05e6589c6b06ef Mon Sep 17 00:00:00 2001 From: Shunmugaraj Date: Thu, 27 Oct 2022 13:45:55 +0300 Subject: [PATCH 3/3] added the changelog.d --- changelog.d/6989.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6989.feature diff --git a/changelog.d/6989.feature b/changelog.d/6989.feature new file mode 100644 index 0000000000..fe8ad6f4a8 --- /dev/null +++ b/changelog.d/6989.feature @@ -0,0 +1 @@ +Incognito mode for large rooms like announcements room #6989