mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
wip
This commit is contained in:
@@ -486,7 +486,7 @@ struct ChatView: View {
|
||||
HStack {
|
||||
if let directMember = directMember {
|
||||
ProfileImage(imageStr: directMember.image)
|
||||
.frame(width: 30, height: 30)
|
||||
.frame(width: 20, height: 20)
|
||||
.onTapGesture { selectedMember = directMember }
|
||||
.appSheet(item: $selectedMember) { member in
|
||||
GroupMemberInfoView(groupInfo: groupInfo, member: directMember, navigation: true)
|
||||
@@ -550,6 +550,8 @@ struct ChatView: View {
|
||||
@State private var playbackState: VoiceMessagePlaybackState = .noPlayback
|
||||
@State private var playbackTime: TimeInterval?
|
||||
|
||||
@State private var allowMemberMenu: Bool = true
|
||||
|
||||
var body: some View {
|
||||
let alignment: Alignment = ci.chatDir.sent ? .trailing : .leading
|
||||
let uiMenu: Binding<UIMenu> = Binding(
|
||||
@@ -642,7 +644,15 @@ struct ChatView: View {
|
||||
menu.append(rm)
|
||||
}
|
||||
if ci.meta.itemDeleted == nil && !ci.isLiveDummy && !live {
|
||||
menu.append(replyUIAction())
|
||||
if ci.directMember == nil {
|
||||
menu.append(replyUIAction())
|
||||
}
|
||||
if case let .group(groupInfo) = chat.chatInfo,
|
||||
let toDirectMember = ci.memberToReplyDirectlyTo,
|
||||
let toDirectMemberWithConn = ChatModel.shared.getGroupMember(toDirectMember.groupMemberId),
|
||||
toDirectMemberWithConn.allowedToSendDirectlyTo(groupInfo: groupInfo) {
|
||||
menu.append(replyDirectlyUIAction(toDirectMemberWithConn, groupInfo))
|
||||
}
|
||||
}
|
||||
menu.append(shareUIAction())
|
||||
menu.append(copyUIAction())
|
||||
@@ -697,7 +707,45 @@ struct ChatView: View {
|
||||
if composeState.editing {
|
||||
composeState = ComposeState(contextItem: .quotedItem(chatItem: ci))
|
||||
} else {
|
||||
composeState = composeState.copy(contextItem: .quotedItem(chatItem: ci))
|
||||
composeState = composeState.copy(
|
||||
directMember: .noDirectMember,
|
||||
contextItem: .quotedItem(chatItem: ci)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func replyDirectlyUIAction(_ toDirectMember: GroupMember, _ groupInfo: GroupInfo) -> UIAction {
|
||||
UIAction(
|
||||
title: NSLocalizedString("Reply directly", comment: "chat item action"),
|
||||
image: UIImage(systemName: "arrowshape.turn.up.left")
|
||||
) { _ in
|
||||
let canSend = toDirectMember.canSendDirectlyTo(groupInfo: groupInfo)
|
||||
switch canSend {
|
||||
case .notConnected:
|
||||
AlertManager.shared.showAlert(Alert(
|
||||
title: Text("Can't send directly!"),
|
||||
message: Text("Member is not connected.")
|
||||
))
|
||||
case .notSupported:
|
||||
AlertManager.shared.showAlert(Alert(
|
||||
title: Text("Can't send directly!"),
|
||||
message: Text("Member doesn't support this feature, ask them to update.")
|
||||
))
|
||||
case .canSend:
|
||||
withAnimation {
|
||||
if composeState.editing {
|
||||
composeState = ComposeState(
|
||||
directMember: .directMember(groupMember: toDirectMember),
|
||||
contextItem: .quotedItem(chatItem: ci)
|
||||
)
|
||||
} else {
|
||||
composeState = composeState.copy(
|
||||
directMember: .directMember(groupMember: toDirectMember),
|
||||
contextItem: .quotedItem(chatItem: ci)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,6 +273,7 @@ struct ComposeView: View {
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
contextDirectMemberView()
|
||||
contextItemView()
|
||||
switch (composeState.editing, composeState.preview) {
|
||||
case (true, .filePreview): EmptyView()
|
||||
@@ -605,7 +606,10 @@ struct ComposeView: View {
|
||||
case let .directMember(groupMember):
|
||||
ContextDirectMemberView(
|
||||
directMember: groupMember,
|
||||
cancelDirectMemberContext: { composeState = composeState.copy(directMember: .directMemberCancelled) }
|
||||
cancelDirectMemberContext: { composeState = composeState.copy(
|
||||
directMember: .directMemberCancelled,
|
||||
contextItem: .noContextItem
|
||||
)}
|
||||
)
|
||||
case .directMemberCancelled:
|
||||
ContextDirectMemberView(
|
||||
|
||||
@@ -17,9 +17,11 @@ struct ContextDirectMemberView: View {
|
||||
var body: some View {
|
||||
HStack {
|
||||
if let directMember = directMember {
|
||||
ProfileImage(imageStr: directMember.image)
|
||||
.frame(width: 30, height: 30)
|
||||
.padding(.trailing, 2)
|
||||
if let image = directMember.image {
|
||||
ProfileImage(imageStr: directMember.image)
|
||||
.frame(width: 30, height: 30)
|
||||
.padding(.trailing, 2)
|
||||
}
|
||||
Text("Directly to \(directMember.chatViewName)")
|
||||
.lineLimit(1)
|
||||
} else {
|
||||
|
||||
@@ -1807,6 +1807,30 @@ public struct GroupMember: Identifiable, Decodable {
|
||||
return GroupMemberRole.allCases.filter { $0 <= userRole }
|
||||
}
|
||||
|
||||
public func allowedToSendDirectlyTo(groupInfo: GroupInfo) -> Bool {
|
||||
let userRole = groupInfo.membership.memberRole
|
||||
return (
|
||||
(groupInfo.fullGroupPreferences.directMessages.on && userRole >= .author)
|
||||
|| userRole >= .admin
|
||||
|| memberRole >= .admin
|
||||
)
|
||||
}
|
||||
|
||||
public enum CanSendDirectlyTo {
|
||||
case canSend
|
||||
case notConnected
|
||||
case notSupported
|
||||
}
|
||||
|
||||
public func canSendDirectlyTo(groupInfo: GroupInfo) -> CanSendDirectlyTo {
|
||||
// TODO group-direct: check version
|
||||
if let activeConn = activeConn {
|
||||
return .canSend
|
||||
} else {
|
||||
return .notConnected
|
||||
}
|
||||
}
|
||||
|
||||
public var memberIncognito: Bool {
|
||||
memberProfile.profileId != memberContactProfileId
|
||||
}
|
||||
@@ -1834,6 +1858,7 @@ public struct GroupMemberRef: Decodable {
|
||||
|
||||
public enum GroupMemberRole: String, Identifiable, CaseIterable, Comparable, Decodable {
|
||||
case observer = "observer"
|
||||
case author = "author"
|
||||
case member = "member"
|
||||
case admin = "admin"
|
||||
case owner = "owner"
|
||||
@@ -1843,6 +1868,7 @@ public enum GroupMemberRole: String, Identifiable, CaseIterable, Comparable, Dec
|
||||
public var text: String {
|
||||
switch self {
|
||||
case .observer: return NSLocalizedString("observer", comment: "member role")
|
||||
case .author: return NSLocalizedString("author", comment: "member role")
|
||||
case .member: return NSLocalizedString("member", comment: "member role")
|
||||
case .admin: return NSLocalizedString("admin", comment: "member role")
|
||||
case .owner: return NSLocalizedString("owner", comment: "member role")
|
||||
@@ -1852,9 +1878,10 @@ public enum GroupMemberRole: String, Identifiable, CaseIterable, Comparable, Dec
|
||||
private var comparisonValue: Int {
|
||||
switch self {
|
||||
case .observer: return 0
|
||||
case .member: return 1
|
||||
case .admin: return 2
|
||||
case .owner: return 3
|
||||
case .author: return 1
|
||||
case .member: return 2
|
||||
case .admin: return 3
|
||||
case .owner: return 4
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2141,6 +2168,14 @@ public struct ChatItem: Identifiable, Decodable {
|
||||
}
|
||||
}
|
||||
|
||||
public var memberToReplyDirectlyTo: GroupMember? {
|
||||
switch chatDir {
|
||||
case let .groupSnd(directMember): return directMember
|
||||
case let .groupRcv(groupMember, _): return groupMember
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
public func memberToModerate(_ chatInfo: ChatInfo) -> (GroupInfo, GroupMember)? {
|
||||
switch (chatInfo, chatDir) {
|
||||
case let (.group(groupInfo), .groupRcv(groupMember, .msGroup)):
|
||||
@@ -2254,7 +2289,6 @@ public struct ChatItem: Identifiable, Decodable {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO group-direct: possibly this has to take sendRef as parameter instead (for directMember)
|
||||
public static func liveDummy(_ chatType: ChatType) -> ChatItem {
|
||||
var item = ChatItem(
|
||||
chatDir: chatType == ChatType.direct ? CIDirection.directSnd : CIDirection.groupSnd(directMember: nil),
|
||||
|
||||
+1
-1
@@ -1633,7 +1633,7 @@ data class ChatItem (
|
||||
@Serializable
|
||||
enum class MessageScope(val messageScope: String) {
|
||||
@SerialName("group") MSGroup("group"),
|
||||
@SerialName("private") MSDirect("direct");
|
||||
@SerialName("direct") MSDirect("direct");
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
||||
Reference in New Issue
Block a user