Add toggle not invite notifications. (#2207)

This commit is contained in:
Doug
2023-12-06 09:53:10 +00:00
committed by GitHub
parent 92cfd93028
commit 2a2a9b6eae
15 changed files with 203 additions and 14 deletions

View File

@@ -1710,6 +1710,47 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol {
setCallEnabledEnabledReceivedInvocations.append(enabled)
try await setCallEnabledEnabledClosure?(enabled)
}
//MARK: - isInviteForMeEnabled
var isInviteForMeEnabledThrowableError: Error?
var isInviteForMeEnabledCallsCount = 0
var isInviteForMeEnabledCalled: Bool {
return isInviteForMeEnabledCallsCount > 0
}
var isInviteForMeEnabledReturnValue: Bool!
var isInviteForMeEnabledClosure: (() async throws -> Bool)?
func isInviteForMeEnabled() async throws -> Bool {
if let error = isInviteForMeEnabledThrowableError {
throw error
}
isInviteForMeEnabledCallsCount += 1
if let isInviteForMeEnabledClosure = isInviteForMeEnabledClosure {
return try await isInviteForMeEnabledClosure()
} else {
return isInviteForMeEnabledReturnValue
}
}
//MARK: - setInviteForMeEnabled
var setInviteForMeEnabledEnabledThrowableError: Error?
var setInviteForMeEnabledEnabledCallsCount = 0
var setInviteForMeEnabledEnabledCalled: Bool {
return setInviteForMeEnabledEnabledCallsCount > 0
}
var setInviteForMeEnabledEnabledReceivedEnabled: Bool?
var setInviteForMeEnabledEnabledReceivedInvocations: [Bool] = []
var setInviteForMeEnabledEnabledClosure: ((Bool) async throws -> Void)?
func setInviteForMeEnabled(enabled: Bool) async throws {
if let error = setInviteForMeEnabledEnabledThrowableError {
throw error
}
setInviteForMeEnabledEnabledCallsCount += 1
setInviteForMeEnabledEnabledReceivedEnabled = enabled
setInviteForMeEnabledEnabledReceivedInvocations.append(enabled)
try await setInviteForMeEnabledEnabledClosure?(enabled)
}
//MARK: - getRoomsWithUserDefinedRules
var getRoomsWithUserDefinedRulesThrowableError: Error?

View File

@@ -42,6 +42,7 @@ extension NotificationSettingsProxyMock {
getRoomsWithUserDefinedRulesReturnValue = []
isRoomMentionEnabledReturnValue = true
isCallEnabledReturnValue = true
isInviteForMeEnabledReturnValue = true
setNotificationModeRoomIdModeClosure = { [weak self] _, mode in
guard let self else { return }
@@ -83,6 +84,14 @@ extension NotificationSettingsProxyMock {
}
}
setInviteForMeEnabledEnabledClosure = { [weak self] enabled in
guard let self else { return }
self.isInviteForMeEnabledReturnValue = enabled
Task {
self.callbacks.send(.settingsDidChange)
}
}
canHomeserverPushEncryptedEventsToDeviceClosure = {
configuration.canHomeserverPushEncryptedEvents
}

View File

@@ -44,6 +44,7 @@ struct NotificationSettingsScreenViewStateBindings {
var enableNotifications = false
var roomMentionsEnabled = false
var callsEnabled = false
var invitationsEnabled = false
var alertInfo: AlertInfo<NotificationSettingsScreenErrorType>?
}
@@ -52,6 +53,7 @@ struct NotificationSettingsScreenSettings {
let directChatsMode: RoomNotificationModeProxy
let roomMentionsEnabled: Bool?
let callsEnabled: Bool?
let invitationsEnabled: Bool?
// Old clients were having specific settings for encrypted and unencrypted rooms,
// so it's possible for `group chats` and `direct chats` settings to be inconsistent (e.g. encrypted `direct chats` can have a different mode that unencrypted `direct chats`)
let inconsistentSettings: [NotificationSettingsScreenInvalidSetting]
@@ -93,6 +95,7 @@ enum NotificationSettingsScreenViewAction {
case directChatsTapped
case roomMentionChanged
case callsChanged
case invitationsChanged
case close
case fixConfigurationMismatchTapped
}

View File

@@ -73,6 +73,11 @@ class NotificationSettingsScreenViewModel: NotificationSettingsScreenViewModelTy
return
}
Task { await enableCalls(state.bindings.callsEnabled) }
case .invitationsChanged:
guard let settings = state.settings, settings.invitationsEnabled != state.bindings.invitationsEnabled else {
return
}
Task { await enableInvitations(state.bindings.invitationsEnabled) }
case .close:
actionsSubject.send(.close)
case .fixConfigurationMismatchTapped:
@@ -146,6 +151,7 @@ class NotificationSettingsScreenViewModel: NotificationSettingsScreenViewModelTy
// The following calls may fail if the associated push rule doesn't exist
let roomMentionsEnabled = try? await notificationSettingsProxy.isRoomMentionEnabled()
let callEnabled = try? await notificationSettingsProxy.isCallEnabled()
let invitationsEnabled = try? await notificationSettingsProxy.isInviteForMeEnabled()
guard !Task.isCancelled else { return }
@@ -153,11 +159,13 @@ class NotificationSettingsScreenViewModel: NotificationSettingsScreenViewModelTy
directChatsMode: directChatsMode,
roomMentionsEnabled: roomMentionsEnabled,
callsEnabled: callEnabled,
invitationsEnabled: invitationsEnabled,
inconsistentSettings: inconsistentSettings)
state.settings = notificationSettings
state.bindings.roomMentionsEnabled = notificationSettings.roomMentionsEnabled ?? false
state.bindings.callsEnabled = notificationSettings.callsEnabled ?? false
state.bindings.invitationsEnabled = notificationSettings.invitationsEnabled ?? false
}
}
@@ -187,7 +195,7 @@ class NotificationSettingsScreenViewModel: NotificationSettingsScreenViewModelTy
guard let notificationSettings = state.settings else { return }
do {
state.applyingChange = true
MXLog.info("[NotificationSettingsScreenViewMode] setRoomMentionEnabled(\(enable))")
MXLog.info("setRoomMentionEnabled(\(enable))")
try await notificationSettingsProxy.setRoomMentionEnabled(enabled: enable)
} catch {
state.bindings.alertInfo = AlertInfo(id: .alert)
@@ -200,7 +208,7 @@ class NotificationSettingsScreenViewModel: NotificationSettingsScreenViewModelTy
guard let notificationSettings = state.settings else { return }
do {
state.applyingChange = true
MXLog.info("[NotificationSettingsScreenViewMode] setCallEnabled(\(enable))")
MXLog.info("setCallEnabled(\(enable))")
try await notificationSettingsProxy.setCallEnabled(enabled: enable)
} catch {
state.bindings.alertInfo = AlertInfo(id: .alert)
@@ -208,6 +216,19 @@ class NotificationSettingsScreenViewModel: NotificationSettingsScreenViewModelTy
}
state.applyingChange = false
}
func enableInvitations(_ enable: Bool) async {
guard let notificationSettings = state.settings else { return }
do {
state.applyingChange = true
MXLog.info("setInviteForMeEnabled(\(enable))")
try await notificationSettingsProxy.setInviteForMeEnabled(enabled: enable)
} catch {
state.bindings.alertInfo = AlertInfo(id: .alert)
state.bindings.callsEnabled = notificationSettings.invitationsEnabled ?? false
}
state.applyingChange = false
}
}
extension UNUserNotificationCenter {

View File

@@ -37,6 +37,9 @@ struct NotificationSettingsScreen: View {
if context.viewState.showCallsSettings, context.viewState.settings?.callsEnabled != nil {
callsSection
}
if context.viewState.settings?.invitationsEnabled != nil {
additionalSettingsSection
}
}
}
}
@@ -153,6 +156,21 @@ struct NotificationSettingsScreen: View {
}
}
private var additionalSettingsSection: some View {
Section {
ListRow(label: .plain(title: L10n.screenNotificationSettingsInviteForMeLabel),
kind: .toggle($context.invitationsEnabled))
.disabled(context.viewState.settings?.invitationsEnabled == nil)
.allowsHitTesting(!context.viewState.applyingChange)
.onChange(of: context.invitationsEnabled) { _ in
context.send(viewAction: .invitationsChanged)
}
} header: {
Text(L10n.screenNotificationSettingsAdditionalSettingsSectionTitle)
.compoundListSectionHeader()
}
}
private var configurationMismatchSection: some View {
Section {
ListRow(kind: .custom {
@@ -242,7 +260,9 @@ struct NotificationSettingsScreen_Previews: PreviewProvider, TestablePreview {
static var previews: some View {
NotificationSettingsScreen(context: viewModel.context)
.snapshot(delay: 0.1)
NotificationSettingsScreen(context: viewModelConfigurationMismatch.context)
.snapshot(delay: 0.1)
.previewDisplayName("Configuration mismatch")
}
}

View File

@@ -141,6 +141,18 @@ final class NotificationSettingsProxy: NotificationSettingsProxyProtocol {
await updatedSettings()
}
func isInviteForMeEnabled() async throws -> Bool {
try await notificationSettings.isInviteForMeEnabled()
}
func setInviteForMeEnabled(enabled: Bool) async throws {
let backgroundTask = await backgroundTaskService?.startBackgroundTask(withName: "setInviteForMeEnabled")
defer { backgroundTask?.stop() }
try await notificationSettings.setInviteForMeEnabled(enabled: enabled)
await updatedSettings()
}
func getRoomsWithUserDefinedRules() async throws -> [String] {
await notificationSettings.getRoomsWithUserDefinedRules(enabled: true)
}

View File

@@ -40,6 +40,8 @@ protocol NotificationSettingsProxyProtocol {
func setUserMentionEnabled(enabled: Bool) async throws
func isCallEnabled() async throws -> Bool
func setCallEnabled(enabled: Bool) async throws
func isInviteForMeEnabled() async throws -> Bool
func setInviteForMeEnabled(enabled: Bool) async throws
func getRoomsWithUserDefinedRules() async throws -> [String]
func canHomeserverPushEncryptedEventsToDevice() async -> Bool
}

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9704334caaadde07dcdf78efa200853d9315bf630296adfae54963fc5ec5d989
size 103239
oid sha256:ef3b3ede5511460271ea3879651efd4424b5d16b4242965c8c068a55e5c7fc4c
size 113310

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b3d623d6e0ddd1ec3387a38461a58e1381494ee21c45344e31ad3b708604ca2a
size 126931
oid sha256:e924d67a0b598ddc9a015f774512fc1460195c8b7292862b44cc353dba36278b
size 139993

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d2162569e78dffee8d4095998dc31a3672ff3dbb43f0b1f58a44850a18c4c5f6
size 117932
oid sha256:af2f6e2f7e5b16d2bd08224e4a1cea85766196e54cead0ea1ed07529caae3da0
size 132174

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ba9fd9cbc5f49630dd1853f2d49611f1d4bb47166ae7ddff79319e0c1d0088bf
size 165797
oid sha256:e61e23b4a91d4510c1386d1c3a39c99a43c394fadc6e3d73949ce74aab34adc6
size 182864

View File

@@ -388,4 +388,84 @@ class NotificationSettingsScreenViewModelTests: XCTestCase {
XCTAssertNotNil(context.alertInfo)
}
func testToggleInvitationsOff() async throws {
notificationSettingsProxy.isInviteForMeEnabledReturnValue = true
let deferredInitialFetch = deferFulfillment(viewModel.context.$viewState) { state in
state.settings != nil
}
viewModel.fetchInitialContent()
try await deferredInitialFetch.fulfill()
context.invitationsEnabled = false
let deferred = deferFulfillment(notificationSettingsProxy.callbacks) { callback in
callback == .settingsDidChange
}
context.send(viewAction: .invitationsChanged)
try await deferred.fulfill()
XCTAssert(notificationSettingsProxy.setInviteForMeEnabledEnabledCalled)
XCTAssertEqual(notificationSettingsProxy.setInviteForMeEnabledEnabledReceivedEnabled, false)
}
func testToggleInvitationsOn() async throws {
notificationSettingsProxy.isInviteForMeEnabledReturnValue = false
let deferredInitialFetch = deferFulfillment(viewModel.context.$viewState) { state in
state.settings != nil
}
viewModel.fetchInitialContent()
try await deferredInitialFetch.fulfill()
context.invitationsEnabled = true
let deferred = deferFulfillment(notificationSettingsProxy.callbacks) { callback in
callback == .settingsDidChange
}
context.send(viewAction: .invitationsChanged)
try await deferred.fulfill()
XCTAssert(notificationSettingsProxy.setInviteForMeEnabledEnabledCalled)
XCTAssertEqual(notificationSettingsProxy.setInviteForMeEnabledEnabledReceivedEnabled, true)
}
func testToggleInvitesFailure() async throws {
notificationSettingsProxy.setInviteForMeEnabledEnabledThrowableError = NotificationSettingsError.Generic(msg: "error")
notificationSettingsProxy.isInviteForMeEnabledReturnValue = false
let deferredInitialFetch = deferFulfillment(viewModel.context.$viewState) { state in
state.settings != nil
}
viewModel.fetchInitialContent()
try await deferredInitialFetch.fulfill()
context.invitationsEnabled = true
var deferred = deferFulfillment(context.$viewState) { state in
state.applyingChange == true
}
context.send(viewAction: .invitationsChanged)
try await deferred.fulfill()
deferred = deferFulfillment(context.$viewState) { state in
state.applyingChange == false
}
try await deferred.fulfill()
XCTAssertNotNil(context.alertInfo)
}
}

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3d858bdd5b55a445ce924c4bba25a8ca420086c033ca5e17b4a73cf571d90c15
size 97653
oid sha256:6ca120ad1ccae3415ebf22f9db7fc8389e2b21682ae336de2545651c2027cc87
size 155222

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3d858bdd5b55a445ce924c4bba25a8ca420086c033ca5e17b4a73cf571d90c15
size 97653
oid sha256:321892e72a5da150eb1a2db3b81576eac4a9474aec8cee5c68c8c3315b3dbe46
size 126720

1
changelog.d/2205.change Normal file
View File

@@ -0,0 +1 @@
Add notification toggle for invitations.