diff --git a/Sources/ChatFeature/Controllers/GroupChatController.swift b/Sources/ChatFeature/Controllers/GroupChatController.swift index c6b0d6d224a35e3127b297267f5955cecb8be541..689bc36c514bcadaa759248cb2bf2e23748eb408 100644 --- a/Sources/ChatFeature/Controllers/GroupChatController.swift +++ b/Sources/ChatFeature/Controllers/GroupChatController.swift @@ -602,17 +602,21 @@ extension GroupChatController: UICollectionViewDelegate { self?.viewModel.retry(item) } - let menu: UIMenu + var children = [UIAction]() if item.status == .sendingFailed { - menu = UIMenu(title: "", children: [copy, retry, delete]) + children = [copy, retry, delete] } else if item.status == .sending { - menu = UIMenu(title: "", children: [copy]) + children = [copy] } else { - menu = UIMenu(title: "", children: [copy, reply, delete, report]) + children = [copy, reply, delete] + + if self.viewModel.isReportingEnabled { + children.append(report) + } } - return menu + return UIMenu(title: "", children: children) } } } diff --git a/Sources/ChatFeature/Controllers/SingleChatController.swift b/Sources/ChatFeature/Controllers/SingleChatController.swift index 03b182e5bb886051eb9c22e352fd65ef52f0619b..08aa3944146d0b4a482459bd372a973ec3816928 100644 --- a/Sources/ChatFeature/Controllers/SingleChatController.swift +++ b/Sources/ChatFeature/Controllers/SingleChatController.swift @@ -655,13 +655,20 @@ extension SingleChatController: UICollectionViewDelegate { guard let self = self else { return nil } let item = self.sections[indexPath.section].elements[indexPath.item] - return UIMenu(title: "", children: [ + var children = [ ActionFactory.build(from: item, action: .copy, closure: self.viewModel.didRequestCopy(_:)), ActionFactory.build(from: item, action: .retry, closure: self.viewModel.didRequestRetry(_:)), ActionFactory.build(from: item, action: .reply, closure: self.viewModel.didRequestReply(_:)), - ActionFactory.build(from: item, action: .delete, closure: self.viewModel.didRequestDeleteSingle(_:)), - ActionFactory.build(from: item, action: .report, closure: self.viewModel.didRequestReport(_:)) - ].compactMap { $0 }) + ActionFactory.build(from: item, action: .delete, closure: self.viewModel.didRequestDeleteSingle(_:)) + ] + + if self.viewModel.isReportingEnabled { + children.append( + ActionFactory.build(from: item, action: .report, closure: self.viewModel.didRequestReport(_:)) + ) + } + + return UIMenu(title: "", children: children.compactMap { $0 }) } } diff --git a/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift b/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift index e9ca955393db78a4ccfc23bb52089032647bfcde..420269748c9c903fc9c464ef9b4d2d3cc531d244 100644 --- a/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift +++ b/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift @@ -23,6 +23,7 @@ final class GroupChatViewModel { @Dependency private var toastController: ToastController @KeyObject(.username, defaultValue: nil) var username: String? + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool var hudPublisher: AnyPublisher<HUDStatus, Never> { hudSubject.eraseToAnyPublisher() @@ -130,7 +131,7 @@ final class GroupChatViewModel { var name = (contact.nickname ?? contact.username) ?? "Fetching username..." - if contact.isBlocked { + if contact.isBlocked, isReportingEnabled { name = "\(name) (Blocked)" } diff --git a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift index 8ba933ad52ff63b6beca403e84bd688ccb043ac9..e08b4df2d74000446b9eafc65292168ac5f24766 100644 --- a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift +++ b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift @@ -33,6 +33,7 @@ final class SingleChatViewModel: NSObject { @Dependency private var sendReport: SendReport @KeyObject(.username, defaultValue: nil) var username: String? + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool var contact: Contact { contactSubject.value } private var stagedReply: Reply? diff --git a/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift b/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift index d3918b04206d620af85be2266599369bf9ab85ea..266d095df5c1201df43d39292a4a860201185d21 100644 --- a/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift +++ b/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift @@ -24,6 +24,8 @@ typealias SearchSnapshot = NSDiffableDataSourceSnapshot<SearchSection, SearchIte final class ChatListViewModel { @Dependency private var session: SessionType + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool + var isOnline: AnyPublisher<Bool, Never> { session.isOnline } @@ -37,7 +39,12 @@ final class ChatListViewModel { } var recentsPublisher: AnyPublisher<RecentsSnapshot, Never> { - let query = Contact.Query(isRecent: true, isBlocked: false, isBanned: false) + let query = Contact.Query( + isRecent: true, + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false : nil + ) + return session.dbManager.fetchContactsPublisher(query) .assertNoFailure() .map { @@ -50,8 +57,13 @@ final class ChatListViewModel { } var searchPublisher: AnyPublisher<SearchSnapshot, Never> { + let contactsQuery = Contact.Query( + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false : nil + ) + let contactsStream = session.dbManager - .fetchContactsPublisher(.init(isBlocked: false, isBanned: false)) + .fetchContactsPublisher(contactsQuery) .assertNoFailure() .map { $0.filter { $0.id != self.session.myId }} @@ -107,13 +119,17 @@ final class ChatListViewModel { var badgeCountPublisher: AnyPublisher<Int, Never> { let groupQuery = Group.Query(authStatus: [.pending]) - let contactsQuery = Contact.Query(authStatus: [ - .verified, - .confirming, - .confirmationFailed, - .verificationFailed, - .verificationInProgress - ], isBlocked: false, isBanned: false) + let contactsQuery = Contact.Query( + authStatus: [ + .verified, + .confirming, + .confirmationFailed, + .verificationFailed, + .verificationInProgress + ], + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false : nil + ) return Publishers.CombineLatest( session.dbManager.fetchContactsPublisher(contactsQuery).assertNoFailure(), @@ -134,12 +150,12 @@ final class ChatListViewModel { contactChatInfoQuery: .init( userId: session.myId, authStatus: [.friend], - isBlocked: false, - isBanned: false + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false : nil ), groupChatInfoQuery: GroupChatInfo.Query( authStatus: [.participating], - excludeBannedContactsMessages: true + excludeBannedContactsMessages: isReportingEnabled ), groupQuery: Group.Query( withMessages: false, diff --git a/Sources/ContactListFeature/ViewModels/ContactListViewModel.swift b/Sources/ContactListFeature/ViewModels/ContactListViewModel.swift index d0915822da605d047de525c55470c6802d983d1f..35711caf508a90002b263cbbdf98dc3409692b6e 100644 --- a/Sources/ContactListFeature/ViewModels/ContactListViewModel.swift +++ b/Sources/ContactListFeature/ViewModels/ContactListViewModel.swift @@ -1,14 +1,21 @@ import Models import Combine import XXModels +import Defaults import Integration import DependencyInjection final class ContactListViewModel { @Dependency private var session: SessionType + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool + var contacts: AnyPublisher<[Contact], Never> { - let query = Contact.Query(authStatus: [.friend], isBlocked: false, isBanned: false) + let query = Contact.Query( + authStatus: [.friend], + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false: nil + ) return session.dbManager.fetchContactsPublisher(query) .assertNoFailure() @@ -17,14 +24,23 @@ final class ContactListViewModel { } var requestCount: AnyPublisher<Int, Never> { - let groupQuery = Group.Query(authStatus: [.pending], isLeaderBlocked: false, isLeaderBanned: false) - let contactsQuery = Contact.Query(authStatus: [ - .verified, - .confirming, - .confirmationFailed, - .verificationFailed, - .verificationInProgress - ], isBlocked: false, isBanned: false) + let groupQuery = Group.Query( + authStatus: [.pending], + isLeaderBlocked: isReportingEnabled ? false : nil, + isLeaderBanned: isReportingEnabled ? false : nil + ) + + let contactsQuery = Contact.Query( + authStatus: [ + .verified, + .confirming, + .confirmationFailed, + .verificationFailed, + .verificationInProgress + ], + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false : nil + ) return Publishers.CombineLatest( session.dbManager.fetchContactsPublisher(contactsQuery).assertNoFailure(), diff --git a/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift b/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift index 668b396b4f3955ceb8fb494234cd3cadf4f7b852..19cadc6ed8f5ea68341b223616f066dfeacf0cb9 100644 --- a/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift +++ b/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift @@ -9,6 +9,7 @@ import DependencyInjection final class CreateGroupViewModel { @KeyObject(.username, defaultValue: "") var username: String + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool // MARK: Injected @@ -42,7 +43,13 @@ final class CreateGroupViewModel { // MARK: Lifecycle init() { - session.dbManager.fetchContactsPublisher(.init(authStatus: [.friend], isBlocked: false, isBanned: false)) + let query = Contact.Query( + authStatus: [.friend], + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false : nil + ) + + session.dbManager.fetchContactsPublisher(query) .assertNoFailure() .map { $0.filter { $0.id != self.session.myId }} .map { $0.sorted(by: { $0.username! < $1.username! })} diff --git a/Sources/Defaults/KeyObject.swift b/Sources/Defaults/KeyObject.swift index 0ade4e83639f54a5181b4292936a2d9dee049f60..ddf8aa3aa7cddfe1bec7b0fb7c04563059f7718c 100644 --- a/Sources/Defaults/KeyObject.swift +++ b/Sources/Defaults/KeyObject.swift @@ -41,6 +41,9 @@ public enum Key: String { case dummyTrafficOn case askedDummyTrafficOnce + + case isReportingEnabled + case isReportingOptional } public struct KeyObjectStore { diff --git a/Sources/Integration/Session/Session.swift b/Sources/Integration/Session/Session.swift index 317a4bae5c3facf4a31635d6080ede594eb40fd9..02836d4833bf0d86cb48707f486da5166a8f3044 100644 --- a/Sources/Integration/Session/Session.swift +++ b/Sources/Integration/Session/Session.swift @@ -47,6 +47,7 @@ public final class Session: SessionType { @KeyObject(.icognitoKeyboard, defaultValue: false) var icognitoKeyboard: Bool @KeyObject(.pushNotifications, defaultValue: false) var pushNotifications: Bool @KeyObject(.inappnotifications, defaultValue: true) var inappnotifications: Bool + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool @Dependency var backupService: BackupService @Dependency var toastController: ToastController @@ -461,7 +462,7 @@ public final class Session: SessionType { } if let contact = try! dbManager.fetchContacts(.init(id: [request.0.leaderId])).first { - if contact.isBanned || contact.isBlocked { + if isReportingEnabled, (contact.isBlocked || contact.isBanned) { return } } diff --git a/Sources/LaunchFeature/LaunchViewModel.swift b/Sources/LaunchFeature/LaunchViewModel.swift index 399a87a87e183543ad4967ad805331ff4fc5b972..81b240eb52013e9d282cf014c7d90d22c8818bfa 100644 --- a/Sources/LaunchFeature/LaunchViewModel.swift +++ b/Sources/LaunchFeature/LaunchViewModel.swift @@ -42,6 +42,7 @@ final class LaunchViewModel { @KeyObject(.username, defaultValue: nil) var username: String? @KeyObject(.biometrics, defaultValue: false) var isBiometricsOn: Bool + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool var hudPublisher: AnyPublisher<HUDStatus, Never> { hudSubject.eraseToAnyPublisher() @@ -138,7 +139,12 @@ final class LaunchViewModel { } func getContactWith(userId: Data) -> Contact? { - let query = Contact.Query(id: [userId], isBlocked: false, isBanned: false) + let query = Contact.Query( + id: [userId], + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false : nil + ) + return try! session.dbManager.fetchContacts(query).first } diff --git a/Sources/MenuFeature/ViewModels/MenuViewModel.swift b/Sources/MenuFeature/ViewModels/MenuViewModel.swift index 35dfd9ec60fcfbe99889d710c1078a8823b871c0..62be1c13875d023997b03aca48e3feb333d1422e 100644 --- a/Sources/MenuFeature/ViewModels/MenuViewModel.swift +++ b/Sources/MenuFeature/ViewModels/MenuViewModel.swift @@ -10,16 +10,26 @@ final class MenuViewModel { @KeyObject(.avatar, defaultValue: nil) var avatar: Data? @KeyObject(.username, defaultValue: "") var username: String + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool var requestCount: AnyPublisher<Int, Never> { - let groupQuery = Group.Query(authStatus: [.pending], isLeaderBlocked: false, isLeaderBanned: false) - let contactsQuery = Contact.Query(authStatus: [ - .verified, - .confirming, - .confirmationFailed, - .verificationFailed, - .verificationInProgress - ], isBlocked: false, isBanned: false) + let groupQuery = Group.Query( + authStatus: [.pending], + isLeaderBlocked: isReportingEnabled ? false : nil, + isLeaderBanned: isReportingEnabled ? false : nil + ) + + let contactsQuery = Contact.Query( + authStatus: [ + .verified, + .confirming, + .confirmationFailed, + .verificationFailed, + .verificationInProgress + ], + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false : nil + ) return Publishers.CombineLatest( session.dbManager.fetchContactsPublisher(contactsQuery).assertNoFailure(), diff --git a/Sources/PushFeature/PushHandler.swift b/Sources/PushFeature/PushHandler.swift index 9afec9261f1ee12d72eea3b68605ea989124895f..8f29b148b6c6f9918e427b6058707bd8777d2415 100644 --- a/Sources/PushFeature/PushHandler.swift +++ b/Sources/PushFeature/PushHandler.swift @@ -12,6 +12,7 @@ public final class PushHandler: PushHandling { } @KeyObject(.pushNotifications, defaultValue: false) var isPushEnabled: Bool + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool let requestAuth: RequestAuth public static let defaultRequestAuth = UNUserNotificationCenter.current().requestAuthorization @@ -108,7 +109,7 @@ public final class PushHandler: PushHandling { return ($0.type.unknownSenderContent!, $0) } - if contact.isBlocked || contact.isBanned { + if isReportingEnabled, (contact.isBlocked || contact.isBanned) { return nil } diff --git a/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift index 5da72d12b6a71ae29f19367485d69777d308d05e..650777d18c0d5d68c62323f3b6be8f655666ce92 100644 --- a/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift +++ b/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift @@ -19,6 +19,7 @@ struct RequestReceived: Hashable, Equatable { final class RequestsReceivedViewModel { @Dependency private var session: SessionType + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool @KeyObject(.isShowingHiddenRequests, defaultValue: false) var isShowingHiddenRequests: Bool var hudPublisher: AnyPublisher<HUDStatus, Never> { @@ -56,7 +57,10 @@ final class RequestsReceivedViewModel { authStatus: [ .hidden, .pending - ], isLeaderBlocked: false, isLeaderBanned: false) + ], + isLeaderBlocked: isReportingEnabled ? false : nil, + isLeaderBanned: isReportingEnabled ? false : nil + ) let contactsQuery = Contact.Query( authStatus: [ @@ -65,7 +69,10 @@ final class RequestsReceivedViewModel { .verified, .verificationFailed, .verificationInProgress - ], isBlocked: false, isBanned: false) + ], + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false : nil + ) let groupStream = session.dbManager.fetchGroupsPublisher(groupsQuery).assertNoFailure() let contactsStream = session.dbManager.fetchContactsPublisher(contactsQuery).assertNoFailure() diff --git a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift index 26a6f485f1cb67721a301325e8eff5aefb917be5..fa902162c879b47cf2740c808f39223fe91c6a76 100644 --- a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift +++ b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift @@ -3,6 +3,7 @@ import UIKit import Models import Shared import Combine +import Defaults import XXModels import Integration import ToastFeature @@ -18,6 +19,8 @@ final class RequestsSentViewModel { @Dependency private var session: SessionType @Dependency private var toastController: ToastController + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool + var hudPublisher: AnyPublisher<HUDStatus, Never> { hudSubject.eraseToAnyPublisher() } @@ -33,10 +36,14 @@ final class RequestsSentViewModel { var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler() init() { - let query = Contact.Query(authStatus: [ - .requested, - .requesting - ], isBlocked: false, isBanned: false) + let query = Contact.Query( + authStatus: [ + .requested, + .requesting + ], + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false : nil + ) session.dbManager.fetchContactsPublisher(query) .assertNoFailure() diff --git a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift index d5ea157daa163ad4380bea16df04c72195e9b075..f7dfe937769b34cdc42b8b9441078e734841a294 100644 --- a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift +++ b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift @@ -3,6 +3,7 @@ import UIKit import Shared import Combine import XXModels +import Defaults import Countries import Integration import NetworkMonitor @@ -21,6 +22,8 @@ final class SearchLeftViewModel { @Dependency var session: SessionType @Dependency var networkMonitor: NetworkMonitoring + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool + var hudPublisher: AnyPublisher<HUDStatus, Never> { hudSubject.eraseToAnyPublisher() } @@ -150,7 +153,10 @@ final class SearchLeftViewModel { user.authStatus = contact.authStatus } - if user.authStatus != .friend, !user.isBanned, !user.isBlocked { + if user.authStatus != .friend, !isReportingEnabled { + snapshot.appendSections([.stranger]) + snapshot.appendItems([.stranger(user)], toSection: .stranger) + } else if user.authStatus != .friend, isReportingEnabled, !user.isBanned, !user.isBlocked { snapshot.appendSections([.stranger]) snapshot.appendItems([.stranger(user)], toSection: .stranger) } @@ -159,8 +165,8 @@ final class SearchLeftViewModel { let localsQuery = Contact.Query( text: stateSubject.value.input, authStatus: [.friend], - isBlocked: false, - isBanned: false + isBlocked: isReportingEnabled ? false : nil, + isBanned: isReportingEnabled ? false : nil ) if let locals = try? session.dbManager.fetchContacts(localsQuery), diff --git a/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift b/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift index 148db4ca424581596ccdea381a139ebfbb4cad11..e70b2d364aa68e6fc840260a3cdab275d83bdf0c 100644 --- a/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift +++ b/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift @@ -1,6 +1,7 @@ import Shared import Combine import XXModels +import Defaults import Foundation import Permissions import Integration @@ -24,6 +25,8 @@ final class SearchRightViewModel { @Dependency var session: SessionType @Dependency var permissions: PermissionHandling + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool + var foundPublisher: AnyPublisher<Contact, Never> { foundSubject.eraseToAnyPublisher() } @@ -78,12 +81,12 @@ final class SearchRightViewModel { /// that we already have /// if let alreadyContact = try? session.dbManager.fetchContacts(.init(id: [userId])).first { - if alreadyContact.isBlocked { + if alreadyContact.isBlocked, isReportingEnabled { statusSubject.send(.failed(.unknown("You previously blocked this user."))) return } - if alreadyContact.isBanned { + if alreadyContact.isBanned, isReportingEnabled { statusSubject.send(.failed(.unknown("This user was banned."))) return } diff --git a/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift b/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift index a7d92763d3116ec42ea3fd5c65f8282e69f45471..16d474d890f825d556f3b9d9d41039df75b2bc3c 100644 --- a/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift +++ b/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift @@ -61,17 +61,29 @@ public final class SettingsAdvancedController: UIViewController { .sink { [weak viewModel] in viewModel?.didToggleCrashReporting() } .store(in: &cancellables) + screenView.reportingSwitcher.switcherView + .publisher(for: .valueChanged) + .sink { [weak viewModel] in viewModel?.didToggleReporting() } + .store(in: &cancellables) + viewModel.sharePublisher .receive(on: DispatchQueue.main) .sink { [unowned self] in coordinator.toActivityController(with: [$0], from: self) } .store(in: &cancellables) + viewModel.state + .removeDuplicates() + .map(\.isReportingOptional) + .sink { [unowned self] in screenView.reportingSwitcher.isHidden = !$0 } + .store(in: &cancellables) + viewModel.state .removeDuplicates() .sink { [unowned self] state in screenView.logRecordingSwitcher.switcherView.setOn(state.isRecordingLogs, animated: true) screenView.crashReportingSwitcher.switcherView.setOn(state.isCrashReporting, animated: true) screenView.showUsernamesSwitcher.switcherView.setOn(state.isShowingUsernames, animated: true) + screenView.reportingSwitcher.switcherView.setOn(state.isReportingEnabled, animated: true) }.store(in: &cancellables) } } diff --git a/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift b/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift index 8717024458fee4281461d03a5c05649cca3ce576..60e7f5e777c700efbd5074c0176d5a217bc4a3b2 100644 --- a/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift +++ b/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift @@ -9,12 +9,17 @@ struct AdvancedViewState: Equatable { var isRecordingLogs = false var isCrashReporting = false var isShowingUsernames = false + var isReportingEnabled = false + var isReportingOptional = false } final class SettingsAdvancedViewModel { @KeyObject(.recordingLogs, defaultValue: true) var isRecordingLogs: Bool @KeyObject(.crashReporting, defaultValue: true) var isCrashReporting: Bool + @KeyObject(.isReportingEnabled, defaultValue: true) var isReportingEnabled: Bool + @KeyObject(.isReportingOptional, defaultValue: true) var isReportingOptional: Bool + private let isShowingUsernamesKey = "isShowingUsernames" @Dependency private var logger: XXLogger @@ -29,6 +34,8 @@ final class SettingsAdvancedViewModel { func loadCachedSettings() { stateRelay.value.isRecordingLogs = isRecordingLogs stateRelay.value.isCrashReporting = isCrashReporting + stateRelay.value.isReportingEnabled = isReportingEnabled + stateRelay.value.isReportingOptional = isReportingOptional guard let defaults = UserDefaults(suiteName: "group.elixxir.messenger") else { print("^^^ Couldn't access user defaults in the app group container \(#file):\(#line)") @@ -75,4 +82,9 @@ final class SettingsAdvancedViewModel { stateRelay.value.isCrashReporting.toggle() crashReporter.setEnabled(isCrashReporting) } + + func didToggleReporting() { + isReportingEnabled.toggle() + stateRelay.value.isReportingEnabled.toggle() + } } diff --git a/Sources/SettingsFeature/Views/SettingsAdvancedView.swift b/Sources/SettingsFeature/Views/SettingsAdvancedView.swift index fb3df7c771e7b5a205b5ec610ca7780bce045f88..0e5e5d89159fbb554f78dd781f5a9d3d4cdfe9da 100644 --- a/Sources/SettingsFeature/Views/SettingsAdvancedView.swift +++ b/Sources/SettingsFeature/Views/SettingsAdvancedView.swift @@ -7,6 +7,7 @@ final class SettingsAdvancedView: UIView { let logRecordingSwitcher = SettingsSwitcher() let crashReportingSwitcher = SettingsSwitcher() let showUsernamesSwitcher = SettingsSwitcher() + let reportingSwitcher = SettingsSwitcher() init() { super.init(frame: .zero) @@ -33,21 +34,29 @@ final class SettingsAdvancedView: UIView { icon: Asset.settingsCrash.image ) + reportingSwitcher.set( + title: Localized.Settings.Advanced.Reporting.title, + text: Localized.Settings.Advanced.Reporting.description, + icon: Asset.settingsCrash.image + ) + stackView.axis = .vertical stackView.addArrangedSubview(logRecordingSwitcher) stackView.addArrangedSubview(crashReportingSwitcher) stackView.addArrangedSubview(showUsernamesSwitcher) + stackView.addArrangedSubview(reportingSwitcher) stackView.setCustomSpacing(20, after: logRecordingSwitcher) stackView.setCustomSpacing(10, after: crashReportingSwitcher) stackView.setCustomSpacing(10, after: showUsernamesSwitcher) + stackView.setCustomSpacing(10, after: reportingSwitcher) addSubview(stackView) - stackView.snp.makeConstraints { make in - make.top.equalToSuperview().offset(24) - make.left.equalToSuperview().offset(16) - make.right.equalToSuperview().offset(-16) + stackView.snp.makeConstraints { + $0.top.equalToSuperview().offset(24) + $0.left.equalToSuperview().offset(16) + $0.right.equalToSuperview().offset(-16) } } diff --git a/Sources/Shared/AutoGenerated/Strings.swift b/Sources/Shared/AutoGenerated/Strings.swift index afcdff24e5e7789bae262515880be622e5a14954..975cacada35bc7b5205a6b6761517801ae27c5ea 100644 --- a/Sources/Shared/AutoGenerated/Strings.swift +++ b/Sources/Shared/AutoGenerated/Strings.swift @@ -1110,6 +1110,12 @@ public enum Localized { /// Record logs public static let title = Localized.tr("Localizable", "settings.advanced.logs.title") } + public enum Reporting { + /// Allows you to report users sending innapropriate content + public static let description = Localized.tr("Localizable", "settings.advanced.reporting.description") + /// Enable user reporting feature + public static let title = Localized.tr("Localizable", "settings.advanced.reporting.title") + } public enum ShowUsername { /// Allow us to show a more detailed push notification public static let description = Localized.tr("Localizable", "settings.advanced.showUsername.description") diff --git a/Sources/Shared/Resources/en.lproj/Localizable.strings b/Sources/Shared/Resources/en.lproj/Localizable.strings index 6b61f43701841cb1f2793045fa1cdd4c3e19de6b..24d260d891069004978304b748f6387888c4e71f 100644 --- a/Sources/Shared/Resources/en.lproj/Localizable.strings +++ b/Sources/Shared/Resources/en.lproj/Localizable.strings @@ -630,6 +630,10 @@ = "Enable crash reporting"; "settings.advanced.crashes.description" = "Automatically sends anonymous reports containing crash data"; +"settings.advanced.reporting.title" += "Enable user reporting feature"; +"settings.advanced.reporting.description" += "Allows you to report users sending innapropriate content"; "settings.advanced.accountBackup.title" = "Account Backup";