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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
88 changed files with 115 additions and 477 deletions

View File

@ -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

View File

@ -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 */,

View File

@ -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"
}
}

View File

@ -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

View File

@ -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())

View File

@ -17,7 +17,6 @@
import Foundation
protocol AppCoordinatorProtocol: CoordinatorProtocol {
var notificationManager: NotificationManagerProtocol { get }
var windowManager: WindowManager { get }
@discardableResult func handleDeepLink(_ url: URL) -> Bool
}

View File

@ -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)

View File

@ -16,6 +16,7 @@
import Foundation
// periphery:ignore - markdown protocol
@MainActor
protocol FlowCoordinatorProtocol {
func handleAppRoute(_ appRoute: AppRoute, animated: Bool)

View File

@ -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.

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")

View File

@ -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

View File

@ -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

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)
}

View File

@ -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)

View File

@ -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>?

View File

@ -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)

View File

@ -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.

View File

@ -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
}
}

View File

@ -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,

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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]

View File

@ -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)
}
}
}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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] = []

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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()

View File

@ -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)
}

View File

@ -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)

View File

@ -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?

View File

@ -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> {

View File

@ -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(),

View File

@ -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,

View File

@ -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)")
}

View File

@ -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!

View File

@ -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 {

View File

@ -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 }

View File

@ -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 {

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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)
}
}

View File

@ -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)
}()
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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)
}
}

View File

@ -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 {

View File

@ -518,7 +518,7 @@ class RoomScreenInteractionHandler {
}
} catch {
MXLog.error("Failed to load voice message: \(error)")
audioPlayerState.reportError(error)
audioPlayerState.reportError()
}
return

View File

@ -14,6 +14,7 @@
// limitations under the License.
//
// periphery: ignore - markdown protocol
protocol TextBasedRoomTimelineViewProtocol {
associatedtype TimelineItemType: TextBasedRoomTimelineItem

View File

@ -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)

View File

@ -14,6 +14,7 @@
// limitations under the License.
//
// periphery:ignore:all - subscripts lead to false positives
import Foundation
struct AdvancedSettingsScreenViewState: BindableState {

View File

@ -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

View File

@ -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

View File

@ -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`.

View File

@ -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: [])
}

View File

@ -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?

View File

@ -19,7 +19,6 @@ import Foundation
enum AudioPlayerError: Error {
case genericError
case loadFileError
}
enum AudioPlayerAction {

View File

@ -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

View File

@ -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 {

View File

@ -24,7 +24,6 @@ enum AudioRecorderError: Error, Equatable {
case audioFileCreationFailure
case interrupted
case recordingCancelled
case recordingFailed
case recordPermissionNotGranted
}

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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 = [

View File

@ -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>
}

View File

@ -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 {

View File

@ -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?

View File

@ -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
}

View File

@ -28,7 +28,6 @@ enum ElementCallWidgetDriverError: Error {
enum ElementCallWidgetDriverAction {
case callEnded
case errorReceived(ElementCallWidgetDriverError)
}
// sourcery: AutoMockable

View File

@ -25,5 +25,4 @@ struct EmojiItem: Equatable, Identifiable {
let unicode: String
let keywords: [String]
let shortcodes: [String]
let skins: [String]
}

View File

@ -97,6 +97,5 @@ extension EmojiItem {
label = emojibase.label
shortcodes = emojibase.shortcodes
keywords = emojibase.tags ?? []
skins = emojibase.skins?.map(\.unicode) ?? []
}
}

View File

@ -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
}

View File

@ -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

View File

@ -16,4 +16,5 @@
import Foundation
// periphery: ignore - markdown protocol
protocol DecorationTimelineItemProtocol: RoomTimelineItemProtocol { }

View File

@ -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)
}
}

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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() {

View File

@ -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,

View File

@ -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)
}

View File

@ -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
}