123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- //
- // SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
- // SPDX-License-Identifier: GPL-3.0-or-later
- //
- import Foundation
- import Realm
- @objc extension NCRoom {
- public static func stringFor(notificationLevel level: NCRoomNotificationLevel) -> String {
- var levelString = ""
- switch level {
- case .always:
- levelString = NSLocalizedString("All messages", comment: "")
- case .mention:
- levelString = NSLocalizedString("@-mentions only", comment: "")
- case .never:
- levelString = NSLocalizedString("Off", comment: "")
- default:
- levelString = NSLocalizedString("Default", comment: "")
- }
- return levelString
- }
- public static func stringFor(messageExpiration expiration: NCMessageExpiration) -> String {
- var levelString = ""
- switch expiration {
- case .expiration4Weeks:
- levelString = NSLocalizedString("4 weeks", comment: "")
- case .expiration1Week:
- levelString = NSLocalizedString("1 week", comment: "")
- case .expiration1Day:
- levelString = NSLocalizedString("1 day", comment: "")
- case .expiration8Hours:
- levelString = NSLocalizedString("8 hours", comment: "")
- case .expiration1Hour:
- levelString = NSLocalizedString("1 hour", comment: "")
- default:
- levelString = NSLocalizedString("Off", comment: "")
- }
- return levelString
- }
- public var isPublic: Bool {
- return self.type == .public
- }
- public var isFederated: Bool {
- if let remoteToken, let remoteServer {
- return !remoteToken.isEmpty && !remoteServer.isEmpty
- }
- return false
- }
- public var supportsFederatedCalling: Bool {
- guard self.isFederated else { return false }
- let remoteCapabilitySupported = NCDatabaseManager.sharedInstance().roomHasTalkCapability(kCapabilityFederationV2, for: self)
- let localCapabilitySupported = NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityFederationV2, forAccountId: self.accountId)
- let remoteCallingEnabled = NCDatabaseManager.sharedInstance().roomTalkCapabilities(for: self)?.callEnabled ?? false
- let localCallingEnabled = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: self.accountId)?.callEnabled ?? false
- let capabilitySupported = remoteCapabilitySupported && localCapabilitySupported
- let callingEnabled = remoteCallingEnabled && localCallingEnabled
- return capabilitySupported && callingEnabled
- }
- public var supportsCalling: Bool {
- if self.isFederated, !self.supportsFederatedCalling {
- return false
- }
- return NCDatabaseManager.sharedInstance().roomTalkCapabilities(for: self)?.callEnabled ?? false &&
- self.type != .changelog && self.type != .noteToSelf
- }
- public var supportsMessageExpirationModeration: Bool {
- if self.type == .formerOneToOne || self.type == .changelog {
- return false
- }
- return self.isUserOwnerOrModerator && NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityMessageExpiration)
- }
- public var supportsBanningModeration: Bool {
- let supportedType = self.type == .group || self.type == .public
- return supportedType && self.canModerate && NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityBanV1)
- }
- public var isBreakoutRoom: Bool {
- return self.objectType == NCRoomObjectTypeRoom
- }
- public var isUserOwnerOrModerator: Bool {
- return self.participantType == .owner || self.participantType == .moderator
- }
- public var canModerate: Bool {
- return self.isUserOwnerOrModerator && !self.isLockedOneToOne
- }
- public var isNameEditable: Bool {
- return self.canModerate && self.type != .oneToOne && self.type != .formerOneToOne
- }
- private var isLockedOneToOne: Bool {
- let lockedOneToOne = self.type == .oneToOne && NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityLockedOneToOneRooms)
- let lockedOther = self.type == .formerOneToOne || self.type == .noteToSelf
- return lockedOneToOne || lockedOther
- }
- public var isLeavable: Bool {
- // 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
- if self.type != .oneToOne && self.type != .formerOneToOne && self.participants.count > 1 {
- return true
- }
- return self.canLeaveConversation || self.canModerate
- }
- public var userCanStartCall: Bool {
- if NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityStartCallFlag) && !self.canStartCall {
- return false
- }
- return true
- }
- public var hasUnreadMention: Bool {
- if self.type == .oneToOne || self.type == .formerOneToOne {
- return self.unreadMessages > 0
- }
- return self.unreadMention || self.unreadMentionDirect
- }
- public var callRecordingIsInActiveState: Bool {
- if NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityRecordingV1) {
- // Starting states and running states are considered active
- if self.callRecording != NCCallRecordingState.stopped.rawValue && self.callRecording != NCCallRecordingState.failed.rawValue {
- return true
- }
- }
- return false
- }
- public var deletionMessage: String {
- var message = NSLocalizedString("Do you really want to delete this conversation?", comment: "")
- if self.type == .oneToOne || self.type == .formerOneToOne {
- message = String(format: NSLocalizedString("If you delete the conversation, it will also be deleted for %@", comment: ""), self.displayName)
- } else if self.participants.count > 1 {
- message = NSLocalizedString("If you delete the conversation, it will also be deleted for all other participants.", comment: "")
- }
- return message
- }
- public var notificationLevelString: String {
- return NCRoom.stringFor(notificationLevel: self.notificationLevel)
- }
- public var messageExpirationString: String {
- if let tempMessageExpiration = NCMessageExpiration(rawValue: self.messageExpiration) {
- return NCRoom.stringFor(messageExpiration: tempMessageExpiration)
- }
- return "\(self.messageExpiration)s"
- }
- public var lastMessageString: NSMutableAttributedString? {
- var lastMessage = self.lastMessage
- if self.isFederated && lastMessage == nil {
- let lastMessageDictionary = self.lastMessageProxiedDictionary
- lastMessage = NCChatMessage(dictionary: lastMessageDictionary)
- }
- guard let lastMessage,
- let account = NCDatabaseManager.sharedInstance().talkAccount(forAccountId: self.accountId)
- else { return nil }
- let ownMessage = lastMessage.actorId == account.userId
- var actorName = lastMessage.actorDisplayName.components(separatedBy: " ").first ?? ""
- // For own messages
- if ownMessage {
- actorName = NSLocalizedString("You", comment: "")
- }
- // For guests
- if lastMessage.actorDisplayName.isEmpty {
- actorName = NSLocalizedString("Guest", comment: "")
- }
- // No actor name cases
- if lastMessage.isSystemMessage || (self.type == .oneToOne && !ownMessage) {
- actorName = ""
- }
- // Add separator
- if !actorName.isEmpty {
- actorName = "\(actorName): "
- }
- let lastMessageString = NSMutableAttributedString(string: actorName)
- if let messageIconName = lastMessage.messageIconName, let messageIcon = UIImage(systemName: messageIconName) {
- let attachmentString = NSMutableAttributedString(attachment: NSTextAttachment(image: messageIcon))
- attachmentString.append(NSAttributedString(string: " "))
- lastMessageString.append(attachmentString)
- }
- let parsedMarkdownString = String(lastMessage.parsedMarkdown().string.prefix(80))
- lastMessageString.append(NSAttributedString(string: parsedMarkdownString))
- return lastMessageString.withFont(.preferredFont(forTextStyle: .callout)).withTextColor(.secondaryLabel)
- }
- private var lastMessageProxiedDictionary: [AnyHashable: Any] {
- guard let data = self.lastMessageProxiedJSONString.data(using: .utf8),
- let jsonData = try? JSONSerialization.jsonObject(with: data) as? [AnyHashable: Any]
- else { return [:] }
- return jsonData
- }
- public var lastMessage: NCChatMessage? {
- guard let lastMessageId else { return nil }
- var unmanagedChatMessage: NCChatMessage?
- if let managedChatMessage = NCChatMessage.objects(where: "internalId = %@", lastMessageId).firstObject() {
- unmanagedChatMessage = NCChatMessage(value: managedChatMessage)
- }
- return unmanagedChatMessage
- }
- public var linkURL: String? {
- guard let account = NCDatabaseManager.sharedInstance().talkAccount(forAccountId: self.accountId),
- let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: self.accountId),
- let token = self.token
- else { return nil }
- var indexString = "/index.php"
- if serverCapabilities.modRewriteWorking {
- indexString = ""
- }
- return "\(account.server)\(indexString)/call/\(token)"
- }
- }
|