ios: disable chats in share-sheet based on preferences (#4549)

* claenup

* cleanup

* remove groupFeatureEnabled from Chat

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
Arturs Krumins
2024-08-01 09:48:17 +03:00
committed by GitHub
parent 19cab39ee8
commit cbc86cd81e
6 changed files with 92 additions and 57 deletions

View File

@@ -871,24 +871,6 @@ final class Chat: ObservableObject, Identifiable, ChatLike {
var viewId: String { get { "\(chatInfo.id) \(created.timeIntervalSince1970)" } }
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
}
} else {
return true
}
}
public static var sampleData: Chat = Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: [])
}

View File

@@ -21,7 +21,6 @@ struct ChatItemForwardingView: View {
@State private var searchText: String = ""
@FocusState private var searchFocused
@State private var alert: SomeAlert?
@State private var hasSimplexLink_: Bool?
private let chatsToForwardTo = filterChatsToForwardTo(chats: ChatModel.shared.chats)
var body: some View {
@@ -67,34 +66,6 @@ struct ChatItemForwardingView: View {
}
}
private func prohibitedByPref(_ chat: Chat) -> Bool {
// preference checks should match checks in compose view
let simplexLinkProhibited = hasSimplexLink && !chat.groupFeatureEnabled(.simplexLinks)
let fileProhibited = (ci.content.msgContent?.isMediaOrFileAttachment ?? false) && !chat.groupFeatureEnabled(.files)
let voiceProhibited = (ci.content.msgContent?.isVoice ?? false) && !chat.chatInfo.featureEnabled(.voice)
return switch chat.chatInfo {
case .direct: voiceProhibited
case .group: simplexLinkProhibited || fileProhibited || voiceProhibited
case .local: false
case .contactRequest: false
case .contactConnection: false
case .invalidJSON: false
}
}
private var hasSimplexLink: Bool {
if let hasSimplexLink_ { return hasSimplexLink_ }
let r =
if let mcText = ci.content.msgContent?.text,
let parsedMsg = parseSimpleXMarkdown(mcText) {
parsedMsgHasSimplexLink(parsedMsg)
} else {
false
}
hasSimplexLink_ = r
return r
}
private func emptyList() -> some View {
Text("No filtered chats")
.foregroundColor(theme.colors.secondary)
@@ -102,7 +73,11 @@ struct ChatItemForwardingView: View {
}
@ViewBuilder private func forwardListChatView(_ chat: Chat) -> some View {
let prohibited = prohibitedByPref(chat)
let prohibited = chat.prohibitedByPref(
hasSimplexLink: hasSimplexLink(ci.content.msgContent?.text),
isMediaOrFileAttachment: ci.content.msgContent?.isMediaOrFileAttachment ?? false,
isVoice: ci.content.msgContent?.isVoice ?? false
)
Button {
if prohibited {
alert = SomeAlert(

View File

@@ -1120,10 +1120,6 @@ struct ComposeView: View {
}
}
func parsedMsgHasSimplexLink(_ parsedMsg: [FormattedText]) -> Bool {
parsedMsg.contains(where: { ft in ft.format?.isSimplexLink ?? false })
}
struct ComposeView_Previews: PreviewProvider {
static var previews: some View {
let chat = Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: [])

View File

@@ -27,6 +27,7 @@ class ShareModel: ObservableObject {
@Published var isLoaded = false
@Published var bottomBar: BottomBar = .loadingSpinner
@Published var errorAlert: ErrorAlert?
@Published var hasSimplexLink = false
@Published var alertRequiresPassword = false
enum BottomBar {
@@ -49,7 +50,13 @@ class ShareModel: ObservableObject {
private var itemProvider: NSItemProvider?
var isSendDisbled: Bool { sharedContent == nil || selected == nil }
var isSendDisbled: Bool { sharedContent == nil || selected == nil || isProhibited(selected) }
func isProhibited(_ chat: ChatData?) -> Bool {
if let chat, let sharedContent {
sharedContent.prohibited(in: chat, hasSimplexLink: hasSimplexLink)
} else { false }
}
var filteredChats: Array<ChatData> {
search.isEmpty
@@ -379,6 +386,14 @@ enum SharedContent {
case .data: .file(comment)
}
}
func prohibited(in chatData: ChatData, hasSimplexLink: Bool) -> Bool {
chatData.prohibitedByPref(
hasSimplexLink: hasSimplexLink,
isMediaOrFileAttachment: cryptoFile != nil,
isVoice: false
)
}
}
extension NSItemProvider {

View File

@@ -20,18 +20,31 @@ struct ShareView: View {
ZStack(alignment: .bottom) {
if model.isLoaded {
List(model.filteredChats) { chat in
let isProhibited = model.isProhibited(chat)
let isSelected = model.selected == chat
HStack {
profileImage(
chatInfoId: chat.chatInfo.id,
iconName: chatIconName(chat.chatInfo),
size: 30
)
Text(chat.chatInfo.displayName)
Text(chat.chatInfo.displayName).foregroundStyle(
isProhibited ? .secondary : .primary
)
Spacer()
radioButton(selected: chat == model.selected)
radioButton(selected: isSelected && !isProhibited)
}
.contentShape(Rectangle())
.onTapGesture { model.selected = model.selected == chat ? nil : chat }
.onTapGesture {
if isProhibited {
model.errorAlert = ErrorAlert(
title: "Cannot forward message",
message: "Selected chat preferences prohibit this message."
) { Button("Ok", role: .cancel) { } }
} else {
model.selected = isSelected ? nil : chat
}
}
.tag(chat)
}
} else {
@@ -66,6 +79,9 @@ struct ShareView: View {
Button("Ok") { model.completion() }
}
}
.onChange(of: model.comment) {
model.hasSimplexLink = hasSimplexLink($0)
}
}
private func compose(isLoading: Bool) -> some View {
@@ -77,7 +93,7 @@ struct ShareView: View {
HStack {
Group {
if #available(iOSApplicationExtension 16.0, *) {
TextField("Comment", text: $model.comment, axis: .vertical)
TextField("Comment", text: $model.comment, axis: .vertical).lineLimit(6)
} else {
TextField("Comment", text: $model.comment)
}

View File

@@ -14,6 +14,45 @@ public protocol ChatLike {
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
}
} 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)
@@ -60,3 +99,15 @@ public func chatIconName(_ cInfo: ChatInfo) -> String {
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 })
}