/** * @copyright Copyright (c) 2020 Ivan Sein * * @author Ivan Sein * * @license GNU GPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #import "NCRoom.h" #import "NCDatabaseManager.h" NSString * const NCRoomObjectTypeFile = @"file"; NSString * const NCRoomObjectTypeSharePassword = @"share:password"; @implementation NCRoom + (instancetype)roomWithDictionary:(NSDictionary *)roomDict { if (!roomDict) { return nil; } NCRoom *room = [[self alloc] init]; room.roomId = [[roomDict objectForKey:@"id"] integerValue]; room.token = [roomDict objectForKey:@"token"]; room.type = (NCRoomType)[[roomDict objectForKey:@"type"] integerValue]; room.roomDescription = [roomDict objectForKey:@"description"]; room.count = [[roomDict objectForKey:@"count"] integerValue]; room.hasPassword = [[roomDict objectForKey:@"hasPassword"] boolValue]; room.participantType = (NCParticipantType)[[roomDict objectForKey:@"participantType"] integerValue]; room.attendeeId = [[roomDict objectForKey:@"attendeeId"] integerValue]; room.attendeePin = [roomDict objectForKey:@"attendeePin"]; room.lastPing = [[roomDict objectForKey:@"lastPing"] integerValue]; room.numGuests = [[roomDict objectForKey:@"numGuests"] integerValue]; room.unreadMessages = [[roomDict objectForKey:@"unreadMessages"] integerValue]; room.unreadMention = [[roomDict objectForKey:@"unreadMention"] boolValue]; room.unreadMentionDirect = [[roomDict objectForKey:@"unreadMentionDirect"] boolValue]; room.guestList = [roomDict objectForKey:@"guestList"]; room.lastActivity = [[roomDict objectForKey:@"lastActivity"] integerValue]; room.isFavorite = [[roomDict objectForKey:@"isFavorite"] boolValue]; room.notificationLevel = (NCRoomNotificationLevel)[[roomDict objectForKey:@"notificationLevel"] integerValue]; room.notificationCalls = [[roomDict objectForKey:@"notificationCalls"] boolValue]; room.objectType = [roomDict objectForKey:@"objectType"]; room.objectId = [roomDict objectForKey:@"objectId"]; room.readOnlyState = (NCRoomReadOnlyState)[[roomDict objectForKey:@"readOnly"] integerValue]; room.listable = (NCRoomListableScope)[[roomDict objectForKey:@"listable"] integerValue]; room.messageExpiration = [[roomDict objectForKey:@"messageExpiration"] integerValue]; room.lobbyState = (NCRoomLobbyState)[[roomDict objectForKey:@"lobbyState"] integerValue]; room.lobbyTimer = [[roomDict objectForKey:@"lobbyTimer"] integerValue]; room.sipState = (NCRoomSIPState)[[roomDict objectForKey:@"sipEnabled"] integerValue]; room.canEnableSIP = [[roomDict objectForKey:@"canEnableSIP"] boolValue]; room.lastReadMessage = [[roomDict objectForKey:@"lastReadMessage"] integerValue]; room.lastCommonReadMessage = [[roomDict objectForKey:@"lastCommonReadMessage"] integerValue]; room.canStartCall = [[roomDict objectForKey:@"canStartCall"] boolValue]; room.hasCall = [[roomDict objectForKey:@"hasCall"] boolValue]; room.canLeaveConversation = [[roomDict objectForKey:@"canLeaveConversation"] boolValue]; room.canDeleteConversation = [[roomDict objectForKey:@"canDeleteConversation"] boolValue]; room.participantFlags = [[roomDict objectForKey:@"participantFlags"] integerValue]; room.permissions = [[roomDict objectForKey:@"permissions"] integerValue]; room.attendeePermissions = [[roomDict objectForKey:@"attendeePermissions"] integerValue]; room.callPermissions = [[roomDict objectForKey:@"callPermissions"] integerValue]; room.defaultPermissions = [[roomDict objectForKey:@"defaultPermissions"] integerValue]; // Local-only field -> update only if there's actually a value if ([roomDict objectForKey:@"pendingMessage"] != nil) { room.pendingMessage = [roomDict objectForKey:@"pendingMessage"]; } id name = [roomDict objectForKey:@"name"]; if ([name isKindOfClass:[NSString class]]) { room.name = name; } else { room.name = [name stringValue]; } id displayName = [roomDict objectForKey:@"displayName"]; if ([displayName isKindOfClass:[NSString class]]) { room.displayName = displayName; } else { room.displayName = [displayName stringValue]; } id participants = [roomDict objectForKey:@"participants"]; if ([participants isKindOfClass:[NSDictionary class]]) { room.participants = (RLMArray *)[participants allKeys]; } // Optional attribute id status = [roomDict objectForKey:@"status"]; if ([status isKindOfClass:[NSString class]]) { room.status = status; } // Optional attribute id statusIcon = [roomDict objectForKey:@"statusIcon"]; if ([statusIcon isKindOfClass:[NSString class]]) { room.statusIcon = statusIcon; } // Optional attribute id statusMessage = [roomDict objectForKey:@"statusMessage"]; if ([statusMessage isKindOfClass:[NSString class]]) { room.statusMessage = statusMessage; } return room; } + (instancetype)roomWithDictionary:(NSDictionary *)roomDict andAccountId:(NSString *)accountId { NCRoom *room = [self roomWithDictionary:roomDict]; if (room) { room.accountId = accountId; room.internalId = [NSString stringWithFormat:@"%@@%@", room.accountId, room.token]; } return room; } + (void)updateRoom:(NCRoom *)managedRoom withRoom:(NCRoom *)room { managedRoom.name = room.name; managedRoom.displayName = room.displayName; managedRoom.type = room.type; managedRoom.roomDescription = room.roomDescription; managedRoom.count = room.count; managedRoom.hasPassword = room.hasPassword; managedRoom.participantType = room.participantType; managedRoom.attendeeId = room.attendeeId; managedRoom.attendeePin = room.attendeePin; managedRoom.lastPing = room.lastPing; managedRoom.numGuests = room.numGuests; managedRoom.unreadMessages = room.unreadMessages; managedRoom.unreadMention = room.unreadMention; managedRoom.unreadMentionDirect = room.unreadMentionDirect; managedRoom.guestList = room.guestList; managedRoom.participants = room.participants; managedRoom.lastActivity = room.lastActivity; managedRoom.lastMessageId = room.lastMessageId; managedRoom.isFavorite = room.isFavorite; managedRoom.notificationLevel = room.notificationLevel; managedRoom.notificationCalls = room.notificationCalls; managedRoom.objectType = room.objectType; managedRoom.objectId = room.objectId; managedRoom.readOnlyState = room.readOnlyState; managedRoom.listable = room.listable; managedRoom.messageExpiration = room.messageExpiration; managedRoom.lobbyState = room.lobbyState; managedRoom.lobbyTimer = room.lobbyTimer; managedRoom.sipState = room.sipState; managedRoom.canEnableSIP = room.canEnableSIP; managedRoom.lastReadMessage = room.lastReadMessage; managedRoom.lastCommonReadMessage = room.lastCommonReadMessage; managedRoom.canStartCall = room.canStartCall; managedRoom.hasCall = room.hasCall; managedRoom.lastUpdate = room.lastUpdate; managedRoom.canLeaveConversation = room.canLeaveConversation; managedRoom.canDeleteConversation = room.canDeleteConversation; managedRoom.status = room.status; managedRoom.statusIcon = room.statusIcon; managedRoom.statusMessage = room.statusMessage; managedRoom.participantFlags = room.participantFlags; managedRoom.permissions = room.permissions; managedRoom.attendeePermissions = room.attendeePermissions; managedRoom.callPermissions = room.callPermissions; managedRoom.defaultPermissions = room.defaultPermissions; } + (NSString *)primaryKey { return @"internalId"; } - (BOOL)isPublic { return self.type == kNCRoomTypePublic; } - (BOOL)isUserOwnerOrModerator { return self.participantType == kNCParticipantTypeOwner || self.participantType == kNCParticipantTypeModerator; } - (BOOL)canModerate { return [self isUserOwnerOrModerator] && ![self isLockedOneToOne]; } - (BOOL)isNameEditable { return [self canModerate] && self.type != kNCRoomTypeOneToOne; } - (BOOL)isLockedOneToOne { return self.type == kNCRoomTypeOneToOne && [[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityLockedOneToOneRooms]; } - (BOOL)userCanStartCall { if ([[NCDatabaseManager sharedInstance] serverHasTalkCapability:kCapabilityStartCallFlag] && !self.canStartCall) { return NO; } return YES; } - (BOOL)hasUnreadMention { return self.unreadMention || self.unreadMentionDirect || (self.type == kNCRoomTypeOneToOne && self.unreadMessages > 0); } - (BOOL)isLeavable { // Allow users to leave when there are no moderators in the room // (No need to check room type because in one2one rooms users will always be moderators) // or when in a group call and there are other participants. // We can also check "canLeaveConversation" since v2 return self.canLeaveConversation || ![self canModerate] || (self.type != kNCRoomTypeOneToOne && [self.participants count] > 1); } - (NSString *)deletionMessage { NSString *message = NSLocalizedString(@"Do you really want to delete this conversation?", nil); if (self.type == kNCRoomTypeOneToOne) { message = [NSString stringWithFormat:NSLocalizedString(@"If you delete the conversation, it will also be deleted for %@", nil), self.displayName]; } else if ([self.participants count] > 1) { message = NSLocalizedString(@"If you delete the conversation, it will also be deleted for all other participants.", nil); } return message; } - (NSString *)notificationLevelString { return [self stringForNotificationLevel:self.notificationLevel]; } - (NSString *)stringForNotificationLevel:(NCRoomNotificationLevel)level { NSString *levelString = NSLocalizedString(@"Default", nil); switch (level) { case kNCRoomNotificationLevelAlways: levelString = NSLocalizedString(@"All messages", nil); break; case kNCRoomNotificationLevelMention: levelString = NSLocalizedString(@"@-mentions only", nil); break; case kNCRoomNotificationLevelNever: levelString = NSLocalizedString(@"Off", nil); break; default: break; } return levelString; } - (NSString *)messageExpirationString { return [self stringForMessageExpiration:self.messageExpiration]; } - (NSString *)stringForMessageExpiration:(NSInteger)messageExpiration { NSString *levelString = NSLocalizedString(@"Off", nil); switch (messageExpiration) { case NCMessageExpiration4Weeks: levelString = NSLocalizedString(@"4 weeks", nil); break; case NCMessageExpiration1Week: levelString = NSLocalizedString(@"1 week", nil); break; case NCMessageExpiration1Day: levelString = NSLocalizedString(@"1 day", nil); break; case NCMessageExpiration8Hours: levelString = NSLocalizedString(@"8 hours", nil); break; case NCMessageExpiration1Hour: levelString = NSLocalizedString(@"1 hour", nil); break; default: break; } return levelString; } - (NSString *)lastMessageString { TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; BOOL ownMessage = [self.lastMessage.actorId isEqualToString:activeAccount.userId]; NSString *actorName = [[self.lastMessage.actorDisplayName componentsSeparatedByString:@" "] objectAtIndex:0]; // For own messages if (ownMessage) { actorName = NSLocalizedString(@"You", nil); } // For guests if ([self.lastMessage.actorDisplayName isEqualToString:@""]) { actorName = NSLocalizedString(@"Guest", nil); } // No actor name cases if (self.lastMessage.isSystemMessage || (self.type == kNCRoomTypeOneToOne && !ownMessage) || self.type == kNCRoomTypeChangelog) { actorName = @""; } // Use only the first name if (![actorName isEqualToString:@""]) { actorName = [NSString stringWithFormat:@"%@: ", [[actorName componentsSeparatedByString:@" "] objectAtIndex:0]]; } // Add the last message NSString *lastMessage = [NSString stringWithFormat:@"%@%@", actorName, self.lastMessage.parsedMessage.string]; return lastMessage; } - (NCChatMessage *)lastMessage { if (self.lastMessageId) { NCChatMessage *unmanagedChatMessage = nil; NCChatMessage *managedChatMessage = [NCChatMessage objectsWhere:@"internalId = %@", self.lastMessageId].firstObject; if (managedChatMessage) { unmanagedChatMessage = [[NCChatMessage alloc] initWithValue:managedChatMessage]; } return unmanagedChatMessage; } return nil; } @end