mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-03-30 20:45:49 +00:00
* rfc: bot messages and buttons * update * update bot rfc * core: add bot commands to chat preferences and peer type to profile * update postgresql schema * update query plans * chat sessions preference * markdown for bot commands * schema * core: file preference, options to create bot from CLI * core: different command type * ios: commands menu * update types * update ios * improve command markdown * core, ios: update types * android, desktop: clickable commands in messages in chats with bots * android, desktop: commands menu * command menu button, bot icon * ios: connect flow for bots * android, desktop: connect flow for bots * icon * CLI commands to view and set commands, remove "hidden" property of command, bot api docs * corrections * fix inheriting profile preferences to business groups * note on business address * ios: export localizations * fix test * commands to set file preference on user/contact, tidy up layout and display of command and attachment buttons
115 lines
3.7 KiB
Swift
115 lines
3.7 KiB
Swift
//
|
|
// ChatUtils.swift
|
|
// SimpleXChat
|
|
//
|
|
// Created by Levitating Pineapple on 15/07/2024.
|
|
// Copyright © 2024 SimpleX Chat. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
public protocol ChatLike {
|
|
var chatInfo: ChatInfo { get}
|
|
var chatItems: [ChatItem] { get }
|
|
var chatStats: ChatStats { 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 .reports: p.reports.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]) -> [C] {
|
|
var filteredChats = chats.filter { c in
|
|
c.chatInfo.chatType != .local && canForwardToChat(c.chatInfo)
|
|
}
|
|
if 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 chatIconName(_ cInfo: ChatInfo) -> String {
|
|
switch cInfo {
|
|
case let .direct(contact): contact.chatIconName
|
|
case let .group(groupInfo, _): groupInfo.chatIconName
|
|
case .local: "folder.circle.fill"
|
|
case .contactRequest: "person.crop.circle.fill"
|
|
default: "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 })
|
|
}
|