From 148ee3d6b288bc75b6cf28ae20af92b306ac19fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Kuz=CC=81ma?= Date: Fri, 1 Sep 2023 15:47:34 +0200 Subject: [PATCH] Revert "T11574732: Fix renaming file issue from List on Full Screen Player and Mini Player" This reverts commit e060b5b174d8237c64c2e79d0007a5ecaa0371fa. --- MEGA.xcodeproj/project.pbxproj | 48 +---- .../AudioPlayerPlaybackTests.swift | 0 .../NodeInfoRepositoryTests.swift | 0 .../AudioPlayerRepositoryTests.swift | 57 ------ .../Mocks/MockAudioPlayerHandler.swift | 5 +- .../Mocks/MockAudioPlayerRepository.swift | 38 ---- .../AudioPlayerViewRouterTests.swift | 2 + .../UseCases/AudioPlayerUseCaseTests.swift | 84 -------- .../Mocks/MockAudioPlayerUseCase.swift | 29 --- .../ViewModel/AudioPlayerViewModelTests.swift | 154 +++------------ .../ViewModel/MiniPlayerViewModelTests.swift | 185 +----------------- MEGAUnitTests/Mocks/AudioPlayerItem.swift | 4 - .../Sources/MEGASDKRepoMock/SDK/MockSdk.swift | 10 - .../AudioPlayer/AudioPlayerManager.swift | 5 +- .../Repository/AudioPlayerRepository.swift | 42 ---- .../AudioPlayerViewModel.swift | 130 +----------- .../AudioPlayerViewRouter.swift | 10 +- .../MiniPlayerViewController.swift | 4 +- .../MiniPlayerScene/MiniPlayerViewModel.swift | 112 +---------- .../MiniPlayerViewRouter.swift | 5 +- ...layerTrackNameUpdateCheckerViewModel.swift | 19 -- .../UseCases/AudioPlayerUseCase.swift | 29 --- 22 files changed, 58 insertions(+), 914 deletions(-) rename MEGAUnitTests/AudioPlayer/{Repository => }/AudioPlayerPlaybackTests.swift (100%) rename MEGAUnitTests/AudioPlayer/{Repository => }/NodeInfoRepositoryTests.swift (100%) delete mode 100644 MEGAUnitTests/AudioPlayer/Repository/AudioPlayerRepositoryTests.swift delete mode 100644 MEGAUnitTests/AudioPlayer/Repository/Mocks/MockAudioPlayerRepository.swift delete mode 100644 MEGAUnitTests/AudioPlayer/UseCases/AudioPlayerUseCaseTests.swift delete mode 100644 MEGAUnitTests/AudioPlayer/UseCases/Mocks/MockAudioPlayerUseCase.swift delete mode 100644 iMEGA/AudioPlayer/Repository/AudioPlayerRepository.swift delete mode 100644 iMEGA/AudioPlayer/Scenes/Shared/AudioPlayerTrackNameUpdateCheckerViewModel.swift delete mode 100644 iMEGA/AudioPlayer/UseCases/AudioPlayerUseCase.swift diff --git a/MEGA.xcodeproj/project.pbxproj b/MEGA.xcodeproj/project.pbxproj index a900142754..4091e31b0d 100644 --- a/MEGA.xcodeproj/project.pbxproj +++ b/MEGA.xcodeproj/project.pbxproj @@ -137,18 +137,12 @@ 243F74912A42D8380050D5E4 /* OfflineViewController+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 243F74902A42D8380050D5E4 /* OfflineViewController+Additions.swift */; }; 244F0A6E2A457ED0007DC61B /* AdvancedTableViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 244F0A6D2A457ED0007DC61B /* AdvancedTableViewControllerTests.swift */; }; 245385FA2A13C05B00208B31 /* NodeInfoViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 245385F92A13C05B00208B31 /* NodeInfoViewControllerTests.swift */; }; - 245543B62A9F64FA0057103F /* MockAudioPlayerUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 245543B52A9F64FA0057103F /* MockAudioPlayerUseCase.swift */; }; - 245543B82A9F659C0057103F /* MockAudioPlayerRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 245543B72A9F659C0057103F /* MockAudioPlayerRepository.swift */; }; 24575FEF2A499A62003EAE79 /* CloudDriveViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24575FEE2A499A62003EAE79 /* CloudDriveViewControllerTests.swift */; }; 245CB1A82A32DDFD005F6527 /* AppMetaData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 245CB1A72A32DDFD005F6527 /* AppMetaData.swift */; }; 245CB1AA2A32DE30005F6527 /* DeviceMetaData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 245CB1A92A32DE30005F6527 /* DeviceMetaData.swift */; }; 246013122A459166007EF5ED /* AdvancedViewRouterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 246013112A459166007EF5ED /* AdvancedViewRouterTests.swift */; }; 2461E7042A8CC90600A8FFA6 /* StreamingInfoRepositoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2461E7032A8CC90600A8FFA6 /* StreamingInfoRepositoryTests.swift */; }; 246A311F2A45709200BF8DDB /* AdvancedTableViewController+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 246A311E2A45709200BF8DDB /* AdvancedTableViewController+Additions.swift */; }; - 247279B62A9EF2D100877FC1 /* AudioPlayerRepositoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247279B52A9EF2D100877FC1 /* AudioPlayerRepositoryTests.swift */; }; - 247279B92A9EFC2A00877FC1 /* AudioPlayerRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247279B82A9EFC2A00877FC1 /* AudioPlayerRepository.swift */; }; - 247279BD2A9EFD9900877FC1 /* AudioPlayerUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247279BC2A9EFD9900877FC1 /* AudioPlayerUseCaseTests.swift */; }; - 247279C22A9F0DB400877FC1 /* AudioPlayerUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247279C12A9F0DB400877FC1 /* AudioPlayerUseCase.swift */; }; 247FC1BE2A4F1C3700CC8518 /* QASettingsRouterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247FC1BD2A4F1C3700CC8518 /* QASettingsRouterTests.swift */; }; 2488EBC32A13B503005F910E /* NodeActionViewControllerGenericDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2488EBC22A13B503005F910E /* NodeActionViewControllerGenericDelegateTests.swift */; }; 248A031B2A79026800F183A2 /* MEGAAVViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 248A031A2A79026800F183A2 /* MEGAAVViewControllerTests.swift */; }; @@ -162,7 +156,6 @@ 24B6276F2A8F687E00AD588C /* NodeInfoRepositoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24B6276E2A8F687E00AD588C /* NodeInfoRepositoryTests.swift */; }; 24BD7B062A36FD430052668B /* AppMetaDataFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24BD7B052A36FD430052668B /* AppMetaDataFactory.swift */; }; 24BD7B082A36FD5F0052668B /* DeviceMetaDataFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24BD7B072A36FD5F0052668B /* DeviceMetaDataFactory.swift */; }; - 24E384442A9C4357006865F1 /* AudioPlayerTrackNameUpdateCheckerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E384432A9C4357006865F1 /* AudioPlayerTrackNameUpdateCheckerViewModel.swift */; }; 24E99B462A65257700E4D6A5 /* ToggleSecureFingerprintFlagUIAlertAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E99B452A65257700E4D6A5 /* ToggleSecureFingerprintFlagUIAlertAdapter.swift */; }; 24F231592A5FB33A000BFBBA /* AudioPlayerViewRouterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F231582A5FB33A000BFBBA /* AudioPlayerViewRouterTests.swift */; }; 2533401E2A78A3CF002C7AAE /* CustomModalAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2533401D2A78A3CF002C7AAE /* CustomModalAlertView.swift */; }; @@ -2648,18 +2641,12 @@ 243F74902A42D8380050D5E4 /* OfflineViewController+Additions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OfflineViewController+Additions.swift"; sourceTree = ""; }; 244F0A6D2A457ED0007DC61B /* AdvancedTableViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedTableViewControllerTests.swift; sourceTree = ""; }; 245385F92A13C05B00208B31 /* NodeInfoViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeInfoViewControllerTests.swift; sourceTree = ""; }; - 245543B52A9F64FA0057103F /* MockAudioPlayerUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockAudioPlayerUseCase.swift; sourceTree = ""; }; - 245543B72A9F659C0057103F /* MockAudioPlayerRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockAudioPlayerRepository.swift; sourceTree = ""; }; 24575FEE2A499A62003EAE79 /* CloudDriveViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudDriveViewControllerTests.swift; sourceTree = ""; }; 245CB1A72A32DDFD005F6527 /* AppMetaData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMetaData.swift; sourceTree = ""; }; 245CB1A92A32DE30005F6527 /* DeviceMetaData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceMetaData.swift; sourceTree = ""; }; 246013112A459166007EF5ED /* AdvancedViewRouterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedViewRouterTests.swift; sourceTree = ""; }; 2461E7032A8CC90600A8FFA6 /* StreamingInfoRepositoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StreamingInfoRepositoryTests.swift; sourceTree = ""; }; 246A311E2A45709200BF8DDB /* AdvancedTableViewController+Additions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AdvancedTableViewController+Additions.swift"; sourceTree = ""; }; - 247279B52A9EF2D100877FC1 /* AudioPlayerRepositoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerRepositoryTests.swift; sourceTree = ""; }; - 247279B82A9EFC2A00877FC1 /* AudioPlayerRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerRepository.swift; sourceTree = ""; }; - 247279BC2A9EFD9900877FC1 /* AudioPlayerUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerUseCaseTests.swift; sourceTree = ""; }; - 247279C12A9F0DB400877FC1 /* AudioPlayerUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerUseCase.swift; sourceTree = ""; }; 247FC1BD2A4F1C3700CC8518 /* QASettingsRouterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QASettingsRouterTests.swift; sourceTree = ""; }; 2488EBC22A13B503005F910E /* NodeActionViewControllerGenericDelegateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeActionViewControllerGenericDelegateTests.swift; sourceTree = ""; }; 248A031A2A79026800F183A2 /* MEGAAVViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MEGAAVViewControllerTests.swift; sourceTree = ""; }; @@ -2673,7 +2660,6 @@ 24B6276E2A8F687E00AD588C /* NodeInfoRepositoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeInfoRepositoryTests.swift; sourceTree = ""; }; 24BD7B052A36FD430052668B /* AppMetaDataFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMetaDataFactory.swift; sourceTree = ""; }; 24BD7B072A36FD5F0052668B /* DeviceMetaDataFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceMetaDataFactory.swift; sourceTree = ""; }; - 24E384432A9C4357006865F1 /* AudioPlayerTrackNameUpdateCheckerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerTrackNameUpdateCheckerViewModel.swift; sourceTree = ""; }; 24E99B452A65257700E4D6A5 /* ToggleSecureFingerprintFlagUIAlertAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleSecureFingerprintFlagUIAlertAdapter.swift; sourceTree = ""; }; 24F231582A5FB33A000BFBBA /* AudioPlayerViewRouterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerViewRouterTests.swift; sourceTree = ""; }; 2533401D2A78A3CF002C7AAE /* CustomModalAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomModalAlertView.swift; sourceTree = ""; }; @@ -5684,14 +5670,6 @@ path = NodeInfo; sourceTree = ""; }; - 245543B32A9F64E50057103F /* Mocks */ = { - isa = PBXGroup; - children = ( - 245543B52A9F64FA0057103F /* MockAudioPlayerUseCase.swift */, - ); - path = Mocks; - sourceTree = ""; - }; 247FC1BC2A4F1C2400CC8518 /* QASettings */ = { isa = PBXGroup; children = ( @@ -5733,19 +5711,10 @@ C47E7C0125D18FDF00DB6FF5 /* MockNodeInfoRepository.swift */, C47E7C1B25D1A84200DB6FF5 /* MockOfflineFileInfoRepository.swift */, C47E7C2D25D1A8C800DB6FF5 /* MockStreaminginfoRepository.swift */, - 245543B72A9F659C0057103F /* MockAudioPlayerRepository.swift */, ); path = Mocks; sourceTree = ""; }; - 24E384412A9C4349006865F1 /* Shared */ = { - isa = PBXGroup; - children = ( - 24E384432A9C4357006865F1 /* AudioPlayerTrackNameUpdateCheckerViewModel.swift */, - ); - path = Shared; - sourceTree = ""; - }; 24F231562A5FB313000BFBBA /* Scenes */ = { isa = PBXGroup; children = ( @@ -11749,6 +11718,8 @@ 24F231562A5FB313000BFBBA /* Scenes */, C45A2E3625D2F7F100915A83 /* UseCases */, C45A2DF325D2B93B00915A83 /* ViewModel */, + C452B66325CD50260073B22C /* AudioPlayerPlaybackTests.swift */, + 24B6276E2A8F687E00AD588C /* NodeInfoRepositoryTests.swift */, ); path = AudioPlayer; sourceTree = ""; @@ -11756,7 +11727,6 @@ C453AB70256E5F8D005E4E1B /* Scenes */ = { isa = PBXGroup; children = ( - 24E384412A9C4349006865F1 /* Shared */, C49F861F255ABE860074A054 /* AudioPlayerScene */, C453AB75256E5FCF005E4E1B /* AudioPlaylistScene */, C4AF4A8B2582833200594716 /* MiniPlayerScene */, @@ -11770,7 +11740,6 @@ 9DAC1B622951589E00562475 /* NodeInfoRepository.swift */, C4D665C325B1F84E002196E9 /* OfflineFileInfoRepository.swift */, C450CFB625B83E5F005C707D /* StreamingInfoRepository.swift */, - 247279B82A9EFC2A00877FC1 /* AudioPlayerRepository.swift */, ); path = Repository; sourceTree = ""; @@ -11782,7 +11751,6 @@ C453AB7E256E7AE8005E4E1B /* NodeInfoUseCase.swift */, C4D665B725B1F835002196E9 /* OfflineFileInfoUseCase.swift */, C450CFC225B84350005C707D /* StreamingInfoUseCase.swift */, - 247279C12A9F0DB400877FC1 /* AudioPlayerUseCase.swift */, ); path = UseCases; sourceTree = ""; @@ -11832,11 +11800,9 @@ C45A2E3625D2F7F100915A83 /* UseCases */ = { isa = PBXGroup; children = ( - 245543B32A9F64E50057103F /* Mocks */, C45A2E3725D2F80900915A83 /* NodeInfoUseCaseTests.swift */, C45A2E4925D2F81800915A83 /* OfflineFileInfoUseCaseTests.swift */, C45A2E5325D2F82600915A83 /* StreamingInfoUseCaseTests.swift */, - 247279BC2A9EFD9900877FC1 /* AudioPlayerUseCaseTests.swift */, ); path = UseCases; sourceTree = ""; @@ -11942,9 +11908,6 @@ children = ( 24D59EDC2A8CD52900503F43 /* Mocks */, 2461E7032A8CC90600A8FFA6 /* StreamingInfoRepositoryTests.swift */, - 247279B52A9EF2D100877FC1 /* AudioPlayerRepositoryTests.swift */, - C452B66325CD50260073B22C /* AudioPlayerPlaybackTests.swift */, - 24B6276E2A8F687E00AD588C /* NodeInfoRepositoryTests.swift */, ); path = Repository; sourceTree = ""; @@ -13167,7 +13130,6 @@ 8366518826497B3600BC02F0 /* CallParticipantCell.swift in Sources */, 838B976826B1615F000E480E /* CallParticipantEntity+Mapping.swift in Sources */, 838A7B6925D5678C00767DB0 /* CallRepository.swift in Sources */, - 247279B92A9EFC2A00877FC1 /* AudioPlayerRepository.swift in Sources */, 8330A99A28882E78003E80DB /* CallsSettingsSoundNotificationsView.swift in Sources */, 8330A99728882E4A003E80DB /* CallsSettingsView.swift in Sources */, 83AE36C22886D033002F1755 /* CallsSettingsViewModel.swift in Sources */, @@ -13396,7 +13358,6 @@ 124667F9275DB82000C94335 /* CustomModalAlertViewController+Business.swift in Sources */, 124667FF275DB82000C94335 /* CustomModalAlertViewController+Config.swift in Sources */, 124667FE275DB82000C94335 /* CustomModalAlertViewController+Contacts.swift in Sources */, - 247279C22A9F0DB400877FC1 /* AudioPlayerUseCase.swift in Sources */, 124667FA275DB82000C94335 /* CustomModalAlertViewController+CookieDialog.swift in Sources */, 83B4FC69292402E100364F04 /* CustomModalAlertViewcontroller+EnableKeyRotation.swift in Sources */, 124667FB275DB82000C94335 /* CustomModalAlertViewController+LaunchTab.swift in Sources */, @@ -13609,7 +13570,6 @@ 5D64660824890BEA006030A5 /* HexColor.swift in Sources */, B69AF66528A1E5190022B094 /* HistoryRetentionPickerViewModel.swift in Sources */, 5DD4B2F1257DEAE000A01306 /* HomeBannerRouter.swift in Sources */, - 24E384442A9C4357006865F1 /* AudioPlayerTrackNameUpdateCheckerViewModel.swift in Sources */, 5D8C5AB724F0A39300EDD7A9 /* HomeLocalisation.swift in Sources */, BF74E1E3253668E1001F663C /* HomeRouter.swift in Sources */, 5DA32DBA24EA27DC0075B613 /* HomeScreenFactory.swift in Sources */, @@ -14992,7 +14952,6 @@ 94A518EF2A6ED0E700728730 /* ChatViewControllerTests.swift in Sources */, 24575FEF2A499A62003EAE79 /* CloudDriveViewControllerTests.swift in Sources */, 94CBB2C42A8A578400C62F32 /* ContactsViewModelTests.swift in Sources */, - 245543B62A9F64FA0057103F /* MockAudioPlayerUseCase.swift in Sources */, A81F9BB427EA023A00D47C0D /* CookieSettingsViewModelTests.swift in Sources */, B5488B7A2A8DBFAD00A069DF /* CountdownTimerTests.swift in Sources */, 943649DF2A4D83DE006CE8B8 /* CustomModalModel+Equatable.swift in Sources */, @@ -15003,7 +14962,6 @@ 274514C22A2F5BDE00BFFB2F /* ElementStoreTests.swift in Sources */, BF2B2C82263F549D006E12A4 /* EndMeetingOptionsViewModelTests.swift in Sources */, 0E72E12A2A285CDD00C900F9 /* EnforceCopyrightWarningViewModelTests.swift in Sources */, - 247279B62A9EF2D100877FC1 /* AudioPlayerRepositoryTests.swift in Sources */, 6D0CA0ED2981D15200CBE9E4 /* ExplorerTypeEntityMappingTests.swift in Sources */, 5BBC13DE26CE62D10010115B /* FavouritesViewModelTests.swift in Sources */, B5E9D41528ACF8CE00504F1F /* FeatureFlagViewModelTests.swift in Sources */, @@ -15019,7 +14977,6 @@ 0E3E07A32A1EA6C700A2A71B /* GetAlbumLinkViewModelTests.swift in Sources */, 0E2FD9DD2A258C3B00FB75F1 /* GetAlbumsLinkViewModelTests.swift in Sources */, 0E3B1A392A1D919B00EC5859 /* GetLinkAlbumInfoCellViewModelTests.swift in Sources */, - 245543B82A9F659C0057103F /* MockAudioPlayerRepository.swift in Sources */, 0E3B1A502A1DC0EF00EC5859 /* GetLinkStringTableViewCellTests.swift in Sources */, 0E3B1A4A2A1DBA5500EC5859 /* GetLinkSwitchOptionCellViewModelTests.swift in Sources */, BF66CA7728B83ACF00DB686E /* HangOrEndCallViewModelTests.swift in Sources */, @@ -15043,7 +15000,6 @@ 248A031B2A79026800F183A2 /* MEGAAVViewControllerTests.swift in Sources */, 0E847F852A68E27D00AFE051 /* MEGALinkManager+AdditionsTests.swift in Sources */, BFE556FC27E183B40028EF1F /* MEGANode+Additions_Tests.swift in Sources */, - 247279BD2A9EFD9900877FC1 /* AudioPlayerUseCaseTests.swift in Sources */, BFE556FE27E183B40028EF1F /* MEGANode+FilePaths_Tests.swift in Sources */, 5D62093824ED1511004648A1 /* MEGANotificationUseCaseTests.swift in Sources */, C45A2E2325D2E05100915A83 /* MiniPlayerViewModelTests.swift in Sources */, diff --git a/MEGAUnitTests/AudioPlayer/Repository/AudioPlayerPlaybackTests.swift b/MEGAUnitTests/AudioPlayer/AudioPlayerPlaybackTests.swift similarity index 100% rename from MEGAUnitTests/AudioPlayer/Repository/AudioPlayerPlaybackTests.swift rename to MEGAUnitTests/AudioPlayer/AudioPlayerPlaybackTests.swift diff --git a/MEGAUnitTests/AudioPlayer/Repository/NodeInfoRepositoryTests.swift b/MEGAUnitTests/AudioPlayer/NodeInfoRepositoryTests.swift similarity index 100% rename from MEGAUnitTests/AudioPlayer/Repository/NodeInfoRepositoryTests.swift rename to MEGAUnitTests/AudioPlayer/NodeInfoRepositoryTests.swift diff --git a/MEGAUnitTests/AudioPlayer/Repository/AudioPlayerRepositoryTests.swift b/MEGAUnitTests/AudioPlayer/Repository/AudioPlayerRepositoryTests.swift deleted file mode 100644 index d461e1f319..0000000000 --- a/MEGAUnitTests/AudioPlayer/Repository/AudioPlayerRepositoryTests.swift +++ /dev/null @@ -1,57 +0,0 @@ -import Combine -@testable import MEGA -import MEGADomain -import MEGASDKRepoMock -import XCTest - -final class AudioPlayerRepositoryTests: XCTestCase { - - private var subscriptions = [AnyCancellable]() - - func testInit_doesNotRegisterMEGADelegate() { - let (_, sdk) = makeSUT() - - XCTAssertEqual(sdk.addMEGADelegateCallCount, 0) - } - - func testRegisterMEGADelegate_calledSetDelegate() async { - let (sut, sdk) = makeSUT() - - await sut.registerMEGADelegate() - - XCTAssertEqual(sdk.addMEGADelegateCallCount, 1) - } - - func testUnregisterMEGADelegate_shouldNotCalledRemoveDelegate() async { - let (sut, sdk) = makeSUT() - - await sut.unregisterMEGADelegate() - - XCTAssertEqual(sdk.removeMEGADelegateCallCount, 1) - } - - func testOnNodesUpdate_whenInvoked_sendsUpdate() { - let (sut, sdk) = makeSUT() - let sampleNodes = [MockNode(handle: 1)] - let sampleNodeList = MockNodeList(nodes: sampleNodes) - var receivedEntities: [NodeEntity]? - sut.reloadItemPublisher - .sink(receiveValue: { nodeEntities in receivedEntities = nodeEntities }) - .store(in: &subscriptions) - - sut.onNodesUpdate(sdk, nodeList: sampleNodeList) - - XCTAssertEqual(receivedEntities, sampleNodeList.toNodeEntities()) - } - - // MARK: - Helpers - - private func makeSUT(file: StaticString = #filePath, line: UInt = #line) -> (sut: AudioPlayerRepository, sdk: MockSdk) { - let sdk = MockSdk() - let sut = AudioPlayerRepository(sdk: sdk) - trackForMemoryLeaks(on: sut, file: file, line: line) - trackForMemoryLeaks(on: sdk, file: file, line: line) - return (sut, sdk) - } - -} diff --git a/MEGAUnitTests/AudioPlayer/Repository/Mocks/MockAudioPlayerHandler.swift b/MEGAUnitTests/AudioPlayer/Repository/Mocks/MockAudioPlayerHandler.swift index 76f942c9a8..8e6ba4e85f 100644 --- a/MEGAUnitTests/AudioPlayer/Repository/Mocks/MockAudioPlayerHandler.swift +++ b/MEGAUnitTests/AudioPlayer/Repository/Mocks/MockAudioPlayerHandler.swift @@ -28,15 +28,13 @@ final class MockAudioPlayerHandler: AudioPlayerHandlerProtocol { private var _isPlayerDefined = false - var audioPlayer: AudioPlayer? - private(set) var playerResumePlayback_Calls = [TimeInterval]() func isPlayerDefined() -> Bool { _isPlayerDefined } func isPlayerEmpty() -> Bool { false } func currentPlayer() -> AudioPlayer? { - audioPlayer + AudioPlayer() } func setCurrent( @@ -47,7 +45,6 @@ final class MockAudioPlayerHandler: AudioPlayerHandlerProtocol { addPlayer_calledTimes += 1 addPlayerTracks_calledTimes += 1 _isPlayerDefined = true - audioPlayer = player } func addPlayer(listener: any AudioPlayerObserversProtocol) { diff --git a/MEGAUnitTests/AudioPlayer/Repository/Mocks/MockAudioPlayerRepository.swift b/MEGAUnitTests/AudioPlayer/Repository/Mocks/MockAudioPlayerRepository.swift deleted file mode 100644 index 71c8a9f785..0000000000 --- a/MEGAUnitTests/AudioPlayer/Repository/Mocks/MockAudioPlayerRepository.swift +++ /dev/null @@ -1,38 +0,0 @@ -import Combine -@testable import MEGA -import MEGADomain - -final class MockAudioPlayerRepository: AudioPlayerRepositoryProtocol { - var reloadItemPublisher: AnyPublisher<[NodeEntity], Never> { _reloadItemPublisher.eraseToAnyPublisher() } - - private let _reloadItemPublisher: PassthroughSubject<[NodeEntity], Never> - - init(reloadItemPublisher: PassthroughSubject<[NodeEntity], Never>) { - self._reloadItemPublisher = reloadItemPublisher - } - - enum Message { - case registerMEGADelegate - case unregisterMEGADelegate - } - - static var newRepo: MockAudioPlayerRepository { - let reloadItemPublisher = PassthroughSubject<[NodeEntity], Never>() - let repo = MockAudioPlayerRepository(reloadItemPublisher: reloadItemPublisher) - return repo - } - - private(set) var messages = [Message]() - - func registerMEGADelegate() { - messages.append(.registerMEGADelegate) - } - - func unregisterMEGADelegate() { - messages.append(.unregisterMEGADelegate) - } - - func simulateOnNodesUpdate(with nodes: [NodeEntity]) { - _reloadItemPublisher.send(nodes) - } -} diff --git a/MEGAUnitTests/AudioPlayer/Scenes/AudioPlayerScenes/AudioPlayerViewRouterTests.swift b/MEGAUnitTests/AudioPlayer/Scenes/AudioPlayerScenes/AudioPlayerViewRouterTests.swift index 3187b65860..61dad2472c 100644 --- a/MEGAUnitTests/AudioPlayer/Scenes/AudioPlayerScenes/AudioPlayerViewRouterTests.swift +++ b/MEGAUnitTests/AudioPlayer/Scenes/AudioPlayerScenes/AudioPlayerViewRouterTests.swift @@ -1,6 +1,7 @@ @testable import MEGA import MEGADomain import MEGASDKRepoMock +import MEGATest import XCTest final class AudioPlayerViewRouterTests: XCTestCase { @@ -51,6 +52,7 @@ final class AudioPlayerViewRouterTests: XCTestCase { ), presenter: currentContextViewController ) + trackForMemoryLeaks(on: sut, file: file, line: line) return sut } diff --git a/MEGAUnitTests/AudioPlayer/UseCases/AudioPlayerUseCaseTests.swift b/MEGAUnitTests/AudioPlayer/UseCases/AudioPlayerUseCaseTests.swift deleted file mode 100644 index 3ffaf75086..0000000000 --- a/MEGAUnitTests/AudioPlayer/UseCases/AudioPlayerUseCaseTests.swift +++ /dev/null @@ -1,84 +0,0 @@ -import Combine -@testable import MEGA -import MEGADomain -import XCTest - -final class AudioPlayerUseCaseTests: XCTestCase { - - private var subscriptions = [AnyCancellable]() - - func testInit_doesNotRegister() { - let (_, repository) = makeSUT() - - XCTAssertTrue(repository.messages.isEmpty, "Expect to not triggering sdk") - } - - func testRegisterMEGADelegate_registerDelegate() async { - let (sut, repository) = makeSUT() - - await sut.registerMEGADelegate() - - XCTAssertEqual(repository.messages, [ .registerMEGADelegate ]) - } - - func testUnregisterMEGADelegate_unregisterDelegate() async { - let (sut, repository) = makeSUT() - - await sut.unregisterMEGADelegate() - - XCTAssertEqual(repository.messages, [ .unregisterMEGADelegate ]) - } - - func testReloadItemPublisher_whenNoNodesUpdate_DoesNotReloadsItem() { - let (sut, _) = makeSUT() - var receivedEntities: [NodeEntity]? - let exp = expectation(description: "Wait for subscription") - exp.isInverted = true - sut.reloadItemPublisher() - .sink(receiveValue: { nodeEntities in - receivedEntities = nodeEntities - exp.fulfill() - }) - .store(in: &subscriptions) - wait(for: [exp], timeout: 0.1) - - XCTAssertNil(receivedEntities) - } - - func testReloadItemPublisher_whenHasNodesUpdate_DoesNotReloadsItem() { - let node = NodeEntity(handle: 1) - let (sut, repository) = makeSUT() - var receivedEntities: [NodeEntity]? - let exp = expectation(description: "Wait for subscription") - sut.reloadItemPublisher() - .sink(receiveValue: { nodeEntities in - receivedEntities = nodeEntities - exp.fulfill() - }) - .store(in: &subscriptions) - - repository.simulateOnNodesUpdate(with: [node]) - wait(for: [exp], timeout: 0.1) - - XCTAssertNotNil(receivedEntities) - XCTAssertEqual(receivedEntities, [node]) - } - - // MARK: - Helpers - - private func makeSUT( - reloadItemPublisher: () -> PassthroughSubject<[NodeEntity], Never> = { - let subject = PassthroughSubject<[NodeEntity], Never>() - return subject - }, - file: StaticString = #filePath, - line: UInt = #line - ) -> (sut: AudioPlayerUseCase, repository: MockAudioPlayerRepository) { - let repository = MockAudioPlayerRepository(reloadItemPublisher: reloadItemPublisher()) - let sut = AudioPlayerUseCase(repository: repository) - trackForMemoryLeaks(on: sut, file: file, line: line) - trackForMemoryLeaks(on: repository, file: file, line: line) - return (sut, repository) - } - -} diff --git a/MEGAUnitTests/AudioPlayer/UseCases/Mocks/MockAudioPlayerUseCase.swift b/MEGAUnitTests/AudioPlayer/UseCases/Mocks/MockAudioPlayerUseCase.swift deleted file mode 100644 index 1bdeca47a4..0000000000 --- a/MEGAUnitTests/AudioPlayer/UseCases/Mocks/MockAudioPlayerUseCase.swift +++ /dev/null @@ -1,29 +0,0 @@ -import Combine -@testable import MEGA -import MEGADomain -import MEGASDKRepoMock - -final class MockAudioPlayerUseCase: AudioPlayerUseCaseProtocol { - private(set) var registerMEGADelegateCallCount = 0 - private(set) var unregisterMEGADelegateCallCount = 0 - - private let subject = PassthroughSubject<[NodeEntity], Never>() - - func registerMEGADelegate() { - registerMEGADelegateCallCount += 1 - } - - func unregisterMEGADelegate() { - unregisterMEGADelegateCallCount += 1 - } - - func reloadItemPublisher() -> AnyPublisher<[NodeEntity], Never> { - subject - .eraseToAnyPublisher() - } - - func simulateOnNodesUpdate(_ nodeList: MockNodeList, sdk: MockSdk) { - sdk.setNodes(nodeList.toNodeArray()) - subject.send(nodeList.toNodeArray().toNodeEntities()) - } -} diff --git a/MEGAUnitTests/AudioPlayer/ViewModel/AudioPlayerViewModelTests.swift b/MEGAUnitTests/AudioPlayer/ViewModel/AudioPlayerViewModelTests.swift index 01391aa6a0..dff374bbef 100644 --- a/MEGAUnitTests/AudioPlayer/ViewModel/AudioPlayerViewModelTests.swift +++ b/MEGAUnitTests/AudioPlayer/ViewModel/AudioPlayerViewModelTests.swift @@ -7,7 +7,7 @@ import XCTest final class AudioPlayerViewModelTests: XCTestCase { func testPlaybackActions() { - let (onlineSUT, _, playerHandler, _, _, _) = makeOnlineSUT() + let (onlineSUT, _, playerHandler, _) = makeOnlineSUT() test(viewModel: onlineSUT, action: .onViewDidLoad, expectedCommands: [.showLoading(true), .configureFileLinkPlayer(title: "Track 5", subtitle: Strings.Localizable.fileLink), @@ -68,7 +68,7 @@ final class AudioPlayerViewModelTests: XCTestCase { func testRouterActions() { let router = MockAudioPlayerViewRouter() - let (onlineSUT, _, _, _, _, _) = makeOnlineSUT(router: router) + let (onlineSUT, _, _, _) = makeOnlineSUT(router: router) let (offlineSUT, _) = makeOfflineSUT(router: router) test(viewModel: onlineSUT, action: .dismiss, expectedCommands: []) @@ -97,7 +97,7 @@ final class AudioPlayerViewModelTests: XCTestCase { } func testOnReceiveAudioPlayerActions_shouldInvokeCorrectCommands() { - let (onlineSUT, playbackUseCase, _, _, _, _) = makeOnlineSUT() + let (onlineSUT, playbackUseCase, _, _) = makeOnlineSUT() playbackUseCase._status = .startFromBeginning assert( @@ -110,7 +110,7 @@ final class AudioPlayerViewModelTests: XCTestCase { } func testAudioStartPlayingWithDisplayDialogStatus_shouldDisplayDialog_andPausePlayer_whenAppIsActive() { - let (onlineSUT, playbackUseCase, playerHandler, _, _, _) = makeOnlineSUT() + let (onlineSUT, playbackUseCase, playerHandler, _) = makeOnlineSUT() onlineSUT.checkAppIsActive = { true } playbackUseCase._status = .displayDialog(playbackTime: 1234.0) @@ -130,7 +130,7 @@ final class AudioPlayerViewModelTests: XCTestCase { } func testAudioStartPlayingWithDisplayDialogStatus_shouldNotDisplayDialog_whenAppIsNotActive() { - let (onlineSUT, playbackUseCase, _, _, _, _) = makeOnlineSUT() + let (onlineSUT, playbackUseCase, _, _) = makeOnlineSUT() onlineSUT.checkAppIsActive = { false } playbackUseCase._status = .displayDialog(playbackTime: 1234.0) @@ -144,7 +144,7 @@ final class AudioPlayerViewModelTests: XCTestCase { } func testAudioStartPlayingWithDisplayDialogStatus_shouldResumePlayback_whenAppIsNotActive() { - let (onlineSUT, playbackUseCase, playerHandler, _, _, _) = makeOnlineSUT() + let (onlineSUT, playbackUseCase, playerHandler, _) = makeOnlineSUT() onlineSUT.checkAppIsActive = { false } playbackUseCase._status = .displayDialog(playbackTime: 1234.0) @@ -159,7 +159,7 @@ final class AudioPlayerViewModelTests: XCTestCase { } func testAudioPlaybackContinuation_resumeSession() { - let (onlineSUT, playbackUseCase, playerHandler, _, _, _) = makeOnlineSUT() + let (onlineSUT, playbackUseCase, playerHandler, _) = makeOnlineSUT() playbackUseCase._status = .resumeSession(playbackTime: 1234.0) onlineSUT.audioDidStartPlayingItem(testItem) @@ -171,7 +171,7 @@ final class AudioPlayerViewModelTests: XCTestCase { } func testSelectPlaybackContinuationDialog_shouldSetPreference() { - let (onlineSUT, playbackUseCase, _, _, _, _) = makeOnlineSUT() + let (onlineSUT, playbackUseCase, _, _) = makeOnlineSUT() onlineSUT.dispatch(.onSelectResumePlaybackContinuationDialog(playbackTime: 1234.0)) XCTAssertEqual( @@ -198,11 +198,10 @@ final class AudioPlayerViewModelTests: XCTestCase { XCTAssertNotNil(firstPlayerHandler.currentPlayer()) let (differentSUT, _, differentPlayerHandler, _) = simulateUserViewDidLoadWithNewInstane(audioNode: latestAudioNode) - differentPlayerHandler.setCurrent(player: AudioPlayer(), autoPlayEnabled: false, tracks: []) XCTAssertEqual(differentPlayerHandler.setCurrent_callTimes, 0) try assertThatCleanPlayerStateForReuse(on: differentPlayerHandler, sut: differentSUT) - XCTAssertTrue(differentSUT.isSingleTrackPlayer, "expect single track.") + XCTAssertTrue(differentSUT.isSingleTrackPlayer) differentSUT.invokeCommand = { XCTAssertEqual($0, .configureDefaultPlayer) XCTAssertEqual($0, .shuffleAction(enabled: false)) @@ -211,73 +210,27 @@ final class AudioPlayerViewModelTests: XCTestCase { } } - func testOnNodesUpdate_whenHasUpdatedItemButNotFoundNodeInList_ShouldNotRefresh() { - let firstAudioNode = MockNode(handle: 1, name: "first-audio", nodeType: .file) - let latestAudioNode = MockNode(handle: 2, name: "latest-audio", nodeType: .file) - let updatedNode = MockNode(handle: 3, name: "New name") - let updatedItem: AudioPlayerItem = .mockItem(node: updatedNode) - let (onlineSUT, _, _, _, audioPlayerUseCase, sdk) = makeOnlineSUT( - node: firstAudioNode, - allNodes: [firstAudioNode, latestAudioNode] - ) - var invokedCommands = [AudioPlayerViewModel.Command]() - onlineSUT.invokeCommand = { invokedCommands.append($0) } - let exp = expectation(description: "wait") - - audioPlayerUseCase.simulateOnNodesUpdate(MockNodeList(nodes: [updatedNode]), sdk: sdk) - exp.fulfill() - wait(for: [exp], timeout: 0.1) - - assertThatRefreshItemUIIsNotUpdatedOnRefreshItem(on: onlineSUT, updatedItem: updatedItem, invokedCommands: invokedCommands) - assertThatRefreshItemDataSourceIsNotUpdated(on: onlineSUT, updatedNode: updatedNode, latestAudioNode: latestAudioNode) - } - - func testOnNodesUpdate_whenHasUpdatedItem_refresh() { - let firstAudioNode = MockNode(handle: 1, name: "first-audio", nodeType: .file) - let latestAudioNode = MockNode(handle: 2, name: "latest-audio", nodeType: .file) - let updatedNode = MockNode(handle: 1, name: "New name") - let (onlineSUT, _, _, _, audioPlayerUseCase, sdk) = makeOnlineSUT( - node: firstAudioNode, - allNodes: [firstAudioNode, latestAudioNode] - ) - - assertThatRefreshItemUIUpdatedOnRefreshItem(on: onlineSUT, updatedNode: updatedNode, audioPlayerUseCase: audioPlayerUseCase, sdk: sdk) - assertThatRefreshItemDataSourceUpdated(on: onlineSUT, updatedNode: updatedNode, latestAudioNode: latestAudioNode) - } - // MARK: - Helpers - private func makeOnlineSUT( - router: MockAudioPlayerViewRouter = MockAudioPlayerViewRouter(), - node: MEGANode? = MEGANode(), - allNodes: [MEGANode]? = nil - ) -> ( - sut: AudioPlayerViewModel, - playbackUseCase: MockPlaybackContinuationUseCase, - playerHandler: MockAudioPlayerHandler, - router: MockAudioPlayerViewRouter, - audioPlayerUseCase: MockAudioPlayerUseCase, - sdk: MockSdk - ) { + private func makeOnlineSUT(router: MockAudioPlayerViewRouter = MockAudioPlayerViewRouter()) -> (sut: AudioPlayerViewModel, playbackUseCase: MockPlaybackContinuationUseCase, playerHandler: MockAudioPlayerHandler, router: MockAudioPlayerViewRouter) { let playerHandler = MockAudioPlayerHandler() - let (sut, playbackUseCase, audioPlayerUseCase, sdk) = makeSUT( + let (sut, playbackUseCase) = makeSUT( configEntity: AudioPlayerConfigEntity( - node: node, + node: MEGANode(), isFolderLink: false, fileLink: "", - allNodes: allNodes, playerHandler: playerHandler ), nodeInfoUseCase: NodeInfoUseCase(nodeInfoRepository: MockNodeInfoRepository()), streamingInfoUseCase: StreamingInfoUseCase(streamingInfoRepository: MockStreamingInfoRepository()), router: router ) - return (sut, playbackUseCase, playerHandler, router, audioPlayerUseCase, sdk) + return (sut, playbackUseCase, playerHandler, router) } private func makeOfflineSUT(router: MockAudioPlayerViewRouter = MockAudioPlayerViewRouter()) -> (sut: AudioPlayerViewModel, router: MockAudioPlayerViewRouter) { let playerHandler = MockAudioPlayerHandler() - let (sut, _, _, _) = makeSUT( + let (sut, _) = makeSUT( configEntity: AudioPlayerConfigEntity( fileLink: "file_path", playerHandler: playerHandler @@ -294,15 +247,8 @@ final class AudioPlayerViewModelTests: XCTestCase { streamingInfoUseCase: (any StreamingInfoUseCaseProtocol)? = nil, offlineInfoUseCase: (any OfflineFileInfoUseCaseProtocol)? = nil, router: MockAudioPlayerViewRouter - ) -> ( - sut: AudioPlayerViewModel, - playbackContinuationUseCase: MockPlaybackContinuationUseCase, - audioPlayerUseCase: MockAudioPlayerUseCase, - sdk: MockSdk - ) { + ) -> (sut: AudioPlayerViewModel, playbackContinuationUseCase: MockPlaybackContinuationUseCase) { let mockPlaybackContinuationUseCase = MockPlaybackContinuationUseCase() - let audioPlayerUseCase = MockAudioPlayerUseCase() - let sdk = MockSdk() let sut = AudioPlayerViewModel( configEntity: configEntity, router: router, @@ -310,17 +256,15 @@ final class AudioPlayerViewModelTests: XCTestCase { streamingInfoUseCase: streamingInfoUseCase, offlineInfoUseCase: offlineInfoUseCase, playbackContinuationUseCase: mockPlaybackContinuationUseCase, - audioPlayerUseCase: audioPlayerUseCase, - dispatchQueue: MockDispatchQueue(), - sdk: sdk + dispatchQueue: MockDispatchQueue() ) - return (sut, mockPlaybackContinuationUseCase, audioPlayerUseCase, sdk) + return (sut, mockPlaybackContinuationUseCase) } private func simulateUserViewDidLoadWithNewInstane(audioNode: MockNode) -> (sut: AudioPlayerViewModel, playbackUseCase: MockPlaybackContinuationUseCase, playerHandler: MockAudioPlayerHandler, router: MockAudioPlayerViewRouter) { let router = MockAudioPlayerViewRouter() let configEntity = audioPlayerConfigEntity(node: audioNode) - let (sut, playbackUseCase, _, _) = makeSUT( + let (sut, playbackUseCase) = makeSUT( configEntity: configEntity, nodeInfoUseCase: NodeInfoUseCase(nodeInfoRepository: MockNodeInfoRepository()), streamingInfoUseCase: StreamingInfoUseCase(streamingInfoRepository: MockStreamingInfoRepository()), @@ -334,7 +278,6 @@ final class AudioPlayerViewModelTests: XCTestCase { _ viewModel: AudioPlayerViewModel, when action: (AudioPlayerViewModel) -> Void, shouldInvokeCommands expectedCommands: [AudioPlayerViewModel.Command], - file: StaticString = #filePath, line: UInt = #line ) { var invokedCommands = [AudioPlayerViewModel.Command]() @@ -342,7 +285,7 @@ final class AudioPlayerViewModelTests: XCTestCase { action(viewModel) - XCTAssertEqual(invokedCommands, expectedCommands, file: file, line: line) + XCTAssertEqual(invokedCommands, expectedCommands, line: line) } private var testItem: AudioPlayerItem { @@ -364,67 +307,18 @@ final class AudioPlayerViewModelTests: XCTestCase { } private func assertThatCleanPlayerStateForReuse(on playerHandler: MockAudioPlayerHandler, sut: AudioPlayerViewModel, file: StaticString = #filePath, line: UInt = #line) throws { - let player = try XCTUnwrap(playerHandler.currentPlayer(), "Fail to get currentPlayer", file: file, line: line) + let player = try XCTUnwrap(playerHandler.currentPlayer(), file: file, line: line) assertThatRemovePreviousQueuedTrackInPlayer(on: player, file: file, line: line) assertThatRefreshPlayerListener(on: player, sut: sut, file: file, line: line) } private func assertThatRemovePreviousQueuedTrackInPlayer(on player: AudioPlayer, file: StaticString = #filePath, line: UInt = #line) { - XCTAssertNil(player.queuePlayer, "Expect to remove previous queued track player, but not removed.", file: file, line: line) - XCTAssertTrue(player.tracks.isEmpty, "Expect track is empty, but not empty instead.", file: file, line: line) + XCTAssertNil(player.queuePlayer, file: file, line: line) + XCTAssertTrue(player.tracks.isEmpty, file: file, line: line) } private func assertThatRefreshPlayerListener(on player: AudioPlayer, sut: AudioPlayerViewModel, file: StaticString = #filePath, line: UInt = #line) { - XCTAssertTrue(player.listenerManager.listeners.isEmpty, "Expect listeners empty.", file: file, line: line) - XCTAssertTrue(player.listenerManager.listeners.notContains(where: { $0 as! AnyHashable == sut as AnyHashable }), "Expect listeners not contains observer.", file: file, line: line) - } - - private func assertThatRefreshItemUIIsNotUpdatedOnRefreshItem(on onlineSUT: AudioPlayerViewModel, updatedItem: AudioPlayerItem, invokedCommands: [AudioPlayerViewModel.Command], file: StaticString = #filePath, line: UInt = #line) { - var receivedCommands = [AudioPlayerViewModel.Command]() - invokedCommands.forEach { receivedCommands.append($0) } - XCTAssertTrue(receivedCommands.isEmpty, file: file, line: line) - } - - private func assertThatRefreshItemUIUpdatedOnRefreshItem(on onlineSUT: AudioPlayerViewModel, updatedNode: MEGANode, audioPlayerUseCase: MockAudioPlayerUseCase, sdk: MockSdk, file: StaticString = #filePath, line: UInt = #line) { - assert( - onlineSUT, - when: { _ in audioPlayerUseCase.simulateOnNodesUpdate(MockNodeList(nodes: [updatedNode]), sdk: sdk) }, - shouldInvokeCommands: [ - .reloadNodeInfo(name: "New name", artist: "", thumbnail: nil, size: Optional("Zero KB")), - .showLoading(false) - ], - file: file, - line: line - ) - } - - private func assertThatRefreshItemDataSourceIsNotUpdated(on onlineSUT: AudioPlayerViewModel, updatedNode: MEGANode, latestAudioNode: MEGANode, file: StaticString = #filePath, line: UInt = #line) { - XCTAssertNotEqual(onlineSUT.configEntity.node, updatedNode, file: file, line: line) - onlineSUT.configEntity.playerHandler.currentPlayer()?.tracks - .map { $0.name } - .enumerated() - .forEach { (index, name) in - if index == 1 { - XCTAssertEqual(name, updatedNode.name, file: file, line: line) - } - if index == 2 { - XCTAssertEqual(name, latestAudioNode.name, file: file, line: line) - } - } - } - - private func assertThatRefreshItemDataSourceUpdated(on onlineSUT: AudioPlayerViewModel, updatedNode: MEGANode, latestAudioNode: MEGANode, file: StaticString = #filePath, line: UInt = #line) { - XCTAssertEqual(onlineSUT.configEntity.node, updatedNode, file: file, line: line) - onlineSUT.configEntity.playerHandler.currentPlayer()?.tracks - .map { $0.name } - .enumerated() - .forEach { (index, name) in - if index == 1 { - XCTAssertEqual(name, updatedNode.name, file: file, line: line) - } - if index == 2 { - XCTAssertEqual(name, latestAudioNode.name, file: file, line: line) - } - } + XCTAssertTrue(player.listenerManager.listeners.isEmpty, file: file, line: line) + XCTAssertTrue(player.listenerManager.listeners.notContains(where: { $0 as! AnyHashable == sut as! AnyHashable }), file: file, line: line) } } diff --git a/MEGAUnitTests/AudioPlayer/ViewModel/MiniPlayerViewModelTests.swift b/MEGAUnitTests/AudioPlayer/ViewModel/MiniPlayerViewModelTests.swift index a83b58195d..f9d506edd4 100644 --- a/MEGAUnitTests/AudioPlayer/ViewModel/MiniPlayerViewModelTests.swift +++ b/MEGAUnitTests/AudioPlayer/ViewModel/MiniPlayerViewModelTests.swift @@ -1,4 +1,3 @@ -import Combine @testable import MEGA import MEGADomain import MEGADomainMock @@ -11,7 +10,7 @@ final class MiniPlayerViewModelTests: XCTestCase { private var mockPlaybackContinuationUseCase = MockPlaybackContinuationUseCase() func testAudioPlayerActions() { - let (viewModel, _, _) = makeSUT() + let viewModel = makeSUT() test(viewModel: viewModel, action: .onViewDidLoad, expectedCommands: [.showLoading(false), .initTracks(currentItem: AudioPlayerItem.mockItem, queue: nil, loopMode: false)]) XCTAssertEqual(mockPlayerHandler.addPlayerListener_calledTimes, 1) @@ -27,7 +26,7 @@ final class MiniPlayerViewModelTests: XCTestCase { } func testRouterActions() { - let (viewModel, _, _) = makeSUT() + let viewModel = makeSUT() test(viewModel: viewModel, action: .onClose, expectedCommands: []) XCTAssertEqual(mockRouter.dismiss_calledTimes, 1) @@ -41,7 +40,7 @@ final class MiniPlayerViewModelTests: XCTestCase { expectedPlayerResumePlaybackCalls: [TimeInterval], line: UInt = #line ) { - let (viewModel, _, _) = makeSUT() + let viewModel = makeSUT() mockPlaybackContinuationUseCase._status = continuationStatus viewModel.audioDidStartPlayingItem(testItem) @@ -67,94 +66,31 @@ final class MiniPlayerViewModelTests: XCTestCase { ) } - func testOnViewDidLoad_onViewDidLoad_registerSdk() { - let (onlineSUT, audioPlayerUseCase, _) = makeSUT() - - onlineSUT.dispatch(.onViewDidLoad) - - XCTAssertEqual(audioPlayerUseCase.registerMEGADelegateCallCount, 1) - } - - func testOnNodesUpdate_whenHasUpdatedItemButNotFoundNodeInList_ShouldNotRefresh() { - let firstAudioNode = MockNode(handle: 1, name: "first-audio", nodeType: .file) - let latestAudioNode = MockNode(handle: 2, name: "latest-audio", nodeType: .file) - let updatedNode = MockNode(handle: 3, name: "New name") - let updatedItem: AudioPlayerItem = .mockItem(node: updatedNode) - let (onlineSUT, audioPlayerUseCase, sdk) = makeSUT( - node: firstAudioNode, - allNodes: [firstAudioNode, latestAudioNode] - ) - let exp = expectation(description: "wait") - var invokedCommands = [MiniPlayerViewModel.Command]() - onlineSUT.invokeCommand = { invokedCommands.append($0) } - - audioPlayerUseCase.simulateOnNodesUpdate(MockNodeList(nodes: [updatedNode]), sdk: sdk) - exp.fulfill() - wait(for: [exp], timeout: 0.2) - - XCTAssertEqual(invokedCommands.count, 0) - let receivedItems = invokedCommands.reloadedItems() - XCTAssertFalse(receivedItems.contains(updatedItem), "Expect to not contain updated node. We do not want to update node when node is not on the list.") - assertThatRefreshItemDataSourceIsNotUpdated(on: onlineSUT, updatedNode: updatedNode, latestAudioNode: latestAudioNode) - } - - func testOnNodesUpdate_whenHasUpdatedItemAndNotShowingCurrentItem_refresh() { - let firstAudioNode = MockNode(handle: 1, name: "first-audio", nodeType: .file) - let latestAudioNode = MockNode(handle: 2, name: "latest-audio", nodeType: .file) - let updatedNode = MockNode(handle: 1, name: "New name") - let expectedItem: AudioPlayerItem = .mockItem(node: updatedNode) - let (onlineSUT, audioPlayerUseCase, sdk) = makeSUT( - node: firstAudioNode, - allNodes: [firstAudioNode, latestAudioNode] - ) - let exp = expectation(description: "wait") - var invokedCommands = [MiniPlayerViewModel.Command]() - onlineSUT.invokeCommand = { invokedCommands.append($0) } - - simulateOnNodesUpdate(audioPlayerUseCase, updatedNode, sdk, latestAudioNode) - exp.fulfill() - wait(for: [exp], timeout: 1) - - assertThatRefreshItemReloadNonCurrentItem(invokedCommands: invokedCommands, expectedItem: expectedItem) - assertThatRefreshItemDataSourceUpdated(on: onlineSUT, updatedNode: updatedNode, latestAudioNode: latestAudioNode) - } - // MARK: - Test Helpers private func makeSUT( - node: MEGANode? = nil, - allNodes: [MEGANode]? = nil, file: StaticString = #file, line: UInt = #line - ) -> (sut: MiniPlayerViewModel, audioPlayerUseCase: MockAudioPlayerUseCase, sdk: MockSdk) { + ) -> MiniPlayerViewModel { mockRouter = MockMiniPlayerViewRouter() mockPlayerHandler = MockAudioPlayerHandler() mockPlaybackContinuationUseCase = MockPlaybackContinuationUseCase() - let tracks = allNodes?.compactMap { AudioPlayerItem(name: $0.name ?? "", url: URL(string: "www.any-url.com")!, node: $0) } - let player = AudioPlayer() - player.tracks = tracks ?? [] - mockPlayerHandler.setCurrent(player: player, autoPlayEnabled: false, tracks: tracks ?? []) - let mockAudioPlayerUseCase = MockAudioPlayerUseCase() - let sdk = MockSdk(nodes: allNodes ?? []) let sut = MiniPlayerViewModel( configEntity: AudioPlayerConfigEntity( - node: node, + node: nil, isFolderLink: false, fileLink: nil, relatedFiles: nil, - allNodes: allNodes, playerHandler: mockPlayerHandler ), router: mockRouter, nodeInfoUseCase: NodeInfoUseCase(nodeInfoRepository: MockNodeInfoRepository()), streamingInfoUseCase: StreamingInfoUseCase(streamingInfoRepository: MockStreamingInfoRepository()), offlineInfoUseCase: OfflineFileInfoUseCase(offlineInfoRepository: MockOfflineInfoRepository()), - playbackContinuationUseCase: mockPlaybackContinuationUseCase, - audioPlayerUseCase: mockAudioPlayerUseCase, - sdk: sdk + playbackContinuationUseCase: mockPlaybackContinuationUseCase ) trackForMemoryLeaks(on: sut, file: file, line: line) - return (sut, mockAudioPlayerUseCase, sdk) + return sut } private var testItem: AudioPlayerItem { @@ -165,111 +101,4 @@ final class MiniPlayerViewModelTests: XCTestCase { ) } - private func simulateOnNodesUpdate(_ audioPlayerUseCase: MockAudioPlayerUseCase, _ updatedNode: MockNode, _ sdk: MockSdk, _ latestAudioNode: MockNode) { - audioPlayerUseCase.simulateOnNodesUpdate(MockNodeList(nodes: [updatedNode]), sdk: sdk) - let tracks = [updatedNode, latestAudioNode].compactMap { AudioPlayerItem(name: $0.name ?? "", url: URL(string: "www.any-url.com")!, node: $0) } - let player = AudioPlayer() - player.tracks = tracks - mockPlayerHandler.setCurrent(player: player, autoPlayEnabled: false, tracks: tracks) - } - - private func assertThatRefreshItemReloadNonCurrentItem( - invokedCommands: [MiniPlayerViewModel.Command], - expectedItem: AudioPlayerItem, - file: StaticString = #filePath, - line: UInt = #line - ) { - XCTAssertEqual(invokedCommands.count, 1, file: file, line: line) - guard let command = invokedCommands.first else { - XCTFail("Fail to get command", file: file, line: line) - return - } - - switch command { - case .reloadAt: - break - default: - XCTFail("Expect to get reload command, got other command instead.", file: file, line: line) - } - } - - private func assertThatRefreshItemReloadCurrentItem( - invokedCommands: [MiniPlayerViewModel.Command], - expectedItem: AudioPlayerItem, - file: StaticString = #filePath, - line: UInt = #line - ) { - XCTAssertEqual(invokedCommands.count, 1, file: file, line: line) - guard let command = invokedCommands.first else { - XCTFail("Fail to get command", file: file, line: line) - return - } - - switch command { - case .reload(let currentItem): - XCTAssertEqual(currentItem.name, expectedItem.name, file: file, line: line) - XCTAssertEqual(currentItem.url, expectedItem.url, file: file, line: line) - default: - XCTFail("Expect to get reload command, got other command instead.", file: file, line: line) - } - } - - private func assertThatRefreshItemDataSourceIsNotUpdated( - on onlineSUT: MiniPlayerViewModel, - updatedNode: MEGANode, - latestAudioNode: MEGANode, - file: StaticString = #filePath, - line: UInt = #line - ) { - XCTAssertNotEqual(onlineSUT.configEntity.node, updatedNode, file: file, line: line) - onlineSUT.configEntity.playerHandler.currentPlayer()?.tracks - .map { $0.name } - .enumerated() - .forEach { (index, name) in - if index == 1 { - XCTAssertNotEqual(name, updatedNode.name, file: file, line: line) - } - if index == 2 { - XCTAssertEqual(name, latestAudioNode.name, file: file, line: line) - } - } - } - - private func assertThatRefreshItemDataSourceUpdated( - on onlineSUT: MiniPlayerViewModel, - updatedNode: MEGANode, - latestAudioNode: MEGANode, - file: StaticString = #filePath, - line: UInt = #line - ) { - XCTAssertEqual(onlineSUT.configEntity.node, updatedNode, file: file, line: line) - onlineSUT.configEntity.playerHandler.currentPlayer()?.tracks - .map { $0.name } - .enumerated() - .forEach { (index, name) in - if index == 0 { - XCTAssertEqual(name, updatedNode.name, "fail at index: \(index)", file: file, line: line) - } - if index == 1 { - XCTAssertEqual(name, latestAudioNode.name, "fail at index: \(index)", file: file, line: line) - } - } - } - -} - -private extension Array where Element == MiniPlayerViewModel.Command { - - func reloadedItems(file: StaticString = #filePath, line: UInt = #line) -> [AudioPlayerItem] { - var receivedItems = [AudioPlayerItem]() - enumerated().forEach { (index, command) in - switch command { - case .reload(let currentItem): - receivedItems.append(currentItem) - default: - XCTFail("Expect to got reload command, got other command instead: \(command) at index: \(index)", file: file, line: line) - } - } - return receivedItems - } } diff --git a/MEGAUnitTests/Mocks/AudioPlayerItem.swift b/MEGAUnitTests/Mocks/AudioPlayerItem.swift index 26c69aa5b8..0b34f2a70e 100644 --- a/MEGAUnitTests/Mocks/AudioPlayerItem.swift +++ b/MEGAUnitTests/Mocks/AudioPlayerItem.swift @@ -6,10 +6,6 @@ extension AudioPlayerItem { .init(name: "Track 5", url: URL(string: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3")!, node: MEGANode()) } - static func mockItem(node: MEGANode) -> Self { - .init(name: node.name ?? "", url: URL(string: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3")!, node: node) - } - static var mockArray: [AudioPlayerItem] { [AudioPlayerItem(name: "Track 1", url: URL(string: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3")!, node: nil), AudioPlayerItem(name: "Track 2", url: URL(string: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3")!, node: nil), diff --git a/Modules/Repository/MEGASDKRepo/Sources/MEGASDKRepoMock/SDK/MockSdk.swift b/Modules/Repository/MEGASDKRepo/Sources/MEGASDKRepoMock/SDK/MockSdk.swift index dc30357f79..e8f58ad099 100644 --- a/Modules/Repository/MEGASDKRepo/Sources/MEGASDKRepoMock/SDK/MockSdk.swift +++ b/Modules/Repository/MEGASDKRepo/Sources/MEGASDKRepoMock/SDK/MockSdk.swift @@ -57,8 +57,6 @@ public final class MockSdk: MEGASdk { public var hasGlobalDelegate = false public var hasRequestDelegate = false public var hasTransferDelegate = false - public var addMEGADelegateCallCount = 0 - public var removeMEGADelegateCallCount = 0 public var apiURL: String? public var disablepkp: Bool? public var shareAccessLevel: MEGAShareType = .accessUnknown @@ -213,14 +211,6 @@ public final class MockSdk: MEGASdk { hasTransferDelegate = false } - public override func add(_ delegate: any MEGADelegate) { - addMEGADelegateCallCount += 1 - } - - public override func remove(_ delegate: any MEGADelegate) { - removeMEGADelegateCallCount += 1 - } - public override func copy(_ node: MEGANode, newParent: MEGANode, delegate: any MEGARequestDelegate) { let mockRequest = MockRequest(handle: copiedNodeHandles[node.handle] ?? .invalid) delegate.onRequestFinish?(self, diff --git a/iMEGA/AudioPlayer/AudioPlayer/AudioPlayerManager.swift b/iMEGA/AudioPlayer/AudioPlayer/AudioPlayerManager.swift index c7ba5f0b8c..c84971da83 100644 --- a/iMEGA/AudioPlayer/AudioPlayer/AudioPlayerManager.swift +++ b/iMEGA/AudioPlayer/AudioPlayer/AudioPlayerManager.swift @@ -166,7 +166,7 @@ import MEGAPresentation } private func checkIfCallExist(then clousure: (() -> Void)?) { - if MEGAChatSdk.shared.mnz_existsActiveCall { + if MEGASdkManager.sharedMEGAChatSdk().mnz_existsActiveCall { Helper.cannotPlayContentDuringACallAlert() } else { clousure?() @@ -273,8 +273,7 @@ import MEGAPresentation guard player != nil else { return } - let allNodes = currentPlayer()?.tracks.compactMap(\.node) - miniPlayerRouter = MiniPlayerViewRouter(configEntity: AudioPlayerConfigEntity(node: node, isFolderLink: isFolderLink, fileLink: fileLink, relatedFiles: filePaths, allNodes: allNodes, playerHandler: self, shouldResetPlayer: shouldResetPlayer), presenter: presenter) + miniPlayerRouter = MiniPlayerViewRouter(configEntity: AudioPlayerConfigEntity(node: node, isFolderLink: isFolderLink, fileLink: fileLink, relatedFiles: filePaths, playerHandler: self, shouldResetPlayer: shouldResetPlayer), presenter: presenter) miniPlayerVC = nil diff --git a/iMEGA/AudioPlayer/Repository/AudioPlayerRepository.swift b/iMEGA/AudioPlayer/Repository/AudioPlayerRepository.swift deleted file mode 100644 index 4987265790..0000000000 --- a/iMEGA/AudioPlayer/Repository/AudioPlayerRepository.swift +++ /dev/null @@ -1,42 +0,0 @@ -import Combine -import MEGADomain -import MEGASdk - -protocol AudioPlayerRepositoryProtocol: RepositoryProtocol { - var reloadItemPublisher: AnyPublisher<[NodeEntity], Never> { get } - - func registerMEGADelegate() async - func unregisterMEGADelegate() async -} - -final class AudioPlayerRepository: NSObject, AudioPlayerRepositoryProtocol { - private let sdk: MEGASdk - private let _reloadItemPublisher = PassthroughSubject<[NodeEntity], Never>() - - var reloadItemPublisher: AnyPublisher<[NodeEntity], Never> { - _reloadItemPublisher.eraseToAnyPublisher() - } - - static var newRepo: AudioPlayerRepository { - return AudioPlayerRepository(sdk: .shared) - } - - init(sdk: MEGASdk) { - self.sdk = sdk - } - - func registerMEGADelegate() async { - sdk.add(self) - } - - func unregisterMEGADelegate() async { - sdk.remove(self) - } -} - -extension AudioPlayerRepository: MEGADelegate { - - func onNodesUpdate(_ api: MEGASdk, nodeList: MEGANodeList) { - _reloadItemPublisher.send(nodeList.toNodeArray().toNodeEntities()) - } -} diff --git a/iMEGA/AudioPlayer/Scenes/AudioPlayerScene/AudioPlayerViewModel.swift b/iMEGA/AudioPlayer/Scenes/AudioPlayerScene/AudioPlayerViewModel.swift index 9549ea8d20..67308fc1c0 100644 --- a/iMEGA/AudioPlayer/Scenes/AudioPlayerScene/AudioPlayerViewModel.swift +++ b/iMEGA/AudioPlayer/Scenes/AudioPlayerScene/AudioPlayerViewModel.swift @@ -1,4 +1,3 @@ -import Combine import Foundation import MEGADomain import MEGAFoundation @@ -54,7 +53,7 @@ enum PlayerType: String { case `default`, folderLink, fileLink, offline } -final class AudioPlayerViewModel: NSObject, ViewModelType { +final class AudioPlayerViewModel: ViewModelType { enum Command: CommandType, Equatable { case reloadNodeInfo(name: String, artist: String, thumbnail: UIImage?, size: String?) case reloadThumbnail(thumbnail: UIImage) @@ -76,15 +75,13 @@ final class AudioPlayerViewModel: NSObject, ViewModelType { } // MARK: - Private properties - private(set) var configEntity: AudioPlayerConfigEntity + private var configEntity: AudioPlayerConfigEntity private let router: any AudioPlayerViewRouting private let nodeInfoUseCase: (any NodeInfoUseCaseProtocol)? private let streamingInfoUseCase: (any StreamingInfoUseCaseProtocol)? private let offlineInfoUseCase: (any OfflineFileInfoUseCaseProtocol)? private let playbackContinuationUseCase: any PlaybackContinuationUseCaseProtocol - private let audioPlayerUseCase: any AudioPlayerUseCaseProtocol private let dispatchQueue: any DispatchQueueProtocol - private let sdk: MEGASdk private var repeatItemsState: RepeatMode { didSet { invokeCommand?(.updateRepeat(status: repeatItemsState)) @@ -103,8 +100,6 @@ final class AudioPlayerViewModel: NSObject, ViewModelType { } private(set) var isSingleTrackPlayer: Bool = false - private var subscriptions = [AnyCancellable]() - // MARK: - Internal properties var invokeCommand: ((Command) -> Void)? var checkAppIsActive: () -> Bool = { @@ -118,24 +113,16 @@ final class AudioPlayerViewModel: NSObject, ViewModelType { streamingInfoUseCase: (any StreamingInfoUseCaseProtocol)? = nil, offlineInfoUseCase: (any OfflineFileInfoUseCaseProtocol)? = nil, playbackContinuationUseCase: any PlaybackContinuationUseCaseProtocol, - audioPlayerUseCase: some AudioPlayerUseCaseProtocol, - dispatchQueue: some DispatchQueueProtocol = DispatchQueue.global(), - sdk: MEGASdk = MEGASdk.shared - ) { + dispatchQueue: some DispatchQueueProtocol = DispatchQueue.global()) { self.configEntity = configEntity self.router = router self.nodeInfoUseCase = nodeInfoUseCase self.streamingInfoUseCase = streamingInfoUseCase self.offlineInfoUseCase = offlineInfoUseCase self.playbackContinuationUseCase = playbackContinuationUseCase - self.audioPlayerUseCase = audioPlayerUseCase self.repeatItemsState = configEntity.playerHandler.currentRepeatMode() self.speedModeState = configEntity.playerHandler.currentSpeedMode() self.dispatchQueue = dispatchQueue - self.sdk = sdk - super.init() - - self.setupUpdateItemSubscription() } // MARK: - Private functions @@ -331,28 +318,12 @@ final class AudioPlayerViewModel: NSObject, ViewModelType { initialize(tracks: files, currentTrack: currentTrack) } - private func memoryStyleString(from configEntity: AudioPlayerConfigEntity) -> String { - String.memoryStyleString(fromByteCount: configEntity.node?.size?.int64Value ?? Int64(0)) - } - private func reloadNodeInfoWithCurrentItem() { guard let currentItem = configEntity.playerHandler.playerCurrentItem() else { return } invokeCommand?(.reloadNodeInfo(name: currentItem.name, artist: currentItem.artist ?? "", thumbnail: currentItem.artwork, - size: memoryStyleString(from: configEntity))) - - configEntity.playerHandler.refreshCurrentItemState() - - invokeCommand?(.showLoading(false)) - } - - private func reloadNodeInfoWithCurrentItem(name: String) { - guard let currentItem = configEntity.playerHandler.playerCurrentItem() else { return } - invokeCommand?(.reloadNodeInfo(name: name, - artist: currentItem.artist ?? "", - thumbnail: currentItem.artwork, - size: memoryStyleString(from: configEntity))) + size: String.memoryStyleString(fromByteCount: configEntity.node?.size?.int64Value ?? Int64(0)))) configEntity.playerHandler.refreshCurrentItemState() @@ -363,9 +334,6 @@ final class AudioPlayerViewModel: NSObject, ViewModelType { func dispatch(_ action: AudioPlayerAction) { switch action { case .onViewDidLoad: - Task { - await audioPlayerUseCase.registerMEGADelegate() - } if shouldInitializePlayer() { invokeCommand?(.showLoading(true)) dispatchQueue.async(qos: .userInteractive) { @@ -460,9 +428,6 @@ final class AudioPlayerViewModel: NSObject, ViewModelType { if !configEntity.playerHandler.isPlayerDefined() { streamingInfoUseCase?.stopServer() } - Task { - await audioPlayerUseCase.unregisterMEGADelegate() - } } } } @@ -484,25 +449,17 @@ extension AudioPlayerViewModel: AudioPlayerObserversProtocol { } func audio(player: AVQueuePlayer, name: String, artist: String, thumbnail: UIImage?) { - invokeCommand?(.reloadNodeInfo(name: presentableName(name), artist: artist, thumbnail: thumbnail, size: nil)) + invokeCommand?(.reloadNodeInfo(name: name, artist: artist, thumbnail: thumbnail, size: nil)) } func audio(player: AVQueuePlayer, name: String, artist: String, thumbnail: UIImage?, url: String) { if configEntity.fileLink != nil, !configEntity.isFolderLink { - invokeCommand?(.reloadNodeInfo(name: presentableName(name), artist: artist, thumbnail: thumbnail, size: memoryStyleString(from: configEntity))) + invokeCommand?(.reloadNodeInfo(name: name, artist: artist, thumbnail: thumbnail, size: String.memoryStyleString(fromByteCount: configEntity.node?.size?.int64Value ?? Int64(0)))) } else { - self.invokeCommand?(.reloadNodeInfo(name: presentableName(name), artist: artist, thumbnail: thumbnail, size: String.memoryStyleString(fromByteCount: Int64(0)))) + self.invokeCommand?(.reloadNodeInfo(name: name, artist: artist, thumbnail: thumbnail, size: String.memoryStyleString(fromByteCount: Int64(0)))) } } - private func presentableName(_ originalTrackName: String) -> String { - let nameUpdateCheckerViewModel = AudioPlayerTrackNameUpdateCheckerViewModel( - configEntity: configEntity, - originalTrackName: originalTrackName - ) - return nameUpdateCheckerViewModel.presentableName() - } - func audioPlayerWillStartBlockingAction() { invokeCommand?(.enableUserInteraction(false)) } @@ -573,76 +530,3 @@ extension AudioPlayerViewModel: AudioPlayerObserversProtocol { } } } - -extension AudioPlayerViewModel { - - private func setupUpdateItemSubscription() { - audioPlayerUseCase.reloadItemPublisher() - .sink(receiveValue: { [weak self] nodes in - self?.onNodesUpdate(nodes) - }) - .store(in: &subscriptions) - } - - private func onNodesUpdate(_ nodeList: [NodeEntity]) { - guard - nodeList.count > 0, - let updatedNode = nodeList.first, - let allNodes = configEntity.allNodes - else { - return - } - - let shouldRefreshItem = allNodes.contains { $0.handle == updatedNode.handle } - guard shouldRefreshItem else { return } - - refreshItem(updatedNode) - } - - private func refreshItem(_ updatedNode: NodeEntity) { - guard let node = updatedNode.toMEGANode(in: sdk) else { return } - refreshItemDataSource(with: node) - refreshItemUI(with: node) - } - - private func refreshItemDataSource(with updatedNode: MEGANode) { - configEntity.node = updatedNode - - configEntity.playerHandler.playerCurrentItem()?.name = nodeName(from: updatedNode) - configEntity.playerHandler.playerCurrentItem()?.node = updatedNode - - refreshItemDataSourceTracks(with: updatedNode) - } - - private func refreshItemDataSourceTracks(with updatedNode: MEGANode) { - let tracks = configEntity.playerHandler.currentPlayer()?.tracks ?? [] - let updatedTracks = updateTracks(with: updatedNode, tracks: tracks) - configEntity.playerHandler.currentPlayer()?.tracks = updatedTracks - } - - private func updateTracks(with updatedNode: MEGANode, tracks: [AudioPlayerItem]) -> [AudioPlayerItem] { - var newTracks = tracks - - guard - let trackToUpdate = tracks.filter({ $0.node?.handle == updatedNode.handle }).first, - let trackToUpdateIndex = tracks.firstIndex(where: { $0.node?.handle == updatedNode.handle }) - else { - return tracks - } - - trackToUpdate.name = updatedNode.name ?? trackToUpdate.name - newTracks[trackToUpdateIndex] = trackToUpdate - - return newTracks - } - - private func refreshItemUI(with updatedNode: MEGANode) { - reloadNodeInfoWithCurrentItem(name: nodeName(from: updatedNode)) - } - - private func nodeName(from node: MEGANode) -> String { - let currentPlayingNode = configEntity.node - let newName = node.name ?? (currentPlayingNode?.name ?? "") - return newName - } -} diff --git a/iMEGA/AudioPlayer/Scenes/AudioPlayerScene/AudioPlayerViewRouter.swift b/iMEGA/AudioPlayer/Scenes/AudioPlayerScene/AudioPlayerViewRouter.swift index 18b7e6bdfd..9463d713d3 100644 --- a/iMEGA/AudioPlayer/Scenes/AudioPlayerScene/AudioPlayerViewRouter.swift +++ b/iMEGA/AudioPlayer/Scenes/AudioPlayerScene/AudioPlayerViewRouter.swift @@ -19,16 +19,12 @@ final class AudioPlayerViewRouter: NSObject, AudioPlayerViewRouting { let vc = UIStoryboard(name: "AudioPlayer", bundle: nil) .instantiateViewController(withIdentifier: "AudioPlayerViewControllerID") as! AudioPlayerViewController - let sdk = MEGASdk.shared - if configEntity.playerType == .offline { vc.viewModel = AudioPlayerViewModel( configEntity: configEntity, router: self, offlineInfoUseCase: OfflineFileInfoUseCase(offlineInfoRepository: OfflineInfoRepository()), - playbackContinuationUseCase: DIContainer.playbackContinuationUseCase, - audioPlayerUseCase: AudioPlayerUseCase(repository: AudioPlayerRepository(sdk: sdk)), - sdk: sdk + playbackContinuationUseCase: DIContainer.playbackContinuationUseCase ) } else { vc.viewModel = AudioPlayerViewModel( @@ -36,9 +32,7 @@ final class AudioPlayerViewRouter: NSObject, AudioPlayerViewRouting { router: self, nodeInfoUseCase: NodeInfoUseCase(nodeInfoRepository: NodeInfoRepository()), streamingInfoUseCase: StreamingInfoUseCase(streamingInfoRepository: StreamingInfoRepository()), - playbackContinuationUseCase: DIContainer.playbackContinuationUseCase, - audioPlayerUseCase: AudioPlayerUseCase(repository: AudioPlayerRepository(sdk: sdk)), - sdk: sdk + playbackContinuationUseCase: DIContainer.playbackContinuationUseCase ) } diff --git a/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewController.swift b/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewController.swift index 41f5e4ee33..05e89b42d2 100644 --- a/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewController.swift +++ b/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewController.swift @@ -158,7 +158,7 @@ final class MiniPlayerViewController: UIViewController { switch command { case .reloadPlayerStatus(let percentage, let isPlaying): updatePlayback(percentage, isPlaying) - case .reloadNodeInfo(let thumbnail, _): + case .reloadNodeInfo(let thumbnail): updateCurrent(thumbnail: thumbnail) case .reload(let currentItem): updateCurrent(item: currentItem) @@ -170,8 +170,6 @@ final class MiniPlayerViewController: UIViewController { refreshStateOfLoadingView(show) case .enableUserInteraction(let enabled): userInteraction(enabled: enabled) - case .reloadAt(let index): - collectionView.reloadItems(at: [IndexPath(item: index, section: 0)]) } } } diff --git a/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewModel.swift b/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewModel.swift index ae2481fd65..ad5a630bb7 100644 --- a/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewModel.swift +++ b/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewModel.swift @@ -1,4 +1,3 @@ -import Combine import Foundation import MEGADomain import MEGAFoundation @@ -19,31 +18,26 @@ protocol MiniPlayerViewRouting: Routing { func isAFolderLinkPresenter() -> Bool } -final class MiniPlayerViewModel: NSObject, ViewModelType { +final class MiniPlayerViewModel: ViewModelType { enum Command: CommandType, Equatable { - case reloadNodeInfo(thumbnail: UIImage?, name: String) + case reloadNodeInfo(thumbnail: UIImage?) case reloadPlayerStatus(percentage: Float, isPlaying: Bool) case initTracks(currentItem: AudioPlayerItem, queue: [AudioPlayerItem]?, loopMode: Bool) case change(currentItem: AudioPlayerItem, indexPath: IndexPath) case reload(currentItem: AudioPlayerItem) - case reloadAt(_ index: Int) case showLoading(_ show: Bool) case enableUserInteraction(_ enable: Bool) } // MARK: - Private properties - private(set) var configEntity: AudioPlayerConfigEntity + private var configEntity: AudioPlayerConfigEntity private var shouldInitializePlayer: Bool = false private let router: any MiniPlayerViewRouting private let nodeInfoUseCase: (any NodeInfoUseCaseProtocol)? private let streamingInfoUseCase: (any StreamingInfoUseCaseProtocol)? private let offlineInfoUseCase: (any OfflineFileInfoUseCaseProtocol)? private let playbackContinuationUseCase: any PlaybackContinuationUseCaseProtocol - private let audioPlayerUseCase: any AudioPlayerUseCaseProtocol private let dispatchQueue: any DispatchQueueProtocol - private let sdk: MEGASdk - - private var subscriptions = [AnyCancellable]() // MARK: - Internal properties var invokeCommand: ((Command) -> Void)? @@ -55,23 +49,15 @@ final class MiniPlayerViewModel: NSObject, ViewModelType { streamingInfoUseCase: (any StreamingInfoUseCaseProtocol)?, offlineInfoUseCase: (any OfflineFileInfoUseCaseProtocol)?, playbackContinuationUseCase: any PlaybackContinuationUseCaseProtocol, - audioPlayerUseCase: some AudioPlayerUseCaseProtocol, - sdk: MEGASdk = MEGASdk(), - dispatchQueue: some DispatchQueueProtocol = DispatchQueue.global() - ) { + dispatchQueue: some DispatchQueueProtocol = DispatchQueue.global()) { self.configEntity = configEntity self.router = router self.nodeInfoUseCase = nodeInfoUseCase self.streamingInfoUseCase = streamingInfoUseCase self.offlineInfoUseCase = offlineInfoUseCase self.playbackContinuationUseCase = playbackContinuationUseCase - self.audioPlayerUseCase = audioPlayerUseCase - self.sdk = sdk self.dispatchQueue = dispatchQueue self.shouldInitializePlayer = configEntity.shouldResetPlayer - super.init() - - self.setupUpdateItemSubscription() } // MARK: - Node Init @@ -188,25 +174,14 @@ final class MiniPlayerViewModel: NSObject, ViewModelType { } return } - - currentItem.name = presentableName(currentItem.name) - invokeCommand?(.initTracks(currentItem: currentItem, queue: configEntity.playerHandler.playerPlaylistItems(), loopMode: configEntity.playerHandler.currentRepeatMode() == .loop)) if let artworkImage = currentItem.artwork { - invokeCommand?(.reloadNodeInfo(thumbnail: artworkImage, name: presentableName(configEntity.node?.name ?? ""))) + invokeCommand?(.reloadNodeInfo(thumbnail: artworkImage)) } configEntity.playerHandler.refreshCurrentItemState() } - private func presentableName(_ originalTrackName: String) -> String { - let nameUpdateCheckerViewModel = AudioPlayerTrackNameUpdateCheckerViewModel( - configEntity: configEntity, - originalTrackName: originalTrackName - ) - return nameUpdateCheckerViewModel.presentableName() - } - private func loadNode(from handle: HandleEntity, url: String?, completion: ((MEGANode?) -> Void)? = nil) { if let fileLink = configEntity.fileLink { nodeInfoUseCase?.publicNode(fromFileLink: fileLink) { [weak self] node in @@ -258,19 +233,12 @@ final class MiniPlayerViewModel: NSObject, ViewModelType { if configEntity.isFolderLink, !router.isAFolderLinkPresenter() { nodeInfoUseCase?.folderLinkLogout() } - - Task { - await audioPlayerUseCase.unregisterMEGADelegate() - } } // MARK: - Dispatch action func dispatch(_ action: MiniPlayerAction) { switch action { case .onViewDidLoad: - Task { - await audioPlayerUseCase.registerMEGADelegate() - } invokeCommand?(.showLoading(shouldInitializePlayer)) if shouldInitializePlayer { dispatchQueue.async(qos: .userInteractive) { @@ -291,21 +259,8 @@ final class MiniPlayerViewModel: NSObject, ViewModelType { case .deinit: deInitActions() case .showPlayer(let node, let filePath): - let isFileRenamed = configEntity.node?.name != node?.name - showFullScreenPlayer(isFileRenamed ? configEntity.node : node, path: filePath) - } - } - - private func currentItem(from updatedNode: MEGANode) -> AudioPlayerItem? { - guard - let currentPlayingNode = configEntity.node, updatedNode.handle == currentPlayingNode.handle, - let newNodeName = updatedNode.name ?? currentPlayingNode.name, - let currentItem = configEntity.playerHandler.playerCurrentItem() - else { - return nil + showFullScreenPlayer(node, path: filePath) } - currentItem.name = newNodeName - return currentItem } } @@ -319,15 +274,15 @@ extension MiniPlayerViewModel: AudioPlayerObserversProtocol { } func audio(player: AVQueuePlayer, currentItem: AudioPlayerItem?, currentThumbnail: UIImage?) { - invokeCommand?(.reloadNodeInfo(thumbnail: currentThumbnail, name: presentableName(currentItem?.name ?? ""))) + invokeCommand?(.reloadNodeInfo(thumbnail: currentThumbnail)) } func audio(player: AVQueuePlayer, name: String, artist: String, thumbnail: UIImage?, url: String) { - invokeCommand?(.reloadNodeInfo(thumbnail: thumbnail, name: presentableName(name))) + invokeCommand?(.reloadNodeInfo(thumbnail: thumbnail)) } func audio(player: AVQueuePlayer, name: String, artist: String, thumbnail: UIImage?) { - invokeCommand?(.reloadNodeInfo(thumbnail: thumbnail, name: presentableName(name))) + invokeCommand?(.reloadNodeInfo(thumbnail: thumbnail)) } func audio(player: AVQueuePlayer, currentItem: AudioPlayerItem?, indexPath: IndexPath?) { @@ -363,52 +318,3 @@ extension MiniPlayerViewModel: AudioPlayerObserversProtocol { } } } - -extension MiniPlayerViewModel { - - private func setupUpdateItemSubscription() { - audioPlayerUseCase.reloadItemPublisher() - .sink(receiveValue: { [weak self] nodes in - self?.onNodesUpdate(nodes) - }) - .store(in: &subscriptions) - } - - private func onNodesUpdate(_ nodeList: [NodeEntity]) { - guard - nodeList.count > 0, - let updatedNode = nodeList.first, - let allNodes = configEntity.allNodes - else { - return - } - - let shouldRefreshItem = allNodes.contains { $0.handle == updatedNode.handle } - guard shouldRefreshItem else { return } - - refreshItem(updatedNode) - } - - private func refreshItem(_ updatedEntity: NodeEntity) { - guard let node = updatedEntity.toMEGANode(in: sdk) else { return } - configEntity.node = node - - refreshItemUI(with: node, updatedEntity: updatedEntity) - } - - private func refreshItemUI(with updatedNode: MEGANode, updatedEntity: NodeEntity) { - let isDisplayingCurrentItem = configEntity.playerHandler.currentPlayer()?.currentItem()?.node?.handle == updatedEntity.handle - if isDisplayingCurrentItem { - guard let currentItem = currentItem(from: updatedNode) else { return } - invokeCommand?(.reload(currentItem: currentItem)) - } else { - guard - let tracks = configEntity.playerHandler.currentPlayer()?.tracks, - let index = tracks.firstIndex(where: { $0.node?.handle == updatedEntity.handle }) - else { - return - } - invokeCommand?(.reloadAt(index)) - } - } -} diff --git a/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewRouter.swift b/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewRouter.swift index ce814c4de6..0274e29efc 100644 --- a/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewRouter.swift +++ b/iMEGA/AudioPlayer/Scenes/MiniPlayerScene/MiniPlayerViewRouter.swift @@ -17,7 +17,6 @@ final class MiniPlayerViewRouter: NSObject, MiniPlayerViewRouting { let vc = UIStoryboard(name: "AudioPlayer", bundle: nil).instantiateViewController(withIdentifier: "MiniPlayerViewControllerID") as! MiniPlayerViewController folderSDKLogoutRequired = configEntity.isFolderLink - let sdk = MEGASdk.shared vc.viewModel = MiniPlayerViewModel( configEntity: configEntity, @@ -25,9 +24,7 @@ final class MiniPlayerViewRouter: NSObject, MiniPlayerViewRouting { nodeInfoUseCase: NodeInfoUseCase(nodeInfoRepository: NodeInfoRepository()), streamingInfoUseCase: StreamingInfoUseCase(streamingInfoRepository: StreamingInfoRepository()), offlineInfoUseCase: configEntity.relatedFiles != nil ? OfflineFileInfoUseCase(offlineInfoRepository: OfflineInfoRepository()) : nil, - playbackContinuationUseCase: DIContainer.playbackContinuationUseCase, - audioPlayerUseCase: AudioPlayerUseCase(repository: AudioPlayerRepository(sdk: sdk)), - sdk: sdk + playbackContinuationUseCase: DIContainer.playbackContinuationUseCase ) baseViewController = vc diff --git a/iMEGA/AudioPlayer/Scenes/Shared/AudioPlayerTrackNameUpdateCheckerViewModel.swift b/iMEGA/AudioPlayer/Scenes/Shared/AudioPlayerTrackNameUpdateCheckerViewModel.swift deleted file mode 100644 index b0972a8498..0000000000 --- a/iMEGA/AudioPlayer/Scenes/Shared/AudioPlayerTrackNameUpdateCheckerViewModel.swift +++ /dev/null @@ -1,19 +0,0 @@ -struct AudioPlayerTrackNameUpdateCheckerViewModel { - let configEntity: AudioPlayerConfigEntity - let originalTrackName: String - - func presentableName() -> String { - guard let nodeName = configEntity.node?.name else { - return originalTrackName - } - - let isPlayingExactNode = configEntity.node?.handle == configEntity.playerHandler.playerCurrentItem()?.node?.handle - let isFileRenamed = nodeName != originalTrackName - - guard isPlayingExactNode && isFileRenamed else { - return originalTrackName - } - - return nodeName - } -} diff --git a/iMEGA/AudioPlayer/UseCases/AudioPlayerUseCase.swift b/iMEGA/AudioPlayer/UseCases/AudioPlayerUseCase.swift deleted file mode 100644 index 851dc2ccee..0000000000 --- a/iMEGA/AudioPlayer/UseCases/AudioPlayerUseCase.swift +++ /dev/null @@ -1,29 +0,0 @@ -import Combine -import MEGADomain -import MEGASdk - -protocol AudioPlayerUseCaseProtocol { - func registerMEGADelegate() async - func unregisterMEGADelegate() async - func reloadItemPublisher() -> AnyPublisher<[NodeEntity], Never> -} - -final class AudioPlayerUseCase: AudioPlayerUseCaseProtocol { - private let repository: any AudioPlayerRepositoryProtocol - - init(repository: some AudioPlayerRepositoryProtocol) { - self.repository = repository - } - - func registerMEGADelegate() async { - await repository.registerMEGADelegate() - } - - func unregisterMEGADelegate() async { - await repository.unregisterMEGADelegate() - } - - func reloadItemPublisher() -> AnyPublisher<[NodeEntity], Never> { - repository.reloadItemPublisher - } -}