Periphery cleanup (#5893)

This commit is contained in:
Mauro
2026-07-20 11:16:11 +02:00
committed by GitHub
parent 175aca596e
commit 9093631f8b
275 changed files with 381 additions and 2268 deletions
+99
View File
@@ -0,0 +1,99 @@
---
name: periphery-cleanup
description: Dead-code sweep with Periphery — scan the Pro-configured project, delete unused code, guard false positives (keep-alive handles, future-use code), run unit tests, purge scan cache. Use when user want "clean up dead code", "run periphery", "remove unused code".
---
# Periphery cleanup
Periphery = static analysis, find unused code. Scan build ALL schemes — slow (cold ~30-60 min). Maintenance thing, run rare.
## Scan — always on the Pro variant
Scan run on the Pro-configured project so every source get analysed (plain config leave hook implementations + their call sites out, flood report with false "unused"):
```bash
git submodule update --init --recursive # once, if submodules missing
swift run pipeline configure-element-pro
periphery scan --relative-results --quiet > periphery-report.txt
```
Config live in `.periphery.yml` — schemes already cover every target, don't narrow. Two deliberate settings there:
- `retain_unused_protocol_func_params: true` — protocol signatures are contracts (hooks, delegates); params unused in every conformance stay. NEVER annotate protocol function parameters, config already handle them.
- `index_exclude: compound-ios/**` — Compound excluded: its Inspector app + package tests live outside this project's schemes, so their usage invisible → findings there unreliable (e.g. making things internal break the Inspector). Never act on Compound code from this scan.
Report line format: `path:line:col: warning: <kind> '<name>'`. Build fail → fix build first, scan need compiling project.
## Comment hygiene — strip, scan, restore
Every run: existing `periphery:ignore` comments hide drift — code change, comment stay, nobody notice it useless. So:
1. **Strip + remember.** Before the scan, remove every `periphery:ignore` comment (both spellings: `periphery:ignore` and `periphery: ignore`) and stash them: `git diff > /tmp/periphery-comments.patch` right after stripping, or just rely on `git diff` against HEAD to recall what was where.
2. **Scan.** The report now show ground truth: every declaration that genuinely need protection re-flag.
3. **Restore only what re-flag.** For each finding that match the false-positive table, put the comment back (same reason strings). Findings that DON'T re-flag = comments that were stale → stay deleted. Anything newly flagged that isn't a false positive = real dead code → delete it.
Result: comment set always minimal, always true. The clutter never accumulate.
## Triage — kind → action
| Warning | Action |
|---|---|
| Unused function / property / enum / struct / init | Check false-positive table FIRST. True dead → delete whole declaration + helpers/extensions only it used |
| Assign-only property | DANGER ZONE. Prime keep-alive suspect — read table below before touch |
| Unused parameter | Protocol params never appear (config retain them). ObjC selector / system callback → `ignore:parameters <name> - <reason>`. Free signature → remove param + fix call sites |
| Redundant protocol conformance | `TestablePreview` → SKIP, always (see below). Others: verify nothing need conformance (generics, tests, mocks), then remove conformance only, keep type |
| Redundant public accessibility | Drop `public`, make internal — EXCEPT member that satisfy a public protocol in a public type (e.g. `previews`), Swift refuse internal there; skip or internalise whole type |
| Superfluous ignore comment | Declaration referenced now — comment dead, code alive. Remove comment ONLY, never declaration |
Never touch `Generated/` directories, never edit `Localizable.strings`. Delete bottom-up per file — line numbers stay valid.
## False positives — mark, no delete
Stored-never-read variable often alive ON PURPOSE: keep task / SDK object / coordinator alive past declaration scope. Delete = app break silent (observation stop, flow deallocate, rust handle drop). Mark instead: `// periphery:ignore - <reason>` line above declaration (NEVER `periphery:ignore:all` — whole files that shouldn't be reported, like hand-written mocks, belong in `report_exclude` in `.periphery.yml` instead). Comment go ABOVE any doc comment, never between doc and declaration. Reuse existing reasons from codebase:
| Pattern | How recognise | Reason string |
|---|---|---|
| Rust SDK handle | `TaskHandle`, observation token from SDK, stored after `observe`/`subscribe` call | `required for instance retention in the rust codebase` |
| Keep-alive reference | child flow coordinator, service stored so updates keep flowing | `retaining purpose` or `used to avoid deallocation` or `keep alive to keep receiving updates.` |
| Cancellable task handle | `@CancellableTask` property, `Task` stored so reassign/nil cancel previous | `auto cancels when reassigned` |
| SDK enum exhaustiveness | unused `init` switching over SDK enum | `Unused, but added to detect new cases when updating the SDK.` |
| MVVM-C architecture | empty `ViewModelAction` enum from screen template, unused VM protocol — NEVER delete VM protocols, convention keep them | `required for the architecture` (keep the mark even if a superfluous-comment warning appear — it document intent) |
| Property wrapper internals | `@propertyWrapper`, `@dynamicMemberLookup` subscript | `property wrappers generate false positives` / `subscript are seen as false positives` |
| ObjC selector parameter | parameter only touched by runtime (`displayLink`, `sender` etc.) | `ignore:parameters <name> - required for objc selector` |
| Underscored SwiftUI protocol | `_body` from `TextFieldStyle` etc. — called by SwiftUI, members inside resolve transitively | `called by SwiftUI via the TextFieldStyle protocol` |
| SDK delegate requirement | method required by rust SDK delegate protocol (e.g. `didRefreshTokens`) | `required by the SDK's delegate protocol` |
| Synthesized conformance | field only read via synthesized Hashable/Equatable/Codable (cache keys, diffing models) | `used via the synthesized Hashable conformance` |
| Encoded/decoded schema field | Codable field parsed or serialized but not consumed yet | `documents the schema, parsed but not consumed yet` / `part of the encoded payload` |
| Release-only code | compiled out in Debug scan (`#if !DEBUG` paths, nightly checks) | `only used in release builds` |
| `TestablePreview` conformance | flagged "Redundant protocol conformance" on every preview | NO marker, NO removal — Sourcery read conformance, generate snapshot + a11y tests from it. Remove = tests silently vanish. Skip finding, bulk noise |
**Unsure if keep-alive?** Property type Task / AnyCancellable / TaskHandle / coordinator / SDK proxy, assigned inside async or stream setup → smell like keep-alive. ASK USER before delete. Show declaration, where assigned, your read on it.
## Future-use code
Unused but look intentional — API pair completeness, feature half-landed, "team will need soon". No silent delete, no silent keep. Present to user: what, where, opinion keep-or-delete. User say keep → mark `// periphery:ignore - might be useful to have`.
## Mock cascade after protocol deletions
Delete protocol member → Sourcery regenerate mock WITHOUT its `fooReturnValue` / `fooClosure` helpers → hand-written mock `Configuration` inits and test set-up lines still assigning those helpers break the build. Those lines are inert setup for API nothing call — more dead code, not evidence of use. After protocol deletions: grep non-Generated `Mocks/` + `UnitTests/` for `<name>ReturnValue`, `<name>Closure`, direct assignments to deleted members — delete them too. Compiler walk you to the stragglers; that expected, not a false positive.
Careful with same-name members: one mock file often configure SEVERAL protocols (proxy-level `inviter` vs info-level `inviter`). Strip only lines whose target member actually deleted — the wrong one compile fine (member still exist) but silently un-configure previews; snapshot tests catch it, so run them before calling done.
## Verify — on the PLAIN project
Restore the plain configuration BEFORE running tests — snapshots are recorded against plain Element X; Pro branding fail ~8 preview tests falsely:
```bash
git restore project.yml ElementX.xcodeproj/project.pbxproj "ElementX/Resources/AppIcon.icon/Assets/AppIcon.png"
xcodegen
swift run tools ci unit-tests
```
Sourcery regenerate mocks on build — deleted protocol members clean themselves. All tests pass before call done. Note: the CI helper pipe through `xcbeautify` — if not installed the exit code lie even when tests pass; check the `.xcresult` summary.
## Purge cache — always
Periphery DerivedData cache eat tens of GBs. Scan run rare → cache worthless between runs. Last step, no skip:
```bash
rm -rf ~/Library/Caches/com.github.peripheryapp
```
+22 -10
View File
@@ -1,19 +1,31 @@
project: ElementX.xcodeproj
# Periphery scans all targets built by these schemes. The ElementX scheme also
# builds NSE, ShareExtension and MatrixRustSDKMocks as dependencies. Always run
# the scan with the project configured for the Pro variant so that all of the
# sources are analysed (see the periphery-cleanup skill).
schemes:
- ElementX
- UnitTests
- PreviewTests
- UITests
- IntegrationTests
targets:
- ElementX
- NSE
- ShareExtension
- UnitTests
- PreviewTests
- UITests
- IntegrationTests
- AccessibilityTests
# Compound is excluded: its Inspector app and package tests aren't part of any
# scheme in this project, so usage from them is invisible to the analysis.
index_exclude:
- "**/*?.build/**/*"
- "**/SourcePackages/checkouts/**"
- "compound-ios/**"
report_exclude:
- ElementX/Sources/Mocks/Generated/GeneratedMocks.swift
- ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift
- "**/Generated/**"
# Hand-written mocks: configuration surface is deliberately broader than any test uses.
- "**/Mocks/**"
- "ElementX/Sources/Services/AppLock/LAContextMock.swift"
# Pure payload schema, fields exist to be encoded.
- "ElementX/Sources/Services/Notification/Manager/APNSPayload.swift"
# Backports: everything gated on #available, cleaned up with each OS drop.
- "ElementX/Sources/Other/SwiftUI/Backports.swift"
retain_swift_ui_previews: true
# Protocol signatures are contracts (hooks, delegates) — parameters unused in
# every current conformance are still part of the interface's design.
retain_unused_protocol_func_params: true
@@ -98,7 +98,6 @@ final class AccessibilityTests: XCTestCase {
private static let partiallyUnsupportedDynamicTypeMessage = "Dynamic Type font sizes are partially unsupported"
private static let notHumanReadableMessage = "Label not human-readable"
private static let elementHasNoDescription = "Element has no description"
/// Use this array to filter add specific filters to ignore specific issues for certain elements
private static let ignoredA11yIdentifiers: [String: [FilterType]] = [
@@ -747,10 +747,6 @@ extension AccessibilityTests {
try await performAccessibilityAudit(named: "SwipeRightAction_Previews")
}
func testSwipeToReplyView() async throws {
try await performAccessibilityAudit(named: "SwipeToReplyView_Previews")
}
func testTextRoomTimelineView() async throws {
try await performAccessibilityAudit(named: "TextRoomTimelineView_Previews")
}
@@ -14,7 +14,7 @@ import SwiftSyntaxMacros
///
/// A `volatile` preference instead reads and writes through a generated in-memory store, so its
/// value is never persisted and resets on each launch.
public enum UserPreferenceMacro {
enum UserPreferenceMacro {
enum DiagnosticError: Error, CustomStringConvertible {
case notAStoredProperty
case missingTypeAnnotation
@@ -85,7 +85,7 @@ public enum UserPreferenceMacro {
}
extension UserPreferenceMacro: AccessorMacro {
public static func expansion(of node: AttributeSyntax,
static func expansion(of node: AttributeSyntax,
providingAccessorsOf declaration: some DeclSyntaxProtocol,
in context: some MacroExpansionContext) throws -> [AccessorDeclSyntax] {
let preference = try preference(for: declaration, node: node)
@@ -137,7 +137,7 @@ extension UserPreferenceMacro: AccessorMacro {
}
extension UserPreferenceMacro: PeerMacro {
public static func expansion(of node: AttributeSyntax,
static func expansion(of node: AttributeSyntax,
providingPeersOf declaration: some DeclSyntaxProtocol,
in context: some MacroExpansionContext) throws -> [DeclSyntax] {
let preference = try preference(for: declaration, node: node)
+8 -20
View File
@@ -133,7 +133,6 @@
1318721F4E5F307586D98112 /* VoiceMessageButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8516302ACCA94A0E680AB3B /* VoiceMessageButton.swift */; };
13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */; };
13CBC470FB619A6393A21908 /* RoomNotificationSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8296D6FB451E25CEC0767BBA /* RoomNotificationSettingsScreenCoordinator.swift */; };
1443CEEE42491CF7CD8A146A /* XCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85A1941B874A3BE9CDDF43EF /* XCTestCase.swift */; };
1471A080552631358D152C18 /* AudioPlayerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BDB3E65A79779EDA5D33D8A /* AudioPlayerState.swift */; };
147597951DB07123A87AA1D1 /* landscape_test_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 96CE9D6642DD487D8CC90C9C /* landscape_test_image.jpg */; };
149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */; };
@@ -371,7 +370,6 @@
3B0F9B57D25B07E66F15762A /* MediaUploadPreviewScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2E7C987AE5DC9087BB19F7D /* MediaUploadPreviewScreenModels.swift */; };
3B277D9538090766DA6C4566 /* StateRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2AF1828A5B76B7C371240FE /* StateRoomTimelineView.swift */; };
3B5AB5CF8D8163599C5BF19B /* PillViewOnBubblePreviews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2005B4AD70A792340E2694F1 /* PillViewOnBubblePreviews.swift */; };
3B98049F56025726FB646ABD /* SwipeToReplyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B0E0B55E2EE75AF67029924 /* SwipeToReplyView.swift */; };
3BEBDCB42BABFA3B456FECA7 /* MapTilerURLBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D262A26713C18BB70C82CA5 /* MapTilerURLBuilderTests.swift */; };
3C312A3AEDE58BB1C9BBB07C /* preview_avatar_room.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 12FD5280AF55AB7F50F8E47D /* preview_avatar_room.jpg */; };
3C31E1A65EEB61E72E1113B4 /* AudioRecorderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEC57C204D77908E355EF42 /* AudioRecorderProtocol.swift */; };
@@ -1311,7 +1309,6 @@
D4D7CCECC6C0AAFC42E165BB /* NotificationPermissionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9BBB18FB27F09032AD8769 /* NotificationPermissionsScreenViewModel.swift */; };
D4F3C5656DF09037825E9965 /* ChatsSpaceFiltersScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEF2C15634499348A512A93A /* ChatsSpaceFiltersScreenModels.swift */; };
D55AF9B5B55FEED04771A461 /* RoomFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */; };
D5681C80D8281560AACE0035 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045253F9967A535EE5B16691 /* Label.swift */; };
D5B1531A72387D432939D4E0 /* RoomDirectorySearchProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */; };
D5C2DA52162A978743A183F2 /* SessionVerificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8AA084E10B80D64449C02A9 /* SessionVerificationTests.swift */; };
D5E771132BB36240DE38102F /* RoomMessageEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */; };
@@ -1677,7 +1674,6 @@
03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = "<group>"; };
044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = "<group>"; };
045253F9967A535EE5B16691 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
046C0D3F53B0B5EF0A1F5BEA /* RoomSummaryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryTests.swift; sourceTree = "<group>"; };
048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.swift; sourceTree = "<group>"; };
@@ -1719,7 +1715,6 @@
0AB7A0C06CB527A1095DEB33 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = da; path = da.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
0AC5E094DFE18C3AB7619D34 /* CreateRoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomScreenViewModelProtocol.swift; sourceTree = "<group>"; };
0AE4B7AD74E402BBC46A801A /* LeaveSpaceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeaveSpaceView.swift; sourceTree = "<group>"; };
0B0E0B55E2EE75AF67029924 /* SwipeToReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeToReplyView.swift; sourceTree = "<group>"; };
0B32BBA8887BD7A5C4ECF16F /* RoomModerationRole.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomModerationRole.swift; sourceTree = "<group>"; };
0B5DF0E888F66652F8C4CEC5 /* LiveLocationManagerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveLocationManagerMock.swift; sourceTree = "<group>"; };
0B987FC3FDBAA0E1C5AA235C /* PaginationIndicatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationIndicatorRoomTimelineItem.swift; sourceTree = "<group>"; };
@@ -2431,7 +2426,6 @@
858DA81F2ACF484B7CAD6AE4 /* KnockedRoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockedRoomProxy.swift; sourceTree = "<group>"; };
858F8D0B0D51CC41BAA18E24 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = "<group>"; };
859F51637DA710BBE7B70D6D /* ChatsSpaceFiltersScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsSpaceFiltersScreenViewModel.swift; sourceTree = "<group>"; };
85A1941B874A3BE9CDDF43EF /* XCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestCase.swift; sourceTree = "<group>"; };
85E8591F06B2DAA284181308 /* HomeserverCapabilitiesProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeserverCapabilitiesProxyProtocol.swift; sourceTree = "<group>"; };
85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderProtocol.swift; sourceTree = "<group>"; };
8610C1D21565C950BCA6A454 /* AppLockSetupSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
@@ -3835,7 +3829,6 @@
children = (
307C3E5B9B189497D3250E23 /* AccessibleLongPress.swift */,
1D9F148717D74F73BE724434 /* LongPressWithFeedback.swift */,
0B0E0B55E2EE75AF67029924 /* SwipeToReplyView.swift */,
2DA4F09CB613C54FDC73AE6A /* ThreadDecorator.swift */,
F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */,
1DA7E93C2E148B96EF6A8500 /* TimelineItemAccessibilityModifier.swift */,
@@ -4348,7 +4341,6 @@
04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */,
E3877D3CFAC1D33823359BAF /* HTMLParserStyle.swift */,
4E2245243369B99216C7D84E /* ImageCache.swift */,
045253F9967A535EE5B16691 /* Label.swift */,
F72EFC8C634469F9262659C7 /* NSItemProvider.swift */,
95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */,
5327E3B3C58BEB0E65F4CF98 /* Observable.swift */,
@@ -4369,7 +4361,6 @@
2BFDCA5A09EE70BC17F2EFA7 /* URLComponents.swift */,
AE40D4A5DD857AC16EED945A /* URLSession.swift */,
897DF5E9A70CE05A632FC8AF /* UTType.swift */,
85A1941B874A3BE9CDDF43EF /* XCTestCase.swift */,
E992D7B8BE54B2AB454613AF /* XCUIElement.swift */,
);
path = Extensions;
@@ -7619,16 +7610,16 @@
projectDirPath = "";
projectRoot = "";
targets = (
C0FAEB81CFD9776CD78CE489 /* ElementX */,
FEB53A5BC378C913769656D8 /* NSE */,
19F0C845D67E9BEA4BE7133E /* ShareExtension */,
676A87694F0F247B2AF1A142 /* MatrixRustSDKMocks */,
32C23C8D224D46EFE62AFAD0 /* UnitTests */,
7A17BE29BAC81ADBAC6349D9 /* PreviewTests */,
0E28CD62691FDBC63147D5E3 /* UITests */,
D3DB351B7FBE0F49649171FC /* IntegrationTests */,
C0C687DE1D270F9895FEE186 /* AccessibilityTests */,
C0FAEB81CFD9776CD78CE489 /* ElementX */,
D3DB351B7FBE0F49649171FC /* IntegrationTests */,
676A87694F0F247B2AF1A142 /* MatrixRustSDKMocks */,
FEB53A5BC378C913769656D8 /* NSE */,
F8E276FD6DC43EADB85241BC /* Periphery */,
7A17BE29BAC81ADBAC6349D9 /* PreviewTests */,
19F0C845D67E9BEA4BE7133E /* ShareExtension */,
0E28CD62691FDBC63147D5E3 /* UITests */,
32C23C8D224D46EFE62AFAD0 /* UnitTests */,
);
};
/* End PBXProject section */
@@ -8143,7 +8134,6 @@
44BDD670FF9095ACE240A3A2 /* VoiceMessageMediaManagerTests.swift in Sources */,
A3D7110C1E75E7B4A73BE71C /* VoiceMessageRecorderTests.swift in Sources */,
0B9436A91CFA658202400465 /* WaitingConfirmation.swift in Sources */,
1443CEEE42491CF7CD8A146A /* XCTestCase.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -8607,7 +8597,6 @@
6681D6D3ADF69EBD2625F29A /* KnockedRoomProxyMock.swift in Sources */,
454F8DDC4442C0DE54094902 /* LABiometryType.swift in Sources */,
E468CC731C3F4D678499E52F /* LAContextMock.swift in Sources */,
D5681C80D8281560AACE0035 /* Label.swift in Sources */,
33BA0964A308D2286B39976D /* LabsScreen.swift in Sources */,
D150D6E96CA6CA09FA50E13C /* LabsScreenCoordinator.swift in Sources */,
C900127318820AD04D6C90B8 /* LabsScreenModels.swift in Sources */,
@@ -9150,7 +9139,6 @@
A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */,
066A1E9B94723EE9F3038044 /* Strings.swift in Sources */,
FF34BF2AF731340AF9414A18 /* SwipeRightAction.swift in Sources */,
3B98049F56025726FB646ABD /* SwipeToReplyView.swift in Sources */,
C097D5453640E27D397943CB /* TargetConfiguration.swift in Sources */,
E290C78E7F09F47FD2662986 /* Task.swift in Sources */,
1555A7643D85187D4851040C /* TemplateScreen.swift in Sources */,
+3
View File
@@ -93,6 +93,7 @@ final nonisolated class AppHooks: AppHooksProtocol {
_clientBuilderHook.withLock { $0 }
}
// periphery:ignore - might be useful to have
func registerClientBuilderHook(_ hook: ClientBuilderHookProtocol) {
_clientBuilderHook.withLock { $0 = hook }
}
@@ -108,9 +109,11 @@ final nonisolated class AppHooks: AppHooksProtocol {
}
nonisolated protocol AppHooksProtocol: Sendable {
// periphery:ignore - required for the architecture
func setUp()
}
nonisolated extension AppHooksProtocol {
// periphery:ignore - required for the architecture
func setUp() { }
}
@@ -56,11 +56,9 @@ struct DefaultRemoteSettingsHook: RemoteSettingsHookProtocol {
}
private struct ElementWellKnown: Decodable {
var version: Int?
var enforceElementPro: Bool?
enum CodingKeys: String, CodingKey {
case version
case enforceElementPro = "enforce_element_pro"
}
}
@@ -19,6 +19,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
private let stateMachine: AppCoordinatorStateMachine
private let navigationRootCoordinator: NavigationRootCoordinator
private let userSessionStore: UserSessionStoreProtocol
// periphery:ignore - retaining purpose
private let targetConfiguration: Target.ConfigurationResult
private let appMediator: AppMediator
private let appSettings: AppSettings
@@ -680,7 +681,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
appMediator: appMediator,
appSettings: appSettings,
appHooks: appHooks,
analytics: analyticsService,
userIndicatorController: userIndicatorController)
coordinator.delegate = self
@@ -16,10 +16,6 @@ protocol AppMediatorProtocol {
var appState: UIApplication.State { get }
func beginBackgroundTask(expirationHandler handler: (@MainActor @Sendable () -> Void)?) -> UIBackgroundTaskIdentifier
func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier)
func open(_ url: URL)
func openAppSettings()
@@ -8,7 +8,6 @@
import Foundation
// periphery:ignore - markdown protocol
protocol FlowCoordinatorProtocol {
func start(animated: Bool)
func handleAppRoute(_ appRoute: AppRoute, animated: Bool)
@@ -85,7 +85,6 @@ import SwiftUI
}
}
// periphery:ignore - might be useful to have
/// The currently displayed fullscreen cover coordinator
var fullScreenCoverCoordinator: (any CoordinatorProtocol)? {
fullScreenCoverModule?.coordinator
@@ -626,7 +625,6 @@ private struct NavigationSplitCoordinatorView: View {
}
}
// periphery:ignore - might be useful to have
/// Present a fullscreen cover on top of the stack. If this NavigationStackCoordinator is embedded within a NavigationSplitCoordinator
/// then the presentation will be proxied to the split
/// - Parameters:
@@ -28,7 +28,6 @@ nonisolated protocol CommonSettingsProtocol: AnyObject, Sendable {
var enableOnlySignedDeviceIsolationMode: Bool { get }
var threadsEnabled: Bool { get }
var globalSearchEnabled: Bool { get }
var hideQuietNotificationAlerts: Bool { get }
}
@@ -8,7 +8,7 @@
import Foundation
public nonisolated protocol UserDefaultsProtocol: AnyObject {
nonisolated protocol UserDefaultsProtocol: AnyObject {
func data(forKey key: String) -> Data?
func object(forKey key: String) -> Any?
func removeObject(forKey key: String)
@@ -7,39 +7,39 @@
import Foundation
public final nonisolated class VolatileUserDefaults: UserDefaultsProtocol, Sendable {
final nonisolated class VolatileUserDefaults: UserDefaultsProtocol, Sendable {
private let lock = NSLock()
private nonisolated(unsafe) var _storage: [String: Any]
public private(set) var storage: [String: Any] {
private(set) var storage: [String: Any] {
get { lock.withLock { _storage } }
set { lock.withLock { _storage = newValue } }
}
public init(initialValues: [String: Any] = [:]) {
init(initialValues: [String: Any] = [:]) {
lock.lock()
defer { lock.unlock() }
_storage = initialValues
}
public func data(forKey key: String) -> Data? {
func data(forKey key: String) -> Data? {
storage[key] as? Data
}
public func object(forKey key: String) -> Any? {
func object(forKey key: String) -> Any? {
storage[key]
}
public func removeObject(forKey key: String) {
func removeObject(forKey key: String) {
storage.removeValue(forKey: key)
}
public func set(_ value: Any?, forKey key: String) {
func set(_ value: Any?, forKey key: String) {
storage[key] = value
}
public func reset() {
func reset() {
storage = [:]
}
}
@@ -12,7 +12,6 @@ import SwiftUI
class WindowManager: SecureWindowManagerProtocol {
private let appDelegate: AppDelegate
weak var mainScene: UIWindowScene?
weak var mainSession: UISceneSession?
weak var delegate: SecureWindowManagerDelegate?
private(set) var mainWindow: UIWindow!
@@ -34,7 +33,6 @@ class WindowManager: SecureWindowManagerProtocol {
[mainWindow, overlayWindow, alternateWindow]
}
// periphery:ignore - auto cancels when reassigned
/// The task used to switch windows, so that we don't get stuck in the wrong state with a quick switch.
@CancellableTask private var switchTask: Task<Void, Error>?
/// A duration that allows window switching to wait a couple of frames to avoid a transition through black.
@@ -62,7 +60,6 @@ class WindowManager: SecureWindowManagerProtocol {
}
mainScene = scene
mainSession = session
// Restore the previous window size on macOS as this isn't automatic.
if let previousSize = mainWindow?.frame.size {
@@ -94,7 +91,6 @@ class WindowManager: SecureWindowManagerProtocol {
func handleSceneDisconnection(_ scene: UIWindowScene) {
if scene == mainScene {
mainScene = nil
mainSession = nil
// Leave the mainWindow so we can reapply it's size on macOS.
}
}
@@ -22,7 +22,6 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
private let appMediator: AppMediatorProtocol
private let appSettings: AppSettings
private let appHooks: AppHooks
private let analytics: AnalyticsServiceProtocol
private let userIndicatorController: UserIndicatorControllerProtocol
enum State: StateType {
@@ -108,7 +107,6 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
appMediator: AppMediatorProtocol,
appSettings: AppSettings,
appHooks: AppHooks,
analytics: AnalyticsServiceProtocol,
userIndicatorController: UserIndicatorControllerProtocol) {
self.authenticationService = authenticationService
self.bugReportService = bugReportService
@@ -116,7 +114,6 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
self.appMediator = appMediator
self.appSettings = appSettings
self.appHooks = appHooks
self.analytics = analytics
self.userIndicatorController = userIndicatorController
navigationStackCoordinator = NavigationStackCoordinator()
@@ -443,8 +440,7 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
let parameters = LoginScreenCoordinatorParameters(authenticationService: authenticationService,
loginHint: loginHint,
userIndicatorController: userIndicatorController,
appSettings: appSettings,
analytics: analytics)
appSettings: appSettings)
let coordinator = LoginScreenCoordinator(parameters: parameters)
coordinator.actions
@@ -31,12 +31,10 @@ class ChatsTabFlowCoordinator: FlowCoordinatorProtocol {
private let stateMachine: ChatsTabFlowCoordinatorStateMachine
// periphery:ignore - retaining purpose
private var roomFlowCoordinator: RoomFlowCoordinator?
// periphery:ignore - retaining purpose
private var spaceFlowCoordinator: SpaceFlowCoordinator?
// periphery:ignore - retaining purpose
private var bugReportFlowCoordinator: BugReportFlowCoordinator?
// periphery:ignore - retaining purpose
private var encryptionResetFlowCoordinator: EncryptionResetFlowCoordinator?
@@ -54,8 +52,7 @@ class ChatsTabFlowCoordinator: FlowCoordinatorProtocol {
actionsSubject.eraseToAnyPublisher()
}
init(isNewLogin: Bool,
navigationSplitCoordinator: NavigationSplitCoordinator,
init(navigationSplitCoordinator: NavigationSplitCoordinator,
flowParameters: CommonFlowParameters) {
stateMachine = flowParameters.stateMachineFactory.makeChatsTabFlowStateMachine()
self.navigationSplitCoordinator = navigationSplitCoordinator
@@ -754,8 +751,7 @@ class ChatsTabFlowCoordinator: FlowCoordinatorProtocol {
isPresentedModally: true,
userSession: userSession,
userIndicatorController: flowParameters.userIndicatorController,
analytics: flowParameters.analytics,
appSettings: flowParameters.appSettings)
analytics: flowParameters.analytics)
let coordinator = UserProfileScreenCoordinator(parameters: parameters)
coordinator.actionsPublisher.sink { [weak self] action in
guard let self else { return }
@@ -349,7 +349,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
}
private func presentIdentityConfirmedScreen() {
let coordinator = IdentityConfirmedScreenCoordinator(parameters: .init())
let coordinator = IdentityConfirmedScreenCoordinator()
coordinator.actionsPublisher
.sink { [weak self] action in
guard let self else { return }
@@ -90,11 +90,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
private var pinnedEventsTimelineFlowCoordinator: PinnedEventsTimelineFlowCoordinator?
// periphery:ignore - used to avoid deallocation
private var mediaEventsTimelineFlowCoordinator: MediaEventsTimelineFlowCoordinator?
// periphery:ignore - used to avoid deallocation
private var childRoomFlowCoordinator: RoomFlowCoordinator?
// periphery:ignore - retaining purpose
private var spaceFlowCoordinator: SpaceFlowCoordinator?
// periphery:ignore - retaining purpose
private var membersFlowCoordinator: RoomMembersFlowCoordinator?
private let stateMachine: StateMachine<State, Event> = .init(state: .initial)
@@ -946,8 +944,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
analyticsService: flowParameters.analytics,
userIndicatorController: flowParameters.userIndicatorController,
notificationSettings: userSession.clientProxy.notificationSettings,
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: PlainMentionBuilder()),
appSettings: flowParameters.appSettings)
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: PlainMentionBuilder()))
let coordinator = RoomDetailsScreenCoordinator(parameters: params)
coordinator.actions.sink { [weak self] action in
guard let self else { return }
@@ -1025,8 +1022,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: flowParameters.appSettings),
navigationStackCoordinator: stackCoordinator,
userIndicatorController: flowParameters.userIndicatorController,
orientationManager: flowParameters.appMediator.windowManager,
appSettings: flowParameters.appSettings)
orientationManager: flowParameters.appMediator.windowManager)
let roomDetailsEditCoordinator = RoomDetailsEditScreenCoordinator(parameters: roomDetailsEditParameters)
roomDetailsEditCoordinator.actions.sink { [weak self] action in
@@ -1123,7 +1119,6 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
let parameters = MediaUploadPreviewScreenCoordinatorParameters(mediaURLs: mediaURLs,
caption: caption,
title: title,
isRoomEncrypted: roomProxy.infoPublisher.value.isEncrypted,
shouldShowCaptionWarning: flowParameters.appSettings.shouldShowMediaCaptionWarning,
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: flowParameters.appSettings),
timelineController: timelineController,
@@ -1170,7 +1165,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
}
.store(in: &cancellables)
navigationStackCoordinator.setSheetCoordinator(coordinator) { [weak self] in
navigationStackCoordinator.setSheetCoordinator(coordinator, animated: animated) { [weak self] in
self?.stateMachine.tryEvent(.dismissEmojiPicker)
}
}
@@ -1203,7 +1198,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
stackCoordinator.setRootCoordinator(coordinator)
navigationStackCoordinator.setSheetCoordinator(stackCoordinator) { [weak self] in
navigationStackCoordinator.setSheetCoordinator(stackCoordinator, animated: animated) { [weak self] in
self?.stateMachine.tryEvent(.dismissMapNavigator)
}
}
@@ -1351,8 +1346,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
roomType: roomType,
isSkippable: false,
userDiscoveryService: UserDiscoveryService(clientProxy: userSession.clientProxy),
userIndicatorController: flowParameters.userIndicatorController,
appSettings: flowParameters.appSettings)
userIndicatorController: flowParameters.userIndicatorController)
let coordinator = InviteUsersScreenCoordinator(parameters: inviteParameters)
stackCoordinator.setRootCoordinator(coordinator)
@@ -10,18 +10,6 @@ import Foundation
import SwiftState
extension RoomFlowCoordinator {
struct HashableRoomMemberWrapper: Hashable {
let value: RoomMemberProxyProtocol
static func == (lhs: HashableRoomMemberWrapper, rhs: HashableRoomMemberWrapper) -> Bool {
lhs.value.userID == rhs.value.userID
}
func hash(into hasher: inout Hasher) {
hasher.combine(value.userID)
}
}
enum PresentationAction: Hashable {
case eventFocus(FocusEvent)
case share(ShareExtensionPayload)
@@ -39,8 +39,6 @@ final class RoomMembersFlowCoordinator: FlowCoordinatorProtocol {
}
enum Event: EventType {
case start
case presentRoomMembersList
case presentRoomMemberDetails(userID: String)
@@ -234,8 +232,7 @@ final class RoomMembersFlowCoordinator: FlowCoordinatorProtocol {
roomProxy: roomProxy,
userSession: flowParameters.userSession,
userIndicatorController: flowParameters.userIndicatorController,
analytics: flowParameters.analytics,
appSettings: flowParameters.appSettings)
analytics: flowParameters.analytics)
let coordinator = RoomMemberDetailsScreenCoordinator(parameters: params)
coordinator.actions.sink { [weak self] action in
@@ -264,8 +261,7 @@ final class RoomMembersFlowCoordinator: FlowCoordinatorProtocol {
roomType: .existingRoom(roomProxy: roomProxy),
isSkippable: false,
userDiscoveryService: UserDiscoveryService(clientProxy: flowParameters.userSession.clientProxy),
userIndicatorController: flowParameters.userIndicatorController,
appSettings: flowParameters.appSettings)
userIndicatorController: flowParameters.userIndicatorController)
let coordinator = InviteUsersScreenCoordinator(parameters: inviteParameters)
stackCoordinator.setRootCoordinator(coordinator)
@@ -292,8 +288,7 @@ final class RoomMembersFlowCoordinator: FlowCoordinatorProtocol {
isPresentedModally: false,
userSession: flowParameters.userSession,
userIndicatorController: flowParameters.userIndicatorController,
analytics: flowParameters.analytics,
appSettings: flowParameters.appSettings)
analytics: flowParameters.analytics)
let coordinator = UserProfileScreenCoordinator(parameters: parameters)
coordinator.actionsPublisher.sink { [weak self] action in
guard let self else { return }
@@ -25,7 +25,6 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
// periphery:ignore - retaining purpose
private var appLockSetupFlowCoordinator: AppLockSetupFlowCoordinator?
// periphery:ignore - retaining purpose
private var bugReportFlowCoordinator: BugReportFlowCoordinator?
// periphery:ignore - retaining purpose
private var encryptionSettingsFlowCoordinator: EncryptionSettingsFlowCoordinator?
@@ -60,7 +59,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
case .settings:
presentSettingsScreen(animated: animated)
case .chatBackupSettings:
startEncryptionSettingsFlow(animated: animated)
startEncryptionSettingsFlow()
default:
break
}
@@ -89,7 +88,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
case .logout:
actionsSubject.send(.runLogoutFlow)
case .secureBackup:
startEncryptionSettingsFlow(animated: true)
startEncryptionSettingsFlow()
case .userDetails:
presentUserDetailsEditScreen()
case .linkNewDevice:
@@ -141,7 +140,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
navigationStackCoordinator.push(coordinator)
}
private func startEncryptionSettingsFlow(animated: Bool) {
private func startEncryptionSettingsFlow() {
let coordinator = EncryptionSettingsFlowCoordinator(parameters: .init(userSession: flowParameters.userSession,
appSettings: flowParameters.appSettings,
appHooks: flowParameters.appHooks,
@@ -165,8 +164,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
userSession: flowParameters.userSession,
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: flowParameters.appSettings),
navigationStackCoordinator: navigationStackCoordinator,
userIndicatorController: flowParameters.userIndicatorController,
appSettings: flowParameters.appSettings))
userIndicatorController: flowParameters.userIndicatorController))
coordinator.actions
.sink { [weak self] action in
switch action {
@@ -45,6 +45,7 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol {
private var membersFlowCoordinator: RoomMembersFlowCoordinator?
private var settingsFlowCoordinator: SpaceSettingsFlowCoordinator?
private var rolesAndPermissionsFlowCoordinator: RoomRolesAndPermissionsFlowCoordinator?
// periphery:ignore - retaining purpose
private var createChildRoomFlowCoordinator: StartChatFlowCoordinator?
indirect enum State: StateType {
@@ -40,8 +40,6 @@ final class SpaceSettingsFlowCoordinator: FlowCoordinatorProtocol {
}
enum Event: EventType {
case start
case presentSpaceSettings
case presentEditDetailsScreen
@@ -75,9 +73,6 @@ final class SpaceSettingsFlowCoordinator: FlowCoordinatorProtocol {
private let stateMachine: StateMachine<State, Event>
private var cancellables = Set<AnyCancellable>()
private var membersFlowCoordinator: RoomMembersFlowCoordinator?
private var rolesAndPermissionsFlowCoordinator: RoomRolesAndPermissionsFlowCoordinator?
private var childFlowCoordinator: FlowCoordinatorProtocol?
private let actionsSubject: PassthroughSubject<SpaceSettingsFlowCoordinatorAction, Never> = .init()
@@ -219,8 +214,7 @@ final class SpaceSettingsFlowCoordinator: FlowCoordinatorProtocol {
analyticsService: flowParameters.analytics,
userIndicatorController: flowParameters.userIndicatorController,
notificationSettings: flowParameters.userSession.clientProxy.notificationSettings,
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
appSettings: flowParameters.appSettings))
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder())))
var leftRoom = false
coordinator.actions.sink { [weak self] action in
@@ -259,8 +253,7 @@ final class SpaceSettingsFlowCoordinator: FlowCoordinatorProtocol {
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: flowParameters.appSettings),
navigationStackCoordinator: stackCoordinator,
userIndicatorController: flowParameters.userIndicatorController,
orientationManager: flowParameters.appMediator.windowManager,
appSettings: flowParameters.appSettings)
orientationManager: flowParameters.appMediator.windowManager)
let coordinator = RoomDetailsEditScreenCoordinator(parameters: parameters)
@@ -24,7 +24,9 @@ class SpacesTabFlowCoordinator: FlowCoordinatorProtocol {
private let sidebarNavigationStackCoordinator: NavigationStackCoordinator
private let detailNavigationStackCoordinator: NavigationStackCoordinator
// periphery:ignore - retaining purpose
private var spaceFlowCoordinator: SpaceFlowCoordinator?
// periphery:ignore - retaining purpose
private var startChatFlowCoordinator: StartChatFlowCoordinator?
enum State: StateType {
@@ -146,7 +148,6 @@ class SpacesTabFlowCoordinator: FlowCoordinatorProtocol {
private func presentSpacesScreen() {
let parameters = SpacesScreenCoordinatorParameters(userSession: userSession,
selectedSpacePublisher: selectedSpaceSubject.asCurrentValuePublisher(),
appSettings: flowParameters.appSettings,
userIndicatorController: flowParameters.userIndicatorController)
let coordinator = SpacesScreenCoordinator(parameters: parameters)
coordinator.actionsPublisher
@@ -185,7 +185,6 @@ class StartChatFlowCoordinator: FlowCoordinatorProtocol {
let parameters = StartChatScreenCoordinatorParameters(userSession: flowParameters.userSession,
userDiscoveryService: userDiscoveryService,
userIndicatorController: flowParameters.userIndicatorController,
appSettings: flowParameters.appSettings,
analytics: flowParameters.analytics)
let coordinator = StartChatScreenCoordinator(parameters: parameters)
@@ -273,8 +272,7 @@ class StartChatFlowCoordinator: FlowCoordinatorProtocol {
roomType: .existingRoom(roomProxy: roomProxy),
isSkippable: true,
userDiscoveryService: userDiscoveryService,
userIndicatorController: flowParameters.userIndicatorController,
appSettings: flowParameters.appSettings)
userIndicatorController: flowParameters.userIndicatorController)
let coordinator = InviteUsersScreenCoordinator(parameters: inviteParameters)
coordinator.actions.sink { [weak self] action in
guard let self else { return }
@@ -42,7 +42,6 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
private let searchTabNavigationStackCoordinator: NavigationStackCoordinator?
private let searchTabDetails: NavigationTabCoordinator<HomeTab>.TabDetails?
// periphery:ignore - retaining purpose
private var settingsFlowCoordinator: SettingsFlowCoordinator?
enum State: StateType {
@@ -84,8 +83,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
navigationRootCoordinator.setRootCoordinator(navigationTabCoordinator)
let chatsSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator(hideBrandChrome: flowParameters.appSettings.hideBrandChrome))
chatsTabFlowCoordinator = ChatsTabFlowCoordinator(isNewLogin: isNewLogin,
navigationSplitCoordinator: chatsSplitCoordinator,
chatsTabFlowCoordinator = ChatsTabFlowCoordinator(navigationSplitCoordinator: chatsSplitCoordinator,
flowParameters: flowParameters)
chatsTabDetails = .init(tag: HomeTab.chats, title: L10n.screenHomeTabChats, icon: \.chat, selectedIcon: \.chatSolid)
chatsTabDetails.navigationSplitCoordinator = chatsSplitCoordinator
@@ -33,9 +33,7 @@ extension RoomInfoProxyMock {
id = configuration.id
isEncrypted = false
creators = []
displayName = configuration.name
rawName = nil
topic = nil
avatarURL = configuration.avatarURL
@@ -47,20 +45,11 @@ extension RoomInfoProxyMock {
canonicalAlias = nil
alternativeAliases = []
membership = .knocked
inviter = nil
heroes = []
activeMembersCount = configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count
invitedMembersCount = configuration.members.filter { $0.membership == .invite }.count
joinedMembersCount = configuration.members.filter { $0.membership == .join }.count
highlightCount = 0
notificationCount = 0
cachedUserDefinedNotificationMode = nil
hasRoomCall = false
activeRoomCallParticipants = []
isMarkedUnread = false
unreadMessagesCount = 0
unreadNotificationsCount = 0
unreadMentionsCount = 0
pinnedEventIDs = []
joinRule = .knock
historyVisibility = .shared
@@ -248,23 +248,6 @@ nonisolated class AnalyticsServiceMock: AnalyticsServiceProtocol, @unchecked Sen
startIfEnabledCallsCountLock.withLock { startIfEnabledUnderlyingCallsCount += 1 }
startIfEnabledClosure?()
}
//MARK: - reset
private let resetCallsCountLock = NSLock()
private nonisolated(unsafe) var resetUnderlyingCallsCount = 0
var resetCallsCount: Int {
get { resetCallsCountLock.withLock { resetUnderlyingCallsCount } }
set { resetCallsCountLock.withLock { resetUnderlyingCallsCount = newValue } }
}
var resetCalled: Bool {
return resetCallsCount > 0
}
nonisolated(unsafe) var resetClosure: (() -> Void)?
func reset() {
resetCallsCountLock.withLock { resetUnderlyingCallsCount += 1 }
resetClosure?()
}
//MARK: - resetConsentState
private let resetConsentStateCallsCountLock = NSLock()
@@ -1061,65 +1044,6 @@ nonisolated class AppMediatorMock: AppMediatorProtocol, @unchecked Sendable {
}
nonisolated(unsafe) var underlyingAppState: UIApplication.State!
//MARK: - beginBackgroundTask
private let beginBackgroundTaskExpirationHandlerCallsCountLock = NSLock()
private nonisolated(unsafe) var beginBackgroundTaskExpirationHandlerUnderlyingCallsCount = 0
var beginBackgroundTaskExpirationHandlerCallsCount: Int {
get { beginBackgroundTaskExpirationHandlerCallsCountLock.withLock { beginBackgroundTaskExpirationHandlerUnderlyingCallsCount } }
set { beginBackgroundTaskExpirationHandlerCallsCountLock.withLock { beginBackgroundTaskExpirationHandlerUnderlyingCallsCount = newValue } }
}
var beginBackgroundTaskExpirationHandlerCalled: Bool {
return beginBackgroundTaskExpirationHandlerCallsCount > 0
}
private let beginBackgroundTaskExpirationHandlerReturnValueLock = NSLock()
private nonisolated(unsafe) var beginBackgroundTaskExpirationHandlerUnderlyingReturnValue: UIBackgroundTaskIdentifier!
var beginBackgroundTaskExpirationHandlerReturnValue: UIBackgroundTaskIdentifier! {
get { beginBackgroundTaskExpirationHandlerReturnValueLock.withLock { beginBackgroundTaskExpirationHandlerUnderlyingReturnValue } }
set { beginBackgroundTaskExpirationHandlerReturnValueLock.withLock { beginBackgroundTaskExpirationHandlerUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var beginBackgroundTaskExpirationHandlerClosure: (((@MainActor @Sendable () -> Void)?) -> UIBackgroundTaskIdentifier)?
func beginBackgroundTask(expirationHandler handler: (@MainActor @Sendable () -> Void)?) -> UIBackgroundTaskIdentifier {
beginBackgroundTaskExpirationHandlerCallsCountLock.withLock { beginBackgroundTaskExpirationHandlerUnderlyingCallsCount += 1 }
if let beginBackgroundTaskExpirationHandlerClosure = beginBackgroundTaskExpirationHandlerClosure {
return beginBackgroundTaskExpirationHandlerClosure(handler)
} else {
return beginBackgroundTaskExpirationHandlerReturnValue
}
}
//MARK: - endBackgroundTask
private let endBackgroundTaskCallsCountLock = NSLock()
private nonisolated(unsafe) var endBackgroundTaskUnderlyingCallsCount = 0
var endBackgroundTaskCallsCount: Int {
get { endBackgroundTaskCallsCountLock.withLock { endBackgroundTaskUnderlyingCallsCount } }
set { endBackgroundTaskCallsCountLock.withLock { endBackgroundTaskUnderlyingCallsCount = newValue } }
}
var endBackgroundTaskCalled: Bool {
return endBackgroundTaskCallsCount > 0
}
private let endBackgroundTaskReceivedIdentifierLock = NSLock()
private nonisolated(unsafe) var endBackgroundTaskUnderlyingReceivedIdentifier: UIBackgroundTaskIdentifier?
var endBackgroundTaskReceivedIdentifier: UIBackgroundTaskIdentifier? {
get { endBackgroundTaskReceivedIdentifierLock.withLock { endBackgroundTaskUnderlyingReceivedIdentifier } }
set { endBackgroundTaskReceivedIdentifierLock.withLock { endBackgroundTaskUnderlyingReceivedIdentifier = newValue } }
}
private let endBackgroundTaskReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var endBackgroundTaskUnderlyingReceivedInvocations: [UIBackgroundTaskIdentifier] = []
var endBackgroundTaskReceivedInvocations: [UIBackgroundTaskIdentifier] {
get { endBackgroundTaskReceivedInvocationsLock.withLock { endBackgroundTaskUnderlyingReceivedInvocations } }
set { endBackgroundTaskReceivedInvocationsLock.withLock { endBackgroundTaskUnderlyingReceivedInvocations = newValue } }
}
nonisolated(unsafe) var endBackgroundTaskClosure: ((UIBackgroundTaskIdentifier) -> Void)?
func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier) {
endBackgroundTaskCallsCountLock.withLock { endBackgroundTaskUnderlyingCallsCount += 1 }
endBackgroundTaskReceivedIdentifier = identifier
endBackgroundTaskReceivedInvocationsLock.withLock { endBackgroundTaskUnderlyingReceivedInvocations.append(identifier) }
endBackgroundTaskClosure?(identifier)
}
//MARK: - open
private let openCallsCountLock = NSLock()
@@ -1319,11 +1243,6 @@ nonisolated class AudioPlayerMock: AudioPlayerProtocol, @unchecked Sendable {
set(value) { underlyingState = value }
}
nonisolated(unsafe) var underlyingState: MediaPlayerState!
var playbackSpeed: Float {
get { return underlyingPlaybackSpeed }
set(value) { underlyingPlaybackSpeed = value }
}
nonisolated(unsafe) var underlyingPlaybackSpeed: Float!
var actions: AnyPublisher<AudioPlayerAction, Never> {
get { return underlyingActions }
set(value) { underlyingActions = value }
@@ -5127,7 +5046,6 @@ nonisolated class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Senda
}
nonisolated(unsafe) var underlyingTimeline: TimelineProxyProtocol!
nonisolated(unsafe) var predecessorRoom: PredecessorRoom?
nonisolated(unsafe) var successorRoom: SuccessorRoom?
var id: String {
get { return underlyingId }
set(value) { underlyingId = value }
@@ -5425,48 +5343,6 @@ nonisolated class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Senda
return enableEncryptionReturnValue
}
}
//MARK: - redact
private let redactCallsCountLock = NSLock()
private nonisolated(unsafe) var redactUnderlyingCallsCount = 0
var redactCallsCount: Int {
get { redactCallsCountLock.withLock { redactUnderlyingCallsCount } }
set { redactCallsCountLock.withLock { redactUnderlyingCallsCount = newValue } }
}
var redactCalled: Bool {
return redactCallsCount > 0
}
private let redactReceivedEventIDLock = NSLock()
private nonisolated(unsafe) var redactUnderlyingReceivedEventID: String?
var redactReceivedEventID: String? {
get { redactReceivedEventIDLock.withLock { redactUnderlyingReceivedEventID } }
set { redactReceivedEventIDLock.withLock { redactUnderlyingReceivedEventID = newValue } }
}
private let redactReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var redactUnderlyingReceivedInvocations: [String] = []
var redactReceivedInvocations: [String] {
get { redactReceivedInvocationsLock.withLock { redactUnderlyingReceivedInvocations } }
set { redactReceivedInvocationsLock.withLock { redactUnderlyingReceivedInvocations = newValue } }
}
private let redactReturnValueLock = NSLock()
private nonisolated(unsafe) var redactUnderlyingReturnValue: Result<Void, RoomProxyError>!
var redactReturnValue: Result<Void, RoomProxyError>! {
get { redactReturnValueLock.withLock { redactUnderlyingReturnValue } }
set { redactReturnValueLock.withLock { redactUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var redactClosure: ((String) async -> Result<Void, RoomProxyError>)?
@concurrent func redact(_ eventID: String) async -> Result<Void, RoomProxyError> {
redactCallsCountLock.withLock { redactUnderlyingCallsCount += 1 }
redactReceivedEventID = eventID
redactReceivedInvocationsLock.withLock { redactUnderlyingReceivedInvocations.append(eventID) }
if let redactClosure = redactClosure {
return await redactClosure(eventID)
} else {
return redactReturnValue
}
}
//MARK: - reportContent
private let reportContentReasonCallsCountLock = NSLock()
@@ -5876,48 +5752,6 @@ nonisolated class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Senda
return markAsReadReceiptTypeReturnValue
}
}
//MARK: - edit
private let editEventIDNewContentCallsCountLock = NSLock()
private nonisolated(unsafe) var editEventIDNewContentUnderlyingCallsCount = 0
var editEventIDNewContentCallsCount: Int {
get { editEventIDNewContentCallsCountLock.withLock { editEventIDNewContentUnderlyingCallsCount } }
set { editEventIDNewContentCallsCountLock.withLock { editEventIDNewContentUnderlyingCallsCount = newValue } }
}
var editEventIDNewContentCalled: Bool {
return editEventIDNewContentCallsCount > 0
}
private let editEventIDNewContentReceivedArgumentsLock = NSLock()
private nonisolated(unsafe) var editEventIDNewContentUnderlyingReceivedArguments: (eventID: String, newContent: RoomMessageEventContentWithoutRelation)?
var editEventIDNewContentReceivedArguments: (eventID: String, newContent: RoomMessageEventContentWithoutRelation)? {
get { editEventIDNewContentReceivedArgumentsLock.withLock { editEventIDNewContentUnderlyingReceivedArguments } }
set { editEventIDNewContentReceivedArgumentsLock.withLock { editEventIDNewContentUnderlyingReceivedArguments = newValue } }
}
private let editEventIDNewContentReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var editEventIDNewContentUnderlyingReceivedInvocations: [(eventID: String, newContent: RoomMessageEventContentWithoutRelation)] = []
var editEventIDNewContentReceivedInvocations: [(eventID: String, newContent: RoomMessageEventContentWithoutRelation)] {
get { editEventIDNewContentReceivedInvocationsLock.withLock { editEventIDNewContentUnderlyingReceivedInvocations } }
set { editEventIDNewContentReceivedInvocationsLock.withLock { editEventIDNewContentUnderlyingReceivedInvocations = newValue } }
}
private let editEventIDNewContentReturnValueLock = NSLock()
private nonisolated(unsafe) var editEventIDNewContentUnderlyingReturnValue: Result<Void, RoomProxyError>!
var editEventIDNewContentReturnValue: Result<Void, RoomProxyError>! {
get { editEventIDNewContentReturnValueLock.withLock { editEventIDNewContentUnderlyingReturnValue } }
set { editEventIDNewContentReturnValueLock.withLock { editEventIDNewContentUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var editEventIDNewContentClosure: ((String, RoomMessageEventContentWithoutRelation) async -> Result<Void, RoomProxyError>)?
@concurrent func edit(eventID: String, newContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, RoomProxyError> {
editEventIDNewContentCallsCountLock.withLock { editEventIDNewContentUnderlyingCallsCount += 1 }
editEventIDNewContentReceivedArguments = (eventID: eventID, newContent: newContent)
editEventIDNewContentReceivedInvocationsLock.withLock { editEventIDNewContentUnderlyingReceivedInvocations.append((eventID: eventID, newContent: newContent)) }
if let editEventIDNewContentClosure = editEventIDNewContentClosure {
return await editEventIDNewContentClosure(eventID, newContent)
} else {
return editEventIDNewContentReturnValue
}
}
//MARK: - sendTypingNotification
private let sendTypingNotificationIsTypingCallsCountLock = NSLock()
@@ -6409,34 +6243,6 @@ nonisolated class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Senda
return flagAsFavouriteReturnValue
}
}
//MARK: - powerLevels
private let powerLevelsCallsCountLock = NSLock()
private nonisolated(unsafe) var powerLevelsUnderlyingCallsCount = 0
var powerLevelsCallsCount: Int {
get { powerLevelsCallsCountLock.withLock { powerLevelsUnderlyingCallsCount } }
set { powerLevelsCallsCountLock.withLock { powerLevelsUnderlyingCallsCount = newValue } }
}
var powerLevelsCalled: Bool {
return powerLevelsCallsCount > 0
}
private let powerLevelsReturnValueLock = NSLock()
private nonisolated(unsafe) var powerLevelsUnderlyingReturnValue: Result<RoomPowerLevelsProxyProtocol?, RoomProxyError>!
var powerLevelsReturnValue: Result<RoomPowerLevelsProxyProtocol?, RoomProxyError>! {
get { powerLevelsReturnValueLock.withLock { powerLevelsUnderlyingReturnValue } }
set { powerLevelsReturnValueLock.withLock { powerLevelsUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var powerLevelsClosure: (() async -> Result<RoomPowerLevelsProxyProtocol?, RoomProxyError>)?
@concurrent func powerLevels() async -> Result<RoomPowerLevelsProxyProtocol?, RoomProxyError> {
powerLevelsCallsCountLock.withLock { powerLevelsUnderlyingCallsCount += 1 }
if let powerLevelsClosure = powerLevelsClosure {
return await powerLevelsClosure()
} else {
return powerLevelsReturnValue
}
}
//MARK: - applyPowerLevelChanges
private let applyPowerLevelChangesCallsCountLock = NSLock()
@@ -6507,48 +6313,6 @@ nonisolated class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Senda
return resetPowerLevelsReturnValue
}
}
//MARK: - suggestedRole
private let suggestedRoleForCallsCountLock = NSLock()
private nonisolated(unsafe) var suggestedRoleForUnderlyingCallsCount = 0
var suggestedRoleForCallsCount: Int {
get { suggestedRoleForCallsCountLock.withLock { suggestedRoleForUnderlyingCallsCount } }
set { suggestedRoleForCallsCountLock.withLock { suggestedRoleForUnderlyingCallsCount = newValue } }
}
var suggestedRoleForCalled: Bool {
return suggestedRoleForCallsCount > 0
}
private let suggestedRoleForReceivedUserIDLock = NSLock()
private nonisolated(unsafe) var suggestedRoleForUnderlyingReceivedUserID: String?
var suggestedRoleForReceivedUserID: String? {
get { suggestedRoleForReceivedUserIDLock.withLock { suggestedRoleForUnderlyingReceivedUserID } }
set { suggestedRoleForReceivedUserIDLock.withLock { suggestedRoleForUnderlyingReceivedUserID = newValue } }
}
private let suggestedRoleForReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var suggestedRoleForUnderlyingReceivedInvocations: [String] = []
var suggestedRoleForReceivedInvocations: [String] {
get { suggestedRoleForReceivedInvocationsLock.withLock { suggestedRoleForUnderlyingReceivedInvocations } }
set { suggestedRoleForReceivedInvocationsLock.withLock { suggestedRoleForUnderlyingReceivedInvocations = newValue } }
}
private let suggestedRoleForReturnValueLock = NSLock()
private nonisolated(unsafe) var suggestedRoleForUnderlyingReturnValue: Result<RoomMemberRole, RoomProxyError>!
var suggestedRoleForReturnValue: Result<RoomMemberRole, RoomProxyError>! {
get { suggestedRoleForReturnValueLock.withLock { suggestedRoleForUnderlyingReturnValue } }
set { suggestedRoleForReturnValueLock.withLock { suggestedRoleForUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var suggestedRoleForClosure: ((String) async -> Result<RoomMemberRole, RoomProxyError>)?
@concurrent func suggestedRole(for userID: String) async -> Result<RoomMemberRole, RoomProxyError> {
suggestedRoleForCallsCountLock.withLock { suggestedRoleForUnderlyingCallsCount += 1 }
suggestedRoleForReceivedUserID = userID
suggestedRoleForReceivedInvocationsLock.withLock { suggestedRoleForUnderlyingReceivedInvocations.append(userID) }
if let suggestedRoleForClosure = suggestedRoleForClosure {
return await suggestedRoleForClosure(userID)
} else {
return suggestedRoleForReturnValue
}
}
//MARK: - updatePowerLevelsForUsers
private let updatePowerLevelsForUsersCallsCountLock = NSLock()
@@ -8201,48 +7965,6 @@ nonisolated class MediaProviderMock: MediaProviderProtocol, @unchecked Sendable
return imageFromSourceSizeReturnValue
}
}
//MARK: - loadImageFromSource
private let loadImageFromSourceSizeCallsCountLock = NSLock()
private nonisolated(unsafe) var loadImageFromSourceSizeUnderlyingCallsCount = 0
var loadImageFromSourceSizeCallsCount: Int {
get { loadImageFromSourceSizeCallsCountLock.withLock { loadImageFromSourceSizeUnderlyingCallsCount } }
set { loadImageFromSourceSizeCallsCountLock.withLock { loadImageFromSourceSizeUnderlyingCallsCount = newValue } }
}
var loadImageFromSourceSizeCalled: Bool {
return loadImageFromSourceSizeCallsCount > 0
}
private let loadImageFromSourceSizeReceivedArgumentsLock = NSLock()
private nonisolated(unsafe) var loadImageFromSourceSizeUnderlyingReceivedArguments: (source: MediaSourceProxy, size: CGSize?)?
var loadImageFromSourceSizeReceivedArguments: (source: MediaSourceProxy, size: CGSize?)? {
get { loadImageFromSourceSizeReceivedArgumentsLock.withLock { loadImageFromSourceSizeUnderlyingReceivedArguments } }
set { loadImageFromSourceSizeReceivedArgumentsLock.withLock { loadImageFromSourceSizeUnderlyingReceivedArguments = newValue } }
}
private let loadImageFromSourceSizeReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var loadImageFromSourceSizeUnderlyingReceivedInvocations: [(source: MediaSourceProxy, size: CGSize?)] = []
var loadImageFromSourceSizeReceivedInvocations: [(source: MediaSourceProxy, size: CGSize?)] {
get { loadImageFromSourceSizeReceivedInvocationsLock.withLock { loadImageFromSourceSizeUnderlyingReceivedInvocations } }
set { loadImageFromSourceSizeReceivedInvocationsLock.withLock { loadImageFromSourceSizeUnderlyingReceivedInvocations = newValue } }
}
private let loadImageFromSourceSizeReturnValueLock = NSLock()
private nonisolated(unsafe) var loadImageFromSourceSizeUnderlyingReturnValue: Result<UIImage, MediaProviderError>!
var loadImageFromSourceSizeReturnValue: Result<UIImage, MediaProviderError>! {
get { loadImageFromSourceSizeReturnValueLock.withLock { loadImageFromSourceSizeUnderlyingReturnValue } }
set { loadImageFromSourceSizeReturnValueLock.withLock { loadImageFromSourceSizeUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var loadImageFromSourceSizeClosure: ((MediaSourceProxy, CGSize?) async -> Result<UIImage, MediaProviderError>)?
@concurrent func loadImageFromSource(_ source: MediaSourceProxy, size: CGSize?) async -> Result<UIImage, MediaProviderError> {
loadImageFromSourceSizeCallsCountLock.withLock { loadImageFromSourceSizeUnderlyingCallsCount += 1 }
loadImageFromSourceSizeReceivedArguments = (source: source, size: size)
loadImageFromSourceSizeReceivedInvocationsLock.withLock { loadImageFromSourceSizeUnderlyingReceivedInvocations.append((source: source, size: size)) }
if let loadImageFromSourceSizeClosure = loadImageFromSourceSizeClosure {
return await loadImageFromSourceSizeClosure(source, size)
} else {
return loadImageFromSourceSizeReturnValue
}
}
//MARK: - loadImageDataFromSource
private let loadImageDataFromSourceCallsCountLock = NSLock()
@@ -8453,90 +8175,6 @@ nonisolated class NSEUserSessionMock: NSEUserSessionProtocol, @unchecked Sendabl
}
nonisolated(unsafe) var underlyingThreadsEnabled: Bool!
//MARK: - notificationItemProxy
private let notificationItemProxyRoomIDEventIDCallsCountLock = NSLock()
private nonisolated(unsafe) var notificationItemProxyRoomIDEventIDUnderlyingCallsCount = 0
var notificationItemProxyRoomIDEventIDCallsCount: Int {
get { notificationItemProxyRoomIDEventIDCallsCountLock.withLock { notificationItemProxyRoomIDEventIDUnderlyingCallsCount } }
set { notificationItemProxyRoomIDEventIDCallsCountLock.withLock { notificationItemProxyRoomIDEventIDUnderlyingCallsCount = newValue } }
}
var notificationItemProxyRoomIDEventIDCalled: Bool {
return notificationItemProxyRoomIDEventIDCallsCount > 0
}
private let notificationItemProxyRoomIDEventIDReceivedArgumentsLock = NSLock()
private nonisolated(unsafe) var notificationItemProxyRoomIDEventIDUnderlyingReceivedArguments: (roomID: String, eventID: String)?
var notificationItemProxyRoomIDEventIDReceivedArguments: (roomID: String, eventID: String)? {
get { notificationItemProxyRoomIDEventIDReceivedArgumentsLock.withLock { notificationItemProxyRoomIDEventIDUnderlyingReceivedArguments } }
set { notificationItemProxyRoomIDEventIDReceivedArgumentsLock.withLock { notificationItemProxyRoomIDEventIDUnderlyingReceivedArguments = newValue } }
}
private let notificationItemProxyRoomIDEventIDReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var notificationItemProxyRoomIDEventIDUnderlyingReceivedInvocations: [(roomID: String, eventID: String)] = []
var notificationItemProxyRoomIDEventIDReceivedInvocations: [(roomID: String, eventID: String)] {
get { notificationItemProxyRoomIDEventIDReceivedInvocationsLock.withLock { notificationItemProxyRoomIDEventIDUnderlyingReceivedInvocations } }
set { notificationItemProxyRoomIDEventIDReceivedInvocationsLock.withLock { notificationItemProxyRoomIDEventIDUnderlyingReceivedInvocations = newValue } }
}
private let notificationItemProxyRoomIDEventIDReturnValueLock = NSLock()
private nonisolated(unsafe) var notificationItemProxyRoomIDEventIDUnderlyingReturnValue: NotificationItemProxyProtocol?
var notificationItemProxyRoomIDEventIDReturnValue: NotificationItemProxyProtocol? {
get { notificationItemProxyRoomIDEventIDReturnValueLock.withLock { notificationItemProxyRoomIDEventIDUnderlyingReturnValue } }
set { notificationItemProxyRoomIDEventIDReturnValueLock.withLock { notificationItemProxyRoomIDEventIDUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var notificationItemProxyRoomIDEventIDClosure: ((String, String) async -> NotificationItemProxyProtocol?)?
@concurrent func notificationItemProxy(roomID: String, eventID: String) async -> NotificationItemProxyProtocol? {
notificationItemProxyRoomIDEventIDCallsCountLock.withLock { notificationItemProxyRoomIDEventIDUnderlyingCallsCount += 1 }
notificationItemProxyRoomIDEventIDReceivedArguments = (roomID: roomID, eventID: eventID)
notificationItemProxyRoomIDEventIDReceivedInvocationsLock.withLock { notificationItemProxyRoomIDEventIDUnderlyingReceivedInvocations.append((roomID: roomID, eventID: eventID)) }
if let notificationItemProxyRoomIDEventIDClosure = notificationItemProxyRoomIDEventIDClosure {
return await notificationItemProxyRoomIDEventIDClosure(roomID, eventID)
} else {
return notificationItemProxyRoomIDEventIDReturnValue
}
}
//MARK: - roomForIdentifier
private let roomForIdentifierCallsCountLock = NSLock()
private nonisolated(unsafe) var roomForIdentifierUnderlyingCallsCount = 0
var roomForIdentifierCallsCount: Int {
get { roomForIdentifierCallsCountLock.withLock { roomForIdentifierUnderlyingCallsCount } }
set { roomForIdentifierCallsCountLock.withLock { roomForIdentifierUnderlyingCallsCount = newValue } }
}
var roomForIdentifierCalled: Bool {
return roomForIdentifierCallsCount > 0
}
private let roomForIdentifierReceivedRoomIDLock = NSLock()
private nonisolated(unsafe) var roomForIdentifierUnderlyingReceivedRoomID: String?
var roomForIdentifierReceivedRoomID: String? {
get { roomForIdentifierReceivedRoomIDLock.withLock { roomForIdentifierUnderlyingReceivedRoomID } }
set { roomForIdentifierReceivedRoomIDLock.withLock { roomForIdentifierUnderlyingReceivedRoomID = newValue } }
}
private let roomForIdentifierReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var roomForIdentifierUnderlyingReceivedInvocations: [String] = []
var roomForIdentifierReceivedInvocations: [String] {
get { roomForIdentifierReceivedInvocationsLock.withLock { roomForIdentifierUnderlyingReceivedInvocations } }
set { roomForIdentifierReceivedInvocationsLock.withLock { roomForIdentifierUnderlyingReceivedInvocations = newValue } }
}
private let roomForIdentifierReturnValueLock = NSLock()
private nonisolated(unsafe) var roomForIdentifierUnderlyingReturnValue: Room?
var roomForIdentifierReturnValue: Room? {
get { roomForIdentifierReturnValueLock.withLock { roomForIdentifierUnderlyingReturnValue } }
set { roomForIdentifierReturnValueLock.withLock { roomForIdentifierUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var roomForIdentifierClosure: ((String) -> Room?)?
func roomForIdentifier(_ roomID: String) -> Room? {
roomForIdentifierCallsCountLock.withLock { roomForIdentifierUnderlyingCallsCount += 1 }
roomForIdentifierReceivedRoomID = roomID
roomForIdentifierReceivedInvocationsLock.withLock { roomForIdentifierUnderlyingReceivedInvocations.append(roomID) }
if let roomForIdentifierClosure = roomForIdentifierClosure {
return roomForIdentifierClosure(roomID)
} else {
return roomForIdentifierReturnValue
}
}
}
nonisolated class NetworkMonitorMock: NetworkMonitorProtocol, @unchecked Sendable {
var reachabilityPublisher: CurrentValuePublisher<NetworkMonitorReachability, Never> {
@@ -8571,21 +8209,11 @@ nonisolated class NotificationItemProxyMock: NotificationItemProxyProtocol, @unc
}
nonisolated(unsafe) var underlyingRoomDisplayName: String!
nonisolated(unsafe) var roomAvatarMediaSource: MediaSourceProxy?
var roomJoinedMembers: Int {
get { return underlyingRoomJoinedMembers }
set(value) { underlyingRoomJoinedMembers = value }
}
nonisolated(unsafe) var underlyingRoomJoinedMembers: Int!
var isRoomSpace: Bool {
get { return underlyingIsRoomSpace }
set(value) { underlyingIsRoomSpace = value }
}
nonisolated(unsafe) var underlyingIsRoomSpace: Bool!
var isRoomDirect: Bool {
get { return underlyingIsRoomDirect }
set(value) { underlyingIsRoomDirect = value }
}
nonisolated(unsafe) var underlyingIsRoomDirect: Bool!
var isRoomPrivate: Bool {
get { return underlyingIsRoomPrivate }
set(value) { underlyingIsRoomPrivate = value }
@@ -10509,426 +10137,6 @@ nonisolated class RoomPowerLevelsProxyMock: RoomPowerLevelsProxyProtocol, @unche
return canOwnUserEditRolesAndPermissionsReturnValue
}
}
//MARK: - canUser
private let canUserUserIDSendMessageCallsCountLock = NSLock()
private nonisolated(unsafe) var canUserUserIDSendMessageUnderlyingCallsCount = 0
var canUserUserIDSendMessageCallsCount: Int {
get { canUserUserIDSendMessageCallsCountLock.withLock { canUserUserIDSendMessageUnderlyingCallsCount } }
set { canUserUserIDSendMessageCallsCountLock.withLock { canUserUserIDSendMessageUnderlyingCallsCount = newValue } }
}
var canUserUserIDSendMessageCalled: Bool {
return canUserUserIDSendMessageCallsCount > 0
}
private let canUserUserIDSendMessageReceivedArgumentsLock = NSLock()
private nonisolated(unsafe) var canUserUserIDSendMessageUnderlyingReceivedArguments: (userID: String, messageType: MessageLikeEventType)?
var canUserUserIDSendMessageReceivedArguments: (userID: String, messageType: MessageLikeEventType)? {
get { canUserUserIDSendMessageReceivedArgumentsLock.withLock { canUserUserIDSendMessageUnderlyingReceivedArguments } }
set { canUserUserIDSendMessageReceivedArgumentsLock.withLock { canUserUserIDSendMessageUnderlyingReceivedArguments = newValue } }
}
private let canUserUserIDSendMessageReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var canUserUserIDSendMessageUnderlyingReceivedInvocations: [(userID: String, messageType: MessageLikeEventType)] = []
var canUserUserIDSendMessageReceivedInvocations: [(userID: String, messageType: MessageLikeEventType)] {
get { canUserUserIDSendMessageReceivedInvocationsLock.withLock { canUserUserIDSendMessageUnderlyingReceivedInvocations } }
set { canUserUserIDSendMessageReceivedInvocationsLock.withLock { canUserUserIDSendMessageUnderlyingReceivedInvocations = newValue } }
}
private let canUserUserIDSendMessageReturnValueLock = NSLock()
private nonisolated(unsafe) var canUserUserIDSendMessageUnderlyingReturnValue: Result<Bool, RoomProxyError>!
var canUserUserIDSendMessageReturnValue: Result<Bool, RoomProxyError>! {
get { canUserUserIDSendMessageReturnValueLock.withLock { canUserUserIDSendMessageUnderlyingReturnValue } }
set { canUserUserIDSendMessageReturnValueLock.withLock { canUserUserIDSendMessageUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var canUserUserIDSendMessageClosure: ((String, MessageLikeEventType) -> Result<Bool, RoomProxyError>)?
func canUser(userID: String, sendMessage messageType: MessageLikeEventType) -> Result<Bool, RoomProxyError> {
canUserUserIDSendMessageCallsCountLock.withLock { canUserUserIDSendMessageUnderlyingCallsCount += 1 }
canUserUserIDSendMessageReceivedArguments = (userID: userID, messageType: messageType)
canUserUserIDSendMessageReceivedInvocationsLock.withLock { canUserUserIDSendMessageUnderlyingReceivedInvocations.append((userID: userID, messageType: messageType)) }
if let canUserUserIDSendMessageClosure = canUserUserIDSendMessageClosure {
return canUserUserIDSendMessageClosure(userID, messageType)
} else {
return canUserUserIDSendMessageReturnValue
}
}
//MARK: - canUser
private let canUserUserIDSendStateEventCallsCountLock = NSLock()
private nonisolated(unsafe) var canUserUserIDSendStateEventUnderlyingCallsCount = 0
var canUserUserIDSendStateEventCallsCount: Int {
get { canUserUserIDSendStateEventCallsCountLock.withLock { canUserUserIDSendStateEventUnderlyingCallsCount } }
set { canUserUserIDSendStateEventCallsCountLock.withLock { canUserUserIDSendStateEventUnderlyingCallsCount = newValue } }
}
var canUserUserIDSendStateEventCalled: Bool {
return canUserUserIDSendStateEventCallsCount > 0
}
private let canUserUserIDSendStateEventReceivedArgumentsLock = NSLock()
private nonisolated(unsafe) var canUserUserIDSendStateEventUnderlyingReceivedArguments: (userID: String, event: StateEventType)?
var canUserUserIDSendStateEventReceivedArguments: (userID: String, event: StateEventType)? {
get { canUserUserIDSendStateEventReceivedArgumentsLock.withLock { canUserUserIDSendStateEventUnderlyingReceivedArguments } }
set { canUserUserIDSendStateEventReceivedArgumentsLock.withLock { canUserUserIDSendStateEventUnderlyingReceivedArguments = newValue } }
}
private let canUserUserIDSendStateEventReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var canUserUserIDSendStateEventUnderlyingReceivedInvocations: [(userID: String, event: StateEventType)] = []
var canUserUserIDSendStateEventReceivedInvocations: [(userID: String, event: StateEventType)] {
get { canUserUserIDSendStateEventReceivedInvocationsLock.withLock { canUserUserIDSendStateEventUnderlyingReceivedInvocations } }
set { canUserUserIDSendStateEventReceivedInvocationsLock.withLock { canUserUserIDSendStateEventUnderlyingReceivedInvocations = newValue } }
}
private let canUserUserIDSendStateEventReturnValueLock = NSLock()
private nonisolated(unsafe) var canUserUserIDSendStateEventUnderlyingReturnValue: Result<Bool, RoomProxyError>!
var canUserUserIDSendStateEventReturnValue: Result<Bool, RoomProxyError>! {
get { canUserUserIDSendStateEventReturnValueLock.withLock { canUserUserIDSendStateEventUnderlyingReturnValue } }
set { canUserUserIDSendStateEventReturnValueLock.withLock { canUserUserIDSendStateEventUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var canUserUserIDSendStateEventClosure: ((String, StateEventType) -> Result<Bool, RoomProxyError>)?
func canUser(userID: String, sendStateEvent event: StateEventType) -> Result<Bool, RoomProxyError> {
canUserUserIDSendStateEventCallsCountLock.withLock { canUserUserIDSendStateEventUnderlyingCallsCount += 1 }
canUserUserIDSendStateEventReceivedArguments = (userID: userID, event: event)
canUserUserIDSendStateEventReceivedInvocationsLock.withLock { canUserUserIDSendStateEventUnderlyingReceivedInvocations.append((userID: userID, event: event)) }
if let canUserUserIDSendStateEventClosure = canUserUserIDSendStateEventClosure {
return canUserUserIDSendStateEventClosure(userID, event)
} else {
return canUserUserIDSendStateEventReturnValue
}
}
//MARK: - canUserInvite
private let canUserInviteUserIDCallsCountLock = NSLock()
private nonisolated(unsafe) var canUserInviteUserIDUnderlyingCallsCount = 0
var canUserInviteUserIDCallsCount: Int {
get { canUserInviteUserIDCallsCountLock.withLock { canUserInviteUserIDUnderlyingCallsCount } }
set { canUserInviteUserIDCallsCountLock.withLock { canUserInviteUserIDUnderlyingCallsCount = newValue } }
}
var canUserInviteUserIDCalled: Bool {
return canUserInviteUserIDCallsCount > 0
}
private let canUserInviteUserIDReceivedUserIDLock = NSLock()
private nonisolated(unsafe) var canUserInviteUserIDUnderlyingReceivedUserID: String?
var canUserInviteUserIDReceivedUserID: String? {
get { canUserInviteUserIDReceivedUserIDLock.withLock { canUserInviteUserIDUnderlyingReceivedUserID } }
set { canUserInviteUserIDReceivedUserIDLock.withLock { canUserInviteUserIDUnderlyingReceivedUserID = newValue } }
}
private let canUserInviteUserIDReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var canUserInviteUserIDUnderlyingReceivedInvocations: [String] = []
var canUserInviteUserIDReceivedInvocations: [String] {
get { canUserInviteUserIDReceivedInvocationsLock.withLock { canUserInviteUserIDUnderlyingReceivedInvocations } }
set { canUserInviteUserIDReceivedInvocationsLock.withLock { canUserInviteUserIDUnderlyingReceivedInvocations = newValue } }
}
private let canUserInviteUserIDReturnValueLock = NSLock()
private nonisolated(unsafe) var canUserInviteUserIDUnderlyingReturnValue: Result<Bool, RoomProxyError>!
var canUserInviteUserIDReturnValue: Result<Bool, RoomProxyError>! {
get { canUserInviteUserIDReturnValueLock.withLock { canUserInviteUserIDUnderlyingReturnValue } }
set { canUserInviteUserIDReturnValueLock.withLock { canUserInviteUserIDUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var canUserInviteUserIDClosure: ((String) -> Result<Bool, RoomProxyError>)?
func canUserInvite(userID: String) -> Result<Bool, RoomProxyError> {
canUserInviteUserIDCallsCountLock.withLock { canUserInviteUserIDUnderlyingCallsCount += 1 }
canUserInviteUserIDReceivedUserID = userID
canUserInviteUserIDReceivedInvocationsLock.withLock { canUserInviteUserIDUnderlyingReceivedInvocations.append(userID) }
if let canUserInviteUserIDClosure = canUserInviteUserIDClosure {
return canUserInviteUserIDClosure(userID)
} else {
return canUserInviteUserIDReturnValue
}
}
//MARK: - canUserRedactOther
private let canUserRedactOtherUserIDCallsCountLock = NSLock()
private nonisolated(unsafe) var canUserRedactOtherUserIDUnderlyingCallsCount = 0
var canUserRedactOtherUserIDCallsCount: Int {
get { canUserRedactOtherUserIDCallsCountLock.withLock { canUserRedactOtherUserIDUnderlyingCallsCount } }
set { canUserRedactOtherUserIDCallsCountLock.withLock { canUserRedactOtherUserIDUnderlyingCallsCount = newValue } }
}
var canUserRedactOtherUserIDCalled: Bool {
return canUserRedactOtherUserIDCallsCount > 0
}
private let canUserRedactOtherUserIDReceivedUserIDLock = NSLock()
private nonisolated(unsafe) var canUserRedactOtherUserIDUnderlyingReceivedUserID: String?
var canUserRedactOtherUserIDReceivedUserID: String? {
get { canUserRedactOtherUserIDReceivedUserIDLock.withLock { canUserRedactOtherUserIDUnderlyingReceivedUserID } }
set { canUserRedactOtherUserIDReceivedUserIDLock.withLock { canUserRedactOtherUserIDUnderlyingReceivedUserID = newValue } }
}
private let canUserRedactOtherUserIDReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var canUserRedactOtherUserIDUnderlyingReceivedInvocations: [String] = []
var canUserRedactOtherUserIDReceivedInvocations: [String] {
get { canUserRedactOtherUserIDReceivedInvocationsLock.withLock { canUserRedactOtherUserIDUnderlyingReceivedInvocations } }
set { canUserRedactOtherUserIDReceivedInvocationsLock.withLock { canUserRedactOtherUserIDUnderlyingReceivedInvocations = newValue } }
}
private let canUserRedactOtherUserIDReturnValueLock = NSLock()
private nonisolated(unsafe) var canUserRedactOtherUserIDUnderlyingReturnValue: Result<Bool, RoomProxyError>!
var canUserRedactOtherUserIDReturnValue: Result<Bool, RoomProxyError>! {
get { canUserRedactOtherUserIDReturnValueLock.withLock { canUserRedactOtherUserIDUnderlyingReturnValue } }
set { canUserRedactOtherUserIDReturnValueLock.withLock { canUserRedactOtherUserIDUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var canUserRedactOtherUserIDClosure: ((String) -> Result<Bool, RoomProxyError>)?
func canUserRedactOther(userID: String) -> Result<Bool, RoomProxyError> {
canUserRedactOtherUserIDCallsCountLock.withLock { canUserRedactOtherUserIDUnderlyingCallsCount += 1 }
canUserRedactOtherUserIDReceivedUserID = userID
canUserRedactOtherUserIDReceivedInvocationsLock.withLock { canUserRedactOtherUserIDUnderlyingReceivedInvocations.append(userID) }
if let canUserRedactOtherUserIDClosure = canUserRedactOtherUserIDClosure {
return canUserRedactOtherUserIDClosure(userID)
} else {
return canUserRedactOtherUserIDReturnValue
}
}
//MARK: - canUserRedactOwn
private let canUserRedactOwnUserIDCallsCountLock = NSLock()
private nonisolated(unsafe) var canUserRedactOwnUserIDUnderlyingCallsCount = 0
var canUserRedactOwnUserIDCallsCount: Int {
get { canUserRedactOwnUserIDCallsCountLock.withLock { canUserRedactOwnUserIDUnderlyingCallsCount } }
set { canUserRedactOwnUserIDCallsCountLock.withLock { canUserRedactOwnUserIDUnderlyingCallsCount = newValue } }
}
var canUserRedactOwnUserIDCalled: Bool {
return canUserRedactOwnUserIDCallsCount > 0
}
private let canUserRedactOwnUserIDReceivedUserIDLock = NSLock()
private nonisolated(unsafe) var canUserRedactOwnUserIDUnderlyingReceivedUserID: String?
var canUserRedactOwnUserIDReceivedUserID: String? {
get { canUserRedactOwnUserIDReceivedUserIDLock.withLock { canUserRedactOwnUserIDUnderlyingReceivedUserID } }
set { canUserRedactOwnUserIDReceivedUserIDLock.withLock { canUserRedactOwnUserIDUnderlyingReceivedUserID = newValue } }
}
private let canUserRedactOwnUserIDReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var canUserRedactOwnUserIDUnderlyingReceivedInvocations: [String] = []
var canUserRedactOwnUserIDReceivedInvocations: [String] {
get { canUserRedactOwnUserIDReceivedInvocationsLock.withLock { canUserRedactOwnUserIDUnderlyingReceivedInvocations } }
set { canUserRedactOwnUserIDReceivedInvocationsLock.withLock { canUserRedactOwnUserIDUnderlyingReceivedInvocations = newValue } }
}
private let canUserRedactOwnUserIDReturnValueLock = NSLock()
private nonisolated(unsafe) var canUserRedactOwnUserIDUnderlyingReturnValue: Result<Bool, RoomProxyError>!
var canUserRedactOwnUserIDReturnValue: Result<Bool, RoomProxyError>! {
get { canUserRedactOwnUserIDReturnValueLock.withLock { canUserRedactOwnUserIDUnderlyingReturnValue } }
set { canUserRedactOwnUserIDReturnValueLock.withLock { canUserRedactOwnUserIDUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var canUserRedactOwnUserIDClosure: ((String) -> Result<Bool, RoomProxyError>)?
func canUserRedactOwn(userID: String) -> Result<Bool, RoomProxyError> {
canUserRedactOwnUserIDCallsCountLock.withLock { canUserRedactOwnUserIDUnderlyingCallsCount += 1 }
canUserRedactOwnUserIDReceivedUserID = userID
canUserRedactOwnUserIDReceivedInvocationsLock.withLock { canUserRedactOwnUserIDUnderlyingReceivedInvocations.append(userID) }
if let canUserRedactOwnUserIDClosure = canUserRedactOwnUserIDClosure {
return canUserRedactOwnUserIDClosure(userID)
} else {
return canUserRedactOwnUserIDReturnValue
}
}
//MARK: - canUserKick
private let canUserKickUserIDCallsCountLock = NSLock()
private nonisolated(unsafe) var canUserKickUserIDUnderlyingCallsCount = 0
var canUserKickUserIDCallsCount: Int {
get { canUserKickUserIDCallsCountLock.withLock { canUserKickUserIDUnderlyingCallsCount } }
set { canUserKickUserIDCallsCountLock.withLock { canUserKickUserIDUnderlyingCallsCount = newValue } }
}
var canUserKickUserIDCalled: Bool {
return canUserKickUserIDCallsCount > 0
}
private let canUserKickUserIDReceivedUserIDLock = NSLock()
private nonisolated(unsafe) var canUserKickUserIDUnderlyingReceivedUserID: String?
var canUserKickUserIDReceivedUserID: String? {
get { canUserKickUserIDReceivedUserIDLock.withLock { canUserKickUserIDUnderlyingReceivedUserID } }
set { canUserKickUserIDReceivedUserIDLock.withLock { canUserKickUserIDUnderlyingReceivedUserID = newValue } }
}
private let canUserKickUserIDReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var canUserKickUserIDUnderlyingReceivedInvocations: [String] = []
var canUserKickUserIDReceivedInvocations: [String] {
get { canUserKickUserIDReceivedInvocationsLock.withLock { canUserKickUserIDUnderlyingReceivedInvocations } }
set { canUserKickUserIDReceivedInvocationsLock.withLock { canUserKickUserIDUnderlyingReceivedInvocations = newValue } }
}
private let canUserKickUserIDReturnValueLock = NSLock()
private nonisolated(unsafe) var canUserKickUserIDUnderlyingReturnValue: Result<Bool, RoomProxyError>!
var canUserKickUserIDReturnValue: Result<Bool, RoomProxyError>! {
get { canUserKickUserIDReturnValueLock.withLock { canUserKickUserIDUnderlyingReturnValue } }
set { canUserKickUserIDReturnValueLock.withLock { canUserKickUserIDUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var canUserKickUserIDClosure: ((String) -> Result<Bool, RoomProxyError>)?
func canUserKick(userID: String) -> Result<Bool, RoomProxyError> {
canUserKickUserIDCallsCountLock.withLock { canUserKickUserIDUnderlyingCallsCount += 1 }
canUserKickUserIDReceivedUserID = userID
canUserKickUserIDReceivedInvocationsLock.withLock { canUserKickUserIDUnderlyingReceivedInvocations.append(userID) }
if let canUserKickUserIDClosure = canUserKickUserIDClosure {
return canUserKickUserIDClosure(userID)
} else {
return canUserKickUserIDReturnValue
}
}
//MARK: - canUserBan
private let canUserBanUserIDCallsCountLock = NSLock()
private nonisolated(unsafe) var canUserBanUserIDUnderlyingCallsCount = 0
var canUserBanUserIDCallsCount: Int {
get { canUserBanUserIDCallsCountLock.withLock { canUserBanUserIDUnderlyingCallsCount } }
set { canUserBanUserIDCallsCountLock.withLock { canUserBanUserIDUnderlyingCallsCount = newValue } }
}
var canUserBanUserIDCalled: Bool {
return canUserBanUserIDCallsCount > 0
}
private let canUserBanUserIDReceivedUserIDLock = NSLock()
private nonisolated(unsafe) var canUserBanUserIDUnderlyingReceivedUserID: String?
var canUserBanUserIDReceivedUserID: String? {
get { canUserBanUserIDReceivedUserIDLock.withLock { canUserBanUserIDUnderlyingReceivedUserID } }
set { canUserBanUserIDReceivedUserIDLock.withLock { canUserBanUserIDUnderlyingReceivedUserID = newValue } }
}
private let canUserBanUserIDReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var canUserBanUserIDUnderlyingReceivedInvocations: [String] = []
var canUserBanUserIDReceivedInvocations: [String] {
get { canUserBanUserIDReceivedInvocationsLock.withLock { canUserBanUserIDUnderlyingReceivedInvocations } }
set { canUserBanUserIDReceivedInvocationsLock.withLock { canUserBanUserIDUnderlyingReceivedInvocations = newValue } }
}
private let canUserBanUserIDReturnValueLock = NSLock()
private nonisolated(unsafe) var canUserBanUserIDUnderlyingReturnValue: Result<Bool, RoomProxyError>!
var canUserBanUserIDReturnValue: Result<Bool, RoomProxyError>! {
get { canUserBanUserIDReturnValueLock.withLock { canUserBanUserIDUnderlyingReturnValue } }
set { canUserBanUserIDReturnValueLock.withLock { canUserBanUserIDUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var canUserBanUserIDClosure: ((String) -> Result<Bool, RoomProxyError>)?
func canUserBan(userID: String) -> Result<Bool, RoomProxyError> {
canUserBanUserIDCallsCountLock.withLock { canUserBanUserIDUnderlyingCallsCount += 1 }
canUserBanUserIDReceivedUserID = userID
canUserBanUserIDReceivedInvocationsLock.withLock { canUserBanUserIDUnderlyingReceivedInvocations.append(userID) }
if let canUserBanUserIDClosure = canUserBanUserIDClosure {
return canUserBanUserIDClosure(userID)
} else {
return canUserBanUserIDReturnValue
}
}
//MARK: - canUserTriggerRoomNotification
private let canUserTriggerRoomNotificationUserIDCallsCountLock = NSLock()
private nonisolated(unsafe) var canUserTriggerRoomNotificationUserIDUnderlyingCallsCount = 0
var canUserTriggerRoomNotificationUserIDCallsCount: Int {
get { canUserTriggerRoomNotificationUserIDCallsCountLock.withLock { canUserTriggerRoomNotificationUserIDUnderlyingCallsCount } }
set { canUserTriggerRoomNotificationUserIDCallsCountLock.withLock { canUserTriggerRoomNotificationUserIDUnderlyingCallsCount = newValue } }
}
var canUserTriggerRoomNotificationUserIDCalled: Bool {
return canUserTriggerRoomNotificationUserIDCallsCount > 0
}
private let canUserTriggerRoomNotificationUserIDReceivedUserIDLock = NSLock()
private nonisolated(unsafe) var canUserTriggerRoomNotificationUserIDUnderlyingReceivedUserID: String?
var canUserTriggerRoomNotificationUserIDReceivedUserID: String? {
get { canUserTriggerRoomNotificationUserIDReceivedUserIDLock.withLock { canUserTriggerRoomNotificationUserIDUnderlyingReceivedUserID } }
set { canUserTriggerRoomNotificationUserIDReceivedUserIDLock.withLock { canUserTriggerRoomNotificationUserIDUnderlyingReceivedUserID = newValue } }
}
private let canUserTriggerRoomNotificationUserIDReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var canUserTriggerRoomNotificationUserIDUnderlyingReceivedInvocations: [String] = []
var canUserTriggerRoomNotificationUserIDReceivedInvocations: [String] {
get { canUserTriggerRoomNotificationUserIDReceivedInvocationsLock.withLock { canUserTriggerRoomNotificationUserIDUnderlyingReceivedInvocations } }
set { canUserTriggerRoomNotificationUserIDReceivedInvocationsLock.withLock { canUserTriggerRoomNotificationUserIDUnderlyingReceivedInvocations = newValue } }
}
private let canUserTriggerRoomNotificationUserIDReturnValueLock = NSLock()
private nonisolated(unsafe) var canUserTriggerRoomNotificationUserIDUnderlyingReturnValue: Result<Bool, RoomProxyError>!
var canUserTriggerRoomNotificationUserIDReturnValue: Result<Bool, RoomProxyError>! {
get { canUserTriggerRoomNotificationUserIDReturnValueLock.withLock { canUserTriggerRoomNotificationUserIDUnderlyingReturnValue } }
set { canUserTriggerRoomNotificationUserIDReturnValueLock.withLock { canUserTriggerRoomNotificationUserIDUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var canUserTriggerRoomNotificationUserIDClosure: ((String) -> Result<Bool, RoomProxyError>)?
func canUserTriggerRoomNotification(userID: String) -> Result<Bool, RoomProxyError> {
canUserTriggerRoomNotificationUserIDCallsCountLock.withLock { canUserTriggerRoomNotificationUserIDUnderlyingCallsCount += 1 }
canUserTriggerRoomNotificationUserIDReceivedUserID = userID
canUserTriggerRoomNotificationUserIDReceivedInvocationsLock.withLock { canUserTriggerRoomNotificationUserIDUnderlyingReceivedInvocations.append(userID) }
if let canUserTriggerRoomNotificationUserIDClosure = canUserTriggerRoomNotificationUserIDClosure {
return canUserTriggerRoomNotificationUserIDClosure(userID)
} else {
return canUserTriggerRoomNotificationUserIDReturnValue
}
}
//MARK: - canUserPinOrUnpin
private let canUserPinOrUnpinUserIDCallsCountLock = NSLock()
private nonisolated(unsafe) var canUserPinOrUnpinUserIDUnderlyingCallsCount = 0
var canUserPinOrUnpinUserIDCallsCount: Int {
get { canUserPinOrUnpinUserIDCallsCountLock.withLock { canUserPinOrUnpinUserIDUnderlyingCallsCount } }
set { canUserPinOrUnpinUserIDCallsCountLock.withLock { canUserPinOrUnpinUserIDUnderlyingCallsCount = newValue } }
}
var canUserPinOrUnpinUserIDCalled: Bool {
return canUserPinOrUnpinUserIDCallsCount > 0
}
private let canUserPinOrUnpinUserIDReceivedUserIDLock = NSLock()
private nonisolated(unsafe) var canUserPinOrUnpinUserIDUnderlyingReceivedUserID: String?
var canUserPinOrUnpinUserIDReceivedUserID: String? {
get { canUserPinOrUnpinUserIDReceivedUserIDLock.withLock { canUserPinOrUnpinUserIDUnderlyingReceivedUserID } }
set { canUserPinOrUnpinUserIDReceivedUserIDLock.withLock { canUserPinOrUnpinUserIDUnderlyingReceivedUserID = newValue } }
}
private let canUserPinOrUnpinUserIDReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var canUserPinOrUnpinUserIDUnderlyingReceivedInvocations: [String] = []
var canUserPinOrUnpinUserIDReceivedInvocations: [String] {
get { canUserPinOrUnpinUserIDReceivedInvocationsLock.withLock { canUserPinOrUnpinUserIDUnderlyingReceivedInvocations } }
set { canUserPinOrUnpinUserIDReceivedInvocationsLock.withLock { canUserPinOrUnpinUserIDUnderlyingReceivedInvocations = newValue } }
}
private let canUserPinOrUnpinUserIDReturnValueLock = NSLock()
private nonisolated(unsafe) var canUserPinOrUnpinUserIDUnderlyingReturnValue: Result<Bool, RoomProxyError>!
var canUserPinOrUnpinUserIDReturnValue: Result<Bool, RoomProxyError>! {
get { canUserPinOrUnpinUserIDReturnValueLock.withLock { canUserPinOrUnpinUserIDUnderlyingReturnValue } }
set { canUserPinOrUnpinUserIDReturnValueLock.withLock { canUserPinOrUnpinUserIDUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var canUserPinOrUnpinUserIDClosure: ((String) -> Result<Bool, RoomProxyError>)?
func canUserPinOrUnpin(userID: String) -> Result<Bool, RoomProxyError> {
canUserPinOrUnpinUserIDCallsCountLock.withLock { canUserPinOrUnpinUserIDUnderlyingCallsCount += 1 }
canUserPinOrUnpinUserIDReceivedUserID = userID
canUserPinOrUnpinUserIDReceivedInvocationsLock.withLock { canUserPinOrUnpinUserIDUnderlyingReceivedInvocations.append(userID) }
if let canUserPinOrUnpinUserIDClosure = canUserPinOrUnpinUserIDClosure {
return canUserPinOrUnpinUserIDClosure(userID)
} else {
return canUserPinOrUnpinUserIDReturnValue
}
}
//MARK: - canUserJoinCall
private let canUserJoinCallUserIDCallsCountLock = NSLock()
private nonisolated(unsafe) var canUserJoinCallUserIDUnderlyingCallsCount = 0
var canUserJoinCallUserIDCallsCount: Int {
get { canUserJoinCallUserIDCallsCountLock.withLock { canUserJoinCallUserIDUnderlyingCallsCount } }
set { canUserJoinCallUserIDCallsCountLock.withLock { canUserJoinCallUserIDUnderlyingCallsCount = newValue } }
}
var canUserJoinCallUserIDCalled: Bool {
return canUserJoinCallUserIDCallsCount > 0
}
private let canUserJoinCallUserIDReceivedUserIDLock = NSLock()
private nonisolated(unsafe) var canUserJoinCallUserIDUnderlyingReceivedUserID: String?
var canUserJoinCallUserIDReceivedUserID: String? {
get { canUserJoinCallUserIDReceivedUserIDLock.withLock { canUserJoinCallUserIDUnderlyingReceivedUserID } }
set { canUserJoinCallUserIDReceivedUserIDLock.withLock { canUserJoinCallUserIDUnderlyingReceivedUserID = newValue } }
}
private let canUserJoinCallUserIDReceivedInvocationsLock = NSLock()
private nonisolated(unsafe) var canUserJoinCallUserIDUnderlyingReceivedInvocations: [String] = []
var canUserJoinCallUserIDReceivedInvocations: [String] {
get { canUserJoinCallUserIDReceivedInvocationsLock.withLock { canUserJoinCallUserIDUnderlyingReceivedInvocations } }
set { canUserJoinCallUserIDReceivedInvocationsLock.withLock { canUserJoinCallUserIDUnderlyingReceivedInvocations = newValue } }
}
private let canUserJoinCallUserIDReturnValueLock = NSLock()
private nonisolated(unsafe) var canUserJoinCallUserIDUnderlyingReturnValue: Result<Bool, RoomProxyError>!
var canUserJoinCallUserIDReturnValue: Result<Bool, RoomProxyError>! {
get { canUserJoinCallUserIDReturnValueLock.withLock { canUserJoinCallUserIDUnderlyingReturnValue } }
set { canUserJoinCallUserIDReturnValueLock.withLock { canUserJoinCallUserIDUnderlyingReturnValue = newValue } }
}
nonisolated(unsafe) var canUserJoinCallUserIDClosure: ((String) -> Result<Bool, RoomProxyError>)?
func canUserJoinCall(userID: String) -> Result<Bool, RoomProxyError> {
canUserJoinCallUserIDCallsCountLock.withLock { canUserJoinCallUserIDUnderlyingCallsCount += 1 }
canUserJoinCallUserIDReceivedUserID = userID
canUserJoinCallUserIDReceivedInvocationsLock.withLock { canUserJoinCallUserIDUnderlyingReceivedInvocations.append(userID) }
if let canUserJoinCallUserIDClosure = canUserJoinCallUserIDClosure {
return canUserJoinCallUserIDClosure(userID)
} else {
return canUserJoinCallUserIDReturnValue
}
}
}
nonisolated class RoomPreviewProxyMock: RoomPreviewProxyProtocol, @unchecked Sendable {
var info: RoomPreviewInfoProxy {
@@ -12208,11 +11416,6 @@ nonisolated class TimelineControllerFactoryMock: TimelineControllerFactoryProtoc
}
}
nonisolated class TimelineControllerMock: TimelineControllerProtocol, @unchecked Sendable {
var roomID: String {
get { return underlyingRoomID }
set(value) { underlyingRoomID = value }
}
nonisolated(unsafe) var underlyingRoomID: String!
var timelineKind: TimelineKind {
get { return underlyingTimelineKind }
set(value) { underlyingTimelineKind = value }
@@ -25,8 +25,8 @@ extension InvitedRoomProxyMock {
convenience init(_ configuration: InvitedRoomProxyMockConfiguration) {
self.init()
id = configuration.id
inviter = configuration.inviter
info = RoomInfoProxyMock(configuration)
inviter = configuration.inviter
rejectInvitationReturnValue = .success(())
}
@@ -38,9 +38,7 @@ extension RoomInfoProxyMock {
id = configuration.id
isEncrypted = false
creators = []
displayName = configuration.name
rawName = nil
topic = nil
avatarURL = configuration.avatarURL
@@ -52,20 +50,11 @@ extension RoomInfoProxyMock {
canonicalAlias = nil
alternativeAliases = []
membership = .knocked
inviter = .init(configuration.inviter)
heroes = []
activeMembersCount = configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count
invitedMembersCount = configuration.members.filter { $0.membership == .invite }.count
joinedMembersCount = configuration.members.filter { $0.membership == .join }.count
highlightCount = 0
notificationCount = 0
cachedUserDefinedNotificationMode = nil
hasRoomCall = false
activeRoomCallParticipants = []
isMarkedUnread = false
unreadMessagesCount = 0
unreadNotificationsCount = 0
unreadMentionsCount = 0
pinnedEventIDs = []
joinRule = .invite
historyVisibility = .shared
@@ -89,33 +89,18 @@ extension JoinedRoomProxyMock {
applyPowerLevelChangesReturnValue = .success(())
resetPowerLevelsReturnValue = .success(())
suggestedRoleForClosure = { [weak self] userID in
guard case .success(let member) = await self?.getMember(userID: userID) else {
return .failure(.sdkError(RoomProxyMockError.generic))
}
return .success(member.role.rustRole)
}
updatePowerLevelsForUsersReturnValue = .success(())
let powerLevelsProxyMock = RoomPowerLevelsProxyMock(configuration.powerLevelsConfiguration)
powerLevelsProxyMock.canUserUserIDSendStateEventClosure = { [weak self] userID, _ in
.success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user)
}
powerLevelsProxyMock.canOwnUserSendStateEventClosure = { [weak self] _ in
self?.membersPublisher.value.first { $0.userID == configuration.ownUserID }?.role ?? .user != .user
}
powerLevelsProxyMock.canUserKickUserIDClosure = { [weak self] userID in
.success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user)
}
powerLevelsProxyMock.canOwnUserKickClosure = { [weak self] in
self?.membersPublisher.value.first { $0.userID == configuration.ownUserID }?.role ?? .user != .user
}
powerLevelsProxyMock.canUserBanUserIDClosure = { [weak self] userID in
.success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user)
}
powerLevelsProxyMock.canOwnUserBanClosure = { [weak self] in
self?.membersPublisher.value.first { $0.userID == configuration.ownUserID }?.role ?? .user != .user
}
@@ -124,8 +109,6 @@ extension JoinedRoomProxyMock {
self?.membersPublisher.value.first { $0.userID == configuration.ownUserID }?.role.isAdminOrHigher ?? false
}
powerLevelsReturnValue = .success(powerLevelsProxyMock)
inviteUserIDReturnValue = .success(())
kickUserReasonReturnValue = .success(())
banUserReasonReturnValue = .success(())
@@ -165,9 +148,7 @@ extension RoomInfoProxyMock {
id = configuration.id
isEncrypted = configuration.isEncrypted
creators = []
displayName = configuration.name
rawName = configuration.name
topic = configuration.topic
avatarURL = configuration.avatarURL
isDirect = configuration.isDirect
@@ -177,21 +158,12 @@ extension RoomInfoProxyMock {
canonicalAlias = configuration.canonicalAlias
alternativeAliases = configuration.alternativeAliases
membership = configuration.membership
inviter = configuration.inviter
heroes = configuration.heroes.map(RoomHero.init)
activeMembersCount = configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count
invitedMembersCount = configuration.members.filter { $0.membership == .invite }.count
joinedMembersCount = configuration.members.filter { $0.membership == .join }.count
isDM = isDirect && activeMembersCount <= 2
highlightCount = 0
notificationCount = 0
cachedUserDefinedNotificationMode = .allMessages
hasRoomCall = configuration.hasOngoingCall
activeRoomCallParticipants = []
isMarkedUnread = false
unreadMessagesCount = 0
unreadNotificationsCount = 0
unreadMentionsCount = 0
pinnedEventIDs = configuration.pinnedEventIDs
joinRule = configuration.joinRule
historyVisibility = configuration.historyVisibility
@@ -33,9 +33,7 @@ extension RoomInfoProxyMock {
id = configuration.id
isEncrypted = false
creators = []
displayName = configuration.name
rawName = nil
topic = nil
avatarURL = configuration.avatarURL
@@ -47,20 +45,11 @@ extension RoomInfoProxyMock {
canonicalAlias = nil
alternativeAliases = []
membership = .knocked
inviter = nil
heroes = []
activeMembersCount = configuration.members.filter { $0.membership == .join || $0.membership == .invite }.count
invitedMembersCount = configuration.members.filter { $0.membership == .invite }.count
joinedMembersCount = configuration.members.filter { $0.membership == .join }.count
highlightCount = 0
notificationCount = 0
cachedUserDefinedNotificationMode = nil
hasRoomCall = false
activeRoomCallParticipants = []
isMarkedUnread = false
unreadMessagesCount = 0
unreadNotificationsCount = 0
unreadMentionsCount = 0
pinnedEventIDs = []
joinRule = .knock
historyVisibility = .shared
@@ -45,14 +45,6 @@ extension MediaProviderMock {
return UIImage(systemName: "photo")
}
loadImageFromSourceSizeClosure = { _, _ in
guard let image = UIImage(systemName: "photo") else {
fatalError()
}
return .success(image)
}
loadImageDataFromSourceClosure = { _ in
guard let image = UIImage(systemName: "photo"),
let data = image.pngData() else {
@@ -46,8 +46,6 @@ extension NotificationItemProxyMock {
senderDisplayName = configuration.senderDisplayName
roomAvatarMediaSource = configuration.roomAvatarMediaSource
roomDisplayName = configuration.roomDisplayName
roomJoinedMembers = configuration.roomJoinedMembers
isRoomDirect = configuration.isRoomDirect
isRoomPrivate = configuration.isRoomPrivate
isNoisy = configuration.isNoisy
hasMention = configuration.hasMention
@@ -39,17 +39,6 @@ import MatrixRustSDK
canOwnUserPinOrUnpinReturnValue = configuration.canUserPin
canOwnUserJoinCallReturnValue = configuration.canUserJoinCall
canOwnUserEditRolesAndPermissionsReturnValue = configuration.canUserEditRoomsAndPermissions
canUserUserIDSendMessageReturnValue = .success(configuration.canUserSendMessage)
canUserUserIDSendStateEventReturnValue = .success(configuration.canUserSendState)
canUserInviteUserIDReturnValue = .success(configuration.canUserInvite)
canUserRedactOtherUserIDReturnValue = .success(configuration.canUserRedactOther)
canUserRedactOwnUserIDReturnValue = .success(configuration.canUserRedactOwn)
canUserKickUserIDReturnValue = .success(configuration.canUserKick)
canUserBanUserIDReturnValue = .success(configuration.canUserBan)
canUserTriggerRoomNotificationUserIDReturnValue = .success(configuration.canUserTriggerRoomNotification)
canUserPinOrUnpinUserIDReturnValue = .success(configuration.canUserPin)
canUserJoinCallUserIDReturnValue = .success(configuration.canUserJoinCall)
}
}
@@ -5,8 +5,6 @@
// Please see LICENSE files in the repository root for full details.
//
// periphery:ignore:all
import Combine
import Foundation
import MatrixRustSDK
@@ -6,8 +6,6 @@
// Please see LICENSE files in the repository root for full details.
//
// periphery:ignore:all
import Combine
import Foundation
import MatrixRustSDK
@@ -45,7 +43,6 @@ struct TimelineControllerMockConfiguration {
let timelineItemsTimestamps = configuration.timelineItemsTimestamps
callbacks = PassthroughSubject()
roomID = roomProxy?.id ?? "MockRoomIdentifier"
timelineKind = configuration.timelineKind
paginationState = configuration.paginationState
timelineItems = configuration.timelineItems
@@ -195,7 +195,6 @@ enum A11yIdentifiers {
struct RoomDetailsScreen {
let addTopic = "room_details-add_topic"
let avatar = "room_details-avatar"
let dmAvatar = "room_details-dm_avatar"
let people = "room_details-people"
let notifications = "room_details-notifications"
let pollsHistory = "room_details-polls_history"
@@ -333,8 +332,6 @@ enum A11yIdentifiers {
}
struct SpacesScreen {
let userAvatar = "spaces_screen-user_avatar"
let roomNamePrefix = "spaces_screen-room_name"
func spaceRoomName(_ name: String) -> String {
"\(roomNamePrefix):\(name)"
+1 -1
View File
@@ -13,7 +13,6 @@ nonisolated enum CallIntent: String, Codable, CaseIterable {
}
nonisolated extension CallIntent {
// periphery:ignore - Unused, but added to detect new cases when updating the SDK.
init(rustCallIntent: MatrixRustSDK.RtcCallIntent) {
switch rustCallIntent {
case .audio: self = .audio
@@ -21,6 +20,7 @@ nonisolated extension CallIntent {
}
}
// periphery:ignore - might be useful to have
var rustCallIntent: MatrixRustSDK.RtcCallIntent {
switch self {
case .audio: .audio
@@ -8,7 +8,6 @@
import Foundation
// periphery:ignore - property wrappers generate false positives
@propertyWrapper
struct CancellableTask<S: Sendable, F: Error> {
private var storedValue: Task<S, F>?
@@ -97,10 +97,6 @@ private nonisolated extension [Bit] {
try takeBits(8)
}
mutating func takeUInt16() throws(BitError) -> UInt16 {
try takeBits16(16)
}
mutating func takeBinarySegment(_ version: Int) throws(BitError) -> [UInt8] {
let characterCountLength = version > 9 ? 16 : 8
let charactersCount = try takeBits16(characterCountLength)
@@ -45,18 +45,6 @@ nonisolated extension AttributedString {
return components
}
/// Replaces the specified placeholder with a string that links to the specified URL.
/// - Parameters:
/// - linkPlaceholder: The text in the string that will be replaced. Make sure this is unique within the string.
/// - string: The text for the link that will be substituted into the placeholder.
/// - url: The URL that the link should open.
mutating func replace(_ linkPlaceholder: String, with string: String, asLinkTo url: URL) {
// Replace the placeholder with a link.
var replacement = AttributedString(string)
replacement.link = url
replace(linkPlaceholder, with: replacement)
}
/// Replaces the specified placeholder with the supplied attributed string.
/// - Parameters:
/// - placeholder: The text in the string that will be replaced. Make sure this is unique within the string.
@@ -13,8 +13,4 @@ extension CompoundIcon {
init(asset: ImageAsset) {
self.init(customImage: asset.swiftUIImage)
}
init(asset: ImageAsset, size: CompoundIcon.Size, relativeTo font: Font) {
self.init(customImage: asset.swiftUIImage, size: size, relativeTo: font)
}
}
@@ -13,19 +13,6 @@ protocol ConfirmationDialogProtocol {
}
extension View {
func confirmationDialog<Item: ConfirmationDialogProtocol, Actions: View>(item: Binding<Item?>,
titleVisibility: Visibility = .automatic,
@ViewBuilder actions: (Item) -> Actions) -> some View {
let binding = Binding<Bool>(get: {
item.wrappedValue != nil
}, set: { newValue in
if !newValue {
item.wrappedValue = nil
}
})
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: ConfirmationDialogProtocol, Actions: View, Message: View>(item: Binding<Item?>,
titleVisibility: Visibility = .automatic,
@@ -1,46 +0,0 @@
//
// Copyright 2025 Element Creations Ltd.
// Copyright 2022-2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
import Compound
import SwiftUI
extension Label {
/// Creates a label using a local asset as a Compound icon and a title generated from a string.
/// The icon size will be 24pt, scaling relative to the `bodyLG` with Dynamic Type.
/// - Parameters:
/// - title: A string used as the label’s title.
/// - iconAsset: The asset to use as the custom Compound icon.
///
/// The supplied asset should have a square frame or it may end up distorted.
init(_ title: some StringProtocol, iconAsset: ImageAsset) where Title == Text, Icon == CompoundIcon {
self.init {
Text(title)
} icon: {
CompoundIcon(customImage: iconAsset.swiftUIImage)
}
}
/// Creates a label using a local asset as a Compound icon and a title generated from a string.
/// - Parameters:
/// - title: A string used as the label’s title.
/// - iconAsset: The asset to use as the custom Compound icon.
/// - size: The size of the icon.
/// - font: The font that the icon will scale relative to for Dynamic Type.
///
/// The supplied asset should have a square frame or it may end up distorted.
init(_ title: some StringProtocol,
iconAsset: ImageAsset,
iconSize: CompoundIcon.Size,
relativeTo font: Font) where Title == Text, Icon == CompoundIcon {
self.init {
Text(title)
} icon: {
CompoundIcon(customImage: iconAsset.swiftUIImage, size: iconSize, relativeTo: font)
}
}
}
@@ -10,6 +10,7 @@ import SwiftUI
import UniformTypeIdentifiers
nonisolated extension String {
// periphery:ignore - might be useful to have
/// Returns the string as an `AttributedString` with the specified character tinted in a different color.
/// - Parameters:
/// - character: The character to be tinted.
@@ -10,6 +10,7 @@ import Combine
import Foundation
public extension Task where Success == Never, Failure == Never {
// periphery:ignore - might be useful to have
/// Dispatches the given closure onto the given queue, wrapped within
/// a continuation to make it non-blocking and awaitable.
///
@@ -1,194 +0,0 @@
//
// Copyright 2025 Element Creations Ltd.
// Copyright 2023-2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
import Combine
import XCTest
extension XCTestCase {
/// XCTest utility that assists in subscribing to a publisher and deferring the fulfilment and results until some other actions have been performed.
/// - Parameters:
/// - publisher: The publisher to wait on.
/// - timeout: A timeout after which we give up.
/// - message: An optional custom expectation message
/// - until: callback that evaluates outputs until some condition is reached
/// - Returns: The deferred fulfilment to be executed after some actions and that returns the result of the publisher.
func deferFulfillment<P: Publisher>(_ publisher: P,
timeout: TimeInterval = 10,
message: String? = nil,
until condition: @escaping (P.Output) -> Bool) -> DeferredFulfillment<P.Output> {
var result: Result<P.Output, Error>?
let expectation = expectation(description: message ?? "Awaiting publisher")
var hasFullfilled = false
let cancellable = publisher
.sink { completion in
switch completion {
case .failure(let error):
result = .failure(error)
expectation.fulfill()
case .finished:
break
}
} receiveValue: { value in
if condition(value), !hasFullfilled {
result = .success(value)
expectation.fulfill()
hasFullfilled = true
}
}
return DeferredFulfillment<P.Output> {
await self.fulfillment(of: [expectation], timeout: timeout)
cancellable.cancel()
let unwrappedResult = try XCTUnwrap(result, "Awaited publisher did not produce any output")
return try unwrappedResult.get()
}
}
/// XCTest utility that assists in observing an async sequence, deferring the fulfilment and results until some condition has been met.
/// - Parameters:
/// - asyncSequence: The sequence to wait on.
/// - timeout: A timeout after which we give up.
/// - message: An optional custom expectation message
/// - until: callback that evaluates outputs until some condition is reached
/// - Returns: The deferred fulfilment to be executed after some actions and that returns the result of the sequence.
func deferFulfillment<Value>(_ asyncSequence: any AsyncSequence<Value, Never>,
timeout: TimeInterval = 10,
message: String? = nil,
until condition: @escaping (Value) -> Bool) -> DeferredFulfillment<Value> {
var result: Result<Value, Error>?
let expectation = expectation(description: message ?? "Awaiting sequence")
var hasFulfilled = false
let task = Task {
for await value in asyncSequence {
if condition(value), !hasFulfilled {
result = .success(value)
expectation.fulfill()
hasFulfilled = true
}
}
}
return DeferredFulfillment<Value> {
await self.fulfillment(of: [expectation], timeout: timeout)
task.cancel()
let unwrappedResult = try XCTUnwrap(result, "Awaited sequence did not produce any output")
return try unwrappedResult.get()
}
}
/// XCTest utility that assists in subscribing to a publisher and deferring the fulfilment and results until some other actions have been performed.
/// - Parameters:
/// - publisher: The publisher to wait on.
/// - keyPath: the key path for the expected values
/// - transitionValues: the values through which the keypath needs to transition through
/// - timeout: A timeout after which we give up.
/// - message: An optional custom expectation message
/// - Returns: The deferred fulfilment to be executed after some actions and that returns the result of the publisher.
func deferFulfillment<P: Publisher, K: KeyPath<P.Output, V>, V: Equatable>(_ publisher: P,
keyPath: K,
transitionValues: [V],
timeout: TimeInterval = 10,
message: String? = nil) -> DeferredFulfillment<P.Output> {
var expectedOrder = transitionValues
return deferFulfillment(publisher, timeout: timeout, message: message) { value in
let receivedValue = value[keyPath: keyPath]
if let index = expectedOrder.firstIndex(where: { $0 == receivedValue }), index == 0 {
expectedOrder.remove(at: index)
}
return expectedOrder.isEmpty
}
}
/// XCTest utility that assists in subscribing to an async sequence and deferring the fulfilment and results until some other actions have been performed.
/// - Parameters:
/// - asyncSequence: The sequence to wait on.
/// - transitionValues: the values through which the sequence needs to transition through
/// - timeout: A timeout after which we give up.
/// - message: An optional custom expectation message
/// - Returns: The deferred fulfilment to be executed after some actions and that returns the result of the sequence.
func deferFulfillment<Value: Equatable>(_ asyncSequence: any AsyncSequence<Value, Never>,
transitionValues: [Value],
timeout: TimeInterval = 10,
message: String? = nil) -> DeferredFulfillment<Value> {
var expectedOrder = transitionValues
return deferFulfillment(asyncSequence, timeout: timeout, message: message) { value in
if let index = expectedOrder.firstIndex(where: { $0 == value }), index == 0 {
expectedOrder.remove(at: index)
}
return expectedOrder.isEmpty
}
}
/// XCTest utility that assists in subscribing to a publisher and deferring the failure for a particular value until some other actions have been performed.
/// - Parameters:
/// - publisher: The publisher to wait on.
/// - timeout: A timeout after which we give up.
/// - message: An optional custom expectation message
/// - until: callback that evaluates outputs until some condition is reached
/// - Returns: The deferred fulfilment to be executed after some actions. The publisher's result is not returned from this fulfilment.
func deferFailure<P: Publisher>(_ publisher: P,
timeout: TimeInterval,
message: String? = nil,
until condition: @escaping (P.Output) -> Bool) -> DeferredFulfillment<Void> where P.Failure == Never {
let expectation = expectation(description: message ?? "Awaiting publisher")
expectation.isInverted = true
var hasFulfilled = false
let cancellable = publisher
.sink { value in
if condition(value), !hasFulfilled {
expectation.fulfill()
hasFulfilled = true
}
}
return DeferredFulfillment<Void> {
await self.fulfillment(of: [expectation], timeout: timeout)
cancellable.cancel()
}
}
/// XCTest utility that assists in subscribing to an async sequence and deferring the failure for a particular value until some other actions have been performed.
/// - Parameters:
/// - asyncSequence: The sequence to wait on.
/// - timeout: A timeout after which we give up.
/// - message: An optional custom expectation message
/// - until: callback that evaluates outputs until some condition is reached
/// - Returns: The deferred fulfilment to be executed after some actions. The sequence's result is not returned from this fulfilment.
func deferFailure<Value>(_ asyncSequence: any AsyncSequence<Value, Never>,
timeout: TimeInterval,
message: String? = nil,
until condition: @escaping (Value) -> Bool) -> DeferredFulfillment<Void> {
let expectation = expectation(description: message ?? "Awaiting sequence")
expectation.isInverted = true
var hasFulfilled = false
let task = Task {
for await value in asyncSequence {
if condition(value), !hasFulfilled {
expectation.fulfill()
hasFulfilled = true
}
}
}
return DeferredFulfillment<Void> {
await self.fulfillment(of: [expectation], timeout: timeout)
task.cancel()
}
}
struct DeferredFulfillment<T> {
let closure: () async throws -> T
@discardableResult func fulfill() async throws -> T {
try await closure()
}
}
}
@@ -43,6 +43,7 @@ enum RoomAliasAttribute: AttributedStringKey {
enum EventOnRoomIDAttribute: AttributedStringKey {
struct Value: Hashable {
let roomID: String
// periphery:ignore - used via the synthesized Hashable conformance
let eventID: String
}
@@ -52,6 +53,7 @@ enum EventOnRoomIDAttribute: AttributedStringKey {
enum EventOnRoomAliasAttribute: AttributedStringKey {
struct Value: Hashable {
let alias: String
// periphery:ignore - used via the synthesized Hashable conformance
let eventID: String
}
@@ -73,25 +75,32 @@ enum InlineCodeAttribute: AttributedStringKey {
static let name = "MXInlineCodeAttribute"
}
// periphery: ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
nonisolated extension AttributeScopes {
struct ElementXAttributes: AttributeScope {
let blockquote: BlockquoteAttribute
let userID: UserIDAttribute
// periphery:ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
let userDisplayName: UserDisplayNameAttribute
// periphery:ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
let roomDisplayName: RoomDisplayNameAttribute
let roomID: RoomIDAttribute
let roomAlias: RoomAliasAttribute
let eventOnRoomID: EventOnRoomIDAttribute
let eventOnRoomAlias: EventOnRoomAliasAttribute
// periphery:ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
let allUsersMention: AllUsersMentionAttribute
let codeBlock: CodeBlockAttribute
// periphery:ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
let inlineCode: InlineCodeAttribute
// periphery:ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
let swiftUI: SwiftUIAttributes
// periphery:ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
let uiKit: UIKitAttributes
}
+1 -4
View File
@@ -94,6 +94,7 @@ nonisolated struct InfoPlistReader {
infoPlistValue(forKey: Keys.productionAppName)
}
// periphery:ignore - only used in release builds
/// Whether or not the build is from the Nightly stream.
var isNightlyBuild: Bool {
infoPlistValue(forKey: Keys.isNightlyBuild)
@@ -105,10 +106,6 @@ nonisolated struct InfoPlistReader {
customSchemeForName("Application")
}
var elementCallScheme: String {
customSchemeForName("Element Call")
}
// MARK: - Mention Pills
/// Mention Pills UTType
@@ -96,6 +96,7 @@ nonisolated enum MXLog {
#if DEBUG
private static let devPrefix = URL.documentsDirectory.pathComponents[2].uppercased()
// periphery:ignore - used for debugging
/// A helper method for print debugging, only available on debug builds.
///
/// When running on the simulator this will log `[USERNAME] message` so that
@@ -78,7 +78,9 @@ struct MessageText: UIViewRepresentable {
/// Cache key for `sizeThatFits`. Keyed on the reserved trailing size as well as the proposed
/// width to account for any changes on the send info label that happen after the first rendering.
private struct SizeCacheKey: Hashable {
// periphery:ignore - used via the synthesized Hashable conformance
let width: Double
// periphery:ignore - used via the synthesized Hashable conformance
let reservedSize: CGSize
}
@@ -48,8 +48,6 @@ struct PillView: View {
}
struct PillView_Previews: PreviewProvider, TestablePreview {
static let mockMediaProvider = MediaProviderMock(.init())
static var previews: some View {
PillView(context: PillContext.mock(viewState: .mention(isOwnMention: false,
displayText: PillUtilities.userPillDisplayText(username: "User",
@@ -29,18 +29,10 @@ class ScrollViewAdapter: NSObject, UIScrollViewDelegate {
.init(isScrollingSubject)
}
private let isAtTopEdgeSubject: CurrentValueSubject<Bool, Never> = .init(false)
var isAtTopEdge: CurrentValuePublisher<Bool, Never> {
isAtTopEdgeSubject
.asCurrentValuePublisher()
}
// MARK: - UIScrollViewDelegate
func scrollViewDidScroll(_ scrollView: UIScrollView) {
didScrollSubject.send(())
let insetContentOffset = scrollView.contentOffset.y + scrollView.contentInset.top
isAtTopEdgeSubject.send(insetContentOffset >= 3)
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
@@ -68,6 +68,7 @@ class StateStoreViewModelV2<State: BindableState, ViewAction> {
/// Intentionally non-generic so that it doesn't grow uncontrollably
let mediaProvider: MediaProviderProtocol?
// periphery:ignore - might be useful to have
/// An optional content scanning service so that views can validate media themselves.
/// `nil` when no content scanner is configured for the server, or when the screen
/// intentionally doesn't provide one because it has no media to scan.
@@ -412,7 +412,6 @@ struct LoadableImage_Previews: PreviewProvider, TestablePreview {
mediaProvider.imageFromSourceSizeClosure = { _, _ in nil }
mediaProvider.loadFileFromSourceFilenameClosure = { _, _ in .failure(.failedRetrievingFile) }
mediaProvider.loadImageDataFromSourceClosure = { _ in .failure(.failedRetrievingImage) }
mediaProvider.loadImageFromSourceSizeClosure = { _, _ in .failure(.failedRetrievingImage) }
mediaProvider.loadThumbnailForSourceSourceSizeClosure = { _, _ in .failure(.failedRetrievingThumbnail) }
mediaProvider.loadImageRetryingOnReconnectionSizeClosure = { _, _ in
Task { throw MediaProviderError.failedRetrievingImage }
@@ -41,12 +41,6 @@ struct TopBannerLayer {
}
extension View {
/// Overlays the given banner view at the top edge of this view, using a
/// slide from the top edge when `isVisible` is toggled.
func topBanner(_ banner: some View, isVisible: Bool, footer: some View = EmptyView()) -> some View {
topBanners([TopBannerLayer(banner, isVisible: isVisible)], footer: footer)
}
/// Overlays the given Z-axis banner slots at the top edge of this view.
/// Later items in the array are overlayed on top of earlier ones. Within
/// each slot, visible vertical banners are stacked in a VStack and slide
@@ -182,7 +182,6 @@ enum TestablePreviewsDictionary {
"StaticLocationSheet_Previews" : StaticLocationSheet_Previews.self,
"StickerRoomTimelineView_Previews" : StickerRoomTimelineView_Previews.self,
"SwipeRightAction_Previews" : SwipeRightAction_Previews.self,
"SwipeToReplyView_Previews" : SwipeToReplyView_Previews.self,
"TextRoomTimelineView_Previews" : TextRoomTimelineView_Previews.self,
"ThreadDecorator_Previews" : ThreadDecorator_Previews.self,
"TimelineDeliveryStatusView_Previews" : TimelineDeliveryStatusView_Previews.self,
@@ -58,6 +58,7 @@ private struct PINTextFieldStyle: TextFieldStyle {
let maxLength: Int
let size: PINDigitField.Size
// periphery:ignore - called by SwiftUI via the TextFieldStyle protocol
func _body(configuration: TextField<_Label>) -> some View {
HStack(spacing: 8) {
ForEach(0..<maxLength, id: \.self) { index in
@@ -16,7 +16,6 @@ struct LoginScreenCoordinatorParameters {
let loginHint: String?
let userIndicatorController: UserIndicatorControllerProtocol
let appSettings: AppSettings
let analytics: AnalyticsServiceProtocol
}
enum LoginScreenCoordinatorAction {
@@ -28,13 +27,8 @@ enum LoginScreenCoordinatorAction {
/// Note: This code was brought over from Riot, we should move the authentication service logic into the view model.
final class LoginScreenCoordinator: CoordinatorProtocol {
private let parameters: LoginScreenCoordinatorParameters
private var viewModel: LoginScreenViewModelProtocol
private var authenticationService: AuthenticationServiceProtocol {
parameters.authenticationService
}
private let actionsSubject: PassthroughSubject<LoginScreenCoordinatorAction, Never> = .init()
private var cancellables = Set<AnyCancellable>()
@@ -45,13 +39,10 @@ final class LoginScreenCoordinator: CoordinatorProtocol {
// MARK: - Setup
init(parameters: LoginScreenCoordinatorParameters) {
self.parameters = parameters
viewModel = LoginScreenViewModel(authenticationService: parameters.authenticationService,
loginHint: parameters.loginHint,
userIndicatorController: parameters.userIndicatorController,
appSettings: parameters.appSettings,
analytics: parameters.analytics)
appSettings: parameters.appSettings)
}
// MARK: - Public
@@ -63,14 +63,10 @@ enum LoginScreenViewAction {
}
enum LoginScreenErrorType: Hashable {
/// A specific error message shown in an alert.
case alert(String)
/// An alert that informs the user to check their username/password.
case credentialsAlert
/// An alert that informs the user that their account has been deactivated.
case deactivatedAlert
/// An alert that informs the user about a bad well-known file.
case invalidWellKnownAlert(String)
/// An alert that allows the user to learn about sliding sync.
case slidingSyncAlert
/// An alert that informs the user that Element Pro should be used for a particular server.
@@ -15,7 +15,6 @@ class LoginScreenViewModel: LoginScreenViewModelType, LoginScreenViewModelProtoc
private let authenticationService: AuthenticationServiceProtocol
private let userIndicatorController: UserIndicatorControllerProtocol
private let appSettings: AppSettings
private let analytics: AnalyticsServiceProtocol
private var actionsSubject: PassthroughSubject<LoginScreenViewModelAction, Never> = .init()
var actions: AnyPublisher<LoginScreenViewModelAction, Never> {
@@ -25,12 +24,10 @@ class LoginScreenViewModel: LoginScreenViewModelType, LoginScreenViewModelProtoc
init(authenticationService: AuthenticationServiceProtocol,
loginHint: String?,
userIndicatorController: UserIndicatorControllerProtocol,
appSettings: AppSettings,
analytics: AnalyticsServiceProtocol) {
appSettings: AppSettings) {
self.authenticationService = authenticationService
self.userIndicatorController = userIndicatorController
self.appSettings = appSettings
self.analytics = analytics
let username = switch loginHint {
case .some(let hint) where hint.hasPrefix("mxid:"): String(hint.dropFirst(5)) // MSC4198
@@ -156,8 +156,7 @@ struct LoginScreen_Previews: PreviewProvider, TestablePreview {
let viewModel = LoginScreenViewModel(authenticationService: authenticationService,
loginHint: nil,
userIndicatorController: UserIndicatorControllerMock(),
appSettings: .volatile(),
analytics: AnalyticsServiceMock(.init()))
appSettings: .volatile())
if withCredentials {
viewModel.context.username = "alice"
@@ -25,11 +25,7 @@ enum ServerSelectionScreenCoordinatorAction {
/// Note: This code was brought over from Riot, we should move the authentication service logic into the view model.
final class ServerSelectionScreenCoordinator: CoordinatorProtocol {
private let parameters: ServerSelectionScreenCoordinatorParameters
private let userIndicatorController: UserIndicatorControllerProtocol
private var viewModel: ServerSelectionScreenViewModelProtocol
private var authenticationService: AuthenticationServiceProtocol {
parameters.authenticationService
}
private let actionsSubject: PassthroughSubject<ServerSelectionScreenCoordinatorAction, Never> = .init()
private var cancellables = Set<AnyCancellable>()
@@ -44,7 +40,6 @@ final class ServerSelectionScreenCoordinator: CoordinatorProtocol {
authenticationFlow: parameters.authenticationFlow,
appSettings: parameters.appSettings,
userIndicatorController: parameters.userIndicatorController)
userIndicatorController = parameters.userIndicatorController
}
// MARK: - Public
@@ -57,8 +57,6 @@ enum ServerSelectionScreenViewAction {
}
enum ServerSelectionScreenErrorType: Hashable {
/// An error message to be shown in the text field footer.
case footerMessage(String)
/// An alert that informs the user about a bad well-known file.
case invalidWellKnownAlert(String)
/// An alert that allows the user to learn about sliding sync.
@@ -15,7 +15,6 @@ class AuthenticationStartScreenViewModel: AuthenticationStartScreenViewModelType
private let authenticationService: AuthenticationServiceProtocol
private let provisioningParameters: AccountProvisioningParameters?
private let appMediator: AppMediatorProtocol
private let appSettings: AppSettings
private let userIndicatorController: UserIndicatorControllerProtocol
private let canReportProblem: Bool
@@ -37,7 +36,6 @@ class AuthenticationStartScreenViewModel: AuthenticationStartScreenViewModelType
self.authenticationService = authenticationService
self.provisioningParameters = provisioningParameters
self.appMediator = appMediator
self.appSettings = appSettings
self.userIndicatorController = userIndicatorController
canReportProblem = isBugReportServiceEnabled
@@ -18,7 +18,6 @@ class BugReportScreenViewModel: BugReportScreenViewModelType, BugReportScreenVie
private let logFiles: [URL]
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> {
@@ -179,6 +179,7 @@ private struct CallView: UIViewRepresentable {
}
}
// periphery:ignore:parameters userContentController - delegate convention
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard let handlerID = CallScreenJavaScriptMessageName(rawValue: message.name) else {
return
@@ -290,10 +291,6 @@ private struct CallView: UIViewRepresentable {
return .success(())
}
func stopPictureInPicture() {
pictureInPictureController?.stopPictureInPicture()
}
nonisolated func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
Task { @MainActor in
// We move the view via the delegate so it works when you background the app without calling requestPictureInPicture
@@ -11,8 +11,6 @@ import SwiftUI
typealias ChatsSpaceFiltersScreenViewModelType = StateStoreViewModelV2<ChatsSpaceFiltersScreenViewState, ChatsSpaceFiltersScreenViewAction>
class ChatsSpaceFiltersScreenViewModel: ChatsSpaceFiltersScreenViewModelType, ChatsSpaceFiltersScreenViewModelProtocol, Identifiable {
private let spaceService: SpaceServiceProxyProtocol
private let actionsSubject: PassthroughSubject<ChatsSpaceFiltersScreenViewModelAction, Never> = .init()
var actionsPublisher: AnyPublisher<ChatsSpaceFiltersScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
@@ -22,8 +20,6 @@ class ChatsSpaceFiltersScreenViewModel: ChatsSpaceFiltersScreenViewModelType, Ch
init(spaceService: SpaceServiceProxyProtocol,
mediaProvider: MediaProviderProtocol) {
self.spaceService = spaceService
super.init(initialViewState: ChatsSpaceFiltersScreenViewState(bindings: .init()),
mediaProvider: mediaProvider)
@@ -7,6 +7,7 @@
import Combine
// periphery:ignore - required for the architecture
protocol ChatsSpaceFiltersScreenViewModelProtocol {
var actionsPublisher: AnyPublisher<ChatsSpaceFiltersScreenViewModelAction, Never> { get }
var context: ChatsSpaceFiltersScreenViewModelType.Context { get }
@@ -53,16 +53,6 @@ struct CreateRoomScreenViewState: BindableState {
}
var aliasErrors: Set<CreateRoomScreenAliasErrorState> = []
var aliasErrorDescription: String? {
if aliasErrors.contains(.alreadyExists) {
L10n.errorRoomAddressAlreadyExists
} else if aliasErrors.contains(.invalidSymbols) {
L10n.errorRoomAddressInvalidSymbols
} else {
nil
}
}
var availableAccessTypes: [CreateRoomScreenAccessType] {
var availableAccessTypes: [CreateRoomScreenAccessType] = []
if isSpace {
@@ -6,8 +6,6 @@
// Please see LICENSE files in the repository root for full details.
//
// periphery:ignore:all - this is just a reportInvite remove this comment once generating the final file
import Combine
import SwiftUI
@@ -23,7 +21,6 @@ enum DeclineAndBlockScreenCoordinatorAction {
}
final class DeclineAndBlockScreenCoordinator: CoordinatorProtocol {
private let parameters: DeclineAndBlockScreenCoordinatorParameters
private let viewModel: DeclineAndBlockScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
@@ -34,8 +31,6 @@ final class DeclineAndBlockScreenCoordinator: CoordinatorProtocol {
}
init(parameters: DeclineAndBlockScreenCoordinatorParameters) {
self.parameters = parameters
viewModel = DeclineAndBlockScreenViewModel(userID: parameters.userID,
roomID: parameters.roomID,
clientProxy: parameters.clientProxy,
@@ -6,8 +6,6 @@
// Please see LICENSE in the repository root for full details.
//
// periphery:ignore:all - this is just a editRoomAddress remove this comment once generating the final file
import Combine
import SwiftUI
@@ -21,7 +21,6 @@ enum EmojiPickerScreenCoordinatorAction {
}
final class EmojiPickerScreenCoordinator: CoordinatorProtocol {
private let parameters: EmojiPickerScreenCoordinatorParameters
private var viewModel: EmojiPickerScreenViewModelProtocol
private let actionsSubject: PassthroughSubject<EmojiPickerScreenCoordinatorAction, Never> = .init()
@@ -32,8 +31,6 @@ final class EmojiPickerScreenCoordinator: CoordinatorProtocol {
}
init(parameters: EmojiPickerScreenCoordinatorParameters) {
self.parameters = parameters
viewModel = EmojiPickerScreenViewModel(itemID: parameters.itemID,
selectedEmojis: parameters.selectedEmojis,
emojiProvider: parameters.emojiProvider,
@@ -18,7 +18,6 @@ enum EncryptionResetPasswordScreenCoordinatorAction {
}
final class EncryptionResetPasswordScreenCoordinator: CoordinatorProtocol {
private let parameters: EncryptionResetPasswordScreenCoordinatorParameters
private let viewModel: EncryptionResetPasswordScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
@@ -29,8 +28,6 @@ final class EncryptionResetPasswordScreenCoordinator: CoordinatorProtocol {
}
init(parameters: EncryptionResetPasswordScreenCoordinatorParameters) {
self.parameters = parameters
viewModel = EncryptionResetPasswordScreenViewModel(passwordPublisher: parameters.passwordPublisher)
}
@@ -18,7 +18,6 @@ struct EncryptionResetPasswordScreenViewState: BindableState {
struct EncryptionResetPasswordScreenViewStateBindings {
var password: String
var alertInfo: AlertInfo<UUID>?
}
enum EncryptionResetPasswordScreenViewAction {
@@ -22,7 +22,6 @@ struct EncryptionResetScreenCoordinatorParameters {
}
final class EncryptionResetScreenCoordinator: CoordinatorProtocol {
private let parameters: EncryptionResetScreenCoordinatorParameters
private let viewModel: EncryptionResetScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
@@ -33,7 +32,6 @@ final class EncryptionResetScreenCoordinator: CoordinatorProtocol {
}
init(parameters: EncryptionResetScreenCoordinatorParameters) {
self.parameters = parameters
viewModel = EncryptionResetScreenViewModel(clientProxy: parameters.clientProxy,
userIndicatorController: parameters.userIndicatorController)
}
@@ -17,25 +17,6 @@ enum EncryptionResetScreenViewModelAction {
}
struct EncryptionResetScreenViewState: BindableState {
private let listItem3AttributedText = {
let boldPlaceholder = "{bold}"
var finalString = AttributedString(L10n.screenCreateNewRecoveryKeyListItem3(boldPlaceholder))
var boldString = AttributedString(L10n.screenCreateNewRecoveryKeyListItem3ResetAll)
boldString.bold()
finalString.replace(boldPlaceholder, with: boldString)
return finalString
}()
var listItems: [AttributedString] {
[
AttributedString(L10n.screenCreateNewRecoveryKeyListItem1(InfoPlistReader.main.productionAppName)),
AttributedString(L10n.screenCreateNewRecoveryKeyListItem2),
listItem3AttributedText,
AttributedString(L10n.screenCreateNewRecoveryKeyListItem4),
AttributedString(L10n.screenCreateNewRecoveryKeyListItem5)
]
}
var bindings: EncryptionResetScreenViewStateBindings
}
@@ -24,7 +24,6 @@ class TimelineMediaPreviewDataSource: NSObject, QLPreviewControllerDataSource {
private(set) var previewItems: [TimelineMediaPreviewItem.Media]
let previewItemsPaginationPublisher = PassthroughSubject<Void, Never>()
private let initialItem: EventBasedMessageTimelineItemProtocol
/// The index of the initial item inside of `previewItems` that is to be shown.
let initialItemIndex: Int
@@ -41,7 +40,6 @@ class TimelineMediaPreviewDataSource: NSObject, QLPreviewControllerDataSource {
initialPadding: Int = 100,
paginationState: TimelinePaginationState) {
previewItems = itemViewStates.compactMap(TimelineMediaPreviewItem.Media.init)
self.initialItem = initialItem
if let initialItemArrayIndex = previewItems.firstIndex(where: { $0.id == initialItem.id.eventOrTransactionID }) {
initialItemIndex = initialItemArrayIndex + initialPadding
@@ -74,10 +74,6 @@ struct TimelineMediaPreviewViewStateBindings {
var redactConfirmationItem: TimelineMediaPreviewItem.Media?
}
enum TimelineMediaPreviewAlertType {
case authorizationRequired
}
enum TimelineMediaPreviewViewAction {
case updateCurrentItem(TimelineMediaPreviewItem)
case showItemDetails(TimelineMediaPreviewItem.Media)
@@ -62,7 +62,6 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable {
private var hasBeenPresented = false
private var dismissalObserver: AnyCancellable?
private var cancellables: Set<AnyCancellable> = []
init(viewModel: TimelineMediaPreviewViewModel,
dismissalPublisher: PassthroughSubject<Void, Never>,
@@ -196,7 +196,6 @@ class TimelineMediaPreviewViewModel: TimelineMediaPreviewViewModelType {
canCurrentUserRedactOthers: timelineContext.viewState.canCurrentUserRedactOthers,
canCurrentUserPin: timelineContext.viewState.canCurrentUserPin,
pinnedEventIDs: timelineContext.viewState.pinnedEventIDs,
isDM: timelineContext.viewState.isDM,
isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled,
areThreadsEnabled: timelineContext.viewState.areThreadsEnabled,
timelineKind: timelineContext.viewState.timelineKind,
@@ -335,10 +335,6 @@ private struct DetailsButton: View {
context.viewState.currentItem
}
var isHidden: Bool {
currentItem.mediaItem == nil
}
var body: some View {
if let mediaItem = currentItem.mediaItem {
Button { context.send(viewAction: .showItemDetails(mediaItem)) } label: {
@@ -11,8 +11,6 @@ import SentrySwiftUI
import SwiftUI
struct HomeScreenContent: View {
@Environment(\.verticalSizeClass) private var verticalSizeClass
@ObservedObject var context: HomeScreenViewModel.Context
let scrollViewAdapter: ScrollViewAdapter
@@ -266,17 +266,6 @@ struct HomeScreenRoomCell_Previews: PreviewProvider, TestablePreview {
HomeScreenRoom(summary: summary)
}
static func makeViewModel(roomSummaryProvider: RoomSummaryProviderProtocol) -> HomeScreenViewModel {
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "John Doe", roomSummaryProvider: roomSummaryProvider))))
return HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
appSettings: .volatile(),
analyticsService: AnalyticsServiceMock(.init()),
notificationManager: NotificationManagerMock(),
userIndicatorController: UserIndicatorControllerMock())
}
static func makeRoom(lastMessageState: RoomSummary.LastMessageState? = nil,
heroes: [UserProfile] = []) -> HomeScreenRoom {
let name = if heroes.count == 1 {
@@ -15,7 +15,6 @@ struct InviteUsersScreenCoordinatorParameters {
let isSkippable: Bool
let userDiscoveryService: UserDiscoveryServiceProtocol
let userIndicatorController: UserIndicatorControllerProtocol
let appSettings: AppSettings
}
enum InviteUsersScreenCoordinatorAction {
@@ -37,8 +36,7 @@ final class InviteUsersScreenCoordinator: CoordinatorProtocol {
roomType: parameters.roomType,
isSkippable: parameters.isSkippable,
userDiscoveryService: parameters.userDiscoveryService,
userIndicatorController: parameters.userIndicatorController,
appSettings: parameters.appSettings)
userIndicatorController: parameters.userIndicatorController)
}
func start() {
@@ -9,7 +9,6 @@
import Foundation
import MatrixRustSDK
// periphery:ignore - for generic conformance
enum InviteUsersScreenErrorType: Error {
case unknown
}
@@ -17,7 +17,6 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
private let roomType: InviteUsersScreenRoomType
private let userDiscoveryService: UserDiscoveryServiceProtocol
private let userIndicatorController: UserIndicatorControllerProtocol
private let appSettings: AppSettings
private var suggestedUsers = [UserProfile]()
@@ -30,13 +29,11 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
roomType: InviteUsersScreenRoomType,
isSkippable: Bool,
userDiscoveryService: UserDiscoveryServiceProtocol,
userIndicatorController: UserIndicatorControllerProtocol,
appSettings: AppSettings) {
userIndicatorController: UserIndicatorControllerProtocol) {
clientProxy = userSession.clientProxy
self.roomType = roomType
self.userDiscoveryService = userDiscoveryService
self.userIndicatorController = userIndicatorController
self.appSettings = appSettings
let mandatoryInvitees: [UserProfile] = if case .draft(let invitees) = roomType {
invitees
@@ -194,7 +191,6 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
}
}
// periphery:ignore - automatically cancelled when set to nil
@CancellableTask
private var fetchUsersTask: Task<Void, Never>?
@@ -64,8 +64,7 @@ struct InviteUsersConfirmationSheetView_Previews: PreviewProvider, TestablePrevi
roomType: .existingRoom(roomProxy: JoinedRoomProxyMock(.init(members: []))),
isSkippable: true,
userDiscoveryService: UserDiscoveryServiceMock(),
userIndicatorController: UserIndicatorControllerMock(),
appSettings: .volatile())
userIndicatorController: UserIndicatorControllerMock())
viewModel.state.usersToConfirm = [.mockAlice, .mockCharlie, .mockBob, .mockDan]
@@ -212,8 +212,7 @@ struct InviteUsersScreen_Previews: PreviewProvider, TestablePreview {
roomType: roomType ?? .existingRoom(roomProxy: JoinedRoomProxyMock(.init(members: []))),
isSkippable: isSkippable,
userDiscoveryService: userDiscoveryService,
userIndicatorController: UserIndicatorControllerMock(),
appSettings: .volatile())
userIndicatorController: UserIndicatorControllerMock())
if let searchQuery {
viewModel.context.searchQuery = searchQuery
@@ -48,13 +48,6 @@ struct InviteUsersScreenSelectedItem: View {
avatarImage.overlayRemoveItemButton(action: dismissAction)
}
}
var closeButtonLabel: some View {
CompoundIcon(\.close, size: .custom(12), relativeTo: .compound.bodySM)
.foregroundStyle(.compound.iconOnSolidPrimary)
.padding(2)
.background(.compound.iconPrimary, in: Circle())
}
}
struct InviteUsersScreenSelectedItem_Previews: PreviewProvider, TestablePreview {
@@ -48,6 +48,7 @@ struct JoinRoomScreenRoomDetails {
let isDirect: Bool?
let isSpace: Bool?
// periphery:ignore - might be useful to have
let childrenCount: Int?
let spaceVisibility: SpaceServiceRoomVisibility?
}
@@ -6,8 +6,6 @@
// Please see LICENSE files in the repository root for full details.
//
// periphery:ignore:all - this is just a knockRequestsList remove this comment once generating the final file
import Combine
import SwiftUI
@@ -17,6 +15,7 @@ struct KnockRequestsListScreenCoordinatorParameters {
let userIndicatorController: UserIndicatorControllerProtocol
}
// periphery:ignore - required for the architecture
enum KnockRequestsListScreenCoordinatorAction { }
final class KnockRequestsListScreenCoordinator: CoordinatorProtocol {
@@ -24,7 +23,9 @@ final class KnockRequestsListScreenCoordinator: CoordinatorProtocol {
private var cancellables = Set<AnyCancellable>()
// periphery:ignore - required for the architecture
private let actionsSubject: PassthroughSubject<KnockRequestsListScreenCoordinatorAction, Never> = .init()
// periphery:ignore - required for the architecture
var actionsPublisher: AnyPublisher<KnockRequestsListScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
@@ -35,7 +36,11 @@ final class KnockRequestsListScreenCoordinator: CoordinatorProtocol {
userIndicatorController: parameters.userIndicatorController)
}
func start() { }
func start() {
viewModel.actionsPublisher
.sink { _ in }
.store(in: &cancellables)
}
func toPresentable() -> AnyView {
AnyView(KnockRequestsListScreen(context: viewModel.context))
@@ -6,8 +6,6 @@
// Please see LICENSE files in the repository root for full details.
//
// periphery:ignore:all - this is just a labs remove this comment once generating the final file
import Combine
import SwiftUI
@@ -20,7 +20,6 @@ struct LabsScreenViewState: BindableState {
var bindings: LabsScreenViewStateBindings
}
// periphery: ignore - subscripts are seen as false positive
@dynamicMemberLookup
struct LabsScreenViewStateBindings {
private let labsOptions: LabsOptionsProtocol
@@ -5,8 +5,6 @@
// Please see LICENSE files in the repository root for full details.
//
// periphery:ignore:all - this is just a manageAuthorizedSpaces remove this comment once generating the final file
import Combine
import SwiftUI
@@ -8,6 +8,7 @@
import Combine
// periphery:ignore - required for the architecture
protocol ManageRoomMemberSheetViewModelProtocol {
var actions: AnyPublisher<ManageRoomMemberSheetViewModelAction, Never> { get }
var context: ManageRoomMemberSheetViewModelType.Context { get }
@@ -30,7 +30,6 @@ enum MediaEventsTimelineScreenCoordinatorAction {
}
final class MediaEventsTimelineScreenCoordinator: CoordinatorProtocol {
private let parameters: MediaEventsTimelineScreenCoordinatorParameters
private let viewModel: MediaEventsTimelineScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
@@ -41,8 +40,6 @@ final class MediaEventsTimelineScreenCoordinator: CoordinatorProtocol {
}
init(parameters: MediaEventsTimelineScreenCoordinatorParameters) {
self.parameters = parameters
let mediaTimelineViewModel = TimelineViewModel(roomProxy: parameters.roomProxy,
timelineController: parameters.mediaTimelineController,
userSession: parameters.userSession,
@@ -29,8 +29,6 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
}
}
private var mediaPreviewCancellable: AnyCancellable?
private let actionsSubject: PassthroughSubject<MediaEventsTimelineScreenViewModelAction, Never> = .init()
var actionsPublisher: AnyPublisher<MediaEventsTimelineScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()

Some files were not shown because too many files have changed in this diff Show More