core, mobile: add group feature to allow direct messages (#1465)

* core, mobile: split group features to a separate type (to add directAllowed later)

* add directMessages group feature, update tests
This commit is contained in:
Evgeny Poberezkin
2022-11-29 15:19:20 +00:00
committed by GitHub
parent 303aeaaba5
commit 1872744543
25 changed files with 334 additions and 164 deletions

View File

@@ -29,6 +29,6 @@ struct CIChatFeatureView: View {
struct CIChatFeatureView_Previews: PreviewProvider {
static var previews: some View {
let enabled = FeatureEnabled(forUser: false, forContact: false)
CIChatFeatureView(chatItem: ChatItem.getChatFeatureSample(.fullDelete, enabled), feature: .fullDelete, iconColor: enabled.iconColor)
CIChatFeatureView(chatItem: ChatItem.getChatFeatureSample(.fullDelete, enabled), feature: ChatFeature.fullDelete, iconColor: enabled.iconColor)
}
}

View File

@@ -36,6 +36,7 @@ struct ChatItemView: View {
case let .rcvGroupFeature(feature, preference): chatFeatureView(feature, preference.enable.iconColor)
case let .sndGroupFeature(feature, preference): chatFeatureView(feature, preference.enable.iconColor)
case let .rcvChatFeatureRejected(feature): chatFeatureView(feature, .red)
case let .rcvGroupFeatureRejected(feature): chatFeatureView(feature, .red)
}
}

View File

@@ -32,7 +32,7 @@ struct ContactPreferencesView: View {
}
}
private func featureSection(_ feature: Feature, _ userDefault: FeatureAllowed, _ pref: ContactUserPreference, _ allowFeature: Binding<ContactFeatureAllowed>) -> some View {
private func featureSection(_ feature: ChatFeature, _ userDefault: FeatureAllowed, _ pref: ContactUserPreference, _ allowFeature: Binding<ContactFeatureAllowed>) -> some View {
let enabled = FeatureEnabled.enabled(
user: Preference(allow: allowFeature.wrappedValue.allowed),
contact: pref.contactPreference

View File

@@ -42,7 +42,7 @@ struct GroupMemberInfoView: View {
groupMemberInfoHeader(member)
.listRowBackground(Color.clear)
if let contactId = member.memberContactId {
if let contactId = member.memberContactId, groupInfo.fullGroupPreferences.directMessages.enable == .on {
Section {
openDirectChatButton(contactId)
}

View File

@@ -19,6 +19,7 @@ struct GroupPreferencesView: View {
VStack {
List {
// featureSection(.fullDelete, $preferences.fullDelete.enable)
featureSection(.directMessages, $preferences.directMessages.enable)
featureSection(.voice, $preferences.voice.enable)
if groupInfo.canEdit {
@@ -32,7 +33,7 @@ struct GroupPreferencesView: View {
}
}
private func featureSection(_ feature: Feature, _ enableFeature: Binding<GroupFeatureEnabled>) -> some View {
private func featureSection(_ feature: GroupFeature, _ enableFeature: Binding<GroupFeatureEnabled>) -> some View {
Section {
if (groupInfo.canEdit) {
settingsRow(feature.icon) {
@@ -50,7 +51,7 @@ struct GroupPreferencesView: View {
}
}
} footer: {
Text(feature.enableGroupPrefDescription(enableFeature.wrappedValue, groupInfo.canEdit))
Text(feature.enableDescription(enableFeature.wrappedValue, groupInfo.canEdit))
.frame(height: 36, alignment: .topLeading)
}
}

View File

@@ -30,7 +30,7 @@ struct PreferencesView: View {
}
}
private func featureSection(_ feature: Feature, _ allowFeature: Binding<FeatureAllowed>) -> some View {
private func featureSection(_ feature: ChatFeature, _ allowFeature: Binding<FeatureAllowed>) -> some View {
Section {
settingsRow(feature.icon) {
Picker(feature.text, selection: allowFeature) {

View File

@@ -245,11 +245,15 @@ public enum ContactUserPref: Decodable {
}
}
public enum Feature: String, Decodable {
public protocol Feature {
var iconFilled: String { get }
}
public enum ChatFeature: String, Decodable, Feature {
case fullDelete
case voice
public var values: [Feature] { [.fullDelete, .voice] }
public var values: [ChatFeature] { [.fullDelete, .voice] }
public var id: Self { self }
@@ -311,10 +315,49 @@ public enum Feature: String, Decodable {
: "Voice messages are prohibited in this chat."
}
}
}
public func enableGroupPrefDescription(_ enabled: GroupFeatureEnabled, _ canEdit: Bool) -> LocalizedStringKey {
public enum GroupFeature: String, Decodable, Feature {
case fullDelete
case voice
case directMessages
public var values: [GroupFeature] { [.directMessages, .fullDelete, .voice] }
public var id: Self { self }
public var text: String {
switch self {
case .directMessages: return NSLocalizedString("Direct messages", comment: "chat feature")
case .fullDelete: return NSLocalizedString("Full deletion", comment: "chat feature")
case .voice: return NSLocalizedString("Voice messages", comment: "chat feature")
}
}
public var icon: String {
switch self {
case .directMessages: return "arrow.left.and.right.circle"
case .fullDelete: return "trash.slash"
case .voice: return "mic"
}
}
public var iconFilled: String {
switch self {
case .directMessages: return "arrow.left.and.right.circle.fill"
case .fullDelete: return "trash.slash.fill"
case .voice: return "mic.fill"
}
}
public func enableDescription(_ enabled: GroupFeatureEnabled, _ canEdit: Bool) -> LocalizedStringKey {
if canEdit {
switch self {
case .directMessages:
switch enabled {
case .on: return "Allow sending direct messages to members."
case .off: return "Prohibit sending direct messages to members."
}
case .fullDelete:
switch enabled {
case .on: return "Allow to irreversibly delete sent messages."
@@ -328,15 +371,20 @@ public enum Feature: String, Decodable {
}
} else {
switch self {
case .directMessages:
switch enabled {
case .on: return "Group members can send direct messages."
case .off: return "Direct messages between members are prohibited in this group."
}
case .fullDelete:
switch enabled {
case .on: return "Group members can irreversibly delete sent messages."
case .off: return "Irreversible message deletion is prohibited in this chat."
case .off: return "Irreversible message deletion is prohibited in this group."
}
case .voice:
switch enabled {
case .on: return "Group members can send voice messages."
case .off: return "Voice messages are prohibited in this chat."
case .off: return "Voice messages are prohibited in this group."
}
}
}
@@ -443,31 +491,35 @@ public enum FeatureAllowed: String, Codable, Identifiable {
}
public struct FullGroupPreferences: Decodable, Equatable {
public var directMessages: GroupPreference
public var fullDelete: GroupPreference
public var voice: GroupPreference
public init(fullDelete: GroupPreference, voice: GroupPreference) {
public init(directMessages: GroupPreference, fullDelete: GroupPreference, voice: GroupPreference) {
self.directMessages = directMessages
self.fullDelete = fullDelete
self.voice = voice
}
public static let sampleData = FullGroupPreferences(fullDelete: GroupPreference(enable: .off), voice: GroupPreference(enable: .on))
public static let sampleData = FullGroupPreferences(directMessages: GroupPreference(enable: .off), fullDelete: GroupPreference(enable: .off), voice: GroupPreference(enable: .on))
}
public struct GroupPreferences: Codable {
public var directMessages: GroupPreference?
public var fullDelete: GroupPreference?
public var voice: GroupPreference?
public init(fullDelete: GroupPreference?, voice: GroupPreference?) {
public init(directMessages: GroupPreference?, fullDelete: GroupPreference?, voice: GroupPreference?) {
self.directMessages = directMessages
self.fullDelete = fullDelete
self.voice = voice
}
public static let sampleData = GroupPreferences(fullDelete: GroupPreference(enable: .off), voice: GroupPreference(enable: .on))
public static let sampleData = GroupPreferences(directMessages: GroupPreference(enable: .off), fullDelete: GroupPreference(enable: .off), voice: GroupPreference(enable: .on))
}
public func toGroupPreferences(_ fullPreferences: FullGroupPreferences) -> GroupPreferences {
GroupPreferences(fullDelete: fullPreferences.fullDelete, voice: fullPreferences.voice)
GroupPreferences(directMessages: fullPreferences.directMessages, fullDelete: fullPreferences.fullDelete, voice: fullPreferences.voice)
}
public struct GroupPreference: Codable, Equatable {
@@ -1371,6 +1423,7 @@ public struct ChatItem: Identifiable, Decodable {
case .rcvGroupFeature: return false
case .sndGroupFeature: return showNtfDir
case .rcvChatFeatureRejected: return showNtfDir
case .rcvGroupFeatureRejected: return showNtfDir
}
}
@@ -1462,7 +1515,7 @@ public struct ChatItem: Identifiable, Decodable {
)
}
public static func getChatFeatureSample(_ feature: Feature, _ enabled: FeatureEnabled) -> ChatItem {
public static func getChatFeatureSample(_ feature: ChatFeature, _ enabled: FeatureEnabled) -> ChatItem {
let content = CIContent.rcvChatFeature(feature: feature, enabled: enabled)
return ChatItem(
chatDir: .directRcv,
@@ -1573,11 +1626,12 @@ public enum CIContent: Decodable, ItemContent {
case sndGroupEvent(sndGroupEvent: SndGroupEvent)
case rcvConnEvent(rcvConnEvent: RcvConnEvent)
case sndConnEvent(sndConnEvent: SndConnEvent)
case rcvChatFeature(feature: Feature, enabled: FeatureEnabled)
case sndChatFeature(feature: Feature, enabled: FeatureEnabled)
case rcvGroupFeature(feature: Feature, preference: GroupPreference)
case sndGroupFeature(feature: Feature, preference: GroupPreference)
case rcvChatFeatureRejected(feature: Feature)
case rcvChatFeature(feature: ChatFeature, enabled: FeatureEnabled)
case sndChatFeature(feature: ChatFeature, enabled: FeatureEnabled)
case rcvGroupFeature(groupFeature: GroupFeature, preference: GroupPreference)
case sndGroupFeature(groupFeature: GroupFeature, preference: GroupPreference)
case rcvChatFeatureRejected(feature: ChatFeature)
case rcvGroupFeatureRejected(groupFeature: GroupFeature)
public var text: String {
get {
@@ -1600,6 +1654,7 @@ public enum CIContent: Decodable, ItemContent {
case let .rcvGroupFeature(feature, preference): return "\(feature.text): \(preference.enable.text)"
case let .sndGroupFeature(feature, preference): return "\(feature.text): \(preference.enable.text)"
case let .rcvChatFeatureRejected(feature): return String.localizedStringWithFormat("%@: received, prohibited", feature.text)
case let .rcvGroupFeatureRejected(groupFeature): return String.localizedStringWithFormat("%@: received, prohibited", groupFeature.text)
}
}
}