mirror of
https://github.com/element-hq/element-x-ios.git
synced 2025-03-10 21:39:12 +00:00
Removing Dead Code part 1 (#2234)
This commit is contained in:
parent
09b276d94b
commit
d99d26fcdc
@ -12,7 +12,7 @@ targets:
|
|||||||
- UITests
|
- UITests
|
||||||
- UnitTests
|
- UnitTests
|
||||||
report_exclude:
|
report_exclude:
|
||||||
# includes subscript which is not detectable: https://github.com/apple/swift/issues/56541
|
- ElementX/Sources/Mocks/Generated/GeneratedMocks.swift
|
||||||
- ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenModels.swift
|
- ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift
|
||||||
verbose: true
|
verbose: true
|
||||||
retain_swift_ui_previews: true
|
retain_swift_ui_previews: true
|
||||||
|
@ -315,7 +315,6 @@
|
|||||||
50539366B408780B232C1910 /* EstimatedWaveformView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD0FF64B0E6470F66F42E182 /* EstimatedWaveformView.swift */; };
|
50539366B408780B232C1910 /* EstimatedWaveformView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD0FF64B0E6470F66F42E182 /* EstimatedWaveformView.swift */; };
|
||||||
50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.swift */; };
|
50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.swift */; };
|
||||||
5100F53E6884A15F9BA07CC3 /* AttributedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */; };
|
5100F53E6884A15F9BA07CC3 /* AttributedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */; };
|
||||||
516534FC5C893D57F169D5A8 /* MapTilerGeocoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33720F7AD25E85E4A84669E8 /* MapTilerGeocoding.swift */; };
|
|
||||||
518C93DC6516D3D018DE065F /* UNNotificationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */; };
|
518C93DC6516D3D018DE065F /* UNNotificationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */; };
|
||||||
51C240F4660F7269203A9B3A /* MigrationScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75910F5A36EA8FF9BAD08D18 /* MigrationScreenUITests.swift */; };
|
51C240F4660F7269203A9B3A /* MigrationScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75910F5A36EA8FF9BAD08D18 /* MigrationScreenUITests.swift */; };
|
||||||
520EEDAFBC778AB0B41F2F53 /* ClientMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE6170EFE6A161B0A68AB61 /* ClientMock.swift */; };
|
520EEDAFBC778AB0B41F2F53 /* ClientMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE6170EFE6A161B0A68AB61 /* ClientMock.swift */; };
|
||||||
@ -852,7 +851,6 @@
|
|||||||
D8385A51A3D0FA9283556281 /* RoundedLabelItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 745323FCF9AF21A117252C53 /* RoundedLabelItem.swift */; };
|
D8385A51A3D0FA9283556281 /* RoundedLabelItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 745323FCF9AF21A117252C53 /* RoundedLabelItem.swift */; };
|
||||||
D871C8CF46950F959C9A62C3 /* WelcomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C54464351F170D570110AFCA /* WelcomeScreen.swift */; };
|
D871C8CF46950F959C9A62C3 /* WelcomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C54464351F170D570110AFCA /* WelcomeScreen.swift */; };
|
||||||
D876EC0FED3B6D46C806912A /* AvatarSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E24B88AD3D1599E8CB1376E0 /* AvatarSize.swift */; };
|
D876EC0FED3B6D46C806912A /* AvatarSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E24B88AD3D1599E8CB1376E0 /* AvatarSize.swift */; };
|
||||||
D8CFF02C2730EE5BC4F17ABF /* ElementToggleStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0960A7F5C1B0B6679BDF26F9 /* ElementToggleStyle.swift */; };
|
|
||||||
D9473FC9B077A6EDB7A12001 /* LocationRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 772334731A8BF8E6D90B194D /* LocationRoomTimelineView.swift */; };
|
D9473FC9B077A6EDB7A12001 /* LocationRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 772334731A8BF8E6D90B194D /* LocationRoomTimelineView.swift */; };
|
||||||
D98B5EE8C4F5A2CE84687AE8 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; };
|
D98B5EE8C4F5A2CE84687AE8 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; };
|
||||||
D9F80CE61BF8FF627FDB0543 /* LoadableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352359663A0E52BA20761EE /* LoadableImage.swift */; };
|
D9F80CE61BF8FF627FDB0543 /* LoadableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352359663A0E52BA20761EE /* LoadableImage.swift */; };
|
||||||
@ -1088,7 +1086,6 @@
|
|||||||
086B997409328F091EBA43CE /* RoomScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenUITests.swift; sourceTree = "<group>"; };
|
086B997409328F091EBA43CE /* RoomScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenUITests.swift; sourceTree = "<group>"; };
|
||||||
086C19086DD16E9B38E25954 /* ReportContentViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentViewModelTests.swift; sourceTree = "<group>"; };
|
086C19086DD16E9B38E25954 /* ReportContentViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderProtocol.swift; sourceTree = "<group>"; };
|
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderProtocol.swift; sourceTree = "<group>"; };
|
||||||
0960A7F5C1B0B6679BDF26F9 /* ElementToggleStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementToggleStyle.swift; sourceTree = "<group>"; };
|
|
||||||
099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderTests.swift; sourceTree = "<group>"; };
|
099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderTests.swift; sourceTree = "<group>"; };
|
||||||
09CE2B7AD979BDEE09FEDB08 /* WaitlistScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenModels.swift; sourceTree = "<group>"; };
|
09CE2B7AD979BDEE09FEDB08 /* WaitlistScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenModels.swift; sourceTree = "<group>"; };
|
||||||
0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenCoordinator.swift; sourceTree = "<group>"; };
|
0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
@ -1243,7 +1240,6 @@
|
|||||||
32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutViewModelTests.swift; sourceTree = "<group>"; };
|
32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
33649299575BADC34924ABC6 /* InvitesScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenCoordinator.swift; sourceTree = "<group>"; };
|
33649299575BADC34924ABC6 /* InvitesScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
3368395F06AA180138E185B6 /* PollFormScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenUITests.swift; sourceTree = "<group>"; };
|
3368395F06AA180138E185B6 /* PollFormScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenUITests.swift; sourceTree = "<group>"; };
|
||||||
33720F7AD25E85E4A84669E8 /* MapTilerGeocoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerGeocoding.swift; sourceTree = "<group>"; };
|
|
||||||
33E49C5C6F802B4D94CA78D1 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = "<group>"; };
|
33E49C5C6F802B4D94CA78D1 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
340179A0FC1AD4AEDA7FC134 /* CreateRoomViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomViewModelProtocol.swift; sourceTree = "<group>"; };
|
340179A0FC1AD4AEDA7FC134 /* CreateRoomViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
342BEBC3C5FC3F9943C41C4C /* TemplateScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
342BEBC3C5FC3F9943C41C4C /* TemplateScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
@ -2511,7 +2507,6 @@
|
|||||||
CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */,
|
CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */,
|
||||||
C1FA515B3B0D61EF1E907D2D /* BadgeView.swift */,
|
C1FA515B3B0D61EF1E907D2D /* BadgeView.swift */,
|
||||||
8CC23C63849452BC86EA2852 /* ButtonStyle.swift */,
|
8CC23C63849452BC86EA2852 /* ButtonStyle.swift */,
|
||||||
0960A7F5C1B0B6679BDF26F9 /* ElementToggleStyle.swift */,
|
|
||||||
7EC2F1622C5BBABED6012E12 /* HeroImage.swift */,
|
7EC2F1622C5BBABED6012E12 /* HeroImage.swift */,
|
||||||
B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */,
|
B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */,
|
||||||
C352359663A0E52BA20761EE /* LoadableImage.swift */,
|
C352359663A0E52BA20761EE /* LoadableImage.swift */,
|
||||||
@ -4267,7 +4262,6 @@
|
|||||||
B81B6170DB690013CEB646F4 /* MapLibreModels.swift */,
|
B81B6170DB690013CEB646F4 /* MapLibreModels.swift */,
|
||||||
592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */,
|
592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */,
|
||||||
E062C1750EFC8627DE4CAB8E /* MapTilerAuthorization.swift */,
|
E062C1750EFC8627DE4CAB8E /* MapTilerAuthorization.swift */,
|
||||||
33720F7AD25E85E4A84669E8 /* MapTilerGeocoding.swift */,
|
|
||||||
C23B3FAD8B23C421BC0D1B1E /* MapTilerGeoCodingServiceProtocol.swift */,
|
C23B3FAD8B23C421BC0D1B1E /* MapTilerGeoCodingServiceProtocol.swift */,
|
||||||
1A4D29F2683F5772AC72406F /* MapTilerStaticMap.swift */,
|
1A4D29F2683F5772AC72406F /* MapTilerStaticMap.swift */,
|
||||||
20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */,
|
20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */,
|
||||||
@ -5490,7 +5484,6 @@
|
|||||||
FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */,
|
FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */,
|
||||||
07CC13C5729C24255348CBBD /* ElementCallWidgetDriver.swift in Sources */,
|
07CC13C5729C24255348CBBD /* ElementCallWidgetDriver.swift in Sources */,
|
||||||
370AF5BFCD4384DD455479B6 /* ElementCallWidgetDriverProtocol.swift in Sources */,
|
370AF5BFCD4384DD455479B6 /* ElementCallWidgetDriverProtocol.swift in Sources */,
|
||||||
D8CFF02C2730EE5BC4F17ABF /* ElementToggleStyle.swift in Sources */,
|
|
||||||
7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */,
|
7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */,
|
||||||
7361B011A79BF723D8C9782B /* EmojiCategory.swift in Sources */,
|
7361B011A79BF723D8C9782B /* EmojiCategory.swift in Sources */,
|
||||||
E45C9FA22BC13B477FD3B4AC /* EmojiDetection.swift in Sources */,
|
E45C9FA22BC13B477FD3B4AC /* EmojiDetection.swift in Sources */,
|
||||||
@ -5598,7 +5591,6 @@
|
|||||||
D181AC8FF236B7F91C0A8C28 /* MapTiler.swift in Sources */,
|
D181AC8FF236B7F91C0A8C28 /* MapTiler.swift in Sources */,
|
||||||
FCDA202B246F75BA28E10C5F /* MapTilerAuthorization.swift in Sources */,
|
FCDA202B246F75BA28E10C5F /* MapTilerAuthorization.swift in Sources */,
|
||||||
7ABAB3A1D52B86FACF2F74CF /* MapTilerGeoCodingServiceProtocol.swift in Sources */,
|
7ABAB3A1D52B86FACF2F74CF /* MapTilerGeoCodingServiceProtocol.swift in Sources */,
|
||||||
516534FC5C893D57F169D5A8 /* MapTilerGeocoding.swift in Sources */,
|
|
||||||
D6661A94DBD97658B2ADBD6A /* MapTilerStaticMap.swift in Sources */,
|
D6661A94DBD97658B2ADBD6A /* MapTilerStaticMap.swift in Sources */,
|
||||||
7B5DAB915357BE596529BF25 /* MapTilerStaticMapProtocol.swift in Sources */,
|
7B5DAB915357BE596529BF25 /* MapTilerStaticMapProtocol.swift in Sources */,
|
||||||
83A4DAB181C56987C3E804FF /* MapTilerStyle.swift in Sources */,
|
83A4DAB181C56987C3E804FF /* MapTilerStyle.swift in Sources */,
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"filename" : "text-formatting.svg",
|
|
||||||
"idiom" : "universal"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"author" : "xcode",
|
|
||||||
"version" : 1
|
|
||||||
},
|
|
||||||
"properties" : {
|
|
||||||
"preserves-vector-representation" : true,
|
|
||||||
"template-rendering-intent" : "template"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M6 19C5.71667 19 5.47917 18.9042 5.2875 18.7125C5.09583 18.5208 5 18.2833 5 18C5 17.7167 5.09583 17.4792 5.2875 17.2875C5.47917 17.0958 5.71667 17 6 17H18C18.2833 17 18.5208 17.0958 18.7125 17.2875C18.9042 17.4792 19 17.7167 19 18C19 18.2833 18.9042 18.5208 18.7125 18.7125C18.5208 18.9042 18.2833 19 18 19H6ZM7.35 13.8L10.775 4.6C10.8417 4.41667 10.9542 4.27083 11.1125 4.1625C11.2708 4.05417 11.45 4 11.65 4H12.35C12.55 4 12.7292 4.05417 12.8875 4.1625C13.0458 4.27083 13.1583 4.41667 13.225 4.6L16.65 13.825C16.75 14.1083 16.7167 14.375 16.55 14.625C16.3833 14.875 16.15 15 15.85 15C15.6667 15 15.4958 14.9458 15.3375 14.8375C15.1792 14.7292 15.0667 14.5833 15 14.4L14.25 12.2H9.8L9 14.425C8.93333 14.6083 8.825 14.75 8.675 14.85C8.525 14.95 8.35833 15 8.175 15C7.85833 15 7.6125 14.8708 7.4375 14.6125C7.2625 14.3542 7.23333 14.0833 7.35 13.8ZM10.35 10.6H13.65L12.05 6.05H11.95L10.35 10.6Z" fill="black"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1022 B |
@ -45,6 +45,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
|||||||
|
|
||||||
private var authenticationCoordinator: AuthenticationCoordinator?
|
private var authenticationCoordinator: AuthenticationCoordinator?
|
||||||
private let appLockFlowCoordinator: AppLockFlowCoordinator
|
private let appLockFlowCoordinator: AppLockFlowCoordinator
|
||||||
|
// periphery:ignore - used to avoid deallocation
|
||||||
private var appLockSetupFlowCoordinator: AppLockSetupFlowCoordinator?
|
private var appLockSetupFlowCoordinator: AppLockSetupFlowCoordinator?
|
||||||
private var userSessionFlowCoordinator: UserSessionFlowCoordinator?
|
private var userSessionFlowCoordinator: UserSessionFlowCoordinator?
|
||||||
private var softLogoutCoordinator: SoftLogoutScreenCoordinator?
|
private var softLogoutCoordinator: SoftLogoutScreenCoordinator?
|
||||||
@ -90,7 +91,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
|||||||
|
|
||||||
navigationRootCoordinator = NavigationRootCoordinator()
|
navigationRootCoordinator = NavigationRootCoordinator()
|
||||||
|
|
||||||
Self.setupServiceLocator(navigationRootCoordinator: navigationRootCoordinator, appSettings: appSettings)
|
Self.setupServiceLocator(appSettings: appSettings)
|
||||||
|
|
||||||
ServiceLocator.shared.analytics.startIfEnabled()
|
ServiceLocator.shared.analytics.startIfEnabled()
|
||||||
|
|
||||||
@ -209,9 +210,9 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
|||||||
|
|
||||||
// MARK: - AuthenticationCoordinatorDelegate
|
// MARK: - AuthenticationCoordinatorDelegate
|
||||||
|
|
||||||
func authenticationCoordinator(_ authenticationCoordinator: AuthenticationCoordinator, didLoginWithSession userSession: UserSessionProtocol) {
|
func authenticationCoordinator(didLoginWithSession userSession: UserSessionProtocol) {
|
||||||
self.userSession = userSession
|
self.userSession = userSession
|
||||||
self.authenticationCoordinator = nil
|
authenticationCoordinator = nil
|
||||||
stateMachine.processEvent(.createdUserSession)
|
stateMachine.processEvent(.createdUserSession)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +233,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
|||||||
UIApplication.shared.unregisterForRemoteNotifications()
|
UIApplication.shared.unregisterForRemoteNotifications()
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldDisplayInAppNotification(_ service: NotificationManagerProtocol, content: UNNotificationContent) -> Bool {
|
func shouldDisplayInAppNotification(content: UNNotificationContent) -> Bool {
|
||||||
guard let roomID = content.roomID else {
|
guard let roomID = content.roomID else {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -243,7 +244,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
|||||||
return !userSessionFlowCoordinator.isDisplayingRoomScreen(withRoomID: roomID)
|
return !userSessionFlowCoordinator.isDisplayingRoomScreen(withRoomID: roomID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func notificationTapped(_ service: NotificationManagerProtocol, content: UNNotificationContent) async {
|
func notificationTapped(content: UNNotificationContent) async {
|
||||||
MXLog.info("[AppCoordinator] tappedNotification")
|
MXLog.info("[AppCoordinator] tappedNotification")
|
||||||
|
|
||||||
guard let roomID = content.roomID,
|
guard let roomID = content.roomID,
|
||||||
@ -284,7 +285,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
|||||||
setenv("RUST_BACKTRACE", "1", 1)
|
setenv("RUST_BACKTRACE", "1", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func setupServiceLocator(navigationRootCoordinator: NavigationRootCoordinator, appSettings: AppSettings) {
|
private static func setupServiceLocator(appSettings: AppSettings) {
|
||||||
ServiceLocator.shared.register(userIndicatorController: UserIndicatorController())
|
ServiceLocator.shared.register(userIndicatorController: UserIndicatorController())
|
||||||
ServiceLocator.shared.register(appSettings: appSettings)
|
ServiceLocator.shared.register(appSettings: appSettings)
|
||||||
ServiceLocator.shared.register(networkMonitor: NetworkMonitor())
|
ServiceLocator.shared.register(networkMonitor: NetworkMonitor())
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
protocol AppCoordinatorProtocol: CoordinatorProtocol {
|
protocol AppCoordinatorProtocol: CoordinatorProtocol {
|
||||||
var notificationManager: NotificationManagerProtocol { get }
|
|
||||||
var windowManager: WindowManager { get }
|
var windowManager: WindowManager { get }
|
||||||
@discardableResult func handleDeepLink(_ url: URL) -> Bool
|
@discardableResult func handleDeepLink(_ url: URL) -> Bool
|
||||||
}
|
}
|
||||||
|
@ -87,8 +87,6 @@ final class AppSettings {
|
|||||||
@UserPreference(key: UserDefaultsKeys.lastVersionLaunched, storageType: .userDefaults(store))
|
@UserPreference(key: UserDefaultsKeys.lastVersionLaunched, storageType: .userDefaults(store))
|
||||||
var lastVersionLaunched: String?
|
var lastVersionLaunched: String?
|
||||||
|
|
||||||
let lastLaunchDate = Date()
|
|
||||||
|
|
||||||
/// The Set of room identifiers of invites that the user already saw in the invites list.
|
/// The Set of room identifiers of invites that the user already saw in the invites list.
|
||||||
/// This Set is being used to implement badges for unread invites.
|
/// This Set is being used to implement badges for unread invites.
|
||||||
@UserPreference(key: UserDefaultsKeys.seenInvites, defaultValue: [], storageType: .userDefaults(store))
|
@UserPreference(key: UserDefaultsKeys.seenInvites, defaultValue: [], storageType: .userDefaults(store))
|
||||||
@ -180,7 +178,6 @@ final class AppSettings {
|
|||||||
let bugReportSentryURL: URL = "https://f39ac49e97714316965b777d9f3d6cd8@sentry.tools.element.io/44"
|
let bugReportSentryURL: URL = "https://f39ac49e97714316965b777d9f3d6cd8@sentry.tools.element.io/44"
|
||||||
// Use the name allocated by the bug report server
|
// Use the name allocated by the bug report server
|
||||||
let bugReportApplicationId = "element-x-ios"
|
let bugReportApplicationId = "element-x-ios"
|
||||||
let bugReportUISIId = "element-auto-uisi"
|
|
||||||
/// The maximum size of the upload request. Default value is just below CloudFlare's max request size.
|
/// The maximum size of the upload request. Default value is just below CloudFlare's max request size.
|
||||||
let bugReportMaxUploadSize = 50 * 1024 * 1024
|
let bugReportMaxUploadSize = 50 * 1024 * 1024
|
||||||
|
|
||||||
@ -257,9 +254,6 @@ final class AppSettings {
|
|||||||
// maptiler api key
|
// maptiler api key
|
||||||
let mapTilerApiKey = InfoPlistReader.main.mapLibreAPIKey
|
let mapTilerApiKey = InfoPlistReader.main.mapLibreAPIKey
|
||||||
|
|
||||||
// maptiler geocoding url
|
|
||||||
let geocodingURLFormatString = "https://api.maptiler.com/geocoding/%f,%f.json"
|
|
||||||
|
|
||||||
// MARK: - Feature Flags
|
// MARK: - Feature Flags
|
||||||
|
|
||||||
@UserPreference(key: UserDefaultsKeys.userSuggestionsEnabled, defaultValue: false, storageType: .volatile)
|
@UserPreference(key: UserDefaultsKeys.userSuggestionsEnabled, defaultValue: false, storageType: .volatile)
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
// periphery:ignore - markdown protocol
|
||||||
@MainActor
|
@MainActor
|
||||||
protocol FlowCoordinatorProtocol {
|
protocol FlowCoordinatorProtocol {
|
||||||
func handleAppRoute(_ appRoute: AppRoute, animated: Bool)
|
func handleAppRoute(_ appRoute: AppRoute, animated: Bool)
|
||||||
|
@ -83,8 +83,6 @@ class AppLockFlowCoordinator: CoordinatorProtocol {
|
|||||||
|
|
||||||
private let stateMachine: StateMachine<State, Event>
|
private let stateMachine: StateMachine<State, Event>
|
||||||
|
|
||||||
/// A task used to await biometric unlock before showing the PIN screen.
|
|
||||||
@CancellableTask private var unlockTask: Task<Void, Never>?
|
|
||||||
private var cancellables: Set<AnyCancellable> = []
|
private var cancellables: Set<AnyCancellable> = []
|
||||||
|
|
||||||
/// Whether or not biometric unlock should be attempted instead of asking for a PIN.
|
/// Whether or not biometric unlock should be attempted instead of asking for a PIN.
|
||||||
|
@ -39,7 +39,6 @@ internal enum Asset {
|
|||||||
internal static let addLocation = ImageAsset(name: "images/add-location")
|
internal static let addLocation = ImageAsset(name: "images/add-location")
|
||||||
internal static let attachment = ImageAsset(name: "images/attachment")
|
internal static let attachment = ImageAsset(name: "images/attachment")
|
||||||
internal static let takePhoto = ImageAsset(name: "images/take-photo")
|
internal static let takePhoto = ImageAsset(name: "images/take-photo")
|
||||||
internal static let textFormatting = ImageAsset(name: "images/text-formatting")
|
|
||||||
internal static let bold = ImageAsset(name: "images/bold")
|
internal static let bold = ImageAsset(name: "images/bold")
|
||||||
internal static let bulletList = ImageAsset(name: "images/bullet-list")
|
internal static let bulletList = ImageAsset(name: "images/bullet-list")
|
||||||
internal static let closeRte = ImageAsset(name: "images/close-rte")
|
internal static let closeRte = ImageAsset(name: "images/close-rte")
|
||||||
|
@ -45,18 +45,6 @@ extension ApplicationMock {
|
|||||||
underlyingApplicationState = applicationState
|
underlyingApplicationState = applicationState
|
||||||
underlyingBackgroundTimeRemaining = backgroundTimeRemaining
|
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
|
beginBackgroundTaskWithNameExpirationHandlerClosure = { _, handler in
|
||||||
guard allowTasks else {
|
guard allowTasks else {
|
||||||
return .invalid
|
return .invalid
|
||||||
|
@ -56,18 +56,6 @@ class AnalyticsClientMock: AnalyticsClientProtocol {
|
|||||||
stopCallsCount += 1
|
stopCallsCount += 1
|
||||||
stopClosure?()
|
stopClosure?()
|
||||||
}
|
}
|
||||||
//MARK: - flush
|
|
||||||
|
|
||||||
var flushCallsCount = 0
|
|
||||||
var flushCalled: Bool {
|
|
||||||
return flushCallsCount > 0
|
|
||||||
}
|
|
||||||
var flushClosure: (() -> Void)?
|
|
||||||
|
|
||||||
func flush() {
|
|
||||||
flushCallsCount += 1
|
|
||||||
flushClosure?()
|
|
||||||
}
|
|
||||||
//MARK: - capture
|
//MARK: - capture
|
||||||
|
|
||||||
var captureCallsCount = 0
|
var captureCallsCount = 0
|
||||||
@ -100,22 +88,6 @@ class AnalyticsClientMock: AnalyticsClientProtocol {
|
|||||||
screenReceivedInvocations.append(event)
|
screenReceivedInvocations.append(event)
|
||||||
screenClosure?(event)
|
screenClosure?(event)
|
||||||
}
|
}
|
||||||
//MARK: - updateUserProperties
|
|
||||||
|
|
||||||
var updateUserPropertiesCallsCount = 0
|
|
||||||
var updateUserPropertiesCalled: Bool {
|
|
||||||
return updateUserPropertiesCallsCount > 0
|
|
||||||
}
|
|
||||||
var updateUserPropertiesReceivedUserProperties: AnalyticsEvent.UserProperties?
|
|
||||||
var updateUserPropertiesReceivedInvocations: [AnalyticsEvent.UserProperties] = []
|
|
||||||
var updateUserPropertiesClosure: ((AnalyticsEvent.UserProperties) -> Void)?
|
|
||||||
|
|
||||||
func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties) {
|
|
||||||
updateUserPropertiesCallsCount += 1
|
|
||||||
updateUserPropertiesReceivedUserProperties = userProperties
|
|
||||||
updateUserPropertiesReceivedInvocations.append(userProperties)
|
|
||||||
updateUserPropertiesClosure?(userProperties)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
class AppLockServiceMock: AppLockServiceProtocol {
|
class AppLockServiceMock: AppLockServiceProtocol {
|
||||||
var isMandatory: Bool {
|
var isMandatory: Bool {
|
||||||
@ -323,23 +295,6 @@ class ApplicationMock: ApplicationProtocol {
|
|||||||
|
|
||||||
//MARK: - beginBackgroundTask
|
//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 beginBackgroundTaskWithNameExpirationHandlerCallsCount = 0
|
||||||
var beginBackgroundTaskWithNameExpirationHandlerCalled: Bool {
|
var beginBackgroundTaskWithNameExpirationHandlerCalled: Bool {
|
||||||
return beginBackgroundTaskWithNameExpirationHandlerCallsCount > 0
|
return beginBackgroundTaskWithNameExpirationHandlerCallsCount > 0
|
||||||
@ -739,18 +694,6 @@ class BugReportServiceMock: BugReportServiceProtocol {
|
|||||||
resetCallsCount += 1
|
resetCallsCount += 1
|
||||||
resetClosure?()
|
resetClosure?()
|
||||||
}
|
}
|
||||||
//MARK: - crash
|
|
||||||
|
|
||||||
var crashCallsCount = 0
|
|
||||||
var crashCalled: Bool {
|
|
||||||
return crashCallsCount > 0
|
|
||||||
}
|
|
||||||
var crashClosure: (() -> Void)?
|
|
||||||
|
|
||||||
func crash() {
|
|
||||||
crashCallsCount += 1
|
|
||||||
crashClosure?()
|
|
||||||
}
|
|
||||||
//MARK: - submitBugReport
|
//MARK: - submitBugReport
|
||||||
|
|
||||||
var submitBugReportProgressListenerCallsCount = 0
|
var submitBugReportProgressListenerCallsCount = 0
|
||||||
|
@ -106,10 +106,6 @@ enum RoomAvatarSizeOnScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension AvatarSize {
|
extension AvatarSize {
|
||||||
var size: CGSize {
|
|
||||||
CGSize(width: value, height: value)
|
|
||||||
}
|
|
||||||
|
|
||||||
var scaledSize: CGSize {
|
var scaledSize: CGSize {
|
||||||
CGSize(width: scaledValue, height: scaledValue)
|
CGSize(width: scaledValue, height: scaledValue)
|
||||||
}
|
}
|
||||||
|
@ -130,12 +130,6 @@ private extension String {
|
|||||||
self[index(startIndex, offsetBy: offset)]
|
self[index(startIndex, offsetBy: offset)]
|
||||||
}
|
}
|
||||||
|
|
||||||
subscript(bounds: CountableClosedRange<Int>) -> Substring {
|
|
||||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
|
||||||
let end = index(startIndex, offsetBy: bounds.upperBound)
|
|
||||||
return self[start...end]
|
|
||||||
}
|
|
||||||
|
|
||||||
subscript(bounds: CountableRange<Int>) -> Substring {
|
subscript(bounds: CountableRange<Int>) -> Substring {
|
||||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
||||||
let end = index(startIndex, offsetBy: bounds.upperBound)
|
let end = index(startIndex, offsetBy: bounds.upperBound)
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
// periphery:ignore - property wrappers generate false positives
|
||||||
@propertyWrapper
|
@propertyWrapper
|
||||||
struct CancellableTask<S: Sendable, F: Error> {
|
struct CancellableTask<S: Sendable, F: Error> {
|
||||||
private var storedValue: Task<S, F>?
|
private var storedValue: Task<S, F>?
|
||||||
|
@ -47,18 +47,18 @@ struct CollapsibleReactionLayout: Layout {
|
|||||||
rows: collapsedRows,
|
rows: collapsedRows,
|
||||||
collapseButton: subviewsByType.collapseButton,
|
collapseButton: subviewsByType.collapseButton,
|
||||||
addMoreButton: subviewsByType.addMoreButton)
|
addMoreButton: subviewsByType.addMoreButton)
|
||||||
let size = sizeThatFits(proposal: proposal, rows: collapsedRowsWithButtons)
|
let size = sizeThatFits(rows: collapsedRowsWithButtons)
|
||||||
return size
|
return size
|
||||||
} else {
|
} else {
|
||||||
// Show all subviews with the button at the end
|
// Show all subviews with the button at the end
|
||||||
var rowsWithButtons = calculateRows(proposal: proposal, subviews: Array(subviews))
|
var rowsWithButtons = calculateRows(proposal: proposal, subviews: Array(subviews))
|
||||||
ensureCollapseAndAddMoreButtonsAreOnTheSameRow(&rowsWithButtons)
|
ensureCollapseAndAddMoreButtonsAreOnTheSameRow(&rowsWithButtons)
|
||||||
let size = sizeThatFits(proposal: proposal, rows: rowsWithButtons)
|
let size = sizeThatFits(rows: rowsWithButtons)
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Otherwise we are just calculating the size of all items without the button
|
// Otherwise we are just calculating the size of all items without the button
|
||||||
return sizeThatFits(proposal: proposal, rows: reactionsAndAddMore)
|
return sizeThatFits(rows: reactionsAndAddMore)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ struct CollapsibleReactionLayout: Layout {
|
|||||||
/// - proposal: The proposed size
|
/// - proposal: The proposed size
|
||||||
/// - rows: The list of rows
|
/// - rows: The list of rows
|
||||||
/// - Returns: The size render the rows
|
/// - Returns: The size render the rows
|
||||||
private func sizeThatFits(proposal: ProposedViewSize, rows: [[FlowLayoutSubview]]) -> CGSize {
|
private func sizeThatFits(rows: [[FlowLayoutSubview]]) -> CGSize {
|
||||||
let sizes = rows.map { row in
|
let sizes = rows.map { row in
|
||||||
row.map { subview in
|
row.map { subview in
|
||||||
subview.sizeThatFits(.unspecified)
|
subview.sizeThatFits(.unspecified)
|
||||||
|
@ -31,6 +31,18 @@ extension View {
|
|||||||
})
|
})
|
||||||
return alert(item.wrappedValue?.title ?? "", isPresented: binding, presenting: item.wrappedValue, actions: actions, message: message)
|
return alert(item.wrappedValue?.title ?? "", isPresented: binding, presenting: item.wrappedValue, actions: actions, message: message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// periphery: ignore - not used yet but might be useful
|
||||||
|
func alert<Item, Actions>(item: Binding<Item?>, @ViewBuilder actions: (Item) -> Actions) -> some View where Item: AlertProtocol, Actions: View {
|
||||||
|
let binding = Binding<Bool>(get: {
|
||||||
|
item.wrappedValue != nil
|
||||||
|
}, set: { newValue in
|
||||||
|
if !newValue {
|
||||||
|
item.wrappedValue = nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return alert(item.wrappedValue?.title ?? "", isPresented: binding, presenting: item.wrappedValue, actions: actions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type that describes an alert to be shown to the user.
|
/// A type that describes an alert to be shown to the user.
|
||||||
|
@ -73,13 +73,3 @@ extension Array where Element == RoomTimelineItemProtocol {
|
|||||||
first { $0.id.timelineID == id.timelineID }
|
first { $0.id.timelineID == id.timelineID }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Array {
|
|
||||||
func appending(_ element: Element) -> [Element] {
|
|
||||||
self + [element]
|
|
||||||
}
|
|
||||||
|
|
||||||
func appending(_ elements: [Element]) -> [Element] {
|
|
||||||
self + elements
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -34,6 +34,7 @@ extension View {
|
|||||||
return confirmationDialog(item.wrappedValue?.title ?? "", isPresented: binding, titleVisibility: titleVisibility, presenting: item.wrappedValue, actions: actions)
|
return confirmationDialog(item.wrappedValue?.title ?? "", isPresented: binding, titleVisibility: titleVisibility, presenting: item.wrappedValue, actions: actions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// periphery: ignore - not used yet but might be useful
|
||||||
func confirmationDialog<Item, Actions, Message>(item: Binding<Item?>,
|
func confirmationDialog<Item, Actions, Message>(item: Binding<Item?>,
|
||||||
titleVisibility: Visibility = .automatic,
|
titleVisibility: Visibility = .automatic,
|
||||||
@ViewBuilder actions: (Item) -> Actions,
|
@ViewBuilder actions: (Item) -> Actions,
|
||||||
|
@ -21,9 +21,3 @@ extension MapTilerStyleBuilder {
|
|||||||
self.init(baseURL: appSettings.mapTilerBaseURL, key: appSettings.mapTilerApiKey)
|
self.init(baseURL: appSettings.mapTilerBaseURL, key: appSettings.mapTilerApiKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MapTilerGeoCodingService {
|
|
||||||
init(session: URLSession = .shared, appSettings: AppSettings) {
|
|
||||||
self.init(session: session, key: appSettings.mapTilerApiKey, geocodingURL: appSettings.geocodingURLFormatString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -22,7 +22,6 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
|||||||
private let cacheKey: String
|
private let cacheKey: String
|
||||||
private let temporaryBlockquoteMarkingColor = UIColor.magenta
|
private let temporaryBlockquoteMarkingColor = UIColor.magenta
|
||||||
private let temporaryCodeBlockMarkingColor = UIColor.cyan
|
private let temporaryCodeBlockMarkingColor = UIColor.cyan
|
||||||
private let linkColor = UIColor.blue
|
|
||||||
private let permalinkBaseURL: URL
|
private let permalinkBaseURL: URL
|
||||||
private let mentionBuilder: MentionBuilderProtocol
|
private let mentionBuilder: MentionBuilderProtocol
|
||||||
|
|
||||||
@ -33,10 +32,6 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
|||||||
caches.removeAll()
|
caches.removeAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
static func invalidateCache(for key: String = defaultKey) {
|
|
||||||
caches[key]?.removeAllValues()
|
|
||||||
}
|
|
||||||
|
|
||||||
init(cacheKey: String = defaultKey, permalinkBaseURL: URL, mentionBuilder: MentionBuilderProtocol) {
|
init(cacheKey: String = defaultKey, permalinkBaseURL: URL, mentionBuilder: MentionBuilderProtocol) {
|
||||||
self.cacheKey = cacheKey
|
self.cacheKey = cacheKey
|
||||||
if Self.caches[cacheKey] == nil {
|
if Self.caches[cacheKey] == nil {
|
||||||
@ -73,7 +68,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
|||||||
// that could happen with the default HTML renderer of NSAttributedString which is a
|
// that could happen with the default HTML renderer of NSAttributedString which is a
|
||||||
// webview.
|
// webview.
|
||||||
func fromHTML(_ htmlString: String?) -> AttributedString? {
|
func fromHTML(_ htmlString: String?) -> AttributedString? {
|
||||||
guard var originalHTMLString = htmlString else {
|
guard let originalHTMLString = htmlString else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,27 +18,27 @@ import Foundation
|
|||||||
|
|
||||||
enum BlockquoteAttribute: AttributedStringKey {
|
enum BlockquoteAttribute: AttributedStringKey {
|
||||||
typealias Value = Bool
|
typealias Value = Bool
|
||||||
public static var name = "MXBlockquoteAttribute"
|
static var name = "MXBlockquoteAttribute"
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UserIDAttribute: AttributedStringKey {
|
enum UserIDAttribute: AttributedStringKey {
|
||||||
typealias Value = String
|
typealias Value = String
|
||||||
public static var name = "MXUserIDAttribute"
|
static var name = "MXUserIDAttribute"
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RoomIDAttribute: AttributedStringKey {
|
enum RoomIDAttribute: AttributedStringKey {
|
||||||
typealias Value = String
|
typealias Value = String
|
||||||
public static var name = "MXRoomIDAttribute"
|
static var name = "MXRoomIDAttribute"
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RoomAliasAttribute: AttributedStringKey {
|
enum RoomAliasAttribute: AttributedStringKey {
|
||||||
typealias Value = String
|
typealias Value = String
|
||||||
public static var name = "MXRoomAliasAttribute"
|
static var name = "MXRoomAliasAttribute"
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AllUsersMentionAttribute: AttributedStringKey {
|
enum AllUsersMentionAttribute: AttributedStringKey {
|
||||||
typealias Value = Bool
|
typealias Value = Bool
|
||||||
public static var name = "MXAllUsersMentionAttribute"
|
static var name = "MXAllUsersMentionAttribute"
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EventIDAttributeValue: Hashable {
|
struct EventIDAttributeValue: Hashable {
|
||||||
@ -48,9 +48,10 @@ struct EventIDAttributeValue: Hashable {
|
|||||||
|
|
||||||
enum EventIDAttribute: AttributedStringKey {
|
enum EventIDAttribute: AttributedStringKey {
|
||||||
typealias Value = EventIDAttributeValue
|
typealias Value = EventIDAttributeValue
|
||||||
public static var name = "MXEventIDAttribute"
|
static var name = "MXEventIDAttribute"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// periphery: ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
|
||||||
extension AttributeScopes {
|
extension AttributeScopes {
|
||||||
struct ElementXAttributes: AttributeScope {
|
struct ElementXAttributes: AttributeScope {
|
||||||
let blockquote: BlockquoteAttribute
|
let blockquote: BlockquoteAttribute
|
||||||
@ -69,6 +70,7 @@ extension AttributeScopes {
|
|||||||
var elementX: ElementXAttributes.Type { ElementXAttributes.self }
|
var elementX: ElementXAttributes.Type { ElementXAttributes.self }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// periphery: ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
|
||||||
extension AttributeDynamicLookup {
|
extension AttributeDynamicLookup {
|
||||||
subscript<T: AttributedStringKey>(dynamicMember keyPath: KeyPath<AttributeScopes.ElementXAttributes, T>) -> T {
|
subscript<T: AttributedStringKey>(dynamicMember keyPath: KeyPath<AttributeScopes.ElementXAttributes, T>) -> T {
|
||||||
self[T.self]
|
self[T.self]
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
//
|
|
||||||
// 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 CoreLocation
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct MapTilerGeoCodingService: MapTilerGeoCodingServiceProtocol {
|
|
||||||
private let key: String
|
|
||||||
private let session: URLSession
|
|
||||||
private let geocodingURL: String
|
|
||||||
|
|
||||||
init(session: URLSession = .shared, key: String, geocodingURL: String) {
|
|
||||||
self.session = session
|
|
||||||
self.key = key
|
|
||||||
self.geocodingURL = geocodingURL
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct GeocodedPlace: Decodable {
|
|
||||||
struct FeatureCollection: Decodable {
|
|
||||||
let placeName: String
|
|
||||||
}
|
|
||||||
|
|
||||||
let features: [FeatureCollection]
|
|
||||||
}
|
|
||||||
|
|
||||||
func reverseGeoCoding(for coordinate: CLLocationCoordinate2D) async -> Result<String, MapTilerGeocodingError> {
|
|
||||||
let latitude = coordinate.latitude
|
|
||||||
let longitude = coordinate.longitude
|
|
||||||
|
|
||||||
let path = String(format: geocodingURL, longitude, latitude)
|
|
||||||
guard var url = URL(string: path) else { return .failure(.wrongGeocodingURL) }
|
|
||||||
let authorization = MapTilerAuthorization(key: key)
|
|
||||||
url = authorization.authorizeURL(url)
|
|
||||||
url.append(queryItems: [.init(name: "limit", value: "1")])
|
|
||||||
|
|
||||||
var request = URLRequest(url: url)
|
|
||||||
request.httpMethod = "GET"
|
|
||||||
|
|
||||||
do {
|
|
||||||
let (data, response) = try await session.dataWithRetry(for: request)
|
|
||||||
|
|
||||||
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
|
|
||||||
let errorDescription = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "Unknown"
|
|
||||||
MXLog.error("Failed to get reverse geocoding: \(errorDescription)")
|
|
||||||
MXLog.error("Response: \(response)")
|
|
||||||
return .failure(.geocodingFailed)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the JSON data
|
|
||||||
let decoder = JSONDecoder()
|
|
||||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
|
||||||
let decodedResponse = try decoder.decode(GeocodedPlace.self, from: data)
|
|
||||||
guard let placeName = decodedResponse.features.first?.placeName else { return .failure(.geocodingFailed) }
|
|
||||||
return .success(placeName)
|
|
||||||
} catch {
|
|
||||||
return .failure(.geocodingFailed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -45,6 +45,6 @@ public extension Animation {
|
|||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - animation: Animation
|
/// - animation: Animation
|
||||||
/// - body: operations to be animated
|
/// - body: operations to be animated
|
||||||
public func withElementAnimation<Result>(_ animation: Animation? = .default, _ body: () throws -> Result) rethrows -> Result {
|
func withElementAnimation<Result>(_ animation: Animation? = .default, _ body: () throws -> Result) rethrows -> Result {
|
||||||
try withAnimation(animation?.disabledDuringTests(), body)
|
try withAnimation(animation?.disabledDuringTests(), body)
|
||||||
}
|
}
|
||||||
|
@ -79,11 +79,8 @@ struct ShimmerOverlay_Previews: PreviewProvider, TestablePreview {
|
|||||||
static let viewModel = HomeScreenViewModel(userSession: MockUserSession(clientProxy: MockClientProxy(userID: ""),
|
static let viewModel = HomeScreenViewModel(userSession: MockUserSession(clientProxy: MockClientProxy(userID: ""),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock()),
|
voiceMessageMediaManager: VoiceMessageMediaManagerMock()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
|
||||||
mentionBuilder: MentionBuilder()),
|
|
||||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
|
@ -27,7 +27,11 @@ struct CustomLayoutLabelStyle: LabelStyle {
|
|||||||
let spacing: CGFloat
|
let spacing: CGFloat
|
||||||
var alignment: VerticalAlignment
|
var alignment: VerticalAlignment
|
||||||
|
|
||||||
enum IconLayout { case leading, trailing }
|
enum IconLayout {
|
||||||
|
case leading
|
||||||
|
case trailing
|
||||||
|
}
|
||||||
|
|
||||||
var iconLayout: IconLayout
|
var iconLayout: IconLayout
|
||||||
|
|
||||||
fileprivate init(spacing: CGFloat, alignment: VerticalAlignment, iconLayout: IconLayout) {
|
fileprivate init(spacing: CGFloat, alignment: VerticalAlignment, iconLayout: IconLayout) {
|
||||||
@ -38,10 +42,11 @@ struct CustomLayoutLabelStyle: LabelStyle {
|
|||||||
|
|
||||||
func makeBody(configuration: Configuration) -> some View {
|
func makeBody(configuration: Configuration) -> some View {
|
||||||
HStack(alignment: alignment, spacing: spacing) {
|
HStack(alignment: alignment, spacing: spacing) {
|
||||||
if iconLayout == .leading {
|
switch iconLayout {
|
||||||
|
case .leading:
|
||||||
configuration.icon
|
configuration.icon
|
||||||
configuration.title
|
configuration.title
|
||||||
} else {
|
case .trailing:
|
||||||
configuration.title
|
configuration.title
|
||||||
configuration.icon
|
configuration.icon
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ struct AppActivityView: UIViewControllerRepresentable {
|
|||||||
private var onCancel: (() -> Void)?
|
private var onCancel: (() -> Void)?
|
||||||
private var onComplete: CompletionType?
|
private var onComplete: CompletionType?
|
||||||
|
|
||||||
public init(activityItems: [Any],
|
init(activityItems: [Any],
|
||||||
applicationActivities: [UIActivity]? = nil,
|
applicationActivities: [UIActivity]? = nil,
|
||||||
excludedActivityTypes: [UIActivity.ActivityType] = [],
|
excludedActivityTypes: [UIActivity.ActivityType] = [],
|
||||||
onCancel: (() -> Void)? = nil,
|
onCancel: (() -> Void)? = nil,
|
||||||
@ -38,7 +38,7 @@ struct AppActivityView: UIViewControllerRepresentable {
|
|||||||
self.onComplete = onComplete
|
self.onComplete = onComplete
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeUIViewController(context: Context) -> UIViewControllerType {
|
func makeUIViewController(context: Context) -> UIViewControllerType {
|
||||||
let viewController = UIViewControllerType(activityItems: activityItems, applicationActivities: applicationActivities)
|
let viewController = UIViewControllerType(activityItems: activityItems, applicationActivities: applicationActivities)
|
||||||
viewController.excludedActivityTypes = excludedActivityTypes
|
viewController.excludedActivityTypes = excludedActivityTypes
|
||||||
|
|
||||||
@ -57,9 +57,9 @@ struct AppActivityView: UIViewControllerRepresentable {
|
|||||||
return viewController
|
return viewController
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { }
|
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { }
|
||||||
|
|
||||||
public static func dismantleUIViewController(_ uiViewController: UIViewControllerType, coordinator: Coordinator) {
|
static func dismantleUIViewController(_ uiViewController: UIViewControllerType, coordinator: Coordinator) {
|
||||||
uiViewController.completionWithItemsHandler = nil
|
uiViewController.completionWithItemsHandler = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2022 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 SwiftUI
|
|
||||||
|
|
||||||
/// A toggle style that uses a button, with a checked/unchecked image like a checkbox.
|
|
||||||
struct ElementToggleStyle: ToggleStyle {
|
|
||||||
func makeBody(configuration: Configuration) -> some View {
|
|
||||||
Button { configuration.isOn.toggle() } label: {
|
|
||||||
Image(systemName: configuration.isOn ? "checkmark.square.fill" : "square")
|
|
||||||
.font(.title3.weight(.regular))
|
|
||||||
.imageScale(.large)
|
|
||||||
.foregroundColor(.compound.textActionPrimary)
|
|
||||||
}
|
|
||||||
.buttonStyle(.plain)
|
|
||||||
}
|
|
||||||
}
|
|
@ -57,7 +57,6 @@ struct EstimatedWaveformView: View {
|
|||||||
var lineWidth: CGFloat = 2
|
var lineWidth: CGFloat = 2
|
||||||
var linePadding: CGFloat = 2
|
var linePadding: CGFloat = 2
|
||||||
var waveform: EstimatedWaveform
|
var waveform: EstimatedWaveform
|
||||||
private let minimumGraphAmplitude: CGFloat = 1
|
|
||||||
var progress: CGFloat = 0.0
|
var progress: CGFloat = 0.0
|
||||||
|
|
||||||
@State private var normalizedWaveformData: [Float] = []
|
@State private var normalizedWaveformData: [Float] = []
|
||||||
|
@ -30,7 +30,6 @@ enum AppLockScreenCoordinatorAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class AppLockScreenCoordinator: CoordinatorProtocol {
|
final class AppLockScreenCoordinator: CoordinatorProtocol {
|
||||||
private let parameters: AppLockScreenCoordinatorParameters
|
|
||||||
private var viewModel: AppLockScreenViewModelProtocol
|
private var viewModel: AppLockScreenViewModelProtocol
|
||||||
private let actionsSubject: PassthroughSubject<AppLockScreenCoordinatorAction, Never> = .init()
|
private let actionsSubject: PassthroughSubject<AppLockScreenCoordinatorAction, Never> = .init()
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
@ -40,8 +39,6 @@ final class AppLockScreenCoordinator: CoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(parameters: AppLockScreenCoordinatorParameters) {
|
init(parameters: AppLockScreenCoordinatorParameters) {
|
||||||
self.parameters = parameters
|
|
||||||
|
|
||||||
viewModel = AppLockScreenViewModel(appLockService: parameters.appLockService)
|
viewModel = AppLockScreenViewModel(appLockService: parameters.appLockService)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ enum AppLockSetupBiometricsScreenCoordinatorAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class AppLockSetupBiometricsScreenCoordinator: CoordinatorProtocol {
|
final class AppLockSetupBiometricsScreenCoordinator: CoordinatorProtocol {
|
||||||
private let parameters: AppLockSetupBiometricsScreenCoordinatorParameters
|
|
||||||
private var viewModel: AppLockSetupBiometricsScreenViewModelProtocol
|
private var viewModel: AppLockSetupBiometricsScreenViewModelProtocol
|
||||||
private let actionsSubject: PassthroughSubject<AppLockSetupBiometricsScreenCoordinatorAction, Never> = .init()
|
private let actionsSubject: PassthroughSubject<AppLockSetupBiometricsScreenCoordinatorAction, Never> = .init()
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
@ -36,8 +35,6 @@ final class AppLockSetupBiometricsScreenCoordinator: CoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(parameters: AppLockSetupBiometricsScreenCoordinatorParameters) {
|
init(parameters: AppLockSetupBiometricsScreenCoordinatorParameters) {
|
||||||
self.parameters = parameters
|
|
||||||
|
|
||||||
viewModel = AppLockSetupBiometricsScreenViewModel(appLockService: parameters.appLockService)
|
viewModel = AppLockSetupBiometricsScreenViewModel(appLockService: parameters.appLockService)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ enum AppLockSetupPINScreenCoordinatorAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class AppLockSetupPINScreenCoordinator: CoordinatorProtocol {
|
final class AppLockSetupPINScreenCoordinator: CoordinatorProtocol {
|
||||||
private let parameters: AppLockSetupPINScreenCoordinatorParameters
|
|
||||||
private var viewModel: AppLockSetupPINScreenViewModelProtocol
|
private var viewModel: AppLockSetupPINScreenViewModelProtocol
|
||||||
private let actionsSubject: PassthroughSubject<AppLockSetupPINScreenCoordinatorAction, Never> = .init()
|
private let actionsSubject: PassthroughSubject<AppLockSetupPINScreenCoordinatorAction, Never> = .init()
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
@ -48,7 +47,6 @@ final class AppLockSetupPINScreenCoordinator: CoordinatorProtocol {
|
|||||||
init(parameters: AppLockSetupPINScreenCoordinatorParameters) {
|
init(parameters: AppLockSetupPINScreenCoordinatorParameters) {
|
||||||
guard parameters.initialMode != .confirm else { fatalError(".confirm is an invalid initial mode") }
|
guard parameters.initialMode != .confirm else { fatalError(".confirm is an invalid initial mode") }
|
||||||
|
|
||||||
self.parameters = parameters
|
|
||||||
viewModel = AppLockSetupPINScreenViewModel(initialMode: parameters.initialMode,
|
viewModel = AppLockSetupPINScreenViewModel(initialMode: parameters.initialMode,
|
||||||
isMandatory: parameters.isMandatory,
|
isMandatory: parameters.isMandatory,
|
||||||
appLockService: parameters.appLockService)
|
appLockService: parameters.appLockService)
|
||||||
|
@ -45,7 +45,7 @@ class AppLockSetupPINScreenViewModel: AppLockSetupPINScreenViewModelType, AppLoc
|
|||||||
.debounce(for: 0.1, scheduler: DispatchQueue.main) // Show the last digit for long enough to be read.
|
.debounce(for: 0.1, scheduler: DispatchQueue.main) // Show the last digit for long enough to be read.
|
||||||
.sink { [weak self] pinCode in
|
.sink { [weak self] pinCode in
|
||||||
guard pinCode.count == 4 else { return }
|
guard pinCode.count == 4 else { return }
|
||||||
self?.submit(pinCode)
|
self?.submit()
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ class AppLockSetupPINScreenViewModel: AppLockSetupPINScreenViewModelType, AppLoc
|
|||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
/// Handle the entered PIN code.
|
/// Handle the entered PIN code.
|
||||||
private func submit(_ pinCode: String) {
|
private func submit() {
|
||||||
switch state.mode {
|
switch state.mode {
|
||||||
case .create:
|
case .create:
|
||||||
createPIN()
|
createPIN()
|
||||||
|
@ -29,7 +29,6 @@ enum AppLockSetupSettingsScreenCoordinatorAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class AppLockSetupSettingsScreenCoordinator: CoordinatorProtocol {
|
final class AppLockSetupSettingsScreenCoordinator: CoordinatorProtocol {
|
||||||
private let parameters: AppLockSetupSettingsScreenCoordinatorParameters
|
|
||||||
private var viewModel: AppLockSetupSettingsScreenViewModelProtocol
|
private var viewModel: AppLockSetupSettingsScreenViewModelProtocol
|
||||||
private let actionsSubject: PassthroughSubject<AppLockSetupSettingsScreenCoordinatorAction, Never> = .init()
|
private let actionsSubject: PassthroughSubject<AppLockSetupSettingsScreenCoordinatorAction, Never> = .init()
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
@ -39,8 +38,6 @@ final class AppLockSetupSettingsScreenCoordinator: CoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(parameters: AppLockSetupSettingsScreenCoordinatorParameters) {
|
init(parameters: AppLockSetupSettingsScreenCoordinatorParameters) {
|
||||||
self.parameters = parameters
|
|
||||||
|
|
||||||
viewModel = AppLockSetupSettingsScreenViewModel(appLockService: parameters.appLockService)
|
viewModel = AppLockSetupSettingsScreenViewModel(appLockService: parameters.appLockService)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,7 @@ import SwiftUI
|
|||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
protocol AuthenticationCoordinatorDelegate: AnyObject {
|
protocol AuthenticationCoordinatorDelegate: AnyObject {
|
||||||
func authenticationCoordinator(_ authenticationCoordinator: AuthenticationCoordinator,
|
func authenticationCoordinator(didLoginWithSession userSession: UserSessionProtocol)
|
||||||
didLoginWithSession userSession: UserSessionProtocol)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AuthenticationCoordinator: CoordinatorProtocol {
|
class AuthenticationCoordinator: CoordinatorProtocol {
|
||||||
@ -34,6 +33,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
|
|||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
private var oidcPresenter: OIDCAuthenticationPresenter?
|
private var oidcPresenter: OIDCAuthenticationPresenter?
|
||||||
|
// periphery: ignore - used to store the coordinator to avoid deallocation
|
||||||
private var appLockFlowCoordinator: AppLockSetupFlowCoordinator?
|
private var appLockFlowCoordinator: AppLockSetupFlowCoordinator?
|
||||||
|
|
||||||
weak var delegate: AuthenticationCoordinatorDelegate?
|
weak var delegate: AuthenticationCoordinatorDelegate?
|
||||||
@ -245,7 +245,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
|
|||||||
} else if analytics.shouldShowAnalyticsPrompt {
|
} else if analytics.shouldShowAnalyticsPrompt {
|
||||||
showAnalyticsPrompt(userSession: userSession)
|
showAnalyticsPrompt(userSession: userSession)
|
||||||
} else {
|
} else {
|
||||||
delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
|
delegate?.authenticationCoordinator(didLoginWithSession: userSession)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +261,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
|
|||||||
if analytics.shouldShowAnalyticsPrompt {
|
if analytics.shouldShowAnalyticsPrompt {
|
||||||
showAnalyticsPrompt(userSession: userSession)
|
showAnalyticsPrompt(userSession: userSession)
|
||||||
} else {
|
} else {
|
||||||
delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
|
delegate?.authenticationCoordinator(didLoginWithSession: userSession)
|
||||||
}
|
}
|
||||||
case .forceLogout:
|
case .forceLogout:
|
||||||
fatalError("The PIN creation flow should not fail.")
|
fatalError("The PIN creation flow should not fail.")
|
||||||
@ -281,7 +281,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
|
|||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
switch action {
|
switch action {
|
||||||
case .done:
|
case .done:
|
||||||
delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
|
delegate?.authenticationCoordinator(didLoginWithSession: userSession)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
@ -44,7 +44,6 @@ public extension TextFieldStyle where Self == AuthenticationTextFieldStyle {
|
|||||||
/// The text field style used in authentication screens.
|
/// The text field style used in authentication screens.
|
||||||
public struct AuthenticationTextFieldStyle: TextFieldStyle {
|
public struct AuthenticationTextFieldStyle: TextFieldStyle {
|
||||||
@Environment(\.isEnabled) private var isEnabled
|
@Environment(\.isEnabled) private var isEnabled
|
||||||
@Environment(\.colorScheme) private var colorScheme
|
|
||||||
|
|
||||||
@FocusState private var isFocused: Bool
|
@FocusState private var isFocused: Bool
|
||||||
public let labelText: Text?
|
public let labelText: Text?
|
||||||
|
@ -24,6 +24,7 @@ class BugReportScreenViewModel: BugReportScreenViewModelType, BugReportScreenVie
|
|||||||
private let userID: String
|
private let userID: String
|
||||||
private let deviceID: String?
|
private let deviceID: String?
|
||||||
private let actionsSubject: PassthroughSubject<BugReportScreenViewModelAction, Never> = .init()
|
private let actionsSubject: PassthroughSubject<BugReportScreenViewModelAction, Never> = .init()
|
||||||
|
// periphery:ignore - when set to nil this is automatically cancelled
|
||||||
@CancellableTask private var uploadTask: Task<Void, Never>?
|
@CancellableTask private var uploadTask: Task<Void, Never>?
|
||||||
|
|
||||||
var actions: AnyPublisher<BugReportScreenViewModelAction, Never> {
|
var actions: AnyPublisher<BugReportScreenViewModelAction, Never> {
|
||||||
|
@ -140,12 +140,6 @@ struct BugReportScreen: View {
|
|||||||
// MARK: - Previews
|
// MARK: - Previews
|
||||||
|
|
||||||
struct BugReport_Previews: PreviewProvider, TestablePreview {
|
struct BugReport_Previews: PreviewProvider, TestablePreview {
|
||||||
static let viewModel = BugReportScreenViewModel(bugReportService: BugReportServiceMock(),
|
|
||||||
userID: "@mock.client.com",
|
|
||||||
deviceID: nil,
|
|
||||||
screenshot: nil,
|
|
||||||
isModallyPresented: false)
|
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
BugReportScreen(context: BugReportScreenViewModel(bugReportService: BugReportServiceMock(),
|
BugReportScreen(context: BugReportScreenViewModel(bugReportService: BugReportServiceMock(),
|
||||||
|
@ -32,7 +32,6 @@ enum CallScreenCoordinatorAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class CallScreenCoordinator: CoordinatorProtocol {
|
final class CallScreenCoordinator: CoordinatorProtocol {
|
||||||
private let parameters: CallScreenCoordinatorParameters
|
|
||||||
private var viewModel: CallScreenViewModelProtocol
|
private var viewModel: CallScreenViewModelProtocol
|
||||||
private let actionsSubject: PassthroughSubject<CallScreenCoordinatorAction, Never> = .init()
|
private let actionsSubject: PassthroughSubject<CallScreenCoordinatorAction, Never> = .init()
|
||||||
|
|
||||||
@ -42,8 +41,6 @@ final class CallScreenCoordinator: CoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(parameters: CallScreenCoordinatorParameters) {
|
init(parameters: CallScreenCoordinatorParameters) {
|
||||||
self.parameters = parameters
|
|
||||||
|
|
||||||
viewModel = CallScreenViewModel(roomProxy: parameters.roomProxy,
|
viewModel = CallScreenViewModel(roomProxy: parameters.roomProxy,
|
||||||
callBaseURL: parameters.callBaseURL,
|
callBaseURL: parameters.callBaseURL,
|
||||||
clientID: parameters.clientID,
|
clientID: parameters.clientID,
|
||||||
|
@ -23,13 +23,13 @@ typealias CallScreenViewModelType = StateStoreViewModel<CallScreenViewState, Cal
|
|||||||
|
|
||||||
class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol {
|
class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol {
|
||||||
private let roomProxy: RoomProxyProtocol
|
private let roomProxy: RoomProxyProtocol
|
||||||
private let callBaseURL: URL
|
|
||||||
private let clientID: String
|
|
||||||
|
|
||||||
private let widgetDriver: ElementCallWidgetDriverProtocol
|
private let widgetDriver: ElementCallWidgetDriverProtocol
|
||||||
|
|
||||||
private let callController = CXCallController()
|
private let callController = CXCallController()
|
||||||
|
// periphery: ignore - call kit magic do not remove
|
||||||
private let callProvider = CXProvider(configuration: .init())
|
private let callProvider = CXProvider(configuration: .init())
|
||||||
|
|
||||||
private let callID = UUID()
|
private let callID = UUID()
|
||||||
|
|
||||||
private let actionsSubject: PassthroughSubject<CallScreenViewModelAction, Never> = .init()
|
private let actionsSubject: PassthroughSubject<CallScreenViewModelAction, Never> = .init()
|
||||||
@ -51,8 +51,6 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
|
|||||||
clientID: String,
|
clientID: String,
|
||||||
useEncryption: Bool) {
|
useEncryption: Bool) {
|
||||||
self.roomProxy = roomProxy
|
self.roomProxy = roomProxy
|
||||||
self.callBaseURL = callBaseURL
|
|
||||||
self.clientID = clientID
|
|
||||||
|
|
||||||
widgetDriver = roomProxy.elementCallWidgetDriver()
|
widgetDriver = roomProxy.elementCallWidgetDriver()
|
||||||
|
|
||||||
@ -132,12 +130,14 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
|
|||||||
|
|
||||||
// MARK: - CXCallObserverDelegate
|
// MARK: - CXCallObserverDelegate
|
||||||
|
|
||||||
|
// periphery: ignore - call kit magic do not remove
|
||||||
func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
|
func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
|
||||||
MXLog.info("Call changed: \(call)")
|
MXLog.info("Call changed: \(call)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - CXProviderDelegate
|
// MARK: - CXProviderDelegate
|
||||||
|
|
||||||
|
// periphery: ignore - call kit magic do not remove
|
||||||
func providerDidReset(_ provider: CXProvider) {
|
func providerDidReset(_ provider: CXProvider) {
|
||||||
MXLog.info("Call provider did reset: \(provider)")
|
MXLog.info("Call provider did reset: \(provider)")
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,6 @@ private struct WebView: UIViewRepresentable {
|
|||||||
@MainActor
|
@MainActor
|
||||||
class Coordinator: NSObject, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate {
|
class Coordinator: NSObject, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate {
|
||||||
private let viewModelContext: CallScreenViewModel.Context
|
private let viewModelContext: CallScreenViewModel.Context
|
||||||
private var webViewURLObservation: NSKeyValueObservation?
|
|
||||||
|
|
||||||
private(set) var webView: WKWebView!
|
private(set) var webView: WKWebView!
|
||||||
|
|
||||||
|
@ -30,15 +30,6 @@ enum SuggestionItem: Identifiable, Equatable {
|
|||||||
return PillConstants.atRoom
|
return PillConstants.atRoom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var name: String? {
|
|
||||||
switch self {
|
|
||||||
case .user(let user):
|
|
||||||
return user.displayName
|
|
||||||
case .allUsers:
|
|
||||||
return PillConstants.everyone
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MentionSuggestionItem: Identifiable, Equatable {
|
struct MentionSuggestionItem: Identifiable, Equatable {
|
||||||
|
@ -25,6 +25,7 @@ struct SuggestionPattern: Equatable {
|
|||||||
let text: String
|
let text: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// periphery: ignore - markdown protocol
|
||||||
protocol ComposerToolbarViewModelProtocol {
|
protocol ComposerToolbarViewModelProtocol {
|
||||||
var actions: AnyPublisher<ComposerToolbarViewModelAction, Never> { get }
|
var actions: AnyPublisher<ComposerToolbarViewModelAction, Never> { get }
|
||||||
var context: ComposerToolbarViewModelType.Context { get }
|
var context: ComposerToolbarViewModelType.Context { get }
|
||||||
|
@ -313,8 +313,8 @@ struct ComposerToolbar_Previews: PreviewProvider, TestablePreview {
|
|||||||
VStack(spacing: 8) {
|
VStack(spacing: 8) {
|
||||||
ComposerToolbar.textWithVoiceMessage(focused: false)
|
ComposerToolbar.textWithVoiceMessage(focused: false)
|
||||||
ComposerToolbar.textWithVoiceMessage(focused: true)
|
ComposerToolbar.textWithVoiceMessage(focused: true)
|
||||||
ComposerToolbar.voiceMessageRecordingMock(recording: true)
|
ComposerToolbar.voiceMessageRecordingMock()
|
||||||
ComposerToolbar.voiceMessagePreviewMock(recording: false, uploading: false)
|
ComposerToolbar.voiceMessagePreviewMock(uploading: false)
|
||||||
}
|
}
|
||||||
.previewDisplayName("Voice Message")
|
.previewDisplayName("Voice Message")
|
||||||
}
|
}
|
||||||
@ -355,7 +355,7 @@ extension ComposerToolbar {
|
|||||||
keyCommandHandler: { _ in false })
|
keyCommandHandler: { _ in false })
|
||||||
}
|
}
|
||||||
|
|
||||||
static func voiceMessageRecordingMock(recording: Bool) -> ComposerToolbar {
|
static func voiceMessageRecordingMock() -> ComposerToolbar {
|
||||||
let wysiwygViewModel = WysiwygComposerViewModel()
|
let wysiwygViewModel = WysiwygComposerViewModel()
|
||||||
var composerViewModel: ComposerToolbarViewModel {
|
var composerViewModel: ComposerToolbarViewModel {
|
||||||
let model = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel,
|
let model = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel,
|
||||||
@ -371,7 +371,7 @@ extension ComposerToolbar {
|
|||||||
keyCommandHandler: { _ in false })
|
keyCommandHandler: { _ in false })
|
||||||
}
|
}
|
||||||
|
|
||||||
static func voiceMessagePreviewMock(recording: Bool, uploading: Bool) -> ComposerToolbar {
|
static func voiceMessagePreviewMock(uploading: Bool) -> ComposerToolbar {
|
||||||
let wysiwygViewModel = WysiwygComposerViewModel()
|
let wysiwygViewModel = WysiwygComposerViewModel()
|
||||||
let waveformData: [Float] = Array(repeating: 1.0, count: 1000)
|
let waveformData: [Float] = Array(repeating: 1.0, count: 1000)
|
||||||
var composerViewModel: ComposerToolbarViewModel {
|
var composerViewModel: ComposerToolbarViewModel {
|
||||||
|
@ -33,7 +33,6 @@ enum CreateRoomCoordinatorAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class CreateRoomCoordinator: CoordinatorProtocol {
|
final class CreateRoomCoordinator: CoordinatorProtocol {
|
||||||
private let parameters: CreateRoomCoordinatorParameters
|
|
||||||
private var viewModel: CreateRoomViewModelProtocol
|
private var viewModel: CreateRoomViewModelProtocol
|
||||||
private let actionsSubject: PassthroughSubject<CreateRoomCoordinatorAction, Never> = .init()
|
private let actionsSubject: PassthroughSubject<CreateRoomCoordinatorAction, Never> = .init()
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
@ -43,7 +42,6 @@ final class CreateRoomCoordinator: CoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(parameters: CreateRoomCoordinatorParameters) {
|
init(parameters: CreateRoomCoordinatorParameters) {
|
||||||
self.parameters = parameters
|
|
||||||
viewModel = CreateRoomViewModel(userSession: parameters.userSession,
|
viewModel = CreateRoomViewModel(userSession: parameters.userSession,
|
||||||
createRoomParameters: parameters.createRoomParameters,
|
createRoomParameters: parameters.createRoomParameters,
|
||||||
selectedUsers: parameters.selectedUsers,
|
selectedUsers: parameters.selectedUsers,
|
||||||
|
@ -39,7 +39,6 @@ enum HomeScreenCoordinatorAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class HomeScreenCoordinator: CoordinatorProtocol {
|
final class HomeScreenCoordinator: CoordinatorProtocol {
|
||||||
private let parameters: HomeScreenCoordinatorParameters
|
|
||||||
private var viewModel: HomeScreenViewModelProtocol
|
private var viewModel: HomeScreenViewModelProtocol
|
||||||
|
|
||||||
private let actionsSubject: PassthroughSubject<HomeScreenCoordinatorAction, Never> = .init()
|
private let actionsSubject: PassthroughSubject<HomeScreenCoordinatorAction, Never> = .init()
|
||||||
@ -50,13 +49,9 @@ final class HomeScreenCoordinator: CoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(parameters: HomeScreenCoordinatorParameters) {
|
init(parameters: HomeScreenCoordinatorParameters) {
|
||||||
self.parameters = parameters
|
|
||||||
|
|
||||||
viewModel = HomeScreenViewModel(userSession: parameters.userSession,
|
viewModel = HomeScreenViewModel(userSession: parameters.userSession,
|
||||||
attributedStringBuilder: parameters.attributedStringBuilder,
|
|
||||||
selectedRoomPublisher: parameters.selectedRoomPublisher,
|
selectedRoomPublisher: parameters.selectedRoomPublisher,
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
|
|
||||||
viewModel.actions
|
viewModel.actions
|
||||||
|
@ -21,9 +21,7 @@ typealias HomeScreenViewModelType = StateStoreViewModel<HomeScreenViewState, Hom
|
|||||||
|
|
||||||
class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol {
|
class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol {
|
||||||
private let userSession: UserSessionProtocol
|
private let userSession: UserSessionProtocol
|
||||||
private let attributedStringBuilder: AttributedStringBuilderProtocol
|
|
||||||
private let appSettings: AppSettings
|
private let appSettings: AppSettings
|
||||||
private let analytics: AnalyticsService
|
|
||||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
|
|
||||||
private let roomSummaryProvider: RoomSummaryProviderProtocol?
|
private let roomSummaryProvider: RoomSummaryProviderProtocol?
|
||||||
@ -39,15 +37,11 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(userSession: UserSessionProtocol,
|
init(userSession: UserSessionProtocol,
|
||||||
attributedStringBuilder: AttributedStringBuilderProtocol,
|
|
||||||
selectedRoomPublisher: CurrentValuePublisher<String?, Never>,
|
selectedRoomPublisher: CurrentValuePublisher<String?, Never>,
|
||||||
appSettings: AppSettings,
|
appSettings: AppSettings,
|
||||||
analytics: AnalyticsService,
|
|
||||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||||
self.userSession = userSession
|
self.userSession = userSession
|
||||||
self.attributedStringBuilder = attributedStringBuilder
|
|
||||||
self.appSettings = appSettings
|
self.appSettings = appSettings
|
||||||
self.analytics = analytics
|
|
||||||
self.userIndicatorController = userIndicatorController
|
self.userIndicatorController = userIndicatorController
|
||||||
|
|
||||||
roomSummaryProvider = userSession.clientProxy.roomSummaryProvider
|
roomSummaryProvider = userSession.clientProxy.roomSummaryProvider
|
||||||
|
@ -306,14 +306,9 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||||
|
|
||||||
let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
|
||||||
mentionBuilder: MentionBuilder())
|
|
||||||
|
|
||||||
return HomeScreenViewModel(userSession: userSession,
|
return HomeScreenViewModel(userSession: userSession,
|
||||||
attributedStringBuilder: attributedStringBuilder,
|
|
||||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,10 +155,8 @@ struct HomeScreenEmptyStateView_Previews: PreviewProvider, TestablePreview {
|
|||||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||||
|
|
||||||
return HomeScreenViewModel(userSession: userSession,
|
return HomeScreenViewModel(userSession: userSession,
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder()),
|
|
||||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -72,14 +72,9 @@ struct HomeScreenRecoveryKeyConfirmationBanner_Previews: PreviewProvider, Testab
|
|||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||||
|
|
||||||
let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
|
||||||
mentionBuilder: MentionBuilder())
|
|
||||||
|
|
||||||
return HomeScreenViewModel(userSession: userSession,
|
return HomeScreenViewModel(userSession: userSession,
|
||||||
attributedStringBuilder: attributedStringBuilder,
|
|
||||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,11 +186,8 @@ struct HomeScreenRoomCell_Previews: PreviewProvider, TestablePreview {
|
|||||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||||
|
|
||||||
let viewModel = HomeScreenViewModel(userSession: userSession,
|
let viewModel = HomeScreenViewModel(userSession: userSession,
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
|
||||||
mentionBuilder: MentionBuilder()),
|
|
||||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
|
|
||||||
let rooms: [HomeScreenRoom] = summaryProvider.roomListPublisher.value.compactMap { summary -> HomeScreenRoom? in
|
let rooms: [HomeScreenRoom] = summaryProvider.roomListPublisher.value.compactMap { summary -> HomeScreenRoom? in
|
||||||
|
@ -72,14 +72,9 @@ struct HomeScreenSessionVerificationBanner_Previews: PreviewProvider, TestablePr
|
|||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||||
|
|
||||||
let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
|
||||||
mentionBuilder: MentionBuilder())
|
|
||||||
|
|
||||||
return HomeScreenViewModel(userSession: userSession,
|
return HomeScreenViewModel(userSession: userSession,
|
||||||
attributedStringBuilder: attributedStringBuilder,
|
|
||||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,6 @@ import Compound
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct HomeScreenUserMenuButton: View {
|
struct HomeScreenUserMenuButton: View {
|
||||||
@Environment(\.colorScheme) private var colorScheme
|
|
||||||
|
|
||||||
@ObservedObject var context: HomeScreenViewModel.Context
|
@ObservedObject var context: HomeScreenViewModel.Context
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
@ -518,7 +518,7 @@ class RoomScreenInteractionHandler {
|
|||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.error("Failed to load voice message: \(error)")
|
MXLog.error("Failed to load voice message: \(error)")
|
||||||
audioPlayerState.reportError(error)
|
audioPlayerState.reportError()
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// periphery: ignore - markdown protocol
|
||||||
protocol TextBasedRoomTimelineViewProtocol {
|
protocol TextBasedRoomTimelineViewProtocol {
|
||||||
associatedtype TimelineItemType: TextBasedRoomTimelineItem
|
associatedtype TimelineItemType: TextBasedRoomTimelineItem
|
||||||
|
|
||||||
|
@ -20,11 +20,9 @@ import SwiftUI
|
|||||||
typealias AnalyticsSettingsScreenViewModelType = StateStoreViewModel<AnalyticsSettingsScreenViewState, AnalyticsSettingsScreenViewAction>
|
typealias AnalyticsSettingsScreenViewModelType = StateStoreViewModel<AnalyticsSettingsScreenViewState, AnalyticsSettingsScreenViewAction>
|
||||||
|
|
||||||
class AnalyticsSettingsScreenViewModel: AnalyticsSettingsScreenViewModelType, AnalyticsSettingsScreenViewModelProtocol {
|
class AnalyticsSettingsScreenViewModel: AnalyticsSettingsScreenViewModelType, AnalyticsSettingsScreenViewModelProtocol {
|
||||||
private let appSettings: AppSettings
|
|
||||||
private let analytics: AnalyticsService
|
private let analytics: AnalyticsService
|
||||||
|
|
||||||
init(appSettings: AppSettings, analytics: AnalyticsService) {
|
init(appSettings: AppSettings, analytics: AnalyticsService) {
|
||||||
self.appSettings = appSettings
|
|
||||||
self.analytics = analytics
|
self.analytics = analytics
|
||||||
|
|
||||||
let strings = AnalyticsSettingsScreenStrings(termsURL: appSettings.analyticsConfiguration.termsURL)
|
let strings = AnalyticsSettingsScreenStrings(termsURL: appSettings.analyticsConfiguration.termsURL)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// periphery:ignore:all - subscripts lead to false positives
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct AdvancedSettingsScreenViewState: BindableState {
|
struct AdvancedSettingsScreenViewState: BindableState {
|
||||||
|
@ -24,6 +24,7 @@ struct DeveloperOptionsScreenViewState: BindableState {
|
|||||||
var bindings: DeveloperOptionsScreenViewStateBindings
|
var bindings: DeveloperOptionsScreenViewStateBindings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// periphery: ignore - subscripts are seen as false positive
|
||||||
@dynamicMemberLookup
|
@dynamicMemberLookup
|
||||||
struct DeveloperOptionsScreenViewStateBindings {
|
struct DeveloperOptionsScreenViewStateBindings {
|
||||||
private let developerOptions: DeveloperOptionsProtocol
|
private let developerOptions: DeveloperOptionsProtocol
|
||||||
|
@ -31,9 +31,6 @@ protocol AnalyticsClientProtocol {
|
|||||||
/// Stop the analytics client reporting data.
|
/// Stop the analytics client reporting data.
|
||||||
func stop()
|
func stop()
|
||||||
|
|
||||||
/// Send any queued events immediately.
|
|
||||||
func flush()
|
|
||||||
|
|
||||||
/// Capture the supplied analytics event.
|
/// Capture the supplied analytics event.
|
||||||
/// - Parameter event: The event to capture.
|
/// - Parameter event: The event to capture.
|
||||||
func capture(_ event: AnalyticsEventProtocol)
|
func capture(_ event: AnalyticsEventProtocol)
|
||||||
@ -41,14 +38,6 @@ protocol AnalyticsClientProtocol {
|
|||||||
/// Capture the supplied analytics screen event.
|
/// Capture the supplied analytics screen event.
|
||||||
/// - Parameter event: The screen event to capture.
|
/// - Parameter event: The screen event to capture.
|
||||||
func screen(_ event: AnalyticsScreenProtocol)
|
func screen(_ event: AnalyticsScreenProtocol)
|
||||||
|
|
||||||
/// Updates any user properties to help with creating cohorts.
|
|
||||||
/// - Parameter userProperties: The user properties to be updated.
|
|
||||||
///
|
|
||||||
/// Only non-nil properties will be updated when calling this method. There might
|
|
||||||
/// be a delay when updating user properties as these are cached to be included
|
|
||||||
/// as part of the next event that gets captured.
|
|
||||||
func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sourcery: AutoMockable
|
// sourcery: AutoMockable
|
||||||
|
@ -105,13 +105,6 @@ class AnalyticsService {
|
|||||||
appSettings.analyticsConsentState = .unknown
|
appSettings.analyticsConsentState = .unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flushes the event queue in the analytics client, uploading all pending events.
|
|
||||||
/// Normally events are sent in batches. Call this method when you need an event
|
|
||||||
/// to be sent immediately.
|
|
||||||
func forceUpload() {
|
|
||||||
client.flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
/// Capture an event in the `client`.
|
/// Capture an event in the `client`.
|
||||||
|
@ -24,10 +24,6 @@ protocol AudioSessionProtocol: AnyObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension AudioSessionProtocol {
|
extension AudioSessionProtocol {
|
||||||
func setCategory(_ category: AVAudioSession.Category, mode: AVAudioSession.Mode) throws {
|
|
||||||
try setCategory(category, mode: mode, options: [])
|
|
||||||
}
|
|
||||||
|
|
||||||
func setActive(_ active: Bool) throws {
|
func setActive(_ active: Bool) throws {
|
||||||
try setActive(active, options: [])
|
try setActive(active, options: [])
|
||||||
}
|
}
|
||||||
|
@ -46,12 +46,13 @@ class AudioPlayer: NSObject, AudioPlayerProtocol {
|
|||||||
|
|
||||||
private var statusObserver: NSKeyValueObservation?
|
private var statusObserver: NSKeyValueObservation?
|
||||||
private var rateObserver: NSKeyValueObservation?
|
private var rateObserver: NSKeyValueObservation?
|
||||||
private var playToEndObserver: NSObjectProtocol?
|
|
||||||
private var appBackgroundObserver: NSObjectProtocol?
|
|
||||||
private var autoplay = false
|
private var autoplay = false
|
||||||
|
|
||||||
private let audioSession = AVAudioSession.sharedInstance()
|
private let audioSession = AVAudioSession.sharedInstance()
|
||||||
|
|
||||||
|
// periphery:ignore - when set to nil is automatically cancelled
|
||||||
@CancellableTask private var releaseAudioSessionTask: Task<Void, Never>?
|
@CancellableTask private var releaseAudioSessionTask: Task<Void, Never>?
|
||||||
|
|
||||||
private let releaseAudioSessionTimeoutInterval = 5.0
|
private let releaseAudioSessionTimeoutInterval = 5.0
|
||||||
|
|
||||||
private(set) var url: URL?
|
private(set) var url: URL?
|
||||||
|
@ -19,7 +19,6 @@ import Foundation
|
|||||||
|
|
||||||
enum AudioPlayerError: Error {
|
enum AudioPlayerError: Error {
|
||||||
case genericError
|
case genericError
|
||||||
case loadFileError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AudioPlayerAction {
|
enum AudioPlayerAction {
|
||||||
|
@ -110,7 +110,7 @@ class AudioPlayerState: ObservableObject, Identifiable {
|
|||||||
playbackState = .stopped
|
playbackState = .stopped
|
||||||
}
|
}
|
||||||
|
|
||||||
func reportError(_ error: Error) {
|
func reportError() {
|
||||||
playbackState = .error
|
playbackState = .error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +167,7 @@ class AudioPlayerState: ObservableObject, Identifiable {
|
|||||||
displayLink?.add(to: .current, forMode: .common)
|
displayLink?.add(to: .current, forMode: .common)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// periphery:ignore:parameters displayLink - required for objc selector
|
||||||
@objc private func updateProgress(displayLink: CADisplayLink) {
|
@objc private func updateProgress(displayLink: CADisplayLink) {
|
||||||
if let currentTime = audioPlayer?.currentTime, duration > 0 {
|
if let currentTime = audioPlayer?.currentTime, duration > 0 {
|
||||||
progress = currentTime / duration
|
progress = currentTime / duration
|
||||||
|
@ -343,9 +343,9 @@ class AudioRecorder: AudioRecorderProtocol {
|
|||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
NotificationCenter.default.publisher(for: Notification.Name.AVAudioEngineConfigurationChange)
|
NotificationCenter.default.publisher(for: Notification.Name.AVAudioEngineConfigurationChange)
|
||||||
.sink { [weak self] notification in
|
.sink { [weak self] _ in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
self.handleConfigurationChange(notification: notification)
|
self.handleConfigurationChange()
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
@ -396,7 +396,7 @@ class AudioRecorder: AudioRecorderProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleConfigurationChange(notification: Notification) {
|
func handleConfigurationChange() {
|
||||||
guard let audioEngine else { return }
|
guard let audioEngine else { return }
|
||||||
MXLog.warning("Configuration changed: \(audioEngine.inputNode.inputFormat(forBus: 0))")
|
MXLog.warning("Configuration changed: \(audioEngine.inputNode.inputFormat(forBus: 0))")
|
||||||
if internalState != .suspended {
|
if internalState != .suspended {
|
||||||
|
@ -24,7 +24,6 @@ enum AudioRecorderError: Error, Equatable {
|
|||||||
case audioFileCreationFailure
|
case audioFileCreationFailure
|
||||||
case interrupted
|
case interrupted
|
||||||
case recordingCancelled
|
case recordingCancelled
|
||||||
case recordingFailed
|
|
||||||
case recordPermissionNotGranted
|
case recordPermissionNotGranted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ class AudioRecorderState: ObservableObject, Identifiable {
|
|||||||
recordingState = .stopped
|
recordingState = .stopped
|
||||||
}
|
}
|
||||||
|
|
||||||
func reportError(_ error: Error) {
|
func reportError() {
|
||||||
recordingState = .error
|
recordingState = .error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,6 +98,7 @@ class AudioRecorderState: ObservableObject, Identifiable {
|
|||||||
displayLink?.add(to: .current, forMode: .common)
|
displayLink?.add(to: .current, forMode: .common)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// periphery:ignore:parameters displayLink - required for objc selector
|
||||||
@objc private func publishUpdate(displayLink: CADisplayLink) {
|
@objc private func publishUpdate(displayLink: CADisplayLink) {
|
||||||
if let currentTime = audioRecorder?.currentTime {
|
if let currentTime = audioRecorder?.currentTime {
|
||||||
duration = currentTime
|
duration = currentTime
|
||||||
|
@ -19,8 +19,6 @@ import UIKit
|
|||||||
|
|
||||||
// sourcery: AutoMockable
|
// sourcery: AutoMockable
|
||||||
protocol ApplicationProtocol {
|
protocol ApplicationProtocol {
|
||||||
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)
|
||||||
|
@ -29,12 +29,6 @@ protocol BackgroundTaskProtocol: AnyObject {
|
|||||||
/// Flag indicating the background task is reusable. If reusable, `name` is the key to distinguish background tasks.
|
/// Flag indicating the background task is reusable. If reusable, `name` is the key to distinguish background tasks.
|
||||||
var isReusable: Bool { get }
|
var isReusable: Bool { get }
|
||||||
|
|
||||||
/// Elapsed time after the task started. In milliseconds.
|
|
||||||
var elapsedTime: TimeInterval { get }
|
|
||||||
|
|
||||||
/// Expiration handler for the background task
|
|
||||||
var expirationHandler: BackgroundTaskExpirationHandler? { get }
|
|
||||||
|
|
||||||
/// Method to be called when a task reused one more time. Should only be valid for reusable tasks.
|
/// Method to be called when a task reused one more time. Should only be valid for reusable tasks.
|
||||||
func reuse()
|
func reuse()
|
||||||
|
|
||||||
|
@ -116,10 +116,6 @@ class BugReportService: NSObject, BugReportServiceProtocol {
|
|||||||
MXLog.info("Reset.")
|
MXLog.info("Reset.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func crash() {
|
|
||||||
SentrySDK.crash()
|
|
||||||
}
|
|
||||||
|
|
||||||
func submitBugReport(_ bugReport: BugReport,
|
func submitBugReport(_ bugReport: BugReport,
|
||||||
progressListener: CurrentValueSubject<Double, Never>) async -> Result<SubmitBugReportResponse, BugReportServiceError> {
|
progressListener: CurrentValueSubject<Double, Never>) async -> Result<SubmitBugReportResponse, BugReportServiceError> {
|
||||||
var params = [
|
var params = [
|
||||||
|
@ -52,6 +52,7 @@ enum BugReportServiceError: LocalizedError {
|
|||||||
|
|
||||||
// sourcery: AutoMockable
|
// sourcery: AutoMockable
|
||||||
protocol BugReportServiceProtocol {
|
protocol BugReportServiceProtocol {
|
||||||
|
// periphery: ignore
|
||||||
var isRunning: Bool { get }
|
var isRunning: Bool { get }
|
||||||
|
|
||||||
var crashedLastRun: Bool { get }
|
var crashedLastRun: Bool { get }
|
||||||
@ -62,8 +63,6 @@ protocol BugReportServiceProtocol {
|
|||||||
|
|
||||||
func reset()
|
func reset()
|
||||||
|
|
||||||
func crash()
|
|
||||||
|
|
||||||
func submitBugReport(_ bugReport: BugReport,
|
func submitBugReport(_ bugReport: BugReport,
|
||||||
progressListener: CurrentValueSubject<Double, Never>) async -> Result<SubmitBugReportResponse, BugReportServiceError>
|
progressListener: CurrentValueSubject<Double, Never>) async -> Result<SubmitBugReportResponse, BugReportServiceError>
|
||||||
}
|
}
|
||||||
|
@ -25,15 +25,17 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
private let appSettings: AppSettings
|
private let appSettings: AppSettings
|
||||||
private let networkMonitor: NetworkMonitorProtocol
|
private let networkMonitor: NetworkMonitorProtocol
|
||||||
|
|
||||||
private var sessionVerificationControllerProxy: SessionVerificationControllerProxy?
|
|
||||||
private let mediaLoader: MediaLoaderProtocol
|
private let mediaLoader: MediaLoaderProtocol
|
||||||
private let clientQueue: DispatchQueue
|
private let clientQueue: DispatchQueue
|
||||||
|
|
||||||
private var roomListService: RoomListService?
|
private var roomListService: RoomListService?
|
||||||
|
// periphery: ignore - only for retain
|
||||||
private var roomListStateUpdateTaskHandle: TaskHandle?
|
private var roomListStateUpdateTaskHandle: TaskHandle?
|
||||||
|
// periphery: ignore - only for retain
|
||||||
private var roomListStateLoadingStateUpdateTaskHandle: TaskHandle?
|
private var roomListStateLoadingStateUpdateTaskHandle: TaskHandle?
|
||||||
|
|
||||||
private var syncService: SyncService?
|
private var syncService: SyncService?
|
||||||
|
// periphery: ignore - only for retain
|
||||||
private var syncServiceStateUpdateTaskHandle: TaskHandle?
|
private var syncServiceStateUpdateTaskHandle: TaskHandle?
|
||||||
|
|
||||||
private var delegateHandle: TaskHandle?
|
private var delegateHandle: TaskHandle?
|
||||||
@ -49,8 +51,6 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
|
|
||||||
let secureBackupController: SecureBackupControllerProtocol
|
let secureBackupController: SecureBackupControllerProtocol
|
||||||
|
|
||||||
private let roomListRecencyOrderingAllowedEventTypes = ["m.room.message", "m.room.encrypted", "m.sticker"]
|
|
||||||
|
|
||||||
private static var roomCreationPowerLevelOverrides: PowerLevels {
|
private static var roomCreationPowerLevelOverrides: PowerLevels {
|
||||||
.init(usersDefault: nil,
|
.init(usersDefault: nil,
|
||||||
eventsDefault: nil,
|
eventsDefault: nil,
|
||||||
@ -79,7 +79,6 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
private var visibleRoomsListProxyStateObservationToken: AnyCancellable?
|
|
||||||
|
|
||||||
/// Will be `true` whilst the app cleans up and forces a logout. Prevents the sync service from restarting
|
/// Will be `true` whilst the app cleans up and forces a logout. Prevents the sync service from restarting
|
||||||
/// before the client is released which ends up running in a loop. This is a workaround until the sync service
|
/// before the client is released which ends up running in a loop. This is a workaround until the sync service
|
||||||
@ -413,18 +412,6 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func accountDataEvent<Content>(type: String) async -> Result<Content?, ClientProxyError> where Content: Decodable {
|
|
||||||
await Task.dispatch(on: clientQueue) {
|
|
||||||
.failure(.failedRetrievingAccountData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setAccountData<Content: Encodable>(content: Content, type: String) async -> Result<Void, ClientProxyError> {
|
|
||||||
await Task.dispatch(on: clientQueue) {
|
|
||||||
.failure(.failedSettingAccountData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func sessionVerificationControllerProxy() async -> Result<SessionVerificationControllerProxyProtocol, ClientProxyError> {
|
func sessionVerificationControllerProxy() async -> Result<SessionVerificationControllerProxyProtocol, ClientProxyError> {
|
||||||
await Task.dispatch(on: clientQueue) {
|
await Task.dispatch(on: clientQueue) {
|
||||||
do {
|
do {
|
||||||
|
@ -42,8 +42,6 @@ enum ClientProxyError: Error {
|
|||||||
case failedRetrievingUserDisplayName
|
case failedRetrievingUserDisplayName
|
||||||
case failedRetrievingUserAvatarURL
|
case failedRetrievingUserAvatarURL
|
||||||
case failedSettingUserDisplayName
|
case failedSettingUserDisplayName
|
||||||
case failedRetrievingAccountData
|
|
||||||
case failedSettingAccountData
|
|
||||||
case failedRetrievingSessionVerificationController
|
case failedRetrievingSessionVerificationController
|
||||||
case failedLoadingMedia
|
case failedLoadingMedia
|
||||||
case mediaFileError
|
case mediaFileError
|
||||||
@ -123,10 +121,6 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol {
|
|||||||
|
|
||||||
func removeUserAvatar() async -> Result<Void, ClientProxyError>
|
func removeUserAvatar() async -> Result<Void, ClientProxyError>
|
||||||
|
|
||||||
func accountDataEvent<Content: Decodable>(type: String) async -> Result<Content?, ClientProxyError>
|
|
||||||
|
|
||||||
func setAccountData<Content: Encodable>(content: Content, type: String) async -> Result<Void, ClientProxyError>
|
|
||||||
|
|
||||||
func sessionVerificationControllerProxy() async -> Result<SessionVerificationControllerProxyProtocol, ClientProxyError>
|
func sessionVerificationControllerProxy() async -> Result<SessionVerificationControllerProxyProtocol, ClientProxyError>
|
||||||
|
|
||||||
func logout() async -> URL?
|
func logout() async -> URL?
|
||||||
|
@ -117,14 +117,6 @@ class MockClientProxy: ClientProxyProtocol {
|
|||||||
.failure(.failedSettingUserAvatar)
|
.failure(.failedSettingUserAvatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
func accountDataEvent<Content>(type: String) async -> Result<Content?, ClientProxyError> where Content: Decodable {
|
|
||||||
.failure(.failedRetrievingAccountData)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setAccountData<Content>(content: Content, type: String) async -> Result<Void, ClientProxyError> where Content: Encodable {
|
|
||||||
.failure(.failedSettingAccountData)
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadMediaContentForSource(_ source: MediaSourceProxy) async throws -> Data {
|
func loadMediaContentForSource(_ source: MediaSourceProxy) async throws -> Data {
|
||||||
throw ClientProxyError.failedLoadingMedia
|
throw ClientProxyError.failedLoadingMedia
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ enum ElementCallWidgetDriverError: Error {
|
|||||||
|
|
||||||
enum ElementCallWidgetDriverAction {
|
enum ElementCallWidgetDriverAction {
|
||||||
case callEnded
|
case callEnded
|
||||||
case errorReceived(ElementCallWidgetDriverError)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sourcery: AutoMockable
|
// sourcery: AutoMockable
|
||||||
|
@ -25,5 +25,4 @@ struct EmojiItem: Equatable, Identifiable {
|
|||||||
let unicode: String
|
let unicode: String
|
||||||
let keywords: [String]
|
let keywords: [String]
|
||||||
let shortcodes: [String]
|
let shortcodes: [String]
|
||||||
let skins: [String]
|
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,5 @@ extension EmojiItem {
|
|||||||
label = emojibase.label
|
label = emojibase.label
|
||||||
shortcodes = emojibase.shortcodes
|
shortcodes = emojibase.shortcodes
|
||||||
keywords = emojibase.tags ?? []
|
keywords = emojibase.tags ?? []
|
||||||
skins = emojibase.skins?.map(\.unicode) ?? []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ extension NotificationManager: UNUserNotificationCenterDelegate {
|
|||||||
return [.badge, .sound, .list, .banner]
|
return [.badge, .sound, .list, .banner]
|
||||||
}
|
}
|
||||||
|
|
||||||
guard delegate.shouldDisplayInAppNotification(self, content: notification.request.content) else {
|
guard delegate.shouldDisplayInAppNotification(content: notification.request.content) else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,8 +245,7 @@ extension NotificationManager: UNUserNotificationCenterDelegate {
|
|||||||
content: response.notification.request.content,
|
content: response.notification.request.content,
|
||||||
replyText: response.userText)
|
replyText: response.userText)
|
||||||
case UNNotificationDefaultActionIdentifier:
|
case UNNotificationDefaultActionIdentifier:
|
||||||
await delegate?.notificationTapped(self,
|
await delegate?.notificationTapped(content: response.notification.request.content)
|
||||||
content: response.notification.request.content)
|
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,8 @@ import Foundation
|
|||||||
import UserNotifications
|
import UserNotifications
|
||||||
|
|
||||||
protocol NotificationManagerDelegate: AnyObject {
|
protocol NotificationManagerDelegate: AnyObject {
|
||||||
func shouldDisplayInAppNotification(_ service: NotificationManagerProtocol,
|
func shouldDisplayInAppNotification(content: UNNotificationContent) -> Bool
|
||||||
content: UNNotificationContent) -> Bool
|
func notificationTapped(content: UNNotificationContent) async
|
||||||
func notificationTapped(_ service: NotificationManagerProtocol,
|
|
||||||
content: UNNotificationContent) async
|
|
||||||
func handleInlineReply(_ service: NotificationManagerProtocol,
|
func handleInlineReply(_ service: NotificationManagerProtocol,
|
||||||
content: UNNotificationContent,
|
content: UNNotificationContent,
|
||||||
replyText: String) async
|
replyText: String) async
|
||||||
|
@ -16,4 +16,5 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
// periphery: ignore - markdown protocol
|
||||||
protocol DecorationTimelineItemProtocol: RoomTimelineItemProtocol { }
|
protocol DecorationTimelineItemProtocol: RoomTimelineItemProtocol { }
|
||||||
|
@ -38,13 +38,4 @@ class CreateRoomScreenUITests: XCTestCase {
|
|||||||
app.textFields[A11yIdentifiers.createRoomScreen.roomName].typeText("\n")
|
app.textFields[A11yIdentifiers.createRoomScreen.roomName].typeText("\n")
|
||||||
try await app.assertScreenshot(.createRoom, step: 1)
|
try await app.assertScreenshot(.createRoom, step: 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disabled because tapping on the textView doesn't work
|
|
||||||
func disabled_testLongInputTopicText() async throws {
|
|
||||||
let app = Application.launch(.createRoom)
|
|
||||||
let textView = app.textViews[A11yIdentifiers.createRoomScreen.roomTopic]
|
|
||||||
textView.tap()
|
|
||||||
textView.typeText(.init(repeating: "Topic\n", count: 3))
|
|
||||||
try await app.assertScreenshot(.createRoom, step: 2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -624,7 +624,7 @@ class AttributedStringBuilderTests: XCTestCase {
|
|||||||
XCTFail("Couldn't find expected value.")
|
XCTFail("Couldn't find expected value.")
|
||||||
}
|
}
|
||||||
|
|
||||||
private func checkAttachment(attributedString: AttributedString?, expectedRuns: Int, expectedAttachments: Int = 1) {
|
private func checkAttachment(attributedString: AttributedString?, expectedRuns: Int) {
|
||||||
guard let attributedString else {
|
guard let attributedString else {
|
||||||
XCTFail("Could not build the attributed string")
|
XCTFail("Could not build the attributed string")
|
||||||
return
|
return
|
||||||
|
@ -31,9 +31,6 @@ class AudioPlayerStateTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var audioPlayerSeekCallsSubject: PassthroughSubject<Double, Never>!
|
private var audioPlayerSeekCallsSubject: PassthroughSubject<Double, Never>!
|
||||||
private var audioPlayerSeekCalls: AnyPublisher<Double, Never> {
|
|
||||||
audioPlayerSeekCallsSubject.eraseToAnyPublisher()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func buildAudioPlayerMock() -> AudioPlayerMock {
|
private func buildAudioPlayerMock() -> AudioPlayerMock {
|
||||||
let audioPlayerMock = AudioPlayerMock()
|
let audioPlayerMock = AudioPlayerMock()
|
||||||
@ -115,7 +112,7 @@ class AudioPlayerStateTests: XCTestCase {
|
|||||||
|
|
||||||
func testReportError() async throws {
|
func testReportError() async throws {
|
||||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||||
audioPlayerState.reportError(AudioPlayerError.genericError)
|
audioPlayerState.reportError()
|
||||||
XCTAssertEqual(audioPlayerState.playbackState, .error)
|
XCTAssertEqual(audioPlayerState.playbackState, .error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ class AudioRecorderStateTests: XCTestCase {
|
|||||||
|
|
||||||
func testReportError() async throws {
|
func testReportError() async throws {
|
||||||
XCTAssertEqual(audioRecorderState.recordingState, .stopped)
|
XCTAssertEqual(audioRecorderState.recordingState, .stopped)
|
||||||
audioRecorderState.reportError(AudioRecorderError.audioEngineFailure)
|
audioRecorderState.reportError()
|
||||||
XCTAssertEqual(audioRecorderState.recordingState, .error)
|
XCTAssertEqual(audioRecorderState.recordingState, .error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,12 +21,13 @@ import Foundation
|
|||||||
import XCTest
|
import XCTest
|
||||||
|
|
||||||
class BugReportServiceTests: XCTestCase {
|
class BugReportServiceTests: XCTestCase {
|
||||||
var bugReportService: BugReportServiceMock!
|
var bugReportService: BugReportServiceProtocol!
|
||||||
|
|
||||||
override func setUpWithError() throws {
|
override func setUpWithError() throws {
|
||||||
bugReportService = BugReportServiceMock()
|
let bugReportServiceMock = BugReportServiceMock()
|
||||||
bugReportService.underlyingCrashedLastRun = false
|
bugReportServiceMock.underlyingCrashedLastRun = false
|
||||||
bugReportService.submitBugReportProgressListenerReturnValue = .success(SubmitBugReportResponse(reportUrl: "https://www.example.com/123"))
|
bugReportServiceMock.submitBugReportProgressListenerReturnValue = .success(SubmitBugReportResponse(reportUrl: "https://www.example.com/123"))
|
||||||
|
bugReportService = bugReportServiceMock
|
||||||
}
|
}
|
||||||
|
|
||||||
func testInitialStateWithMockService() {
|
func testInitialStateWithMockService() {
|
||||||
|
@ -21,7 +21,7 @@ import XCTest
|
|||||||
@MainActor
|
@MainActor
|
||||||
final class EmojiProviderTests: XCTestCase {
|
final class EmojiProviderTests: XCTestCase {
|
||||||
func testWhenEmojisLoadedCategoriesAreLoadedFromLoader() async throws {
|
func testWhenEmojisLoadedCategoriesAreLoadedFromLoader() async throws {
|
||||||
let item = EmojiItem(label: "test", unicode: "test", keywords: ["1", "2"], shortcodes: ["1", "2"], skins: ["🙂"])
|
let item = EmojiItem(label: "test", unicode: "test", keywords: ["1", "2"], shortcodes: ["1", "2"])
|
||||||
let category = EmojiCategory(id: "test", emojis: [item])
|
let category = EmojiCategory(id: "test", emojis: [item])
|
||||||
|
|
||||||
let emojiLoaderMock = EmojiLoaderMock()
|
let emojiLoaderMock = EmojiLoaderMock()
|
||||||
@ -34,7 +34,7 @@ final class EmojiProviderTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testWhenEmojisLoadedAndSearchStringEmptyAllCategoriesReturned() async throws {
|
func testWhenEmojisLoadedAndSearchStringEmptyAllCategoriesReturned() async throws {
|
||||||
let item = EmojiItem(label: "test", unicode: "test", keywords: ["1", "2"], shortcodes: ["1", "2"], skins: ["🙂"])
|
let item = EmojiItem(label: "test", unicode: "test", keywords: ["1", "2"], shortcodes: ["1", "2"])
|
||||||
let category = EmojiCategory(id: "test", emojis: [item])
|
let category = EmojiCategory(id: "test", emojis: [item])
|
||||||
|
|
||||||
let emojiLoaderMock = EmojiLoaderMock()
|
let emojiLoaderMock = EmojiLoaderMock()
|
||||||
@ -47,8 +47,8 @@ final class EmojiProviderTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testWhenEmojisLoadedSecondTimeCachedValuesAreUsed() async throws {
|
func testWhenEmojisLoadedSecondTimeCachedValuesAreUsed() async throws {
|
||||||
let item = EmojiItem(label: "test", unicode: "test", keywords: ["1", "2"], shortcodes: ["1", "2"], skins: ["🙂"])
|
let item = EmojiItem(label: "test", unicode: "test", keywords: ["1", "2"], shortcodes: ["1", "2"])
|
||||||
let item2 = EmojiItem(label: "test2", unicode: "test2", keywords: ["3", "4"], shortcodes: ["3", "4"], skins: ["🙂"])
|
let item2 = EmojiItem(label: "test2", unicode: "test2", keywords: ["3", "4"], shortcodes: ["3", "4"])
|
||||||
let categoriesForFirstLoad = [EmojiCategory(id: "test",
|
let categoriesForFirstLoad = [EmojiCategory(id: "test",
|
||||||
emojis: [item])]
|
emojis: [item])]
|
||||||
let categoriesForSecondLoad = [EmojiCategory(id: "test2",
|
let categoriesForSecondLoad = [EmojiCategory(id: "test2",
|
||||||
@ -69,12 +69,12 @@ final class EmojiProviderTests: XCTestCase {
|
|||||||
func testWhenEmojisSearchedCorrectNumberOfCategoriesReturned() async throws {
|
func testWhenEmojisSearchedCorrectNumberOfCategoriesReturned() async throws {
|
||||||
let searchString = "smile"
|
let searchString = "smile"
|
||||||
var categories = [EmojiCategory]()
|
var categories = [EmojiCategory]()
|
||||||
let item0WithSearchString = EmojiItem(label: "emoji0", unicode: "\(searchString)_123", keywords: ["key1", "key1"], shortcodes: ["key1", "key1"], skins: ["🙂"])
|
let item0WithSearchString = EmojiItem(label: "emoji0", unicode: "\(searchString)_123", keywords: ["key1", "key1"], shortcodes: ["key1", "key1"])
|
||||||
let item1WithSearchString = EmojiItem(label: searchString, unicode: "emoji1", keywords: ["key1", "key1"], shortcodes: ["key1", "key1"], skins: ["🙂"])
|
let item1WithSearchString = EmojiItem(label: searchString, unicode: "emoji1", keywords: ["key1", "key1"], shortcodes: ["key1", "key1"])
|
||||||
let item2WithSearchString = EmojiItem(label: "emoji_2", unicode: "emoji_2", keywords: ["key1", "\(searchString)_123"], shortcodes: ["key1", "key2"], skins: ["🙂"])
|
let item2WithSearchString = EmojiItem(label: "emoji_2", unicode: "emoji_2", keywords: ["key1", "\(searchString)_123"], shortcodes: ["key1", "key2"])
|
||||||
let item3WithSearchString = EmojiItem(label: "emoji_2", unicode: "emoji_2", keywords: ["key1", "key1"], shortcodes: ["key1", "\(searchString)_123"], skins: ["🙂"])
|
let item3WithSearchString = EmojiItem(label: "emoji_2", unicode: "emoji_2", keywords: ["key1", "key1"], shortcodes: ["key1", "\(searchString)_123"])
|
||||||
let item4WithoutSearchString = EmojiItem(label: "emoji_3", unicode: "emoji_3", keywords: ["key1", "key1"], shortcodes: ["key1", "key1"], skins: ["🙂"])
|
let item4WithoutSearchString = EmojiItem(label: "emoji_3", unicode: "emoji_3", keywords: ["key1", "key1"], shortcodes: ["key1", "key1"])
|
||||||
let item5WithSearchString = EmojiItem(label: "emoji0", unicode: "\(searchString)_123", keywords: ["key1", "key1"], shortcodes: ["key1", "key1"], skins: ["🙂"])
|
let item5WithSearchString = EmojiItem(label: "emoji0", unicode: "\(searchString)_123", keywords: ["key1", "key1"], shortcodes: ["key1", "key1"])
|
||||||
categories.append(EmojiCategory(id: "test",
|
categories.append(EmojiCategory(id: "test",
|
||||||
emojis: [item0WithSearchString,
|
emojis: [item0WithSearchString,
|
||||||
item1WithSearchString,
|
item1WithSearchString,
|
||||||
|
@ -32,10 +32,8 @@ class HomeScreenViewModelTests: XCTestCase {
|
|||||||
viewModel = HomeScreenViewModel(userSession: MockUserSession(clientProxy: clientProxy,
|
viewModel = HomeScreenViewModel(userSession: MockUserSession(clientProxy: clientProxy,
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock()),
|
voiceMessageMediaManager: VoiceMessageMediaManagerMock()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder()),
|
|
||||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||||
appSettings: ServiceLocator.shared.settings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
analytics: ServiceLocator.shared.analytics,
|
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,11 +246,11 @@ extension NotificationManagerTests: NotificationManagerDelegate {
|
|||||||
authorizationStatusWasGranted = false
|
authorizationStatusWasGranted = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldDisplayInAppNotification(_ service: ElementX.NotificationManagerProtocol, content: UNNotificationContent) -> Bool {
|
func shouldDisplayInAppNotification(content: UNNotificationContent) -> Bool {
|
||||||
shouldDisplayInAppNotificationReturnValue
|
shouldDisplayInAppNotificationReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func notificationTapped(_ service: ElementX.NotificationManagerProtocol, content: UNNotificationContent) async {
|
func notificationTapped(content: UNNotificationContent) async {
|
||||||
notificationTappedDelegateCalled = true
|
notificationTappedDelegateCalled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user