Add conversation settings (listable & readonly)

Signed-off-by: Marcel Müller <marcel-mueller@gmx.de>
This commit is contained in:
Marcel Müller 2022-05-28 02:10:39 +02:00
Родитель 7f0516ffe5
Коммит 2d24880dae
11 изменённых файлов: 281 добавлений и 4 удалений

Просмотреть файл

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "listable-conversation.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "listable-conversation@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "listable-conversation@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Двоичные данные
NextcloudTalk/Images.xcassets/listable-conversation.imageset/listable-conversation.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 280 B

Двоичные данные
NextcloudTalk/Images.xcassets/listable-conversation.imageset/listable-conversation@2x.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 467 B

Двоичные данные
NextcloudTalk/Images.xcassets/listable-conversation.imageset/listable-conversation@3x.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 666 B

Просмотреть файл

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "message-text-lock.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "message-text-lock@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "message-text-lock@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Двоичные данные
NextcloudTalk/Images.xcassets/message-text-lock.imageset/message-text-lock.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 310 B

Двоичные данные
NextcloudTalk/Images.xcassets/message-text-lock.imageset/message-text-lock@2x.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 461 B

Двоичные данные
NextcloudTalk/Images.xcassets/message-text-lock.imageset/message-text-lock@3x.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 680 B

Просмотреть файл

@ -47,6 +47,7 @@ typedef void (^NotificationLevelCompletionBlock)(NSError *error);
typedef void (^ReadOnlyCompletionBlock)(NSError *error);
typedef void (^SetLobbyStateCompletionBlock)(NSError *error);
typedef void (^SetSIPStateCompletionBlock)(NSError *error);
typedef void (^ListableCompletionBlock)(NSError *error);
typedef void (^GetParticipantsFromRoomCompletionBlock)(NSMutableArray *participants, NSError *error);
typedef void (^LeaveRoomCompletionBlock)(NSInteger errorCode, NSError *error);
@ -142,6 +143,7 @@ extern NSInteger const kReceivedChatMessagesLimit;
- (NSURLSessionDataTask *)setReadOnlyState:(NCRoomReadOnlyState)state forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ReadOnlyCompletionBlock)block;
- (NSURLSessionDataTask *)setLobbyState:(NCRoomLobbyState)state withTimer:(NSInteger)timer forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SetLobbyStateCompletionBlock)block;
- (NSURLSessionDataTask *)setSIPEnabled:(BOOL)enabled forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SetSIPStateCompletionBlock)block;
- (NSURLSessionDataTask *)setListableScope:(NCRoomListableScope)scope forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ListableCompletionBlock)block;
// Participants Controller
- (NSURLSessionDataTask *)getParticipantsFromRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(GetParticipantsFromRoomCompletionBlock)block;

Просмотреть файл

@ -706,6 +706,30 @@ NSInteger const kReceivedChatMessagesLimit = 100;
return task;
}
- (NSURLSessionDataTask *)setListableScope:(NCRoomListableScope)scope forRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(ListableCompletionBlock)block
{
NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSString *endpoint = [NSString stringWithFormat:@"room/%@/listable", encodedToken];
NSInteger conversationAPIVersion = [self conversationAPIVersionForAccount:account];
NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:conversationAPIVersion forAccount:account];
NSDictionary *parameters = @{@"scope" : @(scope)};
NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
NSURLSessionDataTask *task = [apiSessionManager PUT:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (block) {
block(nil);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSInteger statusCode = [self getResponseStatusCode:task.response];
[self checkResponseStatusCode:statusCode forAccount:account];
if (block) {
block(error);
}
}];
return task;
}
#pragma mark - Participants Controller
- (NSURLSessionDataTask *)getParticipantsFromRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(GetParticipantsFromRoomCompletionBlock)block

Просмотреть файл

