Removing Dead Code part 1 (#2234)

This commit is contained in:
Mauro
2023-12-13 09:51:57 +01:00
committed by GitHub
parent 09b276d94b
commit d99d26fcdc
88 changed files with 115 additions and 477 deletions
@@ -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
}
@@ -86,8 +86,6 @@ final class AppSettings {
/// deleted between runs so should clear data in the shared container and keychain.
@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.
@@ -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.
-1
View File
@@ -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
-4
View File
@@ -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,11 +26,11 @@ struct AppActivityView: UIViewControllerRepresentable {
private var onCancel: (() -> Void)?
private var onComplete: CompletionType?
public init(activityItems: [Any],
applicationActivities: [UIActivity]? = nil,
excludedActivityTypes: [UIActivity.ActivityType] = [],
onCancel: (() -> Void)? = nil,
onComplete: CompletionType? = nil) {
init(activityItems: [Any],
applicationActivities: [UIActivity]? = nil,
excludedActivityTypes: [UIActivity.ActivityType] = [],
onCancel: (() -> Void)? = nil,
onComplete: CompletionType? = nil) {
self.activityItems = activityItems
self.applicationActivities = applicationActivities
self.excludedActivityTypes = excludedActivityTypes
@@ -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()
@@ -115,10 +115,6 @@ class BugReportService: NSObject, BugReportServiceProtocol {
lastCrashEventId = nil
MXLog.info("Reset.")
}
func crash() {
SentrySDK.crash()
}
func submitBugReport(_ bugReport: BugReport,
progressListener: CurrentValueSubject<Double, Never>) async -> Result<SubmitBugReportResponse, BugReportServiceError> {
@@ -52,6 +52,7 @@ enum BugReportServiceError: LocalizedError {
// sourcery: AutoMockable
protocol BugReportServiceProtocol {
// periphery: ignore
var isRunning: Bool { get }
var crashedLastRun: Bool { get }
@@ -61,8 +62,6 @@ protocol BugReportServiceProtocol {
func stop()
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?
@@ -48,8 +50,6 @@ class ClientProxy: ClientProxyProtocol {
let notificationSettings: NotificationSettingsProxyProtocol
let secureBackupController: SecureBackupControllerProtocol
private let roomListRecencyOrderingAllowedEventTypes = ["m.room.message", "m.room.encrypted", "m.sticker"]
private static var roomCreationPowerLevelOverrides: PowerLevels {
.init(usersDefault: 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
@@ -122,11 +120,7 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol {
func setUserAvatar(media: MediaInfo) 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 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 { }