mirror of
https://github.com/element-hq/element-x-ios.git
synced 2025-03-10 13:37:11 +00:00
Removing Dead Code part 1 (#2234)
This commit is contained in:
parent
09b276d94b
commit
d99d26fcdc
@ -12,7 +12,7 @@ targets:
|
||||
- UITests
|
||||
- UnitTests
|
||||
report_exclude:
|
||||
# includes subscript which is not detectable: https://github.com/apple/swift/issues/56541
|
||||
- ElementX/Sources/Screens/Settings/AvancedOptionsScreen/AdvancedSettingsScreenModels.swift
|
||||
- ElementX/Sources/Mocks/Generated/GeneratedMocks.swift
|
||||
- ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift
|
||||
verbose: true
|
||||
retain_swift_ui_previews: true
|
||||
|
@ -315,7 +315,6 @@
|
||||
50539366B408780B232C1910 /* EstimatedWaveformView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD0FF64B0E6470F66F42E182 /* EstimatedWaveformView.swift */; };
|
||||
50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.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 */; };
|
||||
51C240F4660F7269203A9B3A /* MigrationScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75910F5A36EA8FF9BAD08D18 /* MigrationScreenUITests.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 */; };
|
||||
D871C8CF46950F959C9A62C3 /* WelcomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C54464351F170D570110AFCA /* WelcomeScreen.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 */; };
|
||||
D98B5EE8C4F5A2CE84687AE8 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -1243,7 +1240,6 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -2511,7 +2507,6 @@
|
||||
CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */,
|
||||
C1FA515B3B0D61EF1E907D2D /* BadgeView.swift */,
|
||||
8CC23C63849452BC86EA2852 /* ButtonStyle.swift */,
|
||||
0960A7F5C1B0B6679BDF26F9 /* ElementToggleStyle.swift */,
|
||||
7EC2F1622C5BBABED6012E12 /* HeroImage.swift */,
|
||||
B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */,
|
||||
C352359663A0E52BA20761EE /* LoadableImage.swift */,
|
||||
@ -4267,7 +4262,6 @@
|
||||
B81B6170DB690013CEB646F4 /* MapLibreModels.swift */,
|
||||
592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */,
|
||||
E062C1750EFC8627DE4CAB8E /* MapTilerAuthorization.swift */,
|
||||
33720F7AD25E85E4A84669E8 /* MapTilerGeocoding.swift */,
|
||||
C23B3FAD8B23C421BC0D1B1E /* MapTilerGeoCodingServiceProtocol.swift */,
|
||||
1A4D29F2683F5772AC72406F /* MapTilerStaticMap.swift */,
|
||||
20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */,
|
||||
@ -5490,7 +5484,6 @@
|
||||
FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */,
|
||||
07CC13C5729C24255348CBBD /* ElementCallWidgetDriver.swift in Sources */,
|
||||
370AF5BFCD4384DD455479B6 /* ElementCallWidgetDriverProtocol.swift in Sources */,
|
||||
D8CFF02C2730EE5BC4F17ABF /* ElementToggleStyle.swift in Sources */,
|
||||
7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */,
|
||||
7361B011A79BF723D8C9782B /* EmojiCategory.swift in Sources */,
|
||||
E45C9FA22BC13B477FD3B4AC /* EmojiDetection.swift in Sources */,
|
||||
@ -5598,7 +5591,6 @@
|
||||
D181AC8FF236B7F91C0A8C28 /* MapTiler.swift in Sources */,
|
||||
FCDA202B246F75BA28E10C5F /* MapTilerAuthorization.swift in Sources */,
|
||||
7ABAB3A1D52B86FACF2F74CF /* MapTilerGeoCodingServiceProtocol.swift in Sources */,
|
||||
516534FC5C893D57F169D5A8 /* MapTilerGeocoding.swift in Sources */,
|
||||
D6661A94DBD97658B2ADBD6A /* MapTilerStaticMap.swift in Sources */,
|
||||
7B5DAB915357BE596529BF25 /* MapTilerStaticMapProtocol.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 let appLockFlowCoordinator: AppLockFlowCoordinator
|
||||
// periphery:ignore - used to avoid deallocation
|
||||
private var appLockSetupFlowCoordinator: AppLockSetupFlowCoordinator?
|
||||
private var userSessionFlowCoordinator: UserSessionFlowCoordinator?
|
||||
private var softLogoutCoordinator: SoftLogoutScreenCoordinator?
|
||||
@ -90,7 +91,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
||||
|
||||
navigationRootCoordinator = NavigationRootCoordinator()
|
||||
|
||||
Self.setupServiceLocator(navigationRootCoordinator: navigationRootCoordinator, appSettings: appSettings)
|
||||
Self.setupServiceLocator(appSettings: appSettings)
|
||||
|
||||
ServiceLocator.shared.analytics.startIfEnabled()
|
||||
|
||||
@ -209,9 +210,9 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
||||
|
||||
// MARK: - AuthenticationCoordinatorDelegate
|
||||
|
||||
func authenticationCoordinator(_ authenticationCoordinator: AuthenticationCoordinator, didLoginWithSession userSession: UserSessionProtocol) {
|
||||
func authenticationCoordinator(didLoginWithSession userSession: UserSessionProtocol) {
|
||||
self.userSession = userSession
|
||||
self.authenticationCoordinator = nil
|
||||
authenticationCoordinator = nil
|
||||
stateMachine.processEvent(.createdUserSession)
|
||||
}
|
||||
|
||||
@ -232,7 +233,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
||||
UIApplication.shared.unregisterForRemoteNotifications()
|
||||
}
|
||||
|
||||
func shouldDisplayInAppNotification(_ service: NotificationManagerProtocol, content: UNNotificationContent) -> Bool {
|
||||
func shouldDisplayInAppNotification(content: UNNotificationContent) -> Bool {
|
||||
guard let roomID = content.roomID else {
|
||||
return true
|
||||
}
|
||||
@ -243,7 +244,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
||||
return !userSessionFlowCoordinator.isDisplayingRoomScreen(withRoomID: roomID)
|
||||
}
|
||||
|
||||
func notificationTapped(_ service: NotificationManagerProtocol, content: UNNotificationContent) async {
|
||||
func notificationTapped(content: UNNotificationContent) async {
|
||||
MXLog.info("[AppCoordinator] tappedNotification")
|
||||
|
||||
guard let roomID = content.roomID,
|
||||
@ -284,7 +285,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
||||
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(appSettings: appSettings)
|
||||
ServiceLocator.shared.register(networkMonitor: NetworkMonitor())
|
||||
|
@ -17,7 +17,6 @@
|
||||
import Foundation
|
||||
|
||||
protocol AppCoordinatorProtocol: CoordinatorProtocol {
|
||||
var notificationManager: NotificationManagerProtocol { get }
|
||||
var windowManager: WindowManager { get }
|
||||
@discardableResult func handleDeepLink(_ url: URL) -> Bool
|
||||
}
|
||||
|
@ -87,8 +87,6 @@ final class AppSettings {
|
||||
@UserPreference(key: UserDefaultsKeys.lastVersionLaunched, storageType: .userDefaults(store))
|
||||
var lastVersionLaunched: String?
|
||||
|
||||
let lastLaunchDate = Date()
|
||||
|
||||
/// 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.
|
||||
@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"
|
||||
// Use the name allocated by the bug report server
|
||||
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.
|
||||
let bugReportMaxUploadSize = 50 * 1024 * 1024
|
||||
|
||||
@ -257,9 +254,6 @@ final class AppSettings {
|
||||
// maptiler api key
|
||||
let mapTilerApiKey = InfoPlistReader.main.mapLibreAPIKey
|
||||
|
||||
// maptiler geocoding url
|
||||
let geocodingURLFormatString = "https://api.maptiler.com/geocoding/%f,%f.json"
|
||||
|
||||
// MARK: - Feature Flags
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.userSuggestionsEnabled, defaultValue: false, storageType: .volatile)
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
// periphery:ignore - markdown protocol
|
||||
@MainActor
|
||||
protocol FlowCoordinatorProtocol {
|
||||
func handleAppRoute(_ appRoute: AppRoute, animated: Bool)
|
||||
|
@ -83,8 +83,6 @@ class AppLockFlowCoordinator: CoordinatorProtocol {
|
||||
|
||||
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> = []
|
||||
|
||||
/// 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 attachment = ImageAsset(name: "images/attachment")
|
||||
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 bulletList = ImageAsset(name: "images/bullet-list")
|
||||
internal static let closeRte = ImageAsset(name: "images/close-rte")
|
||||
|
@ -45,18 +45,6 @@ extension ApplicationMock {
|
||||
underlyingApplicationState = applicationState
|
||||
underlyingBackgroundTimeRemaining = backgroundTimeRemaining
|
||||
|
||||
beginBackgroundTaskExpirationHandlerClosure = { [weak self] handler in
|
||||
guard let self else {
|
||||
return .invalid
|
||||
}
|
||||
|
||||
guard allowTasks else {
|
||||
return .invalid
|
||||
}
|
||||
|
||||
return beginBackgroundTask(withName: nil, expirationHandler: handler)
|
||||
}
|
||||
|
||||
beginBackgroundTaskWithNameExpirationHandlerClosure = { _, handler in
|
||||
guard allowTasks else {
|
||||
return .invalid
|
||||
|
@ -56,18 +56,6 @@ class AnalyticsClientMock: AnalyticsClientProtocol {
|
||||
stopCallsCount += 1
|
||||
stopClosure?()
|
||||
}
|
||||
//MARK: - flush
|
||||
|
||||
var flushCallsCount = 0
|
||||
var flushCalled: Bool {
|
||||
return flushCallsCount > 0
|
||||
}
|
||||
var flushClosure: (() -> Void)?
|
||||
|
||||
func flush() {
|
||||
flushCallsCount += 1
|
||||
flushClosure?()
|
||||
}
|
||||
//MARK: - capture
|
||||
|
||||
var captureCallsCount = 0
|
||||
@ -100,22 +88,6 @@ class AnalyticsClientMock: AnalyticsClientProtocol {
|
||||
screenReceivedInvocations.append(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 {
|
||||
var isMandatory: Bool {
|
||||
@ -323,23 +295,6 @@ class ApplicationMock: ApplicationProtocol {
|
||||
|
||||
//MARK: - beginBackgroundTask
|
||||
|
||||
var beginBackgroundTaskExpirationHandlerCallsCount = 0
|
||||
var beginBackgroundTaskExpirationHandlerCalled: Bool {
|
||||
return beginBackgroundTaskExpirationHandlerCallsCount > 0
|
||||
}
|
||||
var beginBackgroundTaskExpirationHandlerReturnValue: UIBackgroundTaskIdentifier!
|
||||
var beginBackgroundTaskExpirationHandlerClosure: (((() -> Void)?) -> UIBackgroundTaskIdentifier)?
|
||||
|
||||
func beginBackgroundTask(expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier {
|
||||
beginBackgroundTaskExpirationHandlerCallsCount += 1
|
||||
if let beginBackgroundTaskExpirationHandlerClosure = beginBackgroundTaskExpirationHandlerClosure {
|
||||
return beginBackgroundTaskExpirationHandlerClosure(handler)
|
||||
} else {
|
||||
return beginBackgroundTaskExpirationHandlerReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - beginBackgroundTask
|
||||
|
||||
var beginBackgroundTaskWithNameExpirationHandlerCallsCount = 0
|
||||
var beginBackgroundTaskWithNameExpirationHandlerCalled: Bool {
|
||||
return beginBackgroundTaskWithNameExpirationHandlerCallsCount > 0
|
||||
@ -739,18 +694,6 @@ class BugReportServiceMock: BugReportServiceProtocol {
|
||||
resetCallsCount += 1
|
||||
resetClosure?()
|
||||
}
|
||||
//MARK: - crash
|
||||
|
||||
var crashCallsCount = 0
|
||||
var crashCalled: Bool {
|
||||
return crashCallsCount > 0
|
||||
}
|
||||
var crashClosure: (() -> Void)?
|
||||
|
||||
func crash() {
|
||||
crashCallsCount += 1
|
||||
crashClosure?()
|
||||
}
|
||||
//MARK: - submitBugReport
|
||||
|
||||
var submitBugReportProgressListenerCallsCount = 0
|
||||
|
@ -106,10 +106,6 @@ enum RoomAvatarSizeOnScreen {
|
||||
}
|
||||
|
||||
extension AvatarSize {
|
||||
var size: CGSize {
|
||||
CGSize(width: value, height: value)
|
||||
}
|
||||
|
||||
var scaledSize: CGSize {
|
||||
CGSize(width: scaledValue, height: scaledValue)
|
||||
}
|
||||
|
@ -130,12 +130,6 @@ private extension String {
|
||||
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 {
|
||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
||||
let end = index(startIndex, offsetBy: bounds.upperBound)
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
// periphery:ignore - property wrappers generate false positives
|
||||
@propertyWrapper
|
||||
struct CancellableTask<S: Sendable, F: Error> {
|
||||
private var storedValue: Task<S, F>?
|
||||
|
@ -47,18 +47,18 @@ struct CollapsibleReactionLayout: Layout {
|
||||
rows: collapsedRows,
|
||||
collapseButton: subviewsByType.collapseButton,
|
||||
addMoreButton: subviewsByType.addMoreButton)
|
||||
let size = sizeThatFits(proposal: proposal, rows: collapsedRowsWithButtons)
|
||||
let size = sizeThatFits(rows: collapsedRowsWithButtons)
|
||||
return size
|
||||
} else {
|
||||
// Show all subviews with the button at the end
|
||||
var rowsWithButtons = calculateRows(proposal: proposal, subviews: Array(subviews))
|
||||
ensureCollapseAndAddMoreButtonsAreOnTheSameRow(&rowsWithButtons)
|
||||
let size = sizeThatFits(proposal: proposal, rows: rowsWithButtons)
|
||||
let size = sizeThatFits(rows: rowsWithButtons)
|
||||
return size
|
||||
}
|
||||
} else {
|
||||
// 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
|
||||
/// - rows: The list of 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
|
||||
row.map { subview in
|
||||
subview.sizeThatFits(.unspecified)
|
||||
|
@ -31,6 +31,18 @@ extension View {
|
||||
})
|
||||
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.
|
||||
|
@ -73,13 +73,3 @@ extension Array where Element == RoomTimelineItemProtocol {
|
||||
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)
|
||||
}
|
||||
|
||||
// periphery: ignore - not used yet but might be useful
|
||||
func confirmationDialog<Item, Actions, Message>(item: Binding<Item?>,
|
||||
titleVisibility: Visibility = .automatic,
|
||||
@ViewBuilder actions: (Item) -> Actions,
|
||||
|
@ -21,9 +21,3 @@ extension MapTilerStyleBuilder {
|
||||
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 temporaryBlockquoteMarkingColor = UIColor.magenta
|
||||
private let temporaryCodeBlockMarkingColor = UIColor.cyan
|
||||
private let linkColor = UIColor.blue
|
||||
private let permalinkBaseURL: URL
|
||||
private let mentionBuilder: MentionBuilderProtocol
|
||||
|
||||
@ -33,10 +32,6 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
||||
caches.removeAll()
|
||||
}
|
||||
|
||||
static func invalidateCache(for key: String = defaultKey) {
|
||||
caches[key]?.removeAllValues()
|
||||
}
|
||||
|
||||
init(cacheKey: String = defaultKey, permalinkBaseURL: URL, mentionBuilder: MentionBuilderProtocol) {
|
||||
self.cacheKey = cacheKey
|
||||
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
|
||||
// webview.
|
||||
func fromHTML(_ htmlString: String?) -> AttributedString? {
|
||||
guard var originalHTMLString = htmlString else {
|
||||
guard let originalHTMLString = htmlString else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -18,27 +18,27 @@ import Foundation
|
||||
|
||||
enum BlockquoteAttribute: AttributedStringKey {
|
||||
typealias Value = Bool
|
||||
public static var name = "MXBlockquoteAttribute"
|
||||
static var name = "MXBlockquoteAttribute"
|
||||
}
|
||||
|
||||
enum UserIDAttribute: AttributedStringKey {
|
||||
typealias Value = String
|
||||
public static var name = "MXUserIDAttribute"
|
||||
static var name = "MXUserIDAttribute"
|
||||
}
|
||||
|
||||
enum RoomIDAttribute: AttributedStringKey {
|
||||
typealias Value = String
|
||||
public static var name = "MXRoomIDAttribute"
|
||||
static var name = "MXRoomIDAttribute"
|
||||
}
|
||||
|
||||
enum RoomAliasAttribute: AttributedStringKey {
|
||||
typealias Value = String
|
||||
public static var name = "MXRoomAliasAttribute"
|
||||
static var name = "MXRoomAliasAttribute"
|
||||
}
|
||||
|
||||
enum AllUsersMentionAttribute: AttributedStringKey {
|
||||
typealias Value = Bool
|
||||
public static var name = "MXAllUsersMentionAttribute"
|
||||
static var name = "MXAllUsersMentionAttribute"
|
||||
}
|
||||
|
||||
struct EventIDAttributeValue: Hashable {
|
||||
@ -48,9 +48,10 @@ struct EventIDAttributeValue: Hashable {
|
||||
|
||||
enum EventIDAttribute: AttributedStringKey {
|
||||
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 {
|
||||
struct ElementXAttributes: AttributeScope {
|
||||
let blockquote: BlockquoteAttribute
|
||||
@ -69,6 +70,7 @@ extension AttributeScopes {
|
||||
var elementX: ElementXAttributes.Type { ElementXAttributes.self }
|
||||
}
|
||||
|
||||
// periphery: ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
|
||||
extension AttributeDynamicLookup {
|
||||
subscript<T: AttributedStringKey>(dynamicMember keyPath: KeyPath<AttributeScopes.ElementXAttributes, T>) -> T {
|
||||
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:
|
||||
/// - animation: Animation
|
||||
/// - 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)
|
||||
}
|
||||
|
@ -79,11 +79,8 @@ struct ShimmerOverlay_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = HomeScreenViewModel(userSession: MockUserSession(clientProxy: MockClientProxy(userID: ""),
|
||||
mediaProvider: MockMediaProvider(),
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock()),
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
||||
mentionBuilder: MentionBuilder()),
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
static var previews: some View {
|
||||
|
@ -27,7 +27,11 @@ struct CustomLayoutLabelStyle: LabelStyle {
|
||||
let spacing: CGFloat
|
||||
var alignment: VerticalAlignment
|
||||
|
||||
enum IconLayout { case leading, trailing }
|
||||
enum IconLayout {
|
||||
case leading
|
||||
case trailing
|
||||
}
|
||||
|
||||
var iconLayout: IconLayout
|
||||
|
||||
fileprivate init(spacing: CGFloat, alignment: VerticalAlignment, iconLayout: IconLayout) {
|
||||
@ -38,10 +42,11 @@ struct CustomLayoutLabelStyle: LabelStyle {
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
HStack(alignment: alignment, spacing: spacing) {
|
||||
if iconLayout == .leading {
|
||||
switch iconLayout {
|
||||
case .leading:
|
||||
configuration.icon
|
||||
configuration.title
|
||||
} else {
|
||||
case .trailing:
|
||||
configuration.title
|
||||
configuration.icon
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ struct AppActivityView: UIViewControllerRepresentable {
|
||||
private var onCancel: (() -> Void)?
|
||||
private var onComplete: CompletionType?
|
||||
|
||||
public init(activityItems: [Any],
|
||||
init(activityItems: [Any],
|
||||
applicationActivities: [UIActivity]? = nil,
|
||||
excludedActivityTypes: [UIActivity.ActivityType] = [],
|
||||
onCancel: (() -> Void)? = nil,
|
||||
@ -38,7 +38,7 @@ struct AppActivityView: UIViewControllerRepresentable {
|
||||
self.onComplete = onComplete
|
||||
}
|
||||
|
||||
public func makeUIViewController(context: Context) -> UIViewControllerType {
|
||||
func makeUIViewController(context: Context) -> UIViewControllerType {
|
||||
let viewController = UIViewControllerType(activityItems: activityItems, applicationActivities: applicationActivities)
|
||||
viewController.excludedActivityTypes = excludedActivityTypes
|
||||
|
||||
@ -57,9 +57,9 @@ struct AppActivityView: UIViewControllerRepresentable {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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 linePadding: CGFloat = 2
|
||||
var waveform: EstimatedWaveform
|
||||
private let minimumGraphAmplitude: CGFloat = 1
|
||||
var progress: CGFloat = 0.0
|
||||
|
||||
@State private var normalizedWaveformData: [Float] = []
|
||||
|
@ -30,7 +30,6 @@ enum AppLockScreenCoordinatorAction {
|
||||
}
|
||||
|
||||
final class AppLockScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: AppLockScreenCoordinatorParameters
|
||||
private var viewModel: AppLockScreenViewModelProtocol
|
||||
private let actionsSubject: PassthroughSubject<AppLockScreenCoordinatorAction, Never> = .init()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
@ -40,8 +39,6 @@ final class AppLockScreenCoordinator: CoordinatorProtocol {
|
||||
}
|
||||
|
||||
init(parameters: AppLockScreenCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
|
||||
viewModel = AppLockScreenViewModel(appLockService: parameters.appLockService)
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@ enum AppLockSetupBiometricsScreenCoordinatorAction {
|
||||
}
|
||||
|
||||
final class AppLockSetupBiometricsScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: AppLockSetupBiometricsScreenCoordinatorParameters
|
||||
private var viewModel: AppLockSetupBiometricsScreenViewModelProtocol
|
||||
private let actionsSubject: PassthroughSubject<AppLockSetupBiometricsScreenCoordinatorAction, Never> = .init()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
@ -36,8 +35,6 @@ final class AppLockSetupBiometricsScreenCoordinator: CoordinatorProtocol {
|
||||
}
|
||||
|
||||
init(parameters: AppLockSetupBiometricsScreenCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
|
||||
viewModel = AppLockSetupBiometricsScreenViewModel(appLockService: parameters.appLockService)
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,6 @@ enum AppLockSetupPINScreenCoordinatorAction {
|
||||
}
|
||||
|
||||
final class AppLockSetupPINScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: AppLockSetupPINScreenCoordinatorParameters
|
||||
private var viewModel: AppLockSetupPINScreenViewModelProtocol
|
||||
private let actionsSubject: PassthroughSubject<AppLockSetupPINScreenCoordinatorAction, Never> = .init()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
@ -48,7 +47,6 @@ final class AppLockSetupPINScreenCoordinator: CoordinatorProtocol {
|
||||
init(parameters: AppLockSetupPINScreenCoordinatorParameters) {
|
||||
guard parameters.initialMode != .confirm else { fatalError(".confirm is an invalid initial mode") }
|
||||
|
||||
self.parameters = parameters
|
||||
viewModel = AppLockSetupPINScreenViewModel(initialMode: parameters.initialMode,
|
||||
isMandatory: parameters.isMandatory,
|
||||
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.
|
||||
.sink { [weak self] pinCode in
|
||||
guard pinCode.count == 4 else { return }
|
||||
self?.submit(pinCode)
|
||||
self?.submit()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
@ -64,7 +64,7 @@ class AppLockSetupPINScreenViewModel: AppLockSetupPINScreenViewModelType, AppLoc
|
||||
// MARK: - Private
|
||||
|
||||
/// Handle the entered PIN code.
|
||||
private func submit(_ pinCode: String) {
|
||||
private func submit() {
|
||||
switch state.mode {
|
||||
case .create:
|
||||
createPIN()
|
||||
|
@ -29,7 +29,6 @@ enum AppLockSetupSettingsScreenCoordinatorAction {
|
||||
}
|
||||
|
||||
final class AppLockSetupSettingsScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: AppLockSetupSettingsScreenCoordinatorParameters
|
||||
private var viewModel: AppLockSetupSettingsScreenViewModelProtocol
|
||||
private let actionsSubject: PassthroughSubject<AppLockSetupSettingsScreenCoordinatorAction, Never> = .init()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
@ -39,8 +38,6 @@ final class AppLockSetupSettingsScreenCoordinator: CoordinatorProtocol {
|
||||
}
|
||||
|
||||
init(parameters: AppLockSetupSettingsScreenCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
|
||||
viewModel = AppLockSetupSettingsScreenViewModel(appLockService: parameters.appLockService)
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,7 @@ import SwiftUI
|
||||
|
||||
@MainActor
|
||||
protocol AuthenticationCoordinatorDelegate: AnyObject {
|
||||
func authenticationCoordinator(_ authenticationCoordinator: AuthenticationCoordinator,
|
||||
didLoginWithSession userSession: UserSessionProtocol)
|
||||
func authenticationCoordinator(didLoginWithSession userSession: UserSessionProtocol)
|
||||
}
|
||||
|
||||
class AuthenticationCoordinator: CoordinatorProtocol {
|
||||
@ -34,6 +33,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
private var oidcPresenter: OIDCAuthenticationPresenter?
|
||||
// periphery: ignore - used to store the coordinator to avoid deallocation
|
||||
private var appLockFlowCoordinator: AppLockSetupFlowCoordinator?
|
||||
|
||||
weak var delegate: AuthenticationCoordinatorDelegate?
|
||||
@ -245,7 +245,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
|
||||
} else if analytics.shouldShowAnalyticsPrompt {
|
||||
showAnalyticsPrompt(userSession: userSession)
|
||||
} else {
|
||||
delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
|
||||
delegate?.authenticationCoordinator(didLoginWithSession: userSession)
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,7 +261,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
|
||||
if analytics.shouldShowAnalyticsPrompt {
|
||||
showAnalyticsPrompt(userSession: userSession)
|
||||
} else {
|
||||
delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
|
||||
delegate?.authenticationCoordinator(didLoginWithSession: userSession)
|
||||
}
|
||||
case .forceLogout:
|
||||
fatalError("The PIN creation flow should not fail.")
|
||||
@ -281,7 +281,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .done:
|
||||
delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
|
||||
delegate?.authenticationCoordinator(didLoginWithSession: userSession)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
@ -44,7 +44,6 @@ public extension TextFieldStyle where Self == AuthenticationTextFieldStyle {
|
||||
/// The text field style used in authentication screens.
|
||||
public struct AuthenticationTextFieldStyle: TextFieldStyle {
|
||||
@Environment(\.isEnabled) private var isEnabled
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
||||
@FocusState private var isFocused: Bool
|
||||
public let labelText: Text?
|
||||
|
@ -24,6 +24,7 @@ class BugReportScreenViewModel: BugReportScreenViewModelType, BugReportScreenVie
|
||||
private let userID: String
|
||||
private let deviceID: String?
|
||||
private let actionsSubject: PassthroughSubject<BugReportScreenViewModelAction, Never> = .init()
|
||||
// periphery:ignore - when set to nil this is automatically cancelled
|
||||
@CancellableTask private var uploadTask: Task<Void, Never>?
|
||||
|
||||
var actions: AnyPublisher<BugReportScreenViewModelAction, Never> {
|
||||
|
@ -140,12 +140,6 @@ struct BugReportScreen: View {
|
||||
// MARK: - Previews
|
||||
|
||||
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 {
|
||||
NavigationStack {
|
||||
BugReportScreen(context: BugReportScreenViewModel(bugReportService: BugReportServiceMock(),
|
||||
|
@ -32,7 +32,6 @@ enum CallScreenCoordinatorAction {
|
||||
}
|
||||
|
||||
final class CallScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: CallScreenCoordinatorParameters
|
||||
private var viewModel: CallScreenViewModelProtocol
|
||||
private let actionsSubject: PassthroughSubject<CallScreenCoordinatorAction, Never> = .init()
|
||||
|
||||
@ -42,8 +41,6 @@ final class CallScreenCoordinator: CoordinatorProtocol {
|
||||
}
|
||||
|
||||
init(parameters: CallScreenCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
|
||||
viewModel = CallScreenViewModel(roomProxy: parameters.roomProxy,
|
||||
callBaseURL: parameters.callBaseURL,
|
||||
clientID: parameters.clientID,
|
||||
|
@ -23,13 +23,13 @@ typealias CallScreenViewModelType = StateStoreViewModel<CallScreenViewState, Cal
|
||||
|
||||
class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol {
|
||||
private let roomProxy: RoomProxyProtocol
|
||||
private let callBaseURL: URL
|
||||
private let clientID: String
|
||||
|
||||
private let widgetDriver: ElementCallWidgetDriverProtocol
|
||||
|
||||
private let callController = CXCallController()
|
||||
// periphery: ignore - call kit magic do not remove
|
||||
private let callProvider = CXProvider(configuration: .init())
|
||||
|
||||
private let callID = UUID()
|
||||
|
||||
private let actionsSubject: PassthroughSubject<CallScreenViewModelAction, Never> = .init()
|
||||
@ -51,8 +51,6 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
|
||||
clientID: String,
|
||||
useEncryption: Bool) {
|
||||
self.roomProxy = roomProxy
|
||||
self.callBaseURL = callBaseURL
|
||||
self.clientID = clientID
|
||||
|
||||
widgetDriver = roomProxy.elementCallWidgetDriver()
|
||||
|
||||
@ -132,12 +130,14 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
|
||||
|
||||
// MARK: - CXCallObserverDelegate
|
||||
|
||||
// periphery: ignore - call kit magic do not remove
|
||||
func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
|
||||
MXLog.info("Call changed: \(call)")
|
||||
}
|
||||
|
||||
// MARK: - CXProviderDelegate
|
||||
|
||||
// periphery: ignore - call kit magic do not remove
|
||||
func providerDidReset(_ provider: CXProvider) {
|
||||
MXLog.info("Call provider did reset: \(provider)")
|
||||
}
|
||||
|
@ -53,7 +53,6 @@ private struct WebView: UIViewRepresentable {
|
||||
@MainActor
|
||||
class Coordinator: NSObject, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate {
|
||||
private let viewModelContext: CallScreenViewModel.Context
|
||||
private var webViewURLObservation: NSKeyValueObservation?
|
||||
|
||||
private(set) var webView: WKWebView!
|
||||
|
||||
|
@ -30,15 +30,6 @@ enum SuggestionItem: Identifiable, Equatable {
|
||||
return PillConstants.atRoom
|
||||
}
|
||||
}
|
||||
|
||||
var name: String? {
|
||||
switch self {
|
||||
case .user(let user):
|
||||
return user.displayName
|
||||
case .allUsers:
|
||||
return PillConstants.everyone
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MentionSuggestionItem: Identifiable, Equatable {
|
||||
|
@ -25,6 +25,7 @@ struct SuggestionPattern: Equatable {
|
||||
let text: String
|
||||
}
|
||||
|
||||
// periphery: ignore - markdown protocol
|
||||
protocol ComposerToolbarViewModelProtocol {
|
||||
var actions: AnyPublisher<ComposerToolbarViewModelAction, Never> { get }
|
||||
var context: ComposerToolbarViewModelType.Context { get }
|
||||
|
@ -313,8 +313,8 @@ struct ComposerToolbar_Previews: PreviewProvider, TestablePreview {
|
||||
VStack(spacing: 8) {
|
||||
ComposerToolbar.textWithVoiceMessage(focused: false)
|
||||
ComposerToolbar.textWithVoiceMessage(focused: true)
|
||||
ComposerToolbar.voiceMessageRecordingMock(recording: true)
|
||||
ComposerToolbar.voiceMessagePreviewMock(recording: false, uploading: false)
|
||||
ComposerToolbar.voiceMessageRecordingMock()
|
||||
ComposerToolbar.voiceMessagePreviewMock(uploading: false)
|
||||
}
|
||||
.previewDisplayName("Voice Message")
|
||||
}
|
||||
@ -355,7 +355,7 @@ extension ComposerToolbar {
|
||||
keyCommandHandler: { _ in false })
|
||||
}
|
||||
|
||||
static func voiceMessageRecordingMock(recording: Bool) -> ComposerToolbar {
|
||||
static func voiceMessageRecordingMock() -> ComposerToolbar {
|
||||
let wysiwygViewModel = WysiwygComposerViewModel()
|
||||
var composerViewModel: ComposerToolbarViewModel {
|
||||
let model = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel,
|
||||
@ -371,7 +371,7 @@ extension ComposerToolbar {
|
||||
keyCommandHandler: { _ in false })
|
||||
}
|
||||
|
||||
static func voiceMessagePreviewMock(recording: Bool, uploading: Bool) -> ComposerToolbar {
|
||||
static func voiceMessagePreviewMock(uploading: Bool) -> ComposerToolbar {
|
||||
let wysiwygViewModel = WysiwygComposerViewModel()
|
||||
let waveformData: [Float] = Array(repeating: 1.0, count: 1000)
|
||||
var composerViewModel: ComposerToolbarViewModel {
|
||||
|
@ -33,7 +33,6 @@ enum CreateRoomCoordinatorAction {
|
||||
}
|
||||
|
||||
final class CreateRoomCoordinator: CoordinatorProtocol {
|
||||
private let parameters: CreateRoomCoordinatorParameters
|
||||
private var viewModel: CreateRoomViewModelProtocol
|
||||
private let actionsSubject: PassthroughSubject<CreateRoomCoordinatorAction, Never> = .init()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
@ -43,7 +42,6 @@ final class CreateRoomCoordinator: CoordinatorProtocol {
|
||||
}
|
||||
|
||||
init(parameters: CreateRoomCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
viewModel = CreateRoomViewModel(userSession: parameters.userSession,
|
||||
createRoomParameters: parameters.createRoomParameters,
|
||||
selectedUsers: parameters.selectedUsers,
|
||||
|
@ -39,7 +39,6 @@ enum HomeScreenCoordinatorAction {
|
||||
}
|
||||
|
||||
final class HomeScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: HomeScreenCoordinatorParameters
|
||||
private var viewModel: HomeScreenViewModelProtocol
|
||||
|
||||
private let actionsSubject: PassthroughSubject<HomeScreenCoordinatorAction, Never> = .init()
|
||||
@ -50,13 +49,9 @@ final class HomeScreenCoordinator: CoordinatorProtocol {
|
||||
}
|
||||
|
||||
init(parameters: HomeScreenCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
|
||||
viewModel = HomeScreenViewModel(userSession: parameters.userSession,
|
||||
attributedStringBuilder: parameters.attributedStringBuilder,
|
||||
selectedRoomPublisher: parameters.selectedRoomPublisher,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
viewModel.actions
|
||||
|
@ -21,9 +21,7 @@ typealias HomeScreenViewModelType = StateStoreViewModel<HomeScreenViewState, Hom
|
||||
|
||||
class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol {
|
||||
private let userSession: UserSessionProtocol
|
||||
private let attributedStringBuilder: AttributedStringBuilderProtocol
|
||||
private let appSettings: AppSettings
|
||||
private let analytics: AnalyticsService
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
|
||||
private let roomSummaryProvider: RoomSummaryProviderProtocol?
|
||||
@ -39,15 +37,11 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
}
|
||||
|
||||
init(userSession: UserSessionProtocol,
|
||||
attributedStringBuilder: AttributedStringBuilderProtocol,
|
||||
selectedRoomPublisher: CurrentValuePublisher<String?, Never>,
|
||||
appSettings: AppSettings,
|
||||
analytics: AnalyticsService,
|
||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
self.userSession = userSession
|
||||
self.attributedStringBuilder = attributedStringBuilder
|
||||
self.appSettings = appSettings
|
||||
self.analytics = analytics
|
||||
self.userIndicatorController = userIndicatorController
|
||||
|
||||
roomSummaryProvider = userSession.clientProxy.roomSummaryProvider
|
||||
|
@ -306,14 +306,9 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview {
|
||||
mediaProvider: MockMediaProvider(),
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||
|
||||
let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
||||
mentionBuilder: MentionBuilder())
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
attributedStringBuilder: attributedStringBuilder,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
}
|
||||
}
|
||||
|
@ -155,10 +155,8 @@ struct HomeScreenEmptyStateView_Previews: PreviewProvider, TestablePreview {
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder()),
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
}()
|
||||
}
|
||||
|
@ -72,14 +72,9 @@ struct HomeScreenRecoveryKeyConfirmationBanner_Previews: PreviewProvider, Testab
|
||||
mediaProvider: MockMediaProvider(),
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||
|
||||
let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
||||
mentionBuilder: MentionBuilder())
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
attributedStringBuilder: attributedStringBuilder,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
}
|
||||
}
|
||||
|
@ -186,11 +186,8 @@ struct HomeScreenRoomCell_Previews: PreviewProvider, TestablePreview {
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||
|
||||
let viewModel = HomeScreenViewModel(userSession: userSession,
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
||||
mentionBuilder: MentionBuilder()),
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
let rooms: [HomeScreenRoom] = summaryProvider.roomListPublisher.value.compactMap { summary -> HomeScreenRoom? in
|
||||
|
@ -72,14 +72,9 @@ struct HomeScreenSessionVerificationBanner_Previews: PreviewProvider, TestablePr
|
||||
mediaProvider: MockMediaProvider(),
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||
|
||||
let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
||||
mentionBuilder: MentionBuilder())
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
attributedStringBuilder: attributedStringBuilder,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,6 @@ import Compound
|
||||
import SwiftUI
|
||||
|
||||
struct HomeScreenUserMenuButton: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
||||
@ObservedObject var context: HomeScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
|
@ -518,7 +518,7 @@ class RoomScreenInteractionHandler {
|
||||
}
|
||||
} catch {
|
||||
MXLog.error("Failed to load voice message: \(error)")
|
||||
audioPlayerState.reportError(error)
|
||||
audioPlayerState.reportError()
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -14,6 +14,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// periphery: ignore - markdown protocol
|
||||
protocol TextBasedRoomTimelineViewProtocol {
|
||||
associatedtype TimelineItemType: TextBasedRoomTimelineItem
|
||||
|
||||
|
@ -20,11 +20,9 @@ import SwiftUI
|
||||
typealias AnalyticsSettingsScreenViewModelType = StateStoreViewModel<AnalyticsSettingsScreenViewState, AnalyticsSettingsScreenViewAction>
|
||||
|
||||
class AnalyticsSettingsScreenViewModel: AnalyticsSettingsScreenViewModelType, AnalyticsSettingsScreenViewModelProtocol {
|
||||
private let appSettings: AppSettings
|
||||
private let analytics: AnalyticsService
|
||||
|
||||
init(appSettings: AppSettings, analytics: AnalyticsService) {
|
||||
self.appSettings = appSettings
|
||||
self.analytics = analytics
|
||||
|
||||
let strings = AnalyticsSettingsScreenStrings(termsURL: appSettings.analyticsConfiguration.termsURL)
|
||||
|
@ -14,6 +14,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// periphery:ignore:all - subscripts lead to false positives
|
||||
import Foundation
|
||||
|
||||
struct AdvancedSettingsScreenViewState: BindableState {
|
||||
|
@ -24,6 +24,7 @@ struct DeveloperOptionsScreenViewState: BindableState {
|
||||
var bindings: DeveloperOptionsScreenViewStateBindings
|
||||
}
|
||||
|
||||
// periphery: ignore - subscripts are seen as false positive
|
||||
@dynamicMemberLookup
|
||||
struct DeveloperOptionsScreenViewStateBindings {
|
||||
private let developerOptions: DeveloperOptionsProtocol
|
||||
|
@ -31,9 +31,6 @@ protocol AnalyticsClientProtocol {
|
||||
/// Stop the analytics client reporting data.
|
||||
func stop()
|
||||
|
||||
/// Send any queued events immediately.
|
||||
func flush()
|
||||
|
||||
/// Capture the supplied analytics event.
|
||||
/// - Parameter event: The event to capture.
|
||||
func capture(_ event: AnalyticsEventProtocol)
|
||||
@ -41,14 +38,6 @@ protocol AnalyticsClientProtocol {
|
||||
/// Capture the supplied analytics screen event.
|
||||
/// - Parameter event: The screen event to capture.
|
||||
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
|
||||
|
@ -105,13 +105,6 @@ class AnalyticsService {
|
||||
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
|
||||
|
||||
/// Capture an event in the `client`.
|
||||
|
@ -24,10 +24,6 @@ protocol AudioSessionProtocol: AnyObject {
|
||||
}
|
||||
|
||||
extension AudioSessionProtocol {
|
||||
func setCategory(_ category: AVAudioSession.Category, mode: AVAudioSession.Mode) throws {
|
||||
try setCategory(category, mode: mode, options: [])
|
||||
}
|
||||
|
||||
func setActive(_ active: Bool) throws {
|
||||
try setActive(active, options: [])
|
||||
}
|
||||
|
@ -46,12 +46,13 @@ class AudioPlayer: NSObject, AudioPlayerProtocol {
|
||||
|
||||
private var statusObserver: NSKeyValueObservation?
|
||||
private var rateObserver: NSKeyValueObservation?
|
||||
private var playToEndObserver: NSObjectProtocol?
|
||||
private var appBackgroundObserver: NSObjectProtocol?
|
||||
private var autoplay = false
|
||||
|
||||
private let audioSession = AVAudioSession.sharedInstance()
|
||||
|
||||
// periphery:ignore - when set to nil is automatically cancelled
|
||||
@CancellableTask private var releaseAudioSessionTask: Task<Void, Never>?
|
||||
|
||||
private let releaseAudioSessionTimeoutInterval = 5.0
|
||||
|
||||
private(set) var url: URL?
|
||||
|
@ -19,7 +19,6 @@ import Foundation
|
||||
|
||||
enum AudioPlayerError: Error {
|
||||
case genericError
|
||||
case loadFileError
|
||||
}
|
||||
|
||||
enum AudioPlayerAction {
|
||||
|
@ -110,7 +110,7 @@ class AudioPlayerState: ObservableObject, Identifiable {
|
||||
playbackState = .stopped
|
||||
}
|
||||
|
||||
func reportError(_ error: Error) {
|
||||
func reportError() {
|
||||
playbackState = .error
|
||||
}
|
||||
|
||||
@ -167,6 +167,7 @@ class AudioPlayerState: ObservableObject, Identifiable {
|
||||
displayLink?.add(to: .current, forMode: .common)
|
||||
}
|
||||
|
||||
// periphery:ignore:parameters displayLink - required for objc selector
|
||||
@objc private func updateProgress(displayLink: CADisplayLink) {
|
||||
if let currentTime = audioPlayer?.currentTime, duration > 0 {
|
||||
progress = currentTime / duration
|
||||
|
@ -343,9 +343,9 @@ class AudioRecorder: AudioRecorderProtocol {
|
||||
.store(in: &cancellables)
|
||||
|
||||
NotificationCenter.default.publisher(for: Notification.Name.AVAudioEngineConfigurationChange)
|
||||
.sink { [weak self] notification in
|
||||
.sink { [weak self] _ in
|
||||
guard let self else { return }
|
||||
self.handleConfigurationChange(notification: notification)
|
||||
self.handleConfigurationChange()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
@ -396,7 +396,7 @@ class AudioRecorder: AudioRecorderProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func handleConfigurationChange(notification: Notification) {
|
||||
func handleConfigurationChange() {
|
||||
guard let audioEngine else { return }
|
||||
MXLog.warning("Configuration changed: \(audioEngine.inputNode.inputFormat(forBus: 0))")
|
||||
if internalState != .suspended {
|
||||
|
@ -24,7 +24,6 @@ enum AudioRecorderError: Error, Equatable {
|
||||
case audioFileCreationFailure
|
||||
case interrupted
|
||||
case recordingCancelled
|
||||
case recordingFailed
|
||||
case recordPermissionNotGranted
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ class AudioRecorderState: ObservableObject, Identifiable {
|
||||
recordingState = .stopped
|
||||
}
|
||||
|
||||
func reportError(_ error: Error) {
|
||||
func reportError() {
|
||||
recordingState = .error
|
||||
}
|
||||
|
||||
@ -98,6 +98,7 @@ class AudioRecorderState: ObservableObject, Identifiable {
|
||||
displayLink?.add(to: .current, forMode: .common)
|
||||
}
|
||||
|
||||
// periphery:ignore:parameters displayLink - required for objc selector
|
||||
@objc private func publishUpdate(displayLink: CADisplayLink) {
|
||||
if let currentTime = audioRecorder?.currentTime {
|
||||
duration = currentTime
|
||||
|
@ -19,8 +19,6 @@ import UIKit
|
||||
|
||||
// sourcery: AutoMockable
|
||||
protocol ApplicationProtocol {
|
||||
func beginBackgroundTask(expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier
|
||||
|
||||
func beginBackgroundTask(withName taskName: String?, expirationHandler handler: (() -> Void)?) -> 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.
|
||||
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.
|
||||
func reuse()
|
||||
|
||||
|
@ -116,10 +116,6 @@ class BugReportService: NSObject, BugReportServiceProtocol {
|
||||
MXLog.info("Reset.")
|
||||
}
|
||||
|
||||
func crash() {
|
||||
SentrySDK.crash()
|
||||
}
|
||||
|
||||
func submitBugReport(_ bugReport: BugReport,
|
||||
progressListener: CurrentValueSubject<Double, Never>) async -> Result<SubmitBugReportResponse, BugReportServiceError> {
|
||||
var params = [
|
||||
|
@ -52,6 +52,7 @@ enum BugReportServiceError: LocalizedError {
|
||||
|
||||
// sourcery: AutoMockable
|
||||
protocol BugReportServiceProtocol {
|
||||
// periphery: ignore
|
||||
var isRunning: Bool { get }
|
||||
|
||||
var crashedLastRun: Bool { get }
|
||||
@ -62,8 +63,6 @@ protocol BugReportServiceProtocol {
|
||||
|
||||
func reset()
|
||||
|
||||
func crash()
|
||||
|
||||
func submitBugReport(_ bugReport: BugReport,
|
||||
progressListener: CurrentValueSubject<Double, Never>) async -> Result<SubmitBugReportResponse, BugReportServiceError>
|
||||
}
|
||||
|
@ -25,15 +25,17 @@ class ClientProxy: ClientProxyProtocol {
|
||||
private let appSettings: AppSettings
|
||||
private let networkMonitor: NetworkMonitorProtocol
|
||||
|
||||
private var sessionVerificationControllerProxy: SessionVerificationControllerProxy?
|
||||
private let mediaLoader: MediaLoaderProtocol
|
||||
private let clientQueue: DispatchQueue
|
||||
|
||||
private var roomListService: RoomListService?
|
||||
// periphery: ignore - only for retain
|
||||
private var roomListStateUpdateTaskHandle: TaskHandle?
|
||||
// periphery: ignore - only for retain
|
||||
private var roomListStateLoadingStateUpdateTaskHandle: TaskHandle?
|
||||
|
||||
private var syncService: SyncService?
|
||||
// periphery: ignore - only for retain
|
||||
private var syncServiceStateUpdateTaskHandle: TaskHandle?
|
||||
|
||||
private var delegateHandle: TaskHandle?
|
||||
@ -49,8 +51,6 @@ class ClientProxy: ClientProxyProtocol {
|
||||
|
||||
let secureBackupController: SecureBackupControllerProtocol
|
||||
|
||||
private let roomListRecencyOrderingAllowedEventTypes = ["m.room.message", "m.room.encrypted", "m.sticker"]
|
||||
|
||||
private static var roomCreationPowerLevelOverrides: PowerLevels {
|
||||
.init(usersDefault: nil,
|
||||
eventsDefault: nil,
|
||||
@ -79,7 +79,6 @@ class ClientProxy: ClientProxyProtocol {
|
||||
}
|
||||
|
||||
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
|
||||
/// 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> {
|
||||
await Task.dispatch(on: clientQueue) {
|
||||
do {
|
||||
|
@ -42,8 +42,6 @@ enum ClientProxyError: Error {
|
||||
case failedRetrievingUserDisplayName
|
||||
case failedRetrievingUserAvatarURL
|
||||
case failedSettingUserDisplayName
|
||||
case failedRetrievingAccountData
|
||||
case failedSettingAccountData
|
||||
case failedRetrievingSessionVerificationController
|
||||
case failedLoadingMedia
|
||||
case mediaFileError
|
||||
@ -123,10 +121,6 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol {
|
||||
|
||||
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 logout() async -> URL?
|
||||
|
@ -117,14 +117,6 @@ class MockClientProxy: ClientProxyProtocol {
|
||||
.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 {
|
||||
throw ClientProxyError.failedLoadingMedia
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ enum ElementCallWidgetDriverError: Error {
|
||||
|
||||
enum ElementCallWidgetDriverAction {
|
||||
case callEnded
|
||||
case errorReceived(ElementCallWidgetDriverError)
|
||||
}
|
||||
|
||||
// sourcery: AutoMockable
|
||||
|
@ -25,5 +25,4 @@ struct EmojiItem: Equatable, Identifiable {
|
||||
let unicode: String
|
||||
let keywords: [String]
|
||||
let shortcodes: [String]
|
||||
let skins: [String]
|
||||
}
|
||||
|
@ -97,6 +97,5 @@ extension EmojiItem {
|
||||
label = emojibase.label
|
||||
shortcodes = emojibase.shortcodes
|
||||
keywords = emojibase.tags ?? []
|
||||
skins = emojibase.skins?.map(\.unicode) ?? []
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ extension NotificationManager: UNUserNotificationCenterDelegate {
|
||||
return [.badge, .sound, .list, .banner]
|
||||
}
|
||||
|
||||
guard delegate.shouldDisplayInAppNotification(self, content: notification.request.content) else {
|
||||
guard delegate.shouldDisplayInAppNotification(content: notification.request.content) else {
|
||||
return []
|
||||
}
|
||||
|
||||
@ -245,8 +245,7 @@ extension NotificationManager: UNUserNotificationCenterDelegate {
|
||||
content: response.notification.request.content,
|
||||
replyText: response.userText)
|
||||
case UNNotificationDefaultActionIdentifier:
|
||||
await delegate?.notificationTapped(self,
|
||||
content: response.notification.request.content)
|
||||
await delegate?.notificationTapped(content: response.notification.request.content)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
@ -18,10 +18,8 @@ import Foundation
|
||||
import UserNotifications
|
||||
|
||||
protocol NotificationManagerDelegate: AnyObject {
|
||||
func shouldDisplayInAppNotification(_ service: NotificationManagerProtocol,
|
||||
content: UNNotificationContent) -> Bool
|
||||
func notificationTapped(_ service: NotificationManagerProtocol,
|
||||
content: UNNotificationContent) async
|
||||
func shouldDisplayInAppNotification(content: UNNotificationContent) -> Bool
|
||||
func notificationTapped(content: UNNotificationContent) async
|
||||
func handleInlineReply(_ service: NotificationManagerProtocol,
|
||||
content: UNNotificationContent,
|
||||
replyText: String) async
|
||||
|
@ -16,4 +16,5 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
// periphery: ignore - markdown protocol
|
||||
protocol DecorationTimelineItemProtocol: RoomTimelineItemProtocol { }
|
||||
|
@ -38,13 +38,4 @@ class CreateRoomScreenUITests: XCTestCase {
|
||||
app.textFields[A11yIdentifiers.createRoomScreen.roomName].typeText("\n")
|
||||
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.")
|
||||
}
|
||||
|
||||
private func checkAttachment(attributedString: AttributedString?, expectedRuns: Int, expectedAttachments: Int = 1) {
|
||||
private func checkAttachment(attributedString: AttributedString?, expectedRuns: Int) {
|
||||
guard let attributedString else {
|
||||
XCTFail("Could not build the attributed string")
|
||||
return
|
||||
|
@ -31,9 +31,6 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
}
|
||||
|
||||
private var audioPlayerSeekCallsSubject: PassthroughSubject<Double, Never>!
|
||||
private var audioPlayerSeekCalls: AnyPublisher<Double, Never> {
|
||||
audioPlayerSeekCallsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
private func buildAudioPlayerMock() -> AudioPlayerMock {
|
||||
let audioPlayerMock = AudioPlayerMock()
|
||||
@ -115,7 +112,7 @@ class AudioPlayerStateTests: XCTestCase {
|
||||
|
||||
func testReportError() async throws {
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .stopped)
|
||||
audioPlayerState.reportError(AudioPlayerError.genericError)
|
||||
audioPlayerState.reportError()
|
||||
XCTAssertEqual(audioPlayerState.playbackState, .error)
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ class AudioRecorderStateTests: XCTestCase {
|
||||
|
||||
func testReportError() async throws {
|
||||
XCTAssertEqual(audioRecorderState.recordingState, .stopped)
|
||||
audioRecorderState.reportError(AudioRecorderError.audioEngineFailure)
|
||||
audioRecorderState.reportError()
|
||||
XCTAssertEqual(audioRecorderState.recordingState, .error)
|
||||
}
|
||||
|
||||
|
@ -21,12 +21,13 @@ import Foundation
|
||||
import XCTest
|
||||
|
||||
class BugReportServiceTests: XCTestCase {
|
||||
var bugReportService: BugReportServiceMock!
|
||||
var bugReportService: BugReportServiceProtocol!
|
||||
|
||||
override func setUpWithError() throws {
|
||||
bugReportService = BugReportServiceMock()
|
||||
bugReportService.underlyingCrashedLastRun = false
|
||||
bugReportService.submitBugReportProgressListenerReturnValue = .success(SubmitBugReportResponse(reportUrl: "https://www.example.com/123"))
|
||||
let bugReportServiceMock = BugReportServiceMock()
|
||||
bugReportServiceMock.underlyingCrashedLastRun = false
|
||||
bugReportServiceMock.submitBugReportProgressListenerReturnValue = .success(SubmitBugReportResponse(reportUrl: "https://www.example.com/123"))
|
||||
bugReportService = bugReportServiceMock
|
||||
}
|
||||
|
||||
func testInitialStateWithMockService() {
|
||||
|
@ -21,7 +21,7 @@ import XCTest
|
||||
@MainActor
|
||||
final class EmojiProviderTests: XCTestCase {
|
||||
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 emojiLoaderMock = EmojiLoaderMock()
|
||||
@ -34,7 +34,7 @@ final class EmojiProviderTests: XCTestCase {
|
||||
}
|
||||
|
||||
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 emojiLoaderMock = EmojiLoaderMock()
|
||||
@ -47,8 +47,8 @@ final class EmojiProviderTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testWhenEmojisLoadedSecondTimeCachedValuesAreUsed() async throws {
|
||||
let item = EmojiItem(label: "test", unicode: "test", keywords: ["1", "2"], shortcodes: ["1", "2"], skins: ["🙂"])
|
||||
let item2 = EmojiItem(label: "test2", unicode: "test2", keywords: ["3", "4"], shortcodes: ["3", "4"], 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"])
|
||||
let categoriesForFirstLoad = [EmojiCategory(id: "test",
|
||||
emojis: [item])]
|
||||
let categoriesForSecondLoad = [EmojiCategory(id: "test2",
|
||||
@ -69,12 +69,12 @@ final class EmojiProviderTests: XCTestCase {
|
||||
func testWhenEmojisSearchedCorrectNumberOfCategoriesReturned() async throws {
|
||||
let searchString = "smile"
|
||||
var categories = [EmojiCategory]()
|
||||
let item0WithSearchString = EmojiItem(label: "emoji0", unicode: "\(searchString)_123", keywords: ["key1", "key1"], shortcodes: ["key1", "key1"], skins: ["🙂"])
|
||||
let item1WithSearchString = EmojiItem(label: searchString, unicode: "emoji1", keywords: ["key1", "key1"], shortcodes: ["key1", "key1"], skins: ["🙂"])
|
||||
let item2WithSearchString = EmojiItem(label: "emoji_2", unicode: "emoji_2", keywords: ["key1", "\(searchString)_123"], shortcodes: ["key1", "key2"], skins: ["🙂"])
|
||||
let item3WithSearchString = EmojiItem(label: "emoji_2", unicode: "emoji_2", keywords: ["key1", "key1"], shortcodes: ["key1", "\(searchString)_123"], skins: ["🙂"])
|
||||
let item4WithoutSearchString = EmojiItem(label: "emoji_3", unicode: "emoji_3", keywords: ["key1", "key1"], shortcodes: ["key1", "key1"], skins: ["🙂"])
|
||||
let item5WithSearchString = 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"])
|
||||
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"])
|
||||
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"])
|
||||
categories.append(EmojiCategory(id: "test",
|
||||
emojis: [item0WithSearchString,
|
||||
item1WithSearchString,
|
||||
|
@ -32,10 +32,8 @@ class HomeScreenViewModelTests: XCTestCase {
|
||||
viewModel = HomeScreenViewModel(userSession: MockUserSession(clientProxy: clientProxy,
|
||||
mediaProvider: MockMediaProvider(),
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock()),
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder()),
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
}
|
||||
|
||||
|
@ -246,11 +246,11 @@ extension NotificationManagerTests: NotificationManagerDelegate {
|
||||
authorizationStatusWasGranted = false
|
||||
}
|
||||
|
||||
func shouldDisplayInAppNotification(_ service: ElementX.NotificationManagerProtocol, content: UNNotificationContent) -> Bool {
|
||||
func shouldDisplayInAppNotification(content: UNNotificationContent) -> Bool {
|
||||
shouldDisplayInAppNotificationReturnValue
|
||||
}
|
||||
|
||||
func notificationTapped(_ service: ElementX.NotificationManagerProtocol, content: UNNotificationContent) async {
|
||||
func notificationTapped(content: UNNotificationContent) async {
|
||||
notificationTappedDelegateCalled = true
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user