@ -56,6 +56,7 @@ typedef enum RoomInfoSection {
kRoomInfoSectionSharedItems,
kRoomInfoSectionNotifications,
kRoomInfoSectionGuests,
kRoomInfoSectionConversation,
kRoomInfoSectionWebinar,
kRoomInfoSectionSIP,
kRoomInfoSectionParticipants,
@ -74,6 +75,12 @@ typedef enum GuestAction {
kGuestActionResendInvitations
} GuestAction;
typedef enum ConversationAction {
kConversationActionListable = 0,
kConversationActionListableForEveryone,
kConversationActionReadOnly
} ConversationAction;
typedef enum WebinarAction {
kWebinarActionLobby = 0,
kWebinarActionLobbyTimer,
@ -107,7 +114,9 @@ typedef enum ModificationError {
kModificationErrorLeave,
kModificationErrorLeaveModeration,
kModificationErrorDelete,
kModificationErrorClearHistory
kModificationErrorClearHistory,
kModificationErrorListable,
kModificationErrorReadOnly
} ModificationError;
typedef enum FileAction {
@ -125,6 +134,9 @@ typedef enum FileAction {
@property (nonatomic, strong) NSMutableArray *roomParticipants;
@property (nonatomic, strong) UITextField *roomNameTextField;
@property (nonatomic, strong) UISwitch *publicSwitch;
@property (nonatomic, strong) UISwitch *listableSwitch;
@property (nonatomic, strong) UISwitch *listableForEveryoneSwitch;
@property (nonatomic, strong) UISwitch *readOnlySwitch;
@property (nonatomic, strong) UISwitch *lobbySwitch;
@property (nonatomic, strong) UISwitch *sipSwitch;
@property (nonatomic, strong) UISwitch *callNotificationSwitch;
@ -182,6 +194,15 @@ typedef enum FileAction {
_publicSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[_publicSwitch addTarget: self action: @selector(publicValueChanged:) forControlEvents:UIControlEventValueChanged];
_listableSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[_listableSwitch addTarget: self action: @selector(listableValueChanged:) forControlEvents:UIControlEventValueChanged];
_listableForEveryoneSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[_listableForEveryoneSwitch addTarget: self action: @selector(listableForEveryoneValueChanged:) forControlEvents:UIControlEventValueChanged];
_readOnlySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[_readOnlySwitch addTarget: self action: @selector(readOnlyValueChanged:) forControlEvents:UIControlEventValueChanged];
_lobbySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[_lobbySwitch addTarget: self action: @selector(lobbyValueChanged:) forControlEvents:UIControlEventValueChanged];
@ -288,9 +309,17 @@ typedef enum FileAction {
if (_room.canModerate) {
// Guests section
[sections addObject:[NSNumber numberWithInt:kRoomInfoSectionGuests]];
// Webinar section
if (_room.type != kNCRoomTypeOneToOne && [[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityWebinaryLobby]) {
[sections addObject:[NSNumber numberWithInt:kRoomInfoSectionWebinar]];
if (_room.type != kNCRoomTypeOneToOne) {
// Conversation section
if ([[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityReadOnlyRooms] || [[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityListableRooms]) {
[sections addObject:[NSNumber numberWithInt:kRoomInfoSectionConversation]];
}
// Webinar section
if ([[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityWebinaryLobby]) {
[sections addObject:[NSNumber numberWithInt:kRoomInfoSectionWebinar]];
}
}
}
// SIP section
@ -381,6 +410,25 @@ typedef enum FileAction {
return actionIndexPath;
}
- (NSArray *)getConversationActions
{
NSMutableArray *actions = [[NSMutableArray alloc] init];
// Listable room action
if ([[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityListableRooms]) {
[actions addObject:[NSNumber numberWithInt:kConversationActionListable]];
if (_room.listable == NCRoomListableScopeRegularUsersOnly || _room.listable == NCRoomListableScopeEveryone) {
[actions addObject:[NSNumber numberWithInt:kConversationActionListableForEveryone]];
}
}
// Read only room action
if ([[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityReadOnlyRooms]) {
[actions addObject:[NSNumber numberWithInt:kConversationActionReadOnly]];
}
return [NSArray arrayWithArray:actions];
}
- (NSArray *)getWebinarActions
{
NSMutableArray *actions = [[NSMutableArray alloc] init];
@ -510,6 +558,14 @@ typedef enum FileAction {
errorDescription = NSLocalizedString(@"Could not clear chat history", nil);
break;
case kModificationErrorListable:
errorDescription = NSLocalizedString(@"Could not change listable scope of the conversation", nil);
break;
case kModificationErrorReadOnly:
errorDescription = NSLocalizedString(@"Could not change read-only state of the converstion", nil);
break;
default:
break;
}
@ -824,6 +880,45 @@ typedef enum FileAction {
};
}
- (void)setListableScope:(NCRoomListableScope)scope
{
if (scope == _room.listable) {
return;
}
[self setModifyingRoomUI];
[[NCAPIController sharedInstance] setListableScope:scope forRoom:_room.token forAccount:[[NCDatabaseManager sharedInstance] activeAccount] withCompletionBlock:^(NSError *error) {
if (!error) {
[[NCRoomsManager sharedInstance] updateRoom:self->_room.token];
} else {
NSLog(@"Error setting room listable scope: %@", error.description);
[self.tableView reloadData];
[self showRoomModificationError:kModificationErrorListable];
}
self->_listableSwitch.enabled = YES;
self->_listableForEveryoneSwitch.enabled = YES;
}];
}
- (void)setReadOnlyState:(NCRoomReadOnlyState)state
{
if (state == _room.readOnlyState) {
return;
}
[self setModifyingRoomUI];
[[NCAPIController sharedInstance] setReadOnlyState:state forRoom:_room.token forAccount:[[NCDatabaseManager sharedInstance] activeAccount] withCompletionBlock:^(NSError *error) {
if (!error) {
[[NCRoomsManager sharedInstance] updateRoom:self->_room.token];
} else {
NSLog(@"Error setting room readonly state: %@", error.description);
[self.tableView reloadData];
[self showRoomModificationError:kModificationErrorReadOnly];
}
self->_readOnlySwitch.enabled = true;
}];
}
- (void)previewRoomFile:(NSIndexPath *)indexPath
{
if (_fileDownloadIndicator) {
@ -1208,6 +1303,43 @@ typedef enum FileAction {
}
}
#pragma mark - Listable switches
- (void)listableValueChanged:(id)sender
{
_listableSwitch.enabled = NO;
_listableForEveryoneSwitch.enabled = NO;
if (_listableSwitch.on) {
[self setListableScope:NCRoomListableScopeRegularUsersOnly];
} else {
[self setListableScope:NCRoomListableScopeParticipantsOnly];
}
}
- (void)listableForEveryoneValueChanged:(id)sender
{
_listableSwitch.enabled = NO;
_listableForEveryoneSwitch.enabled = NO;
if (_listableForEveryoneSwitch.on) {
[self setListableScope:NCRoomListableScopeEveryone];
} else {
[self setListableScope:NCRoomListableScopeRegularUsersOnly];
}
}
#pragma mark - ReadOnly switch
- (void)readOnlyValueChanged:(id)sender
{
_readOnlySwitch.enabled = NO;
if (_readOnlySwitch.on) {
[self setReadOnlyState:NCRoomReadOnlyStateReadOnly];
} else {
[self setReadOnlyState:NCRoomReadOnlyStateReadWrite];
}
}
#pragma mark - SIP switch
- (void)sipValueChanged:(id)sender
@ -1308,6 +1440,10 @@ typedef enum FileAction {
return [self getGuestsActions].count;
break;
case kRoomInfoSectionConversation:
return [self getConversationActions].count;
break;
case kRoomInfoSectionWebinar:
return [self getWebinarActions].count;
break;
@ -1387,6 +1523,9 @@ typedef enum FileAction {
case kRoomInfoSectionGuests:
return NSLocalizedString(@"Guests access", nil);
break;
case kRoomInfoSectionConversation:
return NSLocalizedString(@"Conversation settings", nil);
break;
case kRoomInfoSectionWebinar:
return NSLocalizedString(@"Meeting settings", nil);
break;
@ -1435,6 +1574,7 @@ typedef enum FileAction {
case kRoomInfoSectionFile:
case kRoomInfoSectionSharedItems:
case kRoomInfoSectionGuests:
case kRoomInfoSectionConversation:
case kRoomInfoSectionWebinar:
case kRoomInfoSectionSIP:
return 36;
@ -1468,6 +1608,9 @@ typedef enum FileAction {
static NSString *leaveRoomCellIdentifier = @"LeaveRoomCellIdentifier";
static NSString *deleteRoomCellIdentifier = @"DeleteRoomCellIdentifier";
static NSString *sharedItemsCellIdentifier = @"SharedItemsCellIdentifier";
static NSString *listableCellIdentifier = @"ListableCellIdentifier";
static NSString *listableForEveryoneCellIdentifier = @"ListableForEveryoneCellIdentifier";
static NSString *readOnlyStateCellIdentifier = @"ReadOnlyStateCellIdentifier";
NSArray *sections = [self getRoomInfoSections];
RoomInfoSection section = [[sections objectAtIndex:indexPath.section] intValue];
@ -1719,6 +1862,68 @@ typedef enum FileAction {
}
}
break;
case kRoomInfoSectionConversation:
{
NSArray *actions = [self getConversationActions];
ConversationAction action = [[actions objectAtIndex:indexPath.row] intValue];
switch (action) {
case kConversationActionListable:
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:listableCellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:listableCellIdentifier];
}
cell.textLabel.text = NSLocalizedString(@"Open conversation to registered users", nil);
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.accessoryView = _listableSwitch;
_listableSwitch.on = (_room.listable != NCRoomListableScopeParticipantsOnly);
[cell.imageView setImage:[[UIImage imageNamed:@"listable-conversation"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
cell.imageView.tintColor = [UIColor colorWithRed:0.43 green:0.43 blue:0.45 alpha:1];
return cell;
}
break;
case kConversationActionListableForEveryone:
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:listableForEveryoneCellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:listableForEveryoneCellIdentifier];
}
cell.textLabel.text = NSLocalizedString(@"Also open to guest app users", nil);
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.accessoryView = _listableForEveryoneSwitch;
_listableForEveryoneSwitch.on = (_room.listable == NCRoomListableScopeEveryone);
// Still assign an image, but hide it to keep the margin the same as the other cells
[cell.imageView setImage:[[UIImage imageNamed:@"listable-conversation"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
[cell.imageView setHidden:YES];
cell.imageView.tintColor = [UIColor colorWithRed:0.43 green:0.43 blue:0.45 alpha:1];
return cell;
}
break;
case kConversationActionReadOnly:
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:readOnlyStateCellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:readOnlyStateCellIdentifier];
}
cell.textLabel.text = NSLocalizedString(@"Lock conversation", nil);
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.accessoryView = _readOnlySwitch;
_readOnlySwitch.on = _room.readOnlyState;
[cell.imageView setImage:[[UIImage imageNamed:@"message-text-lock"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
cell.imageView.tintColor = [UIColor colorWithRed:0.43 green:0.43 blue:0.45 alpha:1];
return cell;
}
break;
}
}
break;
case kRoomInfoSectionWebinar:
{
NSArray *actions = [self getWebinarActions];