mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Settings to enable and disable sending public RRs (#2384)
This commit is contained in:
@@ -120,6 +120,11 @@
|
|||||||
"common_everyone" = "Everyone";
|
"common_everyone" = "Everyone";
|
||||||
"common_face_id_ios" = "Face ID";
|
"common_face_id_ios" = "Face ID";
|
||||||
"common_file" = "File";
|
"common_file" = "File";
|
||||||
|
"common_filter_favourites" = "Favourites";
|
||||||
|
"common_filter_low_priority" = "Low Priority";
|
||||||
|
"common_filter_people" = "People";
|
||||||
|
"common_filter_rooms" = "Rooms";
|
||||||
|
"common_filter_unreads" = "Unreads";
|
||||||
"common_forward_message" = "Forward message";
|
"common_forward_message" = "Forward message";
|
||||||
"common_gif" = "GIF";
|
"common_gif" = "GIF";
|
||||||
"common_image" = "Image";
|
"common_image" = "Image";
|
||||||
@@ -298,6 +303,8 @@
|
|||||||
"screen_advanced_settings_developer_mode" = "Developer mode";
|
"screen_advanced_settings_developer_mode" = "Developer mode";
|
||||||
"screen_advanced_settings_developer_mode_description" = "Enable to have access to features and functionality for developers.";
|
"screen_advanced_settings_developer_mode_description" = "Enable to have access to features and functionality for developers.";
|
||||||
"screen_advanced_settings_rich_text_editor_description" = "Disable the rich text editor to type Markdown manually.";
|
"screen_advanced_settings_rich_text_editor_description" = "Disable the rich text editor to type Markdown manually.";
|
||||||
|
"screen_advanced_settings_send_read_receipts" = "Read receipts";
|
||||||
|
"screen_advanced_settings_send_read_receipts_description" = "If turned off, your read receipts won't be sent to anyone. You will still receive read receipts from other users.";
|
||||||
"screen_advanced_settings_view_source_description" = "Enable option to view message source in the timeline.";
|
"screen_advanced_settings_view_source_description" = "Enable option to view message source in the timeline.";
|
||||||
"screen_analytics_prompt_data_usage" = "We won't record or profile any personal data";
|
"screen_analytics_prompt_data_usage" = "We won't record or profile any personal data";
|
||||||
"screen_analytics_prompt_help_us_improve" = "Share anonymous usage data to help us identify issues.";
|
"screen_analytics_prompt_help_us_improve" = "Share anonymous usage data to help us identify issues.";
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ final class AppSettings {
|
|||||||
case viewSourceEnabled
|
case viewSourceEnabled
|
||||||
case richTextEditorEnabled
|
case richTextEditorEnabled
|
||||||
case appAppearance
|
case appAppearance
|
||||||
|
case sendReadReceiptsEnabled
|
||||||
|
|
||||||
case elementCallBaseURL
|
case elementCallBaseURL
|
||||||
case elementCallEncryptionEnabled
|
case elementCallEncryptionEnabled
|
||||||
@@ -261,6 +262,11 @@ final class AppSettings {
|
|||||||
// maptiler api key
|
// maptiler api key
|
||||||
let mapTilerApiKey = InfoPlistReader.main.mapLibreAPIKey
|
let mapTilerApiKey = InfoPlistReader.main.mapLibreAPIKey
|
||||||
|
|
||||||
|
// MARK: - Read Receipts
|
||||||
|
|
||||||
|
@UserPreference(key: UserDefaultsKeys.sendReadReceiptsEnabled, defaultValue: true, storageType: .userDefaults(store))
|
||||||
|
var sendReadReceiptsEnabled
|
||||||
|
|
||||||
// MARK: - Feature Flags
|
// MARK: - Feature Flags
|
||||||
|
|
||||||
@UserPreference(key: UserDefaultsKeys.userSuggestionsEnabled, defaultValue: false, storageType: .volatile)
|
@UserPreference(key: UserDefaultsKeys.userSuggestionsEnabled, defaultValue: false, storageType: .volatile)
|
||||||
|
|||||||
@@ -274,6 +274,16 @@ public enum L10n {
|
|||||||
public static var commonFaceIdIos: String { return L10n.tr("Localizable", "common_face_id_ios") }
|
public static var commonFaceIdIos: String { return L10n.tr("Localizable", "common_face_id_ios") }
|
||||||
/// File
|
/// File
|
||||||
public static var commonFile: String { return L10n.tr("Localizable", "common_file") }
|
public static var commonFile: String { return L10n.tr("Localizable", "common_file") }
|
||||||
|
/// Favourites
|
||||||
|
public static var commonFilterFavourites: String { return L10n.tr("Localizable", "common_filter_favourites") }
|
||||||
|
/// Low Priority
|
||||||
|
public static var commonFilterLowPriority: String { return L10n.tr("Localizable", "common_filter_low_priority") }
|
||||||
|
/// People
|
||||||
|
public static var commonFilterPeople: String { return L10n.tr("Localizable", "common_filter_people") }
|
||||||
|
/// Rooms
|
||||||
|
public static var commonFilterRooms: String { return L10n.tr("Localizable", "common_filter_rooms") }
|
||||||
|
/// Unreads
|
||||||
|
public static var commonFilterUnreads: String { return L10n.tr("Localizable", "common_filter_unreads") }
|
||||||
/// Forward message
|
/// Forward message
|
||||||
public static var commonForwardMessage: String { return L10n.tr("Localizable", "common_forward_message") }
|
public static var commonForwardMessage: String { return L10n.tr("Localizable", "common_forward_message") }
|
||||||
/// GIF
|
/// GIF
|
||||||
@@ -718,6 +728,10 @@ public enum L10n {
|
|||||||
public static var screenAdvancedSettingsElementCallBaseUrlValidationError: String { return L10n.tr("Localizable", "screen_advanced_settings_element_call_base_url_validation_error") }
|
public static var screenAdvancedSettingsElementCallBaseUrlValidationError: String { return L10n.tr("Localizable", "screen_advanced_settings_element_call_base_url_validation_error") }
|
||||||
/// Disable the rich text editor to type Markdown manually.
|
/// Disable the rich text editor to type Markdown manually.
|
||||||
public static var screenAdvancedSettingsRichTextEditorDescription: String { return L10n.tr("Localizable", "screen_advanced_settings_rich_text_editor_description") }
|
public static var screenAdvancedSettingsRichTextEditorDescription: String { return L10n.tr("Localizable", "screen_advanced_settings_rich_text_editor_description") }
|
||||||
|
/// Read receipts
|
||||||
|
public static var screenAdvancedSettingsSendReadReceipts: String { return L10n.tr("Localizable", "screen_advanced_settings_send_read_receipts") }
|
||||||
|
/// If turned off, your read receipts won't be sent to anyone. You will still receive read receipts from other users.
|
||||||
|
public static var screenAdvancedSettingsSendReadReceiptsDescription: String { return L10n.tr("Localizable", "screen_advanced_settings_send_read_receipts_description") }
|
||||||
/// Enable option to view message source in the timeline.
|
/// Enable option to view message source in the timeline.
|
||||||
public static var screenAdvancedSettingsViewSourceDescription: String { return L10n.tr("Localizable", "screen_advanced_settings_view_source_description") }
|
public static var screenAdvancedSettingsViewSourceDescription: String { return L10n.tr("Localizable", "screen_advanced_settings_view_source_description") }
|
||||||
/// We won't record or profile any personal data
|
/// We won't record or profile any personal data
|
||||||
|
|||||||
@@ -2789,23 +2789,23 @@ class TimelineProxyMock: TimelineProxyProtocol {
|
|||||||
}
|
}
|
||||||
//MARK: - sendReadReceipt
|
//MARK: - sendReadReceipt
|
||||||
|
|
||||||
var sendReadReceiptForCallsCount = 0
|
var sendReadReceiptForTypeCallsCount = 0
|
||||||
var sendReadReceiptForCalled: Bool {
|
var sendReadReceiptForTypeCalled: Bool {
|
||||||
return sendReadReceiptForCallsCount > 0
|
return sendReadReceiptForTypeCallsCount > 0
|
||||||
}
|
}
|
||||||
var sendReadReceiptForReceivedEventID: String?
|
var sendReadReceiptForTypeReceivedArguments: (eventID: String, type: ReceiptType)?
|
||||||
var sendReadReceiptForReceivedInvocations: [String] = []
|
var sendReadReceiptForTypeReceivedInvocations: [(eventID: String, type: ReceiptType)] = []
|
||||||
var sendReadReceiptForReturnValue: Result<Void, TimelineProxyError>!
|
var sendReadReceiptForTypeReturnValue: Result<Void, TimelineProxyError>!
|
||||||
var sendReadReceiptForClosure: ((String) async -> Result<Void, TimelineProxyError>)?
|
var sendReadReceiptForTypeClosure: ((String, ReceiptType) async -> Result<Void, TimelineProxyError>)?
|
||||||
|
|
||||||
func sendReadReceipt(for eventID: String) async -> Result<Void, TimelineProxyError> {
|
func sendReadReceipt(for eventID: String, type: ReceiptType) async -> Result<Void, TimelineProxyError> {
|
||||||
sendReadReceiptForCallsCount += 1
|
sendReadReceiptForTypeCallsCount += 1
|
||||||
sendReadReceiptForReceivedEventID = eventID
|
sendReadReceiptForTypeReceivedArguments = (eventID: eventID, type: type)
|
||||||
sendReadReceiptForReceivedInvocations.append(eventID)
|
sendReadReceiptForTypeReceivedInvocations.append((eventID: eventID, type: type))
|
||||||
if let sendReadReceiptForClosure = sendReadReceiptForClosure {
|
if let sendReadReceiptForTypeClosure = sendReadReceiptForTypeClosure {
|
||||||
return await sendReadReceiptForClosure(eventID)
|
return await sendReadReceiptForTypeClosure(eventID, type)
|
||||||
} else {
|
} else {
|
||||||
return sendReadReceiptForReturnValue
|
return sendReadReceiptForTypeReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - sendMessageEventContent
|
//MARK: - sendMessageEventContent
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ struct InvitesScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
NavigationView {
|
NavigationView {
|
||||||
InvitesScreen(context: InvitesScreenViewModel.someInvite.context)
|
InvitesScreen(context: InvitesScreenViewModel.someInvite.context)
|
||||||
}
|
}
|
||||||
.snapshot(delay: 2.0)
|
.snapshot(delay: 3.0)
|
||||||
.previewDisplayName("Some Invite")
|
.previewDisplayName("Some Invite")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -42,6 +42,7 @@ protocol AdvancedSettingsProtocol: AnyObject {
|
|||||||
var viewSourceEnabled: Bool { get set }
|
var viewSourceEnabled: Bool { get set }
|
||||||
var richTextEditorEnabled: Bool { get set }
|
var richTextEditorEnabled: Bool { get set }
|
||||||
var appAppearance: AppAppearance { get set }
|
var appAppearance: AppAppearance { get set }
|
||||||
|
var sendReadReceiptsEnabled: Bool { get set }
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AppSettings: AdvancedSettingsProtocol { }
|
extension AppSettings: AdvancedSettingsProtocol { }
|
||||||
|
|||||||
+4
@@ -36,6 +36,10 @@ struct AdvancedSettingsScreen: View {
|
|||||||
|
|
||||||
ListRow(label: .plain(title: L10n.actionViewSource),
|
ListRow(label: .plain(title: L10n.actionViewSource),
|
||||||
kind: .toggle($context.viewSourceEnabled))
|
kind: .toggle($context.viewSourceEnabled))
|
||||||
|
|
||||||
|
ListRow(label: .plain(title: L10n.screenAdvancedSettingsSendReadReceipts,
|
||||||
|
description: L10n.screenAdvancedSettingsSendReadReceiptsDescription),
|
||||||
|
kind: .toggle($context.sendReadReceiptsEnabled))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.compoundList()
|
.compoundList()
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
|
|
||||||
func sendReadReceipt(for itemID: TimelineItemIdentifier) async -> Result<Void, RoomTimelineControllerError> {
|
func sendReadReceipt(for itemID: TimelineItemIdentifier) async -> Result<Void, RoomTimelineControllerError> {
|
||||||
guard let roomProxy, let eventID = itemID.eventID else { return .failure(.generic) }
|
guard let roomProxy, let eventID = itemID.eventID else { return .failure(.generic) }
|
||||||
switch await roomProxy.timeline.sendReadReceipt(for: eventID) {
|
switch await roomProxy.timeline.sendReadReceipt(for: eventID, type: .read) {
|
||||||
case .success:
|
case .success:
|
||||||
return .success(())
|
return .success(())
|
||||||
case .failure:
|
case .failure:
|
||||||
|
|||||||
@@ -93,7 +93,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
let eventID = itemID.eventID
|
let eventID = itemID.eventID
|
||||||
else { return .success(()) }
|
else { return .success(()) }
|
||||||
|
|
||||||
switch await roomProxy.timeline.sendReadReceipt(for: eventID) {
|
switch await roomProxy.timeline.sendReadReceipt(for: eventID,
|
||||||
|
type: appSettings.sendReadReceiptsEnabled ? .read : .readPrivate) {
|
||||||
case .success:
|
case .success:
|
||||||
return .success(())
|
return .success(())
|
||||||
case .failure:
|
case .failure:
|
||||||
|
|||||||
@@ -453,7 +453,7 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendReadReceipt(for eventID: String) async -> Result<Void, TimelineProxyError> {
|
func sendReadReceipt(for eventID: String, type: ReceiptType) async -> Result<Void, TimelineProxyError> {
|
||||||
MXLog.info("Sending read receipt for eventID: \(eventID)")
|
MXLog.info("Sending read receipt for eventID: \(eventID)")
|
||||||
|
|
||||||
sendMessageBackgroundTask = await backgroundTaskService.startBackgroundTask(withName: backgroundTaskName, isReusable: true)
|
sendMessageBackgroundTask = await backgroundTaskService.startBackgroundTask(withName: backgroundTaskName, isReusable: true)
|
||||||
@@ -463,7 +463,7 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
|
|
||||||
return await Task.dispatch(on: lowPriorityDispatchQueue) {
|
return await Task.dispatch(on: lowPriorityDispatchQueue) {
|
||||||
do {
|
do {
|
||||||
try self.timeline.sendReadReceipt(receiptType: .read, eventId: eventID)
|
try self.timeline.sendReadReceipt(receiptType: type, eventId: eventID)
|
||||||
MXLog.info("Finished sending read receipt for eventID: \(eventID)")
|
MXLog.info("Finished sending read receipt for eventID: \(eventID)")
|
||||||
return .success(())
|
return .success(())
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ protocol TimelineProxyProtocol {
|
|||||||
progressSubject: CurrentValueSubject<Double, Never>?,
|
progressSubject: CurrentValueSubject<Double, Never>?,
|
||||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func sendReadReceipt(for eventID: String) async -> Result<Void, TimelineProxyError>
|
func sendReadReceipt(for eventID: String, type: ReceiptType) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func sendMessageEventContent(_ messageContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError>
|
func sendMessageEventContent(_ messageContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
var cancellables = Set<AnyCancellable>()
|
var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
override func setUp() async throws {
|
override func setUp() async throws {
|
||||||
|
AppSettings.reset()
|
||||||
cancellables.removeAll()
|
cancellables.removeAll()
|
||||||
userIndicatorControllerMock = UserIndicatorControllerMock.default
|
userIndicatorControllerMock = UserIndicatorControllerMock.default
|
||||||
}
|
}
|
||||||
@@ -456,8 +457,10 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
try await Task.sleep(for: .milliseconds(100))
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
|
|
||||||
// Then the receipt should be sent.
|
// Then the receipt should be sent.
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForCalled, true)
|
XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCalled, true)
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForReceivedEventID, "t3")
|
let arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments
|
||||||
|
XCTAssertEqual(arguments?.eventID, "t3")
|
||||||
|
XCTAssertEqual(arguments?.type, .read)
|
||||||
|
|
||||||
// And the notifications should be cleared.
|
// And the notifications should be cleared.
|
||||||
XCTAssertEqual(notificationCenter.postNameObjectReceivedArguments?.aName, .roomMarkedAsRead)
|
XCTAssertEqual(notificationCenter.postNameObjectReceivedArguments?.aName, .roomMarkedAsRead)
|
||||||
@@ -473,16 +476,20 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
let (viewModel, _, timelineProxy, timelineController, _) = readReceiptsConfiguration(with: items)
|
let (viewModel, _, timelineProxy, timelineController, _) = readReceiptsConfiguration(with: items)
|
||||||
viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id))
|
viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id))
|
||||||
try await Task.sleep(for: .milliseconds(100))
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForCallsCount, 1)
|
XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCallsCount, 1)
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForReceivedEventID, "t3")
|
var arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments
|
||||||
|
XCTAssertEqual(arguments?.eventID, "t3")
|
||||||
|
XCTAssertEqual(arguments?.type, .read)
|
||||||
|
|
||||||
// When sending a receipt for the first item in the timeline.
|
// When sending a receipt for the first item in the timeline.
|
||||||
viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.first!.id))
|
viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.first!.id))
|
||||||
try await Task.sleep(for: .milliseconds(100))
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
|
|
||||||
// Then the request should be ignored.
|
// Then the request should be ignored.
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForCallsCount, 1)
|
XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCallsCount, 1)
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForReceivedEventID, "t3")
|
arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments
|
||||||
|
XCTAssertEqual(arguments?.eventID, "t3")
|
||||||
|
XCTAssertEqual(arguments?.type, .read)
|
||||||
|
|
||||||
// When a new message is received and marked as read.
|
// When a new message is received and marked as read.
|
||||||
let newMessage = TextRoomTimelineItem(eventID: "t4")
|
let newMessage = TextRoomTimelineItem(eventID: "t4")
|
||||||
@@ -494,8 +501,10 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
try await Task.sleep(for: .milliseconds(100))
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
|
|
||||||
// Then the request should be made.
|
// Then the request should be made.
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForCallsCount, 2)
|
XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCallsCount, 2)
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForReceivedEventID, "t4")
|
arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments
|
||||||
|
XCTAssertEqual(arguments?.eventID, "t4")
|
||||||
|
XCTAssertEqual(arguments?.type, .read)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSendReadReceiptWithoutEvents() async throws {
|
func testSendReadReceiptWithoutEvents() async throws {
|
||||||
@@ -510,7 +519,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
try await Task.sleep(for: .milliseconds(100))
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
|
|
||||||
// Then nothing should be sent.
|
// Then nothing should be sent.
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForCalled, false)
|
XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCalled, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSendReadReceiptVirtualLast() async throws {
|
func testSendReadReceiptVirtualLast() async throws {
|
||||||
@@ -525,8 +534,10 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
try await Task.sleep(for: .milliseconds(100))
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
|
|
||||||
// Then a read receipt should be sent for the item before it.
|
// Then a read receipt should be sent for the item before it.
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForCalled, true)
|
XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCalled, true)
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForReceivedEventID, "t2")
|
let arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments
|
||||||
|
XCTAssertEqual(arguments?.eventID, "t2")
|
||||||
|
XCTAssertEqual(arguments?.type, .read)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSendReadReceiptMultipleRequests() async throws {
|
func testSendReadReceiptMultipleRequests() async throws {
|
||||||
@@ -537,15 +548,17 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
let (viewModel, _, timelineProxy, _, _) = readReceiptsConfiguration(with: items)
|
let (viewModel, _, timelineProxy, _, _) = readReceiptsConfiguration(with: items)
|
||||||
viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id))
|
viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id))
|
||||||
try await Task.sleep(for: .milliseconds(100))
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForCallsCount, 1)
|
XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCallsCount, 1)
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForReceivedEventID, "t2")
|
let arguments = timelineProxy.sendReadReceiptForTypeReceivedArguments
|
||||||
|
XCTAssertEqual(arguments?.eventID, "t2")
|
||||||
|
XCTAssertEqual(arguments?.type, .read)
|
||||||
|
|
||||||
// When sending the same receipt again
|
// When sending the same receipt again
|
||||||
viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id))
|
viewModel.context.send(viewAction: .sendReadReceiptIfNeeded(items.last!.id))
|
||||||
try await Task.sleep(for: .milliseconds(100))
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
|
|
||||||
// Then the second call should be ignored.
|
// Then the second call should be ignored.
|
||||||
XCTAssertEqual(timelineProxy.sendReadReceiptForCallsCount, 1)
|
XCTAssertEqual(timelineProxy.sendReadReceiptForTypeCallsCount, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// swiftlint:enable force_unwrapping
|
// swiftlint:enable force_unwrapping
|
||||||
@@ -564,7 +577,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy.timeline = timelineProxy
|
roomProxy.timeline = timelineProxy
|
||||||
let timelineController = MockRoomTimelineController()
|
let timelineController = MockRoomTimelineController()
|
||||||
|
|
||||||
timelineProxy.sendReadReceiptForReturnValue = .success(())
|
timelineProxy.sendReadReceiptForTypeReturnValue = .success(())
|
||||||
|
|
||||||
roomProxy.underlyingHasUnreadNotifications = true
|
roomProxy.underlyingHasUnreadNotifications = true
|
||||||
timelineController.timelineItems = items
|
timelineController.timelineItems = items
|
||||||
@@ -580,7 +593,6 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
notificationCenter: notificationCenter)
|
notificationCenter: notificationCenter)
|
||||||
|
|
||||||
return (viewModel, roomProxy, timelineProxy, timelineController, notificationCenter)
|
return (viewModel, roomProxy, timelineProxy, timelineController, notificationCenter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:ef4d0a11568fed0fe4849557b05a6cffd4cc53092ac6f6255e7b41268419da1b
|
oid sha256:ca4fa009a4a584047cdec1c4c58abd2d0ae6dc7feefa1ed4133174e3d1beba89
|
||||||
size 114023
|
size 144629
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
Added an advanced setting to turn off sending read receipts.
|
||||||
Reference in New Issue
Block a user