mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Check Application state before sending RR (#1960)
* check the state * better handling * protocol to mock the application state * test improvement
This commit is contained in:
@@ -634,6 +634,7 @@
|
|||||||
A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; };
|
A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; };
|
||||||
A743841F91B62B0E56217B04 /* SecureBackupKeyBackupScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DCB219D7B7B0299358FF81 /* SecureBackupKeyBackupScreenUITests.swift */; };
|
A743841F91B62B0E56217B04 /* SecureBackupKeyBackupScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DCB219D7B7B0299358FF81 /* SecureBackupKeyBackupScreenUITests.swift */; };
|
||||||
A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; };
|
A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; };
|
||||||
|
A7BACE682AE97D4500FFBBEA /* ApplicationMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7BACE672AE97D4500FFBBEA /* ApplicationMock.swift */; };
|
||||||
A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; };
|
A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; };
|
||||||
A7FD7B992E6EE6E5A8429197 /* RoomSummaryDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 142808B69851451AC32A2CEA /* RoomSummaryDetails.swift */; };
|
A7FD7B992E6EE6E5A8429197 /* RoomSummaryDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 142808B69851451AC32A2CEA /* RoomSummaryDetails.swift */; };
|
||||||
A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; };
|
A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; };
|
||||||
@@ -1030,7 +1031,7 @@
|
|||||||
033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
|
033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
|
||||||
035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = "<group>"; };
|
035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = "<group>"; };
|
||||||
0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = "<group>"; };
|
0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = "<group>"; };
|
||||||
0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = "<group>"; };
|
0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = "<group>"; };
|
||||||
03BA7958A4BB9C22CA8884EF /* WaveformViewDragGestureModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaveformViewDragGestureModifier.swift; sourceTree = "<group>"; };
|
03BA7958A4BB9C22CA8884EF /* WaveformViewDragGestureModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaveformViewDragGestureModifier.swift; sourceTree = "<group>"; };
|
||||||
03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = "<group>"; };
|
03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
@@ -1585,6 +1586,7 @@
|
|||||||
A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = "<group>"; };
|
A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = "<group>"; };
|
||||||
A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriverProtocol.swift; sourceTree = "<group>"; };
|
A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriverProtocol.swift; sourceTree = "<group>"; };
|
||||||
A73A07BAEDD74C48795A996A /* AsyncSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncSequence.swift; sourceTree = "<group>"; };
|
A73A07BAEDD74C48795A996A /* AsyncSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncSequence.swift; sourceTree = "<group>"; };
|
||||||
|
A7BACE672AE97D4500FFBBEA /* ApplicationMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationMock.swift; sourceTree = "<group>"; };
|
||||||
A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = "<group>"; };
|
A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
A861DA5932B128FE1DCB5CE2 /* InviteUsersScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenCoordinator.swift; sourceTree = "<group>"; };
|
A861DA5932B128FE1DCB5CE2 /* InviteUsersScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
A8903A9F615BBD0E6D7CD133 /* ApplicationProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationProtocol.swift; sourceTree = "<group>"; };
|
A8903A9F615BBD0E6D7CD133 /* ApplicationProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationProtocol.swift; sourceTree = "<group>"; };
|
||||||
@@ -2439,6 +2441,7 @@
|
|||||||
AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */,
|
AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */,
|
||||||
B23135B06B044CB811139D2F /* Generated */,
|
B23135B06B044CB811139D2F /* Generated */,
|
||||||
E5E545F92D01588360A9BAC5 /* SDK */,
|
E5E545F92D01588360A9BAC5 /* SDK */,
|
||||||
|
A7BACE672AE97D4500FFBBEA /* ApplicationMock.swift */,
|
||||||
);
|
);
|
||||||
path = Mocks;
|
path = Mocks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -5289,6 +5292,7 @@
|
|||||||
0F6C8033FA60CFD36F7CA205 /* AppLockSetupPINScreenViewModel.swift in Sources */,
|
0F6C8033FA60CFD36F7CA205 /* AppLockSetupPINScreenViewModel.swift in Sources */,
|
||||||
4C356F5CCB4CDC99BFA45185 /* AppLockSetupPINScreenViewModelProtocol.swift in Sources */,
|
4C356F5CCB4CDC99BFA45185 /* AppLockSetupPINScreenViewModelProtocol.swift in Sources */,
|
||||||
4E8A2A2CFEB212F14E49E1A1 /* AppLockSetupSettingsScreen.swift in Sources */,
|
4E8A2A2CFEB212F14E49E1A1 /* AppLockSetupSettingsScreen.swift in Sources */,
|
||||||
|
A7BACE682AE97D4500FFBBEA /* ApplicationMock.swift in Sources */,
|
||||||
8DCD9CC5361FF22A5B2C20F1 /* AppLockSetupSettingsScreenCoordinator.swift in Sources */,
|
8DCD9CC5361FF22A5B2C20F1 /* AppLockSetupSettingsScreenCoordinator.swift in Sources */,
|
||||||
6E4E401BE97AC241DA7C7716 /* AppLockSetupSettingsScreenModels.swift in Sources */,
|
6E4E401BE97AC241DA7C7716 /* AppLockSetupSettingsScreenModels.swift in Sources */,
|
||||||
4807E8F51DB54F56B25E1C7E /* AppLockSetupSettingsScreenViewModel.swift in Sources */,
|
4807E8F51DB54F56B25E1C7E /* AppLockSetupSettingsScreenViewModel.swift in Sources */,
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2023 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension ApplicationMock {
|
||||||
|
static var `default`: ApplicationProtocol {
|
||||||
|
ApplicationMock(withState: .active,
|
||||||
|
backgroundTimeRemaining: 10,
|
||||||
|
allowTasks: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
static var mockBroken: ApplicationProtocol {
|
||||||
|
ApplicationMock(withState: .inactive,
|
||||||
|
backgroundTimeRemaining: 0,
|
||||||
|
allowTasks: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
static var mockAboutToSuspend: ApplicationProtocol {
|
||||||
|
ApplicationMock(withState: .background,
|
||||||
|
backgroundTimeRemaining: 2,
|
||||||
|
allowTasks: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static var bgTaskIdentifier = 0
|
||||||
|
|
||||||
|
convenience init(withState applicationState: UIApplication.State,
|
||||||
|
backgroundTimeRemaining: TimeInterval,
|
||||||
|
allowTasks: Bool) {
|
||||||
|
self.init()
|
||||||
|
|
||||||
|
underlyingApplicationState = applicationState
|
||||||
|
underlyingBackgroundTimeRemaining = backgroundTimeRemaining
|
||||||
|
|
||||||
|
beginBackgroundTaskExpirationHandlerClosure = { [weak self] handler in
|
||||||
|
guard let self else {
|
||||||
|
return .invalid
|
||||||
|
}
|
||||||
|
|
||||||
|
guard allowTasks else {
|
||||||
|
return .invalid
|
||||||
|
}
|
||||||
|
|
||||||
|
return beginBackgroundTask(withName: nil, expirationHandler: handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
beginBackgroundTaskWithNameExpirationHandlerClosure = { _, handler in
|
||||||
|
guard allowTasks else {
|
||||||
|
return .invalid
|
||||||
|
}
|
||||||
|
Self.bgTaskIdentifier += 1
|
||||||
|
|
||||||
|
let identifier = UIBackgroundTaskIdentifier(rawValue: Self.bgTaskIdentifier)
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
||||||
|
handler?()
|
||||||
|
}
|
||||||
|
return identifier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -279,6 +279,85 @@ class AppLockServiceMock: AppLockServiceProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class ApplicationMock: ApplicationProtocol {
|
||||||
|
var backgroundTimeRemaining: TimeInterval {
|
||||||
|
get { return underlyingBackgroundTimeRemaining }
|
||||||
|
set(value) { underlyingBackgroundTimeRemaining = value }
|
||||||
|
}
|
||||||
|
var underlyingBackgroundTimeRemaining: TimeInterval!
|
||||||
|
var applicationState: UIApplication.State {
|
||||||
|
get { return underlyingApplicationState }
|
||||||
|
set(value) { underlyingApplicationState = value }
|
||||||
|
}
|
||||||
|
var underlyingApplicationState: UIApplication.State!
|
||||||
|
|
||||||
|
//MARK: - beginBackgroundTask
|
||||||
|
|
||||||
|
var beginBackgroundTaskExpirationHandlerCallsCount = 0
|
||||||
|
var beginBackgroundTaskExpirationHandlerCalled: Bool {
|
||||||
|
return beginBackgroundTaskExpirationHandlerCallsCount > 0
|
||||||
|
}
|
||||||
|
var beginBackgroundTaskExpirationHandlerReturnValue: UIBackgroundTaskIdentifier!
|
||||||
|
var beginBackgroundTaskExpirationHandlerClosure: (((() -> Void)?) -> UIBackgroundTaskIdentifier)?
|
||||||
|
|
||||||
|
func beginBackgroundTask(expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier {
|
||||||
|
beginBackgroundTaskExpirationHandlerCallsCount += 1
|
||||||
|
if let beginBackgroundTaskExpirationHandlerClosure = beginBackgroundTaskExpirationHandlerClosure {
|
||||||
|
return beginBackgroundTaskExpirationHandlerClosure(handler)
|
||||||
|
} else {
|
||||||
|
return beginBackgroundTaskExpirationHandlerReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//MARK: - beginBackgroundTask
|
||||||
|
|
||||||
|
var beginBackgroundTaskWithNameExpirationHandlerCallsCount = 0
|
||||||
|
var beginBackgroundTaskWithNameExpirationHandlerCalled: Bool {
|
||||||
|
return beginBackgroundTaskWithNameExpirationHandlerCallsCount > 0
|
||||||
|
}
|
||||||
|
var beginBackgroundTaskWithNameExpirationHandlerReturnValue: UIBackgroundTaskIdentifier!
|
||||||
|
var beginBackgroundTaskWithNameExpirationHandlerClosure: ((String?, (() -> Void)?) -> UIBackgroundTaskIdentifier)?
|
||||||
|
|
||||||
|
func beginBackgroundTask(withName taskName: String?, expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier {
|
||||||
|
beginBackgroundTaskWithNameExpirationHandlerCallsCount += 1
|
||||||
|
if let beginBackgroundTaskWithNameExpirationHandlerClosure = beginBackgroundTaskWithNameExpirationHandlerClosure {
|
||||||
|
return beginBackgroundTaskWithNameExpirationHandlerClosure(taskName, handler)
|
||||||
|
} else {
|
||||||
|
return beginBackgroundTaskWithNameExpirationHandlerReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//MARK: - endBackgroundTask
|
||||||
|
|
||||||
|
var endBackgroundTaskCallsCount = 0
|
||||||
|
var endBackgroundTaskCalled: Bool {
|
||||||
|
return endBackgroundTaskCallsCount > 0
|
||||||
|
}
|
||||||
|
var endBackgroundTaskReceivedIdentifier: UIBackgroundTaskIdentifier?
|
||||||
|
var endBackgroundTaskReceivedInvocations: [UIBackgroundTaskIdentifier] = []
|
||||||
|
var endBackgroundTaskClosure: ((UIBackgroundTaskIdentifier) -> Void)?
|
||||||
|
|
||||||
|
func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier) {
|
||||||
|
endBackgroundTaskCallsCount += 1
|
||||||
|
endBackgroundTaskReceivedIdentifier = identifier
|
||||||
|
endBackgroundTaskReceivedInvocations.append(identifier)
|
||||||
|
endBackgroundTaskClosure?(identifier)
|
||||||
|
}
|
||||||
|
//MARK: - open
|
||||||
|
|
||||||
|
var openCallsCount = 0
|
||||||
|
var openCalled: Bool {
|
||||||
|
return openCallsCount > 0
|
||||||
|
}
|
||||||
|
var openReceivedUrl: URL?
|
||||||
|
var openReceivedInvocations: [URL] = []
|
||||||
|
var openClosure: ((URL) -> Void)?
|
||||||
|
|
||||||
|
func open(_ url: URL) {
|
||||||
|
openCallsCount += 1
|
||||||
|
openReceivedUrl = url
|
||||||
|
openReceivedInvocations.append(url)
|
||||||
|
openClosure?(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
class AudioConverterMock: AudioConverterProtocol {
|
class AudioConverterMock: AudioConverterProtocol {
|
||||||
|
|
||||||
//MARK: - convertToOpusOgg
|
//MARK: - convertToOpusOgg
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
|||||||
roomProxy: parameters.roomProxy,
|
roomProxy: parameters.roomProxy,
|
||||||
appSettings: parameters.appSettings,
|
appSettings: parameters.appSettings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
application: UIApplication.shared)
|
||||||
|
|
||||||
wysiwygViewModel = WysiwygComposerViewModel(minHeight: ComposerConstant.minHeight,
|
wysiwygViewModel = WysiwygComposerViewModel(minHeight: ComposerConstant.minHeight,
|
||||||
maxCompressedHeight: ComposerConstant.maxHeight,
|
maxCompressedHeight: ComposerConstant.maxHeight,
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
private let roomProxy: RoomProxyProtocol
|
private let roomProxy: RoomProxyProtocol
|
||||||
private let appSettings: AppSettings
|
private let appSettings: AppSettings
|
||||||
private let analytics: AnalyticsService
|
private let analytics: AnalyticsService
|
||||||
|
private let application: ApplicationProtocol
|
||||||
private unowned let userIndicatorController: UserIndicatorControllerProtocol
|
private unowned let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
private let notificationCenterProtocol: NotificationCenterProtocol
|
private let notificationCenterProtocol: NotificationCenterProtocol
|
||||||
private let voiceMessageRecorder: VoiceMessageRecorderProtocol
|
private let voiceMessageRecorder: VoiceMessageRecorderProtocol
|
||||||
@@ -48,6 +49,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
appSettings: AppSettings,
|
appSettings: AppSettings,
|
||||||
analytics: AnalyticsService,
|
analytics: AnalyticsService,
|
||||||
userIndicatorController: UserIndicatorControllerProtocol,
|
userIndicatorController: UserIndicatorControllerProtocol,
|
||||||
|
application: ApplicationProtocol,
|
||||||
notificationCenterProtocol: NotificationCenterProtocol = NotificationCenter.default) {
|
notificationCenterProtocol: NotificationCenterProtocol = NotificationCenter.default) {
|
||||||
self.roomProxy = roomProxy
|
self.roomProxy = roomProxy
|
||||||
self.timelineController = timelineController
|
self.timelineController = timelineController
|
||||||
@@ -56,6 +58,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
self.userIndicatorController = userIndicatorController
|
self.userIndicatorController = userIndicatorController
|
||||||
self.notificationCenterProtocol = notificationCenterProtocol
|
self.notificationCenterProtocol = notificationCenterProtocol
|
||||||
self.mediaPlayerProvider = mediaPlayerProvider
|
self.mediaPlayerProvider = mediaPlayerProvider
|
||||||
|
self.application = application
|
||||||
voiceMessageRecorder = VoiceMessageRecorder(audioRecorder: AudioRecorder(), mediaPlayerProvider: mediaPlayerProvider)
|
voiceMessageRecorder = VoiceMessageRecorder(audioRecorder: AudioRecorder(), mediaPlayerProvider: mediaPlayerProvider)
|
||||||
|
|
||||||
super.init(initialViewState: RoomScreenViewState(roomID: timelineController.roomID,
|
super.init(initialViewState: RoomScreenViewState(roomID: timelineController.roomID,
|
||||||
@@ -327,16 +330,19 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
/// The ID of the newest item in the room that the user has seen.
|
/// The ID of the newest item in the room that the user has seen.
|
||||||
/// This includes both event based items and virtual items.
|
/// This includes both event based items and virtual items.
|
||||||
private var lastReadItemID: TimelineItemIdentifier?
|
private var lastReadItemID: TimelineItemIdentifier?
|
||||||
private func sendReadReceiptIfNeeded(for lastVisibleItemID: TimelineItemIdentifier) async -> Result<Void, RoomTimelineControllerError> {
|
private func sendReadReceiptIfNeeded(for lastVisibleItemID: TimelineItemIdentifier) async {
|
||||||
|
guard application.applicationState == .active else { return }
|
||||||
|
|
||||||
guard lastReadItemID != lastVisibleItemID,
|
guard lastReadItemID != lastVisibleItemID,
|
||||||
let eventItemID = eventBasedItem(nearest: lastVisibleItemID)
|
let eventItemID = eventBasedItem(nearest: lastVisibleItemID) else {
|
||||||
else { return .success(()) }
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure the item is newer than the item that was last marked as read.
|
// Make sure the item is newer than the item that was last marked as read.
|
||||||
if let lastReadItemIndex = state.timelineViewState.timelineIDs.firstIndex(of: lastReadItemID?.timelineID ?? ""),
|
if let lastReadItemIndex = state.timelineViewState.timelineIDs.firstIndex(of: lastReadItemID?.timelineID ?? ""),
|
||||||
let lastVisibleItemIndex = state.timelineViewState.timelineIDs.firstIndex(of: eventItemID.timelineID),
|
let lastVisibleItemIndex = state.timelineViewState.timelineIDs.firstIndex(of: eventItemID.timelineID),
|
||||||
lastReadItemIndex > lastVisibleItemIndex {
|
lastReadItemIndex > lastVisibleItemIndex {
|
||||||
return .success(())
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the last read item ID to avoid attempting duplicate requests.
|
// Update the last read item ID to avoid attempting duplicate requests.
|
||||||
@@ -348,10 +354,10 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch await timelineController.sendReadReceipt(for: eventItemID) {
|
switch await timelineController.sendReadReceipt(for: eventItemID) {
|
||||||
case .success:
|
case .success():
|
||||||
return .success(())
|
break
|
||||||
case .failure:
|
case let .failure(error):
|
||||||
return .failure(.generic)
|
MXLog.error("[TimelineViewController] Failed to send read receipt: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1028,7 +1034,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
|
|
||||||
private func openSystemSettings() {
|
private func openSystemSettings() {
|
||||||
guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
|
guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
|
||||||
UIApplication.shared.open(url)
|
application.open(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1061,7 +1067,8 @@ extension RoomScreenViewModel {
|
|||||||
roomProxy: RoomProxyMock(with: .init(displayName: "Preview room")),
|
roomProxy: RoomProxyMock(with: .init(displayName: "Preview room")),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
application: ApplicationMock.default)
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct ReplyInfo {
|
private struct ReplyInfo {
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ struct RoomHeaderView_Previews: PreviewProvider, TestablePreview {
|
|||||||
roomProxy: RoomProxyMock(with: .init(displayName: "Some Room name", avatarURL: URL.picturesDirectory)),
|
roomProxy: RoomProxyMock(with: .init(displayName: "Some Room name", avatarURL: URL.picturesDirectory)),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
RoomHeaderView(context: viewModel.context)
|
RoomHeaderView(context: viewModel.context)
|
||||||
.previewLayout(.sizeThatFits)
|
.previewLayout(.sizeThatFits)
|
||||||
@@ -76,7 +77,8 @@ struct RoomHeaderView_Previews: PreviewProvider, TestablePreview {
|
|||||||
roomProxy: RoomProxyMock(with: .init(displayName: "Some Room name")),
|
roomProxy: RoomProxyMock(with: .init(displayName: "Some Room name")),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
RoomHeaderView(context: viewModel.context)
|
RoomHeaderView(context: viewModel.context)
|
||||||
.previewLayout(.sizeThatFits)
|
.previewLayout(.sizeThatFits)
|
||||||
|
|||||||
@@ -195,7 +195,8 @@ struct RoomScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
roomProxy: RoomProxyMock(with: .init(displayName: "Preview room", isCallOngoing: true)),
|
roomProxy: RoomProxyMock(with: .init(displayName: "Preview room", isCallOngoing: true)),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
|
|||||||
+2
-1
@@ -65,7 +65,8 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
|
|||||||
members: members)),
|
members: members)),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
static let singleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now")]
|
static let singleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now")]
|
||||||
static let doubleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now"),
|
static let doubleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now"),
|
||||||
|
|||||||
@@ -86,7 +86,8 @@ struct UITimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
roomProxy: RoomProxyMock(with: .init(displayName: "Preview room")),
|
roomProxy: RoomProxyMock(with: .init(displayName: "Preview room")),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
|
|||||||
@@ -174,7 +174,8 @@ struct TimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
roomProxy: RoomProxyMock(with: .init(displayName: "Preview room")),
|
roomProxy: RoomProxyMock(with: .init(displayName: "Preview room")),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
|
|||||||
@@ -17,16 +17,23 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
// sourcery: AutoMockable
|
||||||
protocol ApplicationProtocol {
|
protocol ApplicationProtocol {
|
||||||
func beginBackgroundTask(expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier
|
func beginBackgroundTask(expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier
|
||||||
|
|
||||||
func beginBackgroundTask(withName taskName: String?, expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier
|
func beginBackgroundTask(withName taskName: String?, expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier
|
||||||
|
|
||||||
func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier)
|
func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier)
|
||||||
|
|
||||||
|
func open(_ url: URL)
|
||||||
|
|
||||||
var backgroundTimeRemaining: TimeInterval { get }
|
var backgroundTimeRemaining: TimeInterval { get }
|
||||||
|
|
||||||
var applicationState: UIApplication.State { get }
|
var applicationState: UIApplication.State { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
extension UIApplication: ApplicationProtocol { }
|
extension UIApplication: ApplicationProtocol {
|
||||||
|
func open(_ url: URL) {
|
||||||
|
open(url, options: [:], completionHandler: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class BackgroundTaskTests: XCTestCase {
|
|||||||
|
|
||||||
func testInitAndStop() {
|
func testInitAndStop() {
|
||||||
let service = UIKitBackgroundTaskService {
|
let service = UIKitBackgroundTaskService {
|
||||||
UIApplication.mockHealty
|
ApplicationMock.default
|
||||||
}
|
}
|
||||||
guard let task = service.startBackgroundTask(withName: Constants.bgTaskName) else {
|
guard let task = service.startBackgroundTask(withName: Constants.bgTaskName) else {
|
||||||
XCTFail("Failed to setup test conditions")
|
XCTFail("Failed to setup test conditions")
|
||||||
@@ -53,7 +53,7 @@ class BackgroundTaskTests: XCTestCase {
|
|||||||
|
|
||||||
func testNotReusableInit() {
|
func testNotReusableInit() {
|
||||||
let service = UIKitBackgroundTaskService {
|
let service = UIKitBackgroundTaskService {
|
||||||
UIApplication.mockHealty
|
ApplicationMock.default
|
||||||
}
|
}
|
||||||
|
|
||||||
// create two not reusable task with the same name
|
// create two not reusable task with the same name
|
||||||
@@ -70,7 +70,7 @@ class BackgroundTaskTests: XCTestCase {
|
|||||||
|
|
||||||
func testReusableInit() {
|
func testReusableInit() {
|
||||||
let service = UIKitBackgroundTaskService {
|
let service = UIKitBackgroundTaskService {
|
||||||
UIApplication.mockHealty
|
ApplicationMock.default
|
||||||
}
|
}
|
||||||
|
|
||||||
// create two reusable task with the same name
|
// create two reusable task with the same name
|
||||||
@@ -91,7 +91,7 @@ class BackgroundTaskTests: XCTestCase {
|
|||||||
|
|
||||||
func testMultipleStops() {
|
func testMultipleStops() {
|
||||||
let service = UIKitBackgroundTaskService {
|
let service = UIKitBackgroundTaskService {
|
||||||
UIApplication.mockHealty
|
ApplicationMock.default
|
||||||
}
|
}
|
||||||
|
|
||||||
// create two reusable task with the same name
|
// create two reusable task with the same name
|
||||||
@@ -114,7 +114,7 @@ class BackgroundTaskTests: XCTestCase {
|
|||||||
|
|
||||||
func testNotValidReuse() {
|
func testNotValidReuse() {
|
||||||
let service = UIKitBackgroundTaskService {
|
let service = UIKitBackgroundTaskService {
|
||||||
UIApplication.mockHealty
|
ApplicationMock.default
|
||||||
}
|
}
|
||||||
|
|
||||||
// create two reusable task with the same name
|
// create two reusable task with the same name
|
||||||
@@ -136,7 +136,7 @@ class BackgroundTaskTests: XCTestCase {
|
|||||||
|
|
||||||
func testValidReuse() {
|
func testValidReuse() {
|
||||||
let service = UIKitBackgroundTaskService {
|
let service = UIKitBackgroundTaskService {
|
||||||
UIApplication.mockHealty
|
ApplicationMock.default
|
||||||
}
|
}
|
||||||
|
|
||||||
// create two reusable task with the same name
|
// create two reusable task with the same name
|
||||||
@@ -162,7 +162,7 @@ class BackgroundTaskTests: XCTestCase {
|
|||||||
|
|
||||||
func testBrokenApp() {
|
func testBrokenApp() {
|
||||||
let service = UIKitBackgroundTaskService {
|
let service = UIKitBackgroundTaskService {
|
||||||
UIApplication.mockBroken
|
ApplicationMock.mockBroken
|
||||||
}
|
}
|
||||||
|
|
||||||
// create two reusable task with the same name
|
// create two reusable task with the same name
|
||||||
@@ -173,7 +173,7 @@ class BackgroundTaskTests: XCTestCase {
|
|||||||
|
|
||||||
func testNoTimeApp() {
|
func testNoTimeApp() {
|
||||||
let service = UIKitBackgroundTaskService {
|
let service = UIKitBackgroundTaskService {
|
||||||
UIApplication.mockAboutToSuspend
|
ApplicationMock.mockAboutToSuspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// create two reusable task with the same name
|
// create two reusable task with the same name
|
||||||
@@ -182,67 +182,3 @@ class BackgroundTaskTests: XCTestCase {
|
|||||||
XCTAssertNil(task, "Task should not be created")
|
XCTAssertNil(task, "Task should not be created")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension UIApplication {
|
|
||||||
static var mockHealty: ApplicationProtocol {
|
|
||||||
MockApplication()
|
|
||||||
}
|
|
||||||
|
|
||||||
static var mockBroken: ApplicationProtocol {
|
|
||||||
MockApplication(withState: .inactive,
|
|
||||||
backgroundTimeRemaining: 0,
|
|
||||||
allowTasks: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
static var mockAboutToSuspend: ApplicationProtocol {
|
|
||||||
MockApplication(withState: .background,
|
|
||||||
backgroundTimeRemaining: 2,
|
|
||||||
allowTasks: false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class MockApplication: ApplicationProtocol {
|
|
||||||
let applicationState: UIApplication.State
|
|
||||||
let backgroundTimeRemaining: TimeInterval
|
|
||||||
private let allowTasks: Bool
|
|
||||||
|
|
||||||
init(withState applicationState: UIApplication.State = .active,
|
|
||||||
backgroundTimeRemaining: TimeInterval = 10,
|
|
||||||
allowTasks: Bool = true) {
|
|
||||||
self.applicationState = applicationState
|
|
||||||
self.backgroundTimeRemaining = backgroundTimeRemaining
|
|
||||||
self.allowTasks = allowTasks
|
|
||||||
}
|
|
||||||
|
|
||||||
private static var bgTaskIdentifier = 0
|
|
||||||
|
|
||||||
private var bgTasks: [UIBackgroundTaskIdentifier: Bool] = [:]
|
|
||||||
|
|
||||||
func beginBackgroundTask(expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier {
|
|
||||||
guard allowTasks else {
|
|
||||||
return .invalid
|
|
||||||
}
|
|
||||||
return beginBackgroundTask(withName: nil, expirationHandler: handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func beginBackgroundTask(withName taskName: String?, expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier {
|
|
||||||
guard allowTasks else {
|
|
||||||
return .invalid
|
|
||||||
}
|
|
||||||
Self.bgTaskIdentifier += 1
|
|
||||||
|
|
||||||
let identifier = UIBackgroundTaskIdentifier(rawValue: Self.bgTaskIdentifier)
|
|
||||||
bgTasks[identifier] = true
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
|
||||||
handler?()
|
|
||||||
}
|
|
||||||
return identifier
|
|
||||||
}
|
|
||||||
|
|
||||||
func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier) {
|
|
||||||
guard allowTasks else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
bgTasks.removeValue(forKey: identifier)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ class PillContextTests: XCTestCase {
|
|||||||
roomProxy: proxyMock,
|
roomProxy: proxyMock,
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
application: ApplicationMock.default)
|
||||||
let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
|
let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
|
||||||
|
|
||||||
XCTAssertFalse(context.viewState.isOwnMention)
|
XCTAssertFalse(context.viewState.isOwnMention)
|
||||||
@@ -64,7 +65,8 @@ class PillContextTests: XCTestCase {
|
|||||||
roomProxy: proxyMock,
|
roomProxy: proxyMock,
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
application: ApplicationMock.default)
|
||||||
let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
|
let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
|
||||||
|
|
||||||
XCTAssertTrue(context.viewState.isOwnMention)
|
XCTAssertTrue(context.viewState.isOwnMention)
|
||||||
@@ -83,7 +85,8 @@ class PillContextTests: XCTestCase {
|
|||||||
roomProxy: proxyMock,
|
roomProxy: proxyMock,
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
application: ApplicationMock.default)
|
||||||
let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body)))
|
let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body)))
|
||||||
|
|
||||||
XCTAssertTrue(context.viewState.isOwnMention)
|
XCTAssertTrue(context.viewState.isOwnMention)
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: RoomProxyMock(with: .init(displayName: "")),
|
roomProxy: RoomProxyMock(with: .init(displayName: "")),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
// Then the messages should be grouped together.
|
// Then the messages should be grouped together.
|
||||||
XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.")
|
XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.")
|
||||||
@@ -89,7 +90,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: RoomProxyMock(with: .init(displayName: "")),
|
roomProxy: RoomProxyMock(with: .init(displayName: "")),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
// Then the messages should be grouped by sender.
|
// Then the messages should be grouped by sender.
|
||||||
XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .single, "A message should not be grouped when the sender changes.")
|
XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .single, "A message should not be grouped when the sender changes.")
|
||||||
@@ -121,7 +123,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: RoomProxyMock(with: .init(displayName: "")),
|
roomProxy: RoomProxyMock(with: .init(displayName: "")),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
// Then the first message should not be grouped but the other two should.
|
// Then the first message should not be grouped but the other two should.
|
||||||
XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .single, "When the first message has reactions it should not be grouped.")
|
XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .single, "When the first message has reactions it should not be grouped.")
|
||||||
@@ -150,7 +153,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: RoomProxyMock(with: .init(displayName: "")),
|
roomProxy: RoomProxyMock(with: .init(displayName: "")),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
// Then the first and second messages should be grouped and the last one should not.
|
// Then the first and second messages should be grouped and the last one should not.
|
||||||
XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.")
|
XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.")
|
||||||
@@ -179,7 +183,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: RoomProxyMock(with: .init(displayName: "")),
|
roomProxy: RoomProxyMock(with: .init(displayName: "")),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
// Then the messages should be grouped together.
|
// Then the messages should be grouped together.
|
||||||
XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.")
|
XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.")
|
||||||
@@ -204,7 +209,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: roomProxyMock,
|
roomProxy: roomProxyMock,
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
viewModel.actions
|
viewModel.actions
|
||||||
.sink { action in
|
.sink { action in
|
||||||
switch action {
|
switch action {
|
||||||
@@ -243,7 +249,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: roomProxyMock,
|
roomProxy: roomProxyMock,
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
viewModel.actions
|
viewModel.actions
|
||||||
.sink { action in
|
.sink { action in
|
||||||
@@ -283,7 +290,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: roomProxyMock,
|
roomProxy: roomProxyMock,
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
viewModel.actions
|
viewModel.actions
|
||||||
.sink { _ in
|
.sink { _ in
|
||||||
XCTFail("Should not receive any action")
|
XCTFail("Should not receive any action")
|
||||||
@@ -315,7 +323,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: roomProxyMock,
|
roomProxy: roomProxyMock,
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
viewModel.context.send(viewAction: .retrySend(itemID: .init(timelineID: UUID().uuidString, transactionID: "test retry send id")))
|
viewModel.context.send(viewAction: .retrySend(itemID: .init(timelineID: UUID().uuidString, transactionID: "test retry send id")))
|
||||||
|
|
||||||
@@ -335,7 +344,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: roomProxyMock,
|
roomProxy: roomProxyMock,
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
viewModel.context.send(viewAction: .retrySend(itemID: .random))
|
viewModel.context.send(viewAction: .retrySend(itemID: .random))
|
||||||
|
|
||||||
@@ -354,7 +364,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: roomProxyMock,
|
roomProxy: roomProxyMock,
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
viewModel.context.send(viewAction: .cancelSend(itemID: .init(timelineID: UUID().uuidString, transactionID: "test cancel send id")))
|
viewModel.context.send(viewAction: .cancelSend(itemID: .init(timelineID: UUID().uuidString, transactionID: "test cancel send id")))
|
||||||
|
|
||||||
@@ -374,7 +385,8 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
roomProxy: roomProxyMock,
|
roomProxy: roomProxyMock,
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock)
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default)
|
||||||
|
|
||||||
viewModel.context.send(viewAction: .cancelSend(itemID: .random))
|
viewModel.context.send(viewAction: .cancelSend(itemID: .random))
|
||||||
|
|
||||||
@@ -512,6 +524,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
|||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
analytics: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: userIndicatorControllerMock,
|
userIndicatorController: userIndicatorControllerMock,
|
||||||
|
application: ApplicationMock.default,
|
||||||
notificationCenterProtocol: notificationCenter)
|
notificationCenterProtocol: notificationCenter)
|
||||||
|
|
||||||
return (viewModel, roomProxy, timelineController, notificationCenter)
|
return (viewModel, roomProxy, timelineController, notificationCenter)
|
||||||
|
|||||||
Reference in New Issue
Block a user