Files
simplex-chat/apps/ios/SimpleXChat/ChatUtils.swift
EvgenyandEvgeny @ SimpleX Chat 77f9f4a464 core: add peer type "agent" (#7738)
* add agent peer type

* bot types

* agent app icons

* refactor

* smaller image

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-17 19:23:53 +01:00

116 lines
3.8 KiB
Swift

//
// ChatUtils.swift
// SimpleXChat
//
// Created by Levitating Pineapple on 15/07/2024.
// Copyright © 2024 SimpleX Chat. All rights reserved.
//
import Foundation
import SwiftUI
public protocol ChatLike {
var chatInfo: ChatInfo { get }
}
extension ChatLike {
public func groupFeatureEnabled(_ feature: GroupFeature) -> Bool {
if case let .group(groupInfo, _) = self.chatInfo {
let p = groupInfo.fullGroupPreferences
return switch feature {
case .timedMessages: p.timedMessages.on
case .directMessages: p.directMessages.on(for: groupInfo.membership)
case .fullDelete: p.fullDelete.on
case .reactions: p.reactions.on
case .voice: p.voice.on(for: groupInfo.membership)
case .files: p.files.on(for: groupInfo.membership)
case .simplexLinks: p.simplexLinks.on(for: groupInfo.membership)
case .history: p.history.on
case .support: p.support.on
case .reports: p.reports.on
case .signMessages: p.signMessages.on
}
} else {
return true
}
}
public func prohibitedByPref(
hasSimplexLink: Bool,
isMediaOrFileAttachment: Bool,
isVoice: Bool
) -> Bool {
// preference checks should match checks in compose view
let simplexLinkProhibited = hasSimplexLink && !groupFeatureEnabled(.simplexLinks)
let fileProhibited = isMediaOrFileAttachment && !groupFeatureEnabled(.files)
let voiceProhibited = isVoice && !chatInfo.featureEnabled(.voice)
return switch chatInfo {
case .direct: voiceProhibited
case .group: simplexLinkProhibited || fileProhibited || voiceProhibited
case .local: false
case .contactRequest: false
case .contactConnection: false
case .invalidJSON: false
}
}
}
public func filterChatsToForwardTo<C: ChatLike>(chats: [C], includeLocal: Bool = true) -> [C] {
var filteredChats = chats.filter { c in
c.chatInfo.chatType != .local && canForwardToChat(c.chatInfo)
}
if includeLocal, let privateNotes = chats.first(where: { $0.chatInfo.chatType == .local }) {
filteredChats.insert(privateNotes, at: 0)
}
return filteredChats
}
public func foundChat(_ chat: ChatLike, _ searchStr: String) -> Bool {
let cInfo = chat.chatInfo
return switch cInfo {
case let .direct(contact):
viewNameContains(cInfo, searchStr) ||
contact.profile.displayName.localizedLowercase.contains(searchStr) ||
contact.fullName.localizedLowercase.contains(searchStr)
default:
viewNameContains(cInfo, searchStr)
}
func viewNameContains(_ cInfo: ChatInfo, _ s: String) -> Bool {
cInfo.chatViewName.localizedLowercase.contains(s)
}
}
private func canForwardToChat(_ cInfo: ChatInfo) -> Bool {
switch cInfo {
case let .direct(contact): cInfo.sendMsgEnabled && !contact.sendMsgToConnect
case .group: cInfo.sendMsgEnabled
case .local: cInfo.sendMsgEnabled
case .contactRequest: false
case .contactConnection: false
case .invalidJSON: false
}
}
public func chatIcon(_ cInfo: ChatInfo) -> Image {
switch cInfo {
case let .direct(contact): contact.chatIcon
case let .group(groupInfo, _): Image(systemName: groupInfo.chatIconName)
case .local: Image(systemName: "folder.circle.fill")
case .contactRequest: Image(systemName: "person.crop.circle.fill")
default: Image(systemName: "circle.fill")
}
}
public func hasSimplexLink(_ text: String?) -> Bool {
if let text, let parsedMsg = parseSimpleXMarkdown(text) {
parsedMsgHasSimplexLink(parsedMsg)
} else {
false
}
}
public func parsedMsgHasSimplexLink(_ parsedMsg: [FormattedText]) -> Bool {
parsedMsg.contains(where: { ft in ft.format?.isSimplexLink ?? false })
}