diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 398b38d1fe..d62a3eac31 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,7 +2,6 @@ - [ ] I read the [contributing guide](https://github.com/element-hq/element-ios/blob/develop/CONTRIBUTING.md). - [ ] Pull request contains a [changelog label](https://github.com/element-hq/element-x-ios/blob/develop/CONTRIBUTING.md#changelog). -- [ ] Pull request includes a [sign off](https://github.com/matrix-org/matrix-ios-sdk/blob/develop/CONTRIBUTING.md#sign-off). **UI changes have been tested with:** - [ ] iPhone and iPad simulators in portrait and landscape orientations. diff --git a/.swiftlint.yml b/.swiftlint.yml index 86bc5eeab8..dfef184a30 100755 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -9,6 +9,7 @@ opt_in_rules: - private_action - explicit_init - shorthand_optional_binding + - trailing_closure included: - ElementX diff --git a/CHANGES.md b/CHANGES.md index 3fe9a833a3..4d9516d80c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,52 @@ +## Changes in 1.9.9 (2024-12-05) + +### What's Changed + +🙌 Improvements +* Added historical message error label string by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3580 +* increase ringing timeout from 15 seconds to 90 seconds by @fkwp in https://github.com/element-hq/element-x-ios/pull/3584 +* Compound SendButton v2 by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3589 + +🧱 Build +* Add new development assets and use in mocks/previews. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3581 +* Fix UI snapshots. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3585 + +Others +* Update sdk to 1.0.78 by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3586 + +### New Contributors +* @fkwp made their first contribution in https://github.com/element-hq/element-x-ios/pull/3584 + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.9.8...1.9.9 + +## Changes in 1.9.8 (2024-12-03) + +### What's Changed + +✨ Features +* Enable local echoes for media uploads for all builds. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3579 + +🙌 Improvements +* Add support for copying a caption. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3563 +* Move pinned messages button in details by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3575 +* Add a warning to the media caption composer. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3574 +* Knock a room - added a char counter for the message by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3570 + +🐛 Bugfixes +* Small Knock adjustments by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3568 +* Wait until the sync has stopped before marking a background task as complete. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3564 +* Handle media source validation more gracefully. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3571 + +🗣 Translations +* Translations update by @RiotRobot in https://github.com/element-hq/element-x-ios/pull/3576 + +Others +* Make the Unit Test media files into development assets. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3569 +* Update SDK 1.0.77 by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3578 + + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.9.7...1.9.8 + ## Changes in 1.9.7 (2024-11-28) ### What's Changed diff --git a/Dangerfile.swift b/Dangerfile.swift index 32f1ddca30..137165c1ff 100644 --- a/Dangerfile.swift +++ b/Dangerfile.swift @@ -24,47 +24,10 @@ if danger.github.pullRequest.body?.isEmpty ?? true { warn("Please provide a description for this PR.") } -// Check for a ticket number -if let ticketNumberRegex = try? NSRegularExpression(pattern: "#\\d+") { - let missingTicketNumber = !danger.git.commits.filter { - !$0.message.contains("element-hq/element-x-ios/issues/") && - ticketNumberRegex.firstMatch(in: $0.message, options: [], range: .init(location: 0, length: $0.message.utf16.count)) == nil - }.isEmpty - - if missingTicketNumber { - warn("Some of the commits are missing ticket numbers. Please consider squashing all commits that don't have a tracking number.") - } -} - -// Check for a sign-off -let signOff = "Signed-off-by:" - -let allowList = ["stefanceriu", - "pixlwave", - "langleyd", - "manuroe", - "Velin92"] - -let requiresSignOff = !allowList.contains(where: { - $0.caseInsensitiveCompare(danger.github.pullRequest.user.login) == .orderedSame -}) - -if requiresSignOff { - let hasPRBodySignOff = danger.github.pullRequest.body?.contains(signOff) ?? false - - let isMissingCommitsSignOff = !danger.git.commits.filter { - !$0.message.contains(signOff) - }.isEmpty - - if !hasPRBodySignOff, isMissingCommitsSignOff { - warn("Please add a sign-off to either the PR description or to the commits themselves.") - } -} - // Check for screenshots on view changes let hasChangedViews = !editedFiles.filter { $0.lowercased().contains("/view") }.isEmpty if hasChangedViews { - if (danger.github.pullRequest.body?.contains("user-images") ?? false) == false { + if (danger.github.pullRequest.body?.contains("user-attachments") ?? false) == false { warn("You seem to have made changes to views. Please consider adding screenshots.") } } @@ -75,11 +38,15 @@ if hasPngs { warn("You seem to have made changes to some resource images. Please consider using an SVG or PDF.") } +// Check for nice PR titles +let prTitle = danger.github.pullRequest.title let fixesRegex = try! Regex("(Fixes|Fix) #\\d+") -if danger.github.pullRequest.title.hasSuffix("…") || danger.github.pullRequest.title.starts(with: fixesRegex) { +let semanticRegex = try! Regex("\\w+\\(\\w+\\):") +if prTitle.hasSuffix("…") || prTitle.starts(with: fixesRegex) || prTitle.starts(with: semanticRegex) { fail("Please provide a complete title that can be used as a changelog entry.") } +// Check for changelog tags if danger.github.issue.labels.filter({ $0.name.hasPrefix("pr-") }).count != 1 { fail("Please add a `pr-` label to categorise the changelog entry.") } diff --git a/DevelopmentAssets/Media/preview_avatar_room.jpg b/DevelopmentAssets/Media/preview_avatar_room.jpg new file mode 100644 index 0000000000..29c751ce3c --- /dev/null +++ b/DevelopmentAssets/Media/preview_avatar_room.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b93f7979cdf99dfa5ff92467d0941c49605917a1e92313070c6ad8c121bf1fb +size 206381 diff --git a/DevelopmentAssets/Media/preview_avatar_user.jpg b/DevelopmentAssets/Media/preview_avatar_user.jpg new file mode 100644 index 0000000000..52d952766e --- /dev/null +++ b/DevelopmentAssets/Media/preview_avatar_user.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e573ee1599506ed89de9492677c9570da8a815bc38f33048298e98cc27d3622 +size 596481 diff --git a/DevelopmentAssets/Media/preview_image.jpg b/DevelopmentAssets/Media/preview_image.jpg new file mode 100644 index 0000000000..e13cf36541 --- /dev/null +++ b/DevelopmentAssets/Media/preview_image.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6afb36f6920fc448de6cdf75568eabf8ff7ed8b725105e4899765490d41a73e +size 717231 diff --git a/DevelopmentAssets/Media/preview_video.jpg b/DevelopmentAssets/Media/preview_video.jpg new file mode 100644 index 0000000000..8390351705 --- /dev/null +++ b/DevelopmentAssets/Media/preview_video.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:650ecdfe3c9d19ee92992888faa8cb4b10f63fc968d0bddd4a29f0bd9612938e +size 488037 diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 8bd039e09f..d07d16f1b4 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 02A92F8F4538CECDFB4F2607 /* RoomDirectorySearchScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1562EAF6231151A675BED7A9 /* RoomDirectorySearchScreenCoordinator.swift */; }; 02D8DF8EB7537EB4E9019DDB /* EventBasedTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 218AB05B4E3889731959C5F1 /* EventBasedTimelineItemProtocol.swift */; }; 0307469D99B5FE6C7043AE39 /* KnockRequestsListScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9E8A8EC299E12490588B07C /* KnockRequestsListScreenCoordinator.swift */; }; + 03631FC946FF0BBAD37E22BF /* preview_avatar_user.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 87FC42213E86E8182CFD3A49 /* preview_avatar_user.jpg */; }; 037006FB6DF1374F94E4058D /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDCAC6CAAD65A2C24EA9C4B /* Dictionary.swift */; }; 038AB2E86960FD240231D4C2 /* GeneratedPreviewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A2E4BD7C0CAD25EF924A4C /* GeneratedPreviewTests.swift */; }; 03BD83E8BDD23AE059802E0D /* UITestsScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */; }; @@ -57,6 +58,7 @@ 077CB230153E072C94B1E6C3 /* AppAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D65BCC659FD9087E49B3C25 /* AppAppearance.swift */; }; 07CC13C5729C24255348CBBD /* ElementCallWidgetDriver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */; }; 07F6382E29845D235BFA3308 /* DeactivateAccountScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE78CAD0B964C66FD06EF83E /* DeactivateAccountScreenModels.swift */; }; + 08547E55DD3686A84550996D /* SeparatorMediaEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13F354AD441E2FD83DED89AF /* SeparatorMediaEventsTimelineView.swift */; }; 086D01E79C8E8D3F004FAF21 /* AudioPlayerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC9104846487244648D32C6D /* AudioPlayerProtocol.swift */; }; 08CB4BD12CEEDE6AAE4A18DD /* WindowManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035177BCD8E8308B098AC3C2 /* WindowManager.swift */; }; 095C0ACFC234E0550A6404C5 /* AppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FC803282F9268D49F4ABF14 /* AppCoordinator.swift */; }; @@ -68,6 +70,7 @@ 0A0625A271EE5B06D2AAA069 /* HomeScreenSlidingSyncMigrationBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4691B8DE1D51DE152680098A /* HomeScreenSlidingSyncMigrationBanner.swift */; }; 0A194F5E70B5A628C1BF4476 /* AdvancedSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4999B5FD50AED7CB0F590FF8 /* AdvancedSettingsScreenModels.swift */; }; 0ACAA31FD0399CEEBA3ECC21 /* UserDetailsEditScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85149F56BA333619900E2410 /* UserDetailsEditScreenViewModelProtocol.swift */; }; + 0AD8EF040A60D62F488C18B5 /* KnockRequestProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F957320D0EB7D7B4E30C79D /* KnockRequestProxyMock.swift */; }; 0AE0AB1952F186EB86719B4F /* HomeScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */; }; 0BAF83521871E69D222EE8E4 /* ClientBuilderHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC0CD1CAFD3F8B057F9AEA5 /* ClientBuilderHook.swift */; }; 0BDA19079FD6E17C5AC62E22 /* RoomDetailsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06F22CFA34885B40976061 /* RoomDetailsEditScreen.swift */; }; @@ -83,6 +86,7 @@ 0C932A5158C1D0604DFC5750 /* ComposerToolbarViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA29952595B804DA221A0C1D /* ComposerToolbarViewModelTests.swift */; }; 0CF81807BE5FBFC9E2BBCECF /* PollFormScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3368395F06AA180138E185B6 /* PollFormScreenUITests.swift */; }; 0D4EB2ABAA5FE8CB10FDBCB8 /* TimelineItemFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AA3AF94A06D319BB37E52DA /* TimelineItemFactoryTests.swift */; }; + 0D617A152D099D94271D3BA8 /* SecurityAndPrivacyScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D046ABB22E680F7C5054441B /* SecurityAndPrivacyScreenViewModelProtocol.swift */; }; 0DC815CA24E1BD7F408F37D3 /* CollapsibleTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */; }; 0E08BB72B2258652CF501A8B /* Version in Frameworks */ = {isa = PBXBuildFile; productRef = 2B9ACE4FCACB5A8812154424 /* Version */; }; 0E3A2787C6AEC761A81A938A /* AuthenticationStartScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8609BE4CA71C30D1FCE3AF9B /* AuthenticationStartScreenModels.swift */; }; @@ -98,12 +102,14 @@ 1146E9EDCF8344F7D6E0D553 /* MockCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0376C429FAB1687C3D905F3E /* MockCoder.swift */; }; 119AE9A3FC6E0606C1146528 /* NotificationSettingsEditScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C97F8963B14EB0AF3940DDBF /* NotificationSettingsEditScreenRoomCell.swift */; }; 11A6B8E3CBDBF0A4107FF4CE /* OnboardingFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */; }; + 1224084B7E289E0830BA2C54 /* VoiceMessageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6A293D06BAB2B7A17D9314B /* VoiceMessageRoomTimelineView.swift */; }; 126EE01D8BEAEF26105D83C5 /* RoomDetailsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A5FEF17ED7E6176D922D4F /* RoomDetailsScreen.swift */; }; 128FFD8A3D85845F9A927F47 /* PollRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF8548D48512127CCC17C520 /* PollRoomTimelineView.swift */; }; 12C867E85E6D12EEDFD0B127 /* CustomStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C4762F8D6112E43117DB2F /* CustomStringConvertible.swift */; }; 12CCA59536EDD99A3272CF77 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC3F82523D6F48B926D6AF68 /* AppSettings.swift */; }; 12CD8B5CC30A05061228BF9E /* TimelineItemMenuActionProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9E6065FC6BC4A1B4C629E08 /* TimelineItemMenuActionProvider.swift */; }; 12E6D052D055531A6783E21B /* portrait_test_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = BC51BF90469412ABDE658CDD /* portrait_test_image.jpg */; }; + 12EC6BC99F373FE5C6EB9B64 /* TimelineMediaPreviewDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467498BEA681758BE2F80826 /* TimelineMediaPreviewDetailsView.swift */; }; 1307268DC41730E5BCF7D9A0 /* PollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 638790D3F915F0909315C47A /* PollView.swift */; }; 1318721F4E5F307586D98112 /* VoiceMessageButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8516302ACCA94A0E680AB3B /* VoiceMessageButton.swift */; }; 13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */; }; @@ -128,11 +134,13 @@ 172E6E9A612ADCF10A62CF13 /* BugReportServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A68BCE6438873D2661D93D0 /* BugReportServiceProtocol.swift */; }; 1795EA6A6C4942CAE0459DF0 /* SecureBackupKeyBackupScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82B612853BFB68373249777B /* SecureBackupKeyBackupScreenViewModel.swift */; }; 17BC15DA08A52587466698C5 /* RoomMessageEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */; }; + 1801F1467ABCEA080419E150 /* preview_avatar_user.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 87FC42213E86E8182CFD3A49 /* preview_avatar_user.jpg */; }; 18867F4F1C8991EEC56EA932 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; }; 18978C9438206828C1D5AF2A /* test_animated_image.gif in Resources */ = {isa = PBXBuildFile; fileRef = 53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */; }; 18E3786918486D4C9726BC84 /* FormButtonStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89FBFC09F9DAFF1E4BA97849 /* FormButtonStyles.swift */; }; 18FDE4ED6D83B0771452B43D /* RoomSelectionScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F104596B0620CEFE5DFD31B1 /* RoomSelectionScreenCoordinator.swift */; }; 192A3CDCD0174AD1E4A128E4 /* AudioRecorderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2441E2424E78A40FC95DBA76 /* AudioRecorderTests.swift */; }; + 194585F6CD77242B36D4ADF1 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = DADECBBB672497BCD4822468 /* Result.swift */; }; 1950A80CD198BED283DFC2CE /* ClientProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */; }; 197441F1EF23A5DABACCA79F /* StickerRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5338450E6783A576B5C16DD /* StickerRoomTimelineView.swift */; }; 19DED23340D0855B59693ED2 /* VoiceMessageRecorderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45C9EAA86423D7D3126DE4F /* VoiceMessageRecorderProtocol.swift */; }; @@ -225,6 +233,7 @@ 2CA6ABBC9A88EB89EA52FCCB /* ConfettiScene.scn in Resources */ = {isa = PBXBuildFile; fileRef = B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */; }; 2D0E3983288E2D35613AD681 /* SecureBackupControllerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AB29A2D95D3469B5F016655 /* SecureBackupControllerMock.swift */; }; 2D2D8A53B35BE8D8A01449C6 /* PinnedEventsBannerStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FA38E813BE14149F173F461 /* PinnedEventsBannerStateTests.swift */; }; + 2D38D39B1789B91AE69F477F /* PhotoLibraryManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD955A0380C287C418F1A74D /* PhotoLibraryManagerMock.swift */; }; 2DA27D78560D5F79B917E163 /* AudioConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E44E35AA87F49503E7B3BF6E /* AudioConverter.swift */; }; 2DD9D0FE7CB5CFC80D071451 /* AppLockScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C3E67E09FE5A35D73818C39 /* AppLockScreenModels.swift */; }; 2E43A3D221BE9587BC19C3F1 /* MatrixEntityRegexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */; }; @@ -291,6 +300,7 @@ 3B277D9538090766DA6C4566 /* StateRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2AF1828A5B76B7C371240FE /* StateRoomTimelineView.swift */; }; 3B28408450BCAED911283AA2 /* UserPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35FA991289149D31F4286747 /* UserPreference.swift */; }; 3B98049F56025726FB646ABD /* SwipeToReplyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B0E0B55E2EE75AF67029924 /* SwipeToReplyView.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 */; }; 3C549A0BF39F8A854D45D9FD /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 0DD568A494247444A4B56031 /* Kingfisher */; }; 3C73442084BF8A6939F0F80B /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */; }; @@ -326,6 +336,7 @@ 43F35A7E5703D64DB0519C59 /* ServerSelectionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD469F7513574341181F7EAA /* ServerSelectionScreen.swift */; }; 440123E29E2F9B001A775BBE /* TimelineItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */; }; 44121202B4A260C98BF615A7 /* RoomMembersListScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5B7A755E985FA14469E86B2 /* RoomMembersListScreenUITests.swift */; }; + 446BCD2D0AE27E0CFD1BDC8F /* ImageMediaEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FF584D757E768EA7776A532 /* ImageMediaEventsTimelineView.swift */; }; 44BDD670FF9095ACE240A3A2 /* VoiceMessageMediaManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC4F10BDD56FA77FEC742333 /* VoiceMessageMediaManagerTests.swift */; }; 44DA28B1E1F9C97C5795F7B3 /* AppLockSetupUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8A1BBEF7318CA6B6ACCF4AE /* AppLockSetupUITests.swift */; }; 44F0E1B576C7599DF8022071 /* WysiwygComposer in Frameworks */ = {isa = PBXBuildFile; productRef = CA07D57389DACE18AEB6A5E2 /* WysiwygComposer */; }; @@ -349,6 +360,7 @@ 4807E8F51DB54F56B25E1C7E /* AppLockSetupSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D8C38663020DF2EB2D13F5E /* AppLockSetupSettingsScreenViewModel.swift */; }; 48416BBEB8DDF3E4DED0EDB6 /* ElementCallServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FC8B21E86B137BE4E91F82A /* ElementCallServiceProtocol.swift */; }; 484202C5D50983442D24D061 /* AttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BD6ED18E2EB61E28C340AD /* AttributedString.swift */; }; + 4870F7F72CEBEFDAD1C973A6 /* VoiceMessageMediaEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD3521DF92391551E02004D8 /* VoiceMessageMediaEventsTimelineView.swift */; }; 489BB6A733D3DA0FE7062650 /* IdentityConfirmationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C71B9802433F1B4252291BB /* IdentityConfirmationScreenViewModelProtocol.swift */; }; 491D62ACD19E6F134B1766AF /* RoomNotificationSettingsUserDefinedScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3203C6566DC17B7AECC1B7FD /* RoomNotificationSettingsUserDefinedScreen.swift */; }; 492274DA6691EE985C2FCCAA /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 67E7A6F388D3BF85767609D9 /* Sentry */; }; @@ -384,12 +396,14 @@ 4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */; }; 4EA1CE0E88EA68E862FF0EA2 /* NotificationSettingsEditScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B564D748B67A156F413CD97 /* NotificationSettingsEditScreenModels.swift */; }; 4EAC427267424192964B16B3 /* AppSettingsHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13BE9781699FB510E9263192 /* AppSettingsHook.swift */; }; + 4ED764A24F2A715C25CF07F1 /* TimelineMediaPreviewFileExportPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30856520F3263D0E195710D7 /* TimelineMediaPreviewFileExportPicker.swift */; }; 4F2DF6138E87A4B8C2488CA3 /* VoiceMessageCacheProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A84EE187D0C772E18A4E39 /* VoiceMessageCacheProtocol.swift */; }; 4FDC8A9764CFDA90CE035725 /* Duration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB2253D36E81E045E1CB432 /* Duration.swift */; }; 4FE688FE9375B2FBF424146A /* TextBasedRoomTimelineViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6EA0D8B0BBD8805F7D5A133 /* TextBasedRoomTimelineViewProtocol.swift */; }; 4FF90E2242DBD596E1ED2E27 /* AppCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077D7C3BE199B6E5DDEC07EC /* AppCoordinatorStateMachine.swift */; }; 4FFDC274824F7CC0BBDF581E /* BugReportScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C2BCE0BC1FC69C1B36E688 /* BugReportScreenModels.swift */; }; 50381244BA280451771BE3ED /* PINTextFieldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF13BFD415CA84B1272E94F8 /* PINTextFieldTests.swift */; }; + 5038E69A5E6A89DE1A345E04 /* ShouldScrollOnKeyboardDidShow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 832397B5C3D00A4BF52C5F0B /* ShouldScrollOnKeyboardDidShow.swift */; }; 50539366B408780B232C1910 /* EstimatedWaveformView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD0FF64B0E6470F66F42E182 /* EstimatedWaveformView.swift */; }; 50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.swift */; }; 5100F53E6884A15F9BA07CC3 /* AttributedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */; }; @@ -407,11 +421,13 @@ 53F1196F9C69512306A2693F /* TextRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C19F54A0C4FC9AB7ABD583 /* TextRoomTimelineItemContent.swift */; }; 54AE8860D668AFD96E7E177B /* UITestsScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */; }; 54C774874BED4A8FAD1F22FE /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.swift */; }; + 54FDA3625AACBD9E438D084D /* BlurEffectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07934EF08BB39353E4A94272 /* BlurEffectView.swift */; }; 5518DA4A6C9B4FC4B497EA9A /* LogViewerScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B795AAAB7B8747FE2FF311 /* LogViewerScreenModels.swift */; }; 558E2673B04FDD06A1A12DD3 /* LogViewerScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7463464054DDF194C54F0B04 /* LogViewerScreenViewModelProtocol.swift */; }; 558F37B1A8F2C4CC9B1ACEDA /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = 3262F08E1C3483C22A7A319F /* Compound */; }; 55CDD3968D95D1A820B5491E /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */; }; 55D18AA4F4A2257642EBDB94 /* GlobalSearchScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38354164AF59C5006CD05878 /* GlobalSearchScreenViewModel.swift */; }; + 55DF6DEEF2CEEF40F84B53B0 /* VoiceMessageRoomPlaybackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E3B41C36800DD4558D7BDA7 /* VoiceMessageRoomPlaybackView.swift */; }; 562EFB9AB62B38830D9AA778 /* TimelineMediaFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */; }; 564910A38858306301C1C21E /* DeactivateAccountScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1009E4A78F86DA42E1EAF0 /* DeactivateAccountScreenCoordinator.swift */; }; 564BF06B3E93D6DD55F903B2 /* CreateRoomCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C618CA2B6C8758B06C88013C /* CreateRoomCoordinator.swift */; }; @@ -436,6 +452,7 @@ 5BC6C4ADFE7F2A795ECDE130 /* SecureBackupKeyBackupScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B2D4EEBE8C098BBADD10939 /* SecureBackupKeyBackupScreenCoordinator.swift */; }; 5C02841B2A86327B2C377682 /* NotificationConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C830A64609CBD152F06E0457 /* NotificationConstants.swift */; }; 5C164551F7D26E24F09083D3 /* StaticLocationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C616D90B1E2F033CAA325439 /* StaticLocationScreenViewModelProtocol.swift */; }; + 5C33976A720B64094CBC56B1 /* VideoMediaEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B1FB56520A847DD2532D5C8 /* VideoMediaEventsTimelineView.swift */; }; 5C61810ED7B7CB48346B1B9D /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = E5E7D4EE7CA295E5039FDA21 /* portrait_test_video.mp4 */; }; 5C8804B4F25903516E2DAB81 /* RoomInfoProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40A66E8BC8D9AE4A08EFB2DF /* RoomInfoProxy.swift */; }; 5D27B6537591471A42C89027 /* EmoteRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 450E04B2A976CC4C8CC1807C /* EmoteRoomTimelineItem.swift */; }; @@ -444,15 +461,19 @@ 5D56CE09743C6B90C21B04C2 /* RoomMembersListScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E9E0929CEFA356090BE5FB8 /* RoomMembersListScreenViewModelTests.swift */; }; 5D70FAE4D2BF4553AFFFFE41 /* NotificationItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */; }; 5D99F63CC88BB29383019FC6 /* ShareExtensionModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAC01A97A43BE07B9E94E43 /* ShareExtensionModels.swift */; }; + 5DB4334CBBA142376FF5FFEC /* preview_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 200626E8353AB2729444F991 /* preview_image.jpg */; }; 5DD0EF30070DC0A82C5CCD33 /* RoomMembersListManageMemberSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC853F9B4FBE039D2C16EC6B /* RoomMembersListManageMemberSheet.swift */; }; 5DD85A0FE3D85AEC3C7EFE36 /* DeveloperOptionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7C7CFA6B2A62A685FF6CE3 /* DeveloperOptionsScreenCoordinator.swift */; }; 5EE1D4E316D66943E97FDCF2 /* BloomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7BEB970F500BFB248443FA1 /* BloomView.swift */; }; 5F06AD3C66884CE793AE6119 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */; }; 5F0B5797D1BFF2A51084B4C3 /* PinnedEventsTimelineScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86D7CD5CA270BFC3EBB450CA /* PinnedEventsTimelineScreenViewModel.swift */; }; + 5F35069E13D71DD88633A4B2 /* preview_video.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 45A4B934BA41D6C255900265 /* preview_video.jpg */; }; 5F5488FBC9CFEB6F433D74A4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7109E709A7738E6BCC4553E6 /* Localizable.strings */; }; + 5FA1DCE55973862632961D7C /* PhotoLibraryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7495E1119753B06FF2C2279 /* PhotoLibraryManager.swift */; }; 5FCD8AFA364206EE32B909A3 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B050A6B233D95807A09289E7 /* Settings.bundle */; }; 601AB75BD52B0B4276CEB84A /* SessionVerificationScreenStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 161CD412E75F4086F422AE39 /* SessionVerificationScreenStateMachine.swift */; }; 60ED66E63A169E47489348A8 /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 886A0A498FA01E8EDD451D05 /* Sentry */; }; + 611BEE29B8B622204E1E6B04 /* SecurityAndPrivacyScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97F2F6B6E56055EF173A2DD3 /* SecurityAndPrivacyScreenCoordinator.swift */; }; 6146996D5C4DDD5DA816FC87 /* AuthenticationTextFieldStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCACD75595C40EACD6AD4A74 /* AuthenticationTextFieldStyle.swift */; }; 617624A97BDBB75ED3DD8156 /* RoomScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */; }; 6189B4ABD535CE526FA1107B /* StartChatViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DF438EAFC732D2D95D34BF6 /* StartChatViewModelTests.swift */; }; @@ -512,6 +533,7 @@ 6AEB650311F694A5702255C9 /* UserProfileScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B4932E4EFBC8FAC10972CD /* UserProfileScreenCoordinator.swift */; }; 6B31508C6334C617360C2EAB /* RoomMemberDetailsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */; }; 6B61F5B27412ED4BC2F9769C /* test_audio.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */; }; + 6B80C24A52411EAF10E06E96 /* SecurityAndPrivacyScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBADF8010C813D905C172CE /* SecurityAndPrivacyScreenModels.swift */; }; 6BAD956B909A6E29F6CC6E7C /* ButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */; }; 6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */; }; 6C98153D60FF9B648C166C27 /* TimelineItemMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */; }; @@ -539,6 +561,7 @@ 71AC1CAAC23403FFE847F2C9 /* ComposerToolbarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C90514BE9B8ACCBCF0AD2489 /* ComposerToolbarViewModel.swift */; }; 71B62C48B8079D49F3FBC845 /* ExpiringTaskRunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B7A28A6606D58D1E38C55A /* ExpiringTaskRunnerTests.swift */; }; 71C1347F23868324A4F43940 /* NavigationModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A05E472533ED3C5A31B3 /* NavigationModule.swift */; }; + 7254FB2EFDD43BC8BB7A1213 /* SecurityAndPrivacyScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4AE42C19EDE64B7CB7BE4D0 /* SecurityAndPrivacyScreen.swift */; }; 733E2B19AB1FDA3B93293A28 /* AppLockSetupPINScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3F275432954C8C6B1B7D966 /* AppLockSetupPINScreen.swift */; }; 7354D094A4C59B555F407FA1 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.swift */; }; 73F33E9776B7A50B65A031D2 /* AppLockSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0BA67B3E4EF9D29D14A78CE /* AppLockSettingsScreenViewModelTests.swift */; }; @@ -569,7 +592,9 @@ 77BB228AEA861E50FFD6A228 /* HomeScreenEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */; }; 77C1A2F49CD90D3EFDF376E5 /* MapTilerURLBuildersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */; }; 77D7DAA41AAB36800C1F2E2D /* RoomTimelineProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */; }; + 77E33FF0E4A50B555BF3A8AA /* AudioFileEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC9044BE0E4A66F5B963E834 /* AudioFileEventsTimelineView.swift */; }; 77FACC29F98FE2E65BBB6A5F /* ServerSelectionUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054F469E433864CC6FE6EE8E /* ServerSelectionUITests.swift */; }; + 77FB08C303F4C74C0E8577E2 /* TimelineMediaPreviewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2BB38DF61F5100B8723112 /* TimelineMediaPreviewModels.swift */; }; 7807B1DEE32617896886A8E5 /* FormattingToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE1E6FAA3719E9B7A2D5510B /* FormattingToolbar.swift */; }; 784592335560C2E91D32D177 /* DeveloperOptionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06B098A612DCB5A7358EECD5 /* DeveloperOptionsScreenModels.swift */; }; 785613C0C092B532198EB3BB /* TimelineStartRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44ECC9D66400727DFFEE12E8 /* TimelineStartRoomTimelineView.swift */; }; @@ -598,6 +623,7 @@ 7C0E29E0279866C62EC67A28 /* JoinRoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE5127D6EA05B2E45D0A7D59 /* JoinRoomScreenViewModelTests.swift */; }; 7C164A642E8932B5F9004550 /* test_voice_message.m4a in Resources */ = {isa = PBXBuildFile; fileRef = DCA2D836BD10303F37FAAEED /* test_voice_message.m4a */; }; 7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */; }; + 7C545FFEC9930F7247352593 /* SecurityAndPrivacyScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 978092B01BEAB39F2C4389AE /* SecurityAndPrivacyScreenViewModel.swift */; }; 7C6376192F578E0BA801BFEC /* AnalyticsSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */; }; 7CD16990BA843BE9ED639129 /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DFE4453AB0B34C203447162 /* ImageRoomTimelineItem.swift */; }; 7D249465ED00988EEEC14E05 /* JoinedRoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 867DC9530C42F7B5176BE465 /* JoinedRoomProxyMock.swift */; }; @@ -618,6 +644,7 @@ 8015842CB4DE1BE414D2CDED /* AppLockSetupBiometricsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C62E07C1164F5120727A2A8 /* AppLockSetupBiometricsScreenCoordinator.swift */; }; 804C15D8ADE0EA7A5268F58A /* OverridableAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */; }; 80DEA2A4B20F9E279EAE6B2B /* UserProfile+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */; }; + 80F1B442DB5E2C362ACDD8E2 /* ZoomTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 018194CAFBE80720FECCEDEE /* ZoomTransition.swift */; }; 80F6C8EFCA4564B67F0D34B0 /* DeactivateAccountScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77F75B3E9F99864048A422A /* DeactivateAccountScreenViewModelTests.swift */; }; 81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36C0A6D59717193F49EA986 /* UserSessionTests.swift */; }; 8285FF4B2C2331758C437FF7 /* ReportContentScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 713B48DBF65DE4B0DD445D66 /* ReportContentScreenViewModelProtocol.swift */; }; @@ -626,23 +653,27 @@ 8358D145F9BF94F412BEDCA8 /* RoomRolesAndPermissionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE7969EBCAF078813E18EA1 /* RoomRolesAndPermissionsScreenModels.swift */; }; 83A4DAB181C56987C3E804FF /* MapTilerStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B9F5BC4C80543DE7228B9D /* MapTilerStyle.swift */; }; 83B17A44D3E7E6DF22D9A2A4 /* RoomModerationRole.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B32BBA8887BD7A5C4ECF16F /* RoomModerationRole.swift */; }; + 83D519C509F0F76EDBB60455 /* KnockRequestProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F062DD2CCD95DC33528A16F /* KnockRequestProxy.swift */; }; 84226AD2E1F1FBC965F3B09E /* UnitTestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A8E19C4645D3F5F9FB02355 /* UnitTestsAppCoordinator.swift */; }; 8446C2A7ECEFDA79F622725F /* TimelineReactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54AD70D6E03D2031AE1B5A52 /* TimelineReactionsView.swift */; }; 8478992479B296C45150208F /* AppLockScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC0275CEE9CA078B34028BDF /* AppLockScreenViewModelTests.swift */; }; 847DE3A7EB9FCA2C429C6E85 /* PINTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1D4A6D451F43A03CACD01D /* PINTextField.swift */; }; 84C631E734FD2555B39B681C /* RoomRolesAndPermissionsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48FEFF746DB341CDB18D7AAA /* RoomRolesAndPermissionsScreenViewModelTests.swift */; }; 84CAE3E96D93194DA06B9194 /* CallScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD9AD6AE5FC868962F090740 /* CallScreenViewModelProtocol.swift */; }; + 84E514915DF0C168B08A3A0A /* MediaEventsTimelineFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2178B951602AA921A5FD9DC8 /* MediaEventsTimelineFlowCoordinator.swift */; }; 84EFCB95F9DA2979C8042B26 /* UITestsSignalling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */; }; 8544657DEEE717ED2E22E382 /* RoomNotificationSettingsProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5D1BAA90F3A073D91B4F16B /* RoomNotificationSettingsProxyMock.swift */; }; 854E82E064BA53CD0BC45600 /* LocationRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD6613DE16AD26B3A74DA1F5 /* LocationRoomTimelineItemContent.swift */; }; 8587A53DE8EF94FD796DC375 /* RoomAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEF5FE93A06F563B477F024A /* RoomAvatarImage.swift */; }; 859E2CA2EDF343BD24DE52EB /* RoomDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */; }; + 85BD82E144AB99518A57DDEC /* preview_avatar_room.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 12FD5280AF55AB7F50F8E47D /* preview_avatar_room.jpg */; }; 85F89F3F320F4FADCFFFE68B /* ServerSelectionScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3059CFA00C67D8787273B20 /* ServerSelectionScreenViewModel.swift */; }; 864C0D3A4077BF433DBC691F /* PollRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5281C5CDC4A712265A0B5FBF /* PollRoomTimelineItem.swift */; }; 864C69CF951BF36D25BE0C03 /* DeveloperOptionsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D0A27607AB09784C8501B5C /* DeveloperOptionsScreenViewModelTests.swift */; }; 8658F5034EAD7357CE7F9AC7 /* MatrixUserShareLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E31AB0E77BB70E2BC77463 /* MatrixUserShareLink.swift */; }; 865DD5CA474C6AE6C2BC008E /* NetworkMonitorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1575947B7A6FE08C57FE5EE4 /* NetworkMonitorProtocol.swift */; }; 86675910612A12409262DFBD /* SessionVerificationStateMachineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */; }; + 86769B62BAE17601B3AE1B60 /* TimelineMediaPreviewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53F41CEAAE2BB4E74CDC2278 /* TimelineMediaPreviewViewModel.swift */; }; 8691186F9B99BCDDB7CACDD8 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; }; 86DFA58FBBEB0AF671D2A1E1 /* HomeScreenKnockedCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A103580EBA06155B1343EF16 /* HomeScreenKnockedCell.swift */; }; 86F9D3028A1F4AE819D75560 /* RoomChangePermissionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D879FC4E881E748BB9B34DC /* RoomChangePermissionsScreenCoordinator.swift */; }; @@ -650,7 +681,6 @@ 874FEFB9D4A4AF447E0E086E /* AuthenticationStartScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0F7CCC4A9D1927223F559D5 /* AuthenticationStartScreenViewModelProtocol.swift */; }; 877D3CE8680536DB430DE6A2 /* TimelineItemIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E48C91C8BE55CAE1A3DBC3BC /* TimelineItemIdentifier.swift */; }; 878070573C7BF19E735707B4 /* RoomTimelineItemProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */; }; - 87B4E59A4467F8EC75F82372 /* VoiceMessageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B70A50C41C5871B4DB905E7E /* VoiceMessageRoomTimelineView.swift */; }; 87CEA3E07B602705BC2D2A20 /* ClientBuilderHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC0CD1CAFD3F8B057F9AEA5 /* ClientBuilderHook.swift */; }; 8810A2A30A68252EBB54EE05 /* HomeScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BC7CA1BC1041E93077BBA1 /* HomeScreenModels.swift */; }; 88356DE7F2AD243AB10C7B7A /* Signposter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */; }; @@ -733,6 +763,7 @@ 97969EF0B9C412CD38E5CA93 /* AppLockScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4005D82E9D27BAF006A8FE1 /* AppLockScreenViewModel.swift */; }; 97BAEDD9054FB5F233EE928B /* EncryptionResetScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 306AB507E1027D6C5C147EB6 /* EncryptionResetScreenModels.swift */; }; 981853650217B6C8ECDD998C /* NavigationRootCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */; }; + 9826A4DBBEFA7041A9E0EFAD /* TimelineMediaPreviewScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA57E8563C346B13DDE4A6F4 /* TimelineMediaPreviewScreen.swift */; }; 983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */; }; 9847B056C1A216C314D21E68 /* AuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */; }; 988BA75A182738150894A23F /* UserIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8AE4B3273BA189FDCD4055C /* UserIndicator.swift */; }; @@ -786,6 +817,7 @@ A2172B5A26976F9174228B8A /* AppHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E4AB573FAEBB7B853DD04C /* AppHooks.swift */; }; A23B8B27A1436A1049EEF68E /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; }; A2434D4DFB49A68E5CD0F53C /* MediaLoaderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A02406480C351B8C6E0682C /* MediaLoaderProtocol.swift */; }; + A32384E3D85CA65342D3A908 /* TimelineMediaPreviewRedactConfirmationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C75FE3F524B575D53787868C /* TimelineMediaPreviewRedactConfirmationView.swift */; }; A33784831AD880A670CAA9F9 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */; }; A36AD251013402EDBD666C75 /* AppMediatorMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAC027034248429A438886B /* AppMediatorMock.swift */; }; A37EED79941AD3B7140B3822 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287FC98AF2664EAD79C0D902 /* UIDevice.swift */; }; @@ -817,7 +849,6 @@ A851635B3255C6DC07034A12 /* RoomScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */; }; A8FA7671948E3DF27F320026 /* BugReportFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */; }; A93661C962B12942C08864B6 /* SwiftOGG in Frameworks */ = {isa = PBXBuildFile; productRef = 391D11F92DFC91666AA1503F /* SwiftOGG */; }; - A9482B967FC85DA611514D35 /* VoiceMessageRoomPlaybackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CCD41CD67DB5DA0D436BFE9 /* VoiceMessageRoomPlaybackView.swift */; }; A969147E0EEE0E27EE226570 /* MediaUploadPreviewScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47F29139BC2A804CE5E0757E /* MediaUploadPreviewScreenViewModel.swift */; }; A975D60EA49F6AF73308809F /* RoomMembersListScreenMemberCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC03209FDE8CE0810617BFFF /* RoomMembersListScreenMemberCell.swift */; }; A9A5801D5EE3D4D91F6DDADB /* AnalyticsSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C2527813FDAE23E72A9063 /* AnalyticsSettingsScreenViewModelTests.swift */; }; @@ -879,6 +910,7 @@ B796A25F282C0A340D1B9C12 /* ImageRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B5EDCD05D50BA9B815C66C /* ImageRoomTimelineItemContent.swift */; }; B79E8AB83EBBDCD476D0362F /* PollFormScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D622EC7898469BB1D0881CDD /* PollFormScreen.swift */; }; B7C9E07F4F9CCC8DD7156A20 /* CallScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28146817C61423CACCF942F5 /* CallScreenModels.swift */; }; + B7F58D6903F9D509EDAB9E4F /* MediaEventsTimelineScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7033218DA395B003F7AB29A2 /* MediaEventsTimelineScreenModels.swift */; }; B818580464CFB5400A3EF6AE /* TimelineModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 029D5701F80A9AF7167BB4D0 /* TimelineModels.swift */; }; B855AF29D7D8FC8DAAA73D4A /* test_voice_message.m4a in Resources */ = {isa = PBXBuildFile; fileRef = DCA2D836BD10303F37FAAEED /* test_voice_message.m4a */; }; B879446FD8E65A711EF8F9F7 /* AdvancedSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B63B69F9A2BC74DD40DC75C8 /* AdvancedSettingsScreenViewModel.swift */; }; @@ -909,6 +941,8 @@ BDED6DA7AD1E76018C424143 /* LegalInformationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C34667458773B02AB5FB0B2 /* LegalInformationScreenViewModel.swift */; }; BE8E5985771DF9137C6CE89A /* ProcessInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077B01C13BBA2996272C5FB5 /* ProcessInfo.swift */; }; BEA646DF302711A753F0D420 /* MapTilerStyleBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 225EFCA26877E75CDFE7F48D /* MapTilerStyleBuilderProtocol.swift */; }; + BEC6DFEA506085D3027E353C /* MediaEventsTimelineScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 002399C6CB875C4EBB01CBC0 /* MediaEventsTimelineScreen.swift */; }; + BFDDAF1A36FBC7CF63DCB7DD /* clear.png in Resources */ = {isa = PBXBuildFile; fileRef = 17F7A723A46DF5C95BE15EBF /* clear.png */; }; BFEB24336DFD5F196E6F3456 /* IntentionalMentions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DF5CBAF69BDF5DF31C661E1 /* IntentionalMentions.swift */; }; C0090506A52A1991BAF4BA68 /* NotificationSettingsChatType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07579F9C29001E40715F3014 /* NotificationSettingsChatType.swift */; }; C022284E2774A5E1EF683B4D /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */; }; @@ -916,6 +950,7 @@ C08AAE7563E0722C9383F51C /* RoomMembersListScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B8E176484A89BAC389D4076 /* RoomMembersListScreen.swift */; }; C0B97FFEC0083F3A36609E61 /* TimelineItemMacContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = A243A6E6207297123E60DE48 /* TimelineItemMacContextMenu.swift */; }; C11939FDC40716C4387275A4 /* NotificationSettingsEditScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */; }; + C11D4A49DC29D89CE2BB31B8 /* MediaEventsTimelineScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 976ED77B772F50C4BAD757E7 /* MediaEventsTimelineScreenViewModel.swift */; }; C13128AAA787A4C2CBE4EE82 /* MessageForwardingScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC10CCC8D68B863E20660DBC /* MessageForwardingScreenViewModelProtocol.swift */; }; C1429699A6A5BB09A25775C1 /* AudioPlayerStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89233612A8632AD7E2803620 /* AudioPlayerStateTests.swift */; }; C1910A16BDF131FECA77BE22 /* EmojiPickerScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA38B9851CFCC4D67F5587D /* EmojiPickerScreenCoordinator.swift */; }; @@ -926,6 +961,7 @@ C32765D740C81AD4C42E8F50 /* CreateRoomFlowParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 935C2FB18EFB8EEE96B26330 /* CreateRoomFlowParameters.swift */; }; C3317EF833AB4060988DF098 /* SAS.strings in Resources */ = {isa = PBXBuildFile; fileRef = 135FC689EA39AE1D34153B58 /* SAS.strings */; }; C3522917C0C367C403429EEC /* CoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B251F5B4511D1CA0BA8361FE /* CoordinatorProtocol.swift */; }; + C3AFDF6349E54290AA31EC88 /* preview_video.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 45A4B934BA41D6C255900265 /* preview_video.jpg */; }; C3BB6887CF13B19182E81F87 /* IdentityConfirmationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A03E073077D92AA19C43DCF /* IdentityConfirmationScreenCoordinator.swift */; }; C405528EB4BBEA93579050EE /* VoiceMessageRecordingButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46A2AD86F7E618F468F6FAF5 /* VoiceMessageRecordingButton.swift */; }; C4078364FD9FA00EA9D00A15 /* RoomMembersListScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45CDF9A107BFE6C79B58D6B5 /* RoomMembersListScreenViewModelProtocol.swift */; }; @@ -953,6 +989,7 @@ C8BD80891BAD688EF2C15CDB /* MediaUploadPreviewScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74DD0855F2F76D47E5555082 /* MediaUploadPreviewScreenCoordinator.swift */; }; C8C7AF33AADF88B306CD2695 /* QRCodeLoginService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4427AF4B7FB7EF3E3D424C7 /* QRCodeLoginService.swift */; }; C8E0FA0FF2CD6613264FA6B9 /* MessageForwardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFEA446F8618DBA79A9239CC /* MessageForwardingScreen.swift */; }; + C8E1E4E06B7C7A3A8246FC9B /* MediaEventsTimelineScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8512B82404B1751D0BCC82D2 /* MediaEventsTimelineScreenCoordinator.swift */; }; C915347779B3C7FDD073A87A /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93E1FF0DFBB3768F79FDBF6D /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift */; }; C969A62F3D9F14318481A33B /* KnockedRoomProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858DA81F2ACF484B7CAD6AE4 /* KnockedRoomProxy.swift */; }; C97325EFDCCEE457432A9E82 /* MessageText.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E0B4A34E69BD2132BEC521 /* MessageText.swift */; }; @@ -968,6 +1005,7 @@ CB6956565D858C523E3E3B16 /* ComposerDraftServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7E37072597F67C4DD8CC2DB /* ComposerDraftServiceProtocol.swift */; }; CB6BCBF28E4B76EA08C2926D /* StateRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B16048D30F0438731C41F775 /* StateRoomTimelineItem.swift */; }; CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */; }; + CB9FB2BEF313072C705AC9B5 /* SecurityAndPrivacyScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0315C328FF40F84276364E66 /* SecurityAndPrivacyScreenViewModelTests.swift */; }; CBA9EDF305036039166E76FF /* StartChatScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2AEC1AB349A341FE13DEC1 /* StartChatScreenUITests.swift */; }; CBD2ABE4C1A47ECD99E1488E /* NotificationSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 421FA93BCC2840E66E4F306F /* NotificationSettingsScreenViewModelProtocol.swift */; }; CC0D088F505F33A20DC5590F /* RoomStateEventStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */; }; @@ -994,6 +1032,7 @@ D10BA4F041DC58580A440A32 /* RoomRolesAndPermissionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B1DC3B3FB40A7F4AE9B7BF /* RoomRolesAndPermissionsScreen.swift */; }; D12F440F7973F1489F61389D /* NotificationSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */; }; D181AC8FF236B7F91C0A8C28 /* MapTiler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23AA3F4B285570805CB0CCDD /* MapTiler.swift */; }; + D18B70975644C24F60656C0D /* KnockRequestProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07851F4EA81AA3339806A7B /* KnockRequestProxyProtocol.swift */; }; D19A748E95E2FAB2940570F0 /* CallScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4103AB4340F2974D690A12A /* CallScreen.swift */; }; D2048FD56760BDABA3DB5FC2 /* AppLockServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */; }; D22345698F6548C1EE960940 /* IdentityConfirmedScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */; }; @@ -1001,6 +1040,7 @@ D2825E013A8ECFB66D9A1DE6 /* RoomChangeRolesScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */; }; D29E046C1E3045E0346C479D /* RoomRolesAndPermissionsUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45571C2EBD98ED7E0CEA7AF7 /* RoomRolesAndPermissionsUITests.swift */; }; D2D70B5DB1A5E4AF0CD88330 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 033DB41C51865A2E83174E87 /* target.yml */; }; + D31B34B3902BC597593F3ABB /* preview_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 200626E8353AB2729444F991 /* preview_image.jpg */; }; D33AC79A50DFC26D2498DD28 /* FileRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5098DA7799946A61E34A2373 /* FileRoomTimelineItem.swift */; }; D34E328E9E65904358248FDD /* GlobalSearchScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436A0D98D372B17EAE9AA999 /* GlobalSearchScreenModels.swift */; }; D3FD96913D2B1AAA3149DAC7 /* CreateRoomViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69D42EE0102D2857933625DD /* CreateRoomViewModelTests.swift */; }; @@ -1099,6 +1139,7 @@ EA01A06EEDFEF4AE7652E5F3 /* NSRegularExpresion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */; }; EA6613B29BA671F39CE1B1D2 /* ConfirmationDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */; }; EA78A7512AFB1E5451744EB1 /* AppRouteURLParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */; }; + EA8D941771E762A5D3D7FA0D /* FileMediaEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430C73079A84654BF46A7FF5 /* FileMediaEventsTimelineView.swift */; }; EA974337FA7D040E7C74FE6E /* RoomDetailsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EFE1922F39398ABFB36DF3F /* RoomDetailsViewModelTests.swift */; }; EAB3C1F0BC7F671ED8BDF82D /* CompletionSuggestionServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECF11669EF253E98AA2977A /* CompletionSuggestionServiceProtocol.swift */; }; EAC6FE2CD4F50A43068ADCD8 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; }; @@ -1160,7 +1201,9 @@ F669B55BC237CDA5EC9332FE /* MentionSuggestionItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4100DDE6BF3C566AB66B80CC /* MentionSuggestionItemView.swift */; }; F66BBBE51B258BBB0B918C68 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = C79D91A7F9F378CECEF64B5A /* MatrixRustSDK */; }; F66BCCC825D6CA51724A94D0 /* MediaPlayerProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8A1F98AE670377B20679FF5 /* MediaPlayerProvider.swift */; }; + F6767F17D538578B370DD805 /* TimelineItemBubbleBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE739A6836E86E3780748477 /* TimelineItemBubbleBackground.swift */; }; F697284B9B5F2C00CFEA3B12 /* EmojiDetectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E93D91DE3288010390DEE /* EmojiDetectionTests.swift */; }; + F6BF52CB027393EE03CEC523 /* TimelineMediaPreviewViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1F000589F2CEE6B03ECFAB /* TimelineMediaPreviewViewModelTests.swift */; }; F6DFA23885980118AD7359C5 /* NotificationSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2389732B0E115A999A069083 /* NotificationSettingsScreenCoordinator.swift */; }; F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */; }; F7567DD6635434E8C563BF85 /* AnalyticsClientProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3B97591B2D3D4D67553506D /* AnalyticsClientProtocol.swift */; }; @@ -1195,9 +1238,11 @@ FD29471C72872F8B7580E3E1 /* KeychainControllerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C0D861FC397AC34BCF089E /* KeychainControllerMock.swift */; }; FD4C21F8DA1E273DE94FCD1A /* NotificationItemProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B927CF5EF7FCCDA5EDC474B /* NotificationItemProxyProtocol.swift */; }; FD762761C5D0C30E6255C3D8 /* ServerConfirmationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */; }; + FD9777315A5D9CDC47458AD1 /* MediaEventsTimelineScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A175D0FDEDBFA44C47FE13AE /* MediaEventsTimelineScreenViewModelProtocol.swift */; }; FDC67E8C0EDCB00ABC66C859 /* landscape_test_video.mov in Resources */ = {isa = PBXBuildFile; fileRef = 78BBDF7A05CF53B5CDC13682 /* landscape_test_video.mov */; }; FDD5B4B616D9FF4DE3E9A418 /* QRCodeScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92DB574F954CC2B40F7BE892 /* QRCodeScannerView.swift */; }; FDE47D4686BA0F86BB584633 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = CAA3B9DF998B397C9EE64E8B /* Collections */; }; + FE43747C116CA3D8D6B92F5F /* TimelineMediaPreviewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A62FBD3007312311C14DD8 /* TimelineMediaPreviewCoordinator.swift */; }; FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF1593DD87F974F8509BB619 /* ElementAnimations.swift */; }; FEC03105D1BDE0F49BD7F243 /* PinnedEventsTimelineScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B6572E6EF5D5F4B0C338A40 /* PinnedEventsTimelineScreenModels.swift */; }; FEFD5290B31FCBA6999912C8 /* RoomChangePermissionsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */; }; @@ -1279,10 +1324,12 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 002399C6CB875C4EBB01CBC0 /* MediaEventsTimelineScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEventsTimelineScreen.swift; sourceTree = ""; }; 00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreen.swift; sourceTree = ""; }; 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreen.swift; sourceTree = ""; }; 00E5B2CBEF8F96424F095508 /* RoomDetailsEditScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenViewModelTests.swift; sourceTree = ""; }; 012A284622B32052015F1F89 /* ReadMarkerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineView.swift; sourceTree = ""; }; + 018194CAFBE80720FECCEDEE /* ZoomTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZoomTransition.swift; sourceTree = ""; }; 01B795AAAB7B8747FE2FF311 /* LogViewerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenModels.swift; sourceTree = ""; }; 01C4C7DB37597D7D8379511A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 022E6BD64CB4610B9C95FC02 /* UserDetailsEditScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsEditScreenViewModel.swift; sourceTree = ""; }; @@ -1291,6 +1338,7 @@ 029D5701F80A9AF7167BB4D0 /* TimelineModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineModels.swift; sourceTree = ""; }; 02D155E09BF961BBA8F85263 /* InviteUsersScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenViewModel.swift; sourceTree = ""; }; 02EE0FABA8ED6D6C1D6CE71D /* ReactionsSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionsSummaryView.swift; sourceTree = ""; }; + 0315C328FF40F84276364E66 /* SecurityAndPrivacyScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAndPrivacyScreenViewModelTests.swift; sourceTree = ""; }; 03277E40D0E0DE0712021A71 /* ServerConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenCoordinator.swift; sourceTree = ""; }; 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; @@ -1321,6 +1369,7 @@ 07579F9C29001E40715F3014 /* NotificationSettingsChatType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsChatType.swift; sourceTree = ""; }; 077B01C13BBA2996272C5FB5 /* ProcessInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessInfo.swift; sourceTree = ""; }; 077D7C3BE199B6E5DDEC07EC /* AppCoordinatorStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinatorStateMachine.swift; sourceTree = ""; }; + 07934EF08BB39353E4A94272 /* BlurEffectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurEffectView.swift; sourceTree = ""; }; 07C6B0B087FE6601C3F77816 /* JoinedRoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinedRoomProxy.swift; sourceTree = ""; }; 0825EAFD47332DD459DE893F /* SessionDirectoriesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDirectoriesTests.swift; sourceTree = ""; }; 08283301736A6FE9D558B2CB /* AppLockScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1367,11 +1416,13 @@ 127A57D053CE8C87B5EFB089 /* Consumable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Consumable.swift; sourceTree = ""; }; 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = ""; }; 128501375217576AF0FE3E92 /* RoomAttachmentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomAttachmentPicker.swift; sourceTree = ""; }; + 12FD5280AF55AB7F50F8E47D /* preview_avatar_room.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = preview_avatar_room.jpg; sourceTree = ""; }; 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = ""; }; 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = ""; }; 136F80A613B55BDD071DCEA5 /* JoinRoomScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenModels.swift; sourceTree = ""; }; 13802897C7AFA360EA74C0B0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; 13BE9781699FB510E9263192 /* AppSettingsHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettingsHook.swift; sourceTree = ""; }; + 13F354AD441E2FD83DED89AF /* SeparatorMediaEventsTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorMediaEventsTimelineView.swift; sourceTree = ""; }; 1423AB065857FA546444DB15 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; 1454CF3AABD242F55C8A2615 /* InviteUsersScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenModels.swift; sourceTree = ""; }; 1511B1DCECC0DC75EB267328 /* KnockRequestsListScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListScreen.swift; sourceTree = ""; }; @@ -1385,6 +1436,7 @@ 1715E3D7F53C0748AA50C91C /* PostHogAnalyticsClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogAnalyticsClient.swift; sourceTree = ""; }; 1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingConfigurationTests.swift; sourceTree = ""; }; 17A8AA0DFA06012A9DAB951E /* TimelineProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyMock.swift; sourceTree = ""; }; + 17F7A723A46DF5C95BE15EBF /* clear.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = clear.png; sourceTree = ""; }; 18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenModels.swift; sourceTree = ""; }; 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = ""; }; 18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = ""; }; @@ -1429,12 +1481,15 @@ 1F7C6DDBB5D12F6EF6A3D6E1 /* CollapsibleReactionLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleReactionLayout.swift; sourceTree = ""; }; 1FAF8C2226A57B9AB7446B31 /* AppLockSetupPINScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenCoordinator.swift; sourceTree = ""; }; 1FD51B4D5173F7FC886F5360 /* NoticeRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItemContent.swift; sourceTree = ""; }; + 1FF584D757E768EA7776A532 /* ImageMediaEventsTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageMediaEventsTimelineView.swift; sourceTree = ""; }; + 200626E8353AB2729444F991 /* preview_image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = preview_image.jpg; sourceTree = ""; }; 201305507D7DFD16E544563A /* EmojiLoaderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiLoaderProtocol.swift; sourceTree = ""; }; 203D1ACC20287F8986C959D3 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStaticMapProtocol.swift; sourceTree = ""; }; 20E69F67D2A70ABD08CA6D54 /* NotificationPermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; 2141693488CE5446BB391964 /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = ""; }; 216F0DDC98F2A2C162D09C28 /* FileRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineItemContent.swift; sourceTree = ""; }; + 2178B951602AA921A5FD9DC8 /* MediaEventsTimelineFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEventsTimelineFlowCoordinator.swift; sourceTree = ""; }; 218AB05B4E3889731959C5F1 /* EventBasedTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedTimelineItemProtocol.swift; sourceTree = ""; }; 21BA866267F84BF4350B0CB7 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pt-BR"; path = "pt-BR.lproj/Localizable.stringsdict"; sourceTree = ""; }; 21DD8599815136EFF5B73F38 /* UserFlowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserFlowTests.swift; sourceTree = ""; }; @@ -1483,12 +1538,14 @@ 2910422CB628D3B2BBE47449 /* SeparatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineView.swift; sourceTree = ""; }; 295E28C3B9EAADF519BF2F44 /* AuthenticationFlowCoordinatorUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationFlowCoordinatorUITests.swift; sourceTree = ""; }; 29A953B6C0C431DBF4DD00B4 /* RoomSummary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummary.swift; sourceTree = ""; }; + 2A2BB38DF61F5100B8723112 /* TimelineMediaPreviewModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewModels.swift; sourceTree = ""; }; 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilder.swift; sourceTree = ""; }; 2AB2C848BB9A7A9B618B7B89 /* TextBasedRoomTimelineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineTests.swift; sourceTree = ""; }; 2AC3FDB58F57386741A4FC7F /* DeactivateAccountScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreenViewModel.swift; sourceTree = ""; }; 2AE807361805463F5AEDD1CA /* VoiceMessagePreviewComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessagePreviewComposer.swift; sourceTree = ""; }; 2AE83A3DD63BCFBB956FE5CB /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = nl; path = nl.lproj/Localizable.stringsdict; sourceTree = ""; }; 2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenViewModelProtocol.swift; sourceTree = ""; }; + 2B1FB56520A847DD2532D5C8 /* VideoMediaEventsTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoMediaEventsTimelineView.swift; sourceTree = ""; }; 2BA894BC09972DC45E497D37 /* TimelineInteractionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineInteractionHandler.swift; sourceTree = ""; }; 2BB385E148DE55C85C0A02D6 /* SoftLogoutScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenModels.swift; sourceTree = ""; }; 2BDB3E65A79779EDA5D33D8A /* AudioPlayerState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerState.swift; sourceTree = ""; }; @@ -1512,6 +1569,7 @@ 303FCADE77DF1F3670C086ED /* BugReportScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModel.swift; sourceTree = ""; }; 306AB507E1027D6C5C147EB6 /* EncryptionResetScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenModels.swift; sourceTree = ""; }; 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreen.swift; sourceTree = ""; }; + 30856520F3263D0E195710D7 /* TimelineMediaPreviewFileExportPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewFileExportPicker.swift; sourceTree = ""; }; 309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriver.swift; sourceTree = ""; }; 30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerTests.swift; sourceTree = ""; }; 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadReceipt.swift; sourceTree = ""; }; @@ -1560,7 +1618,6 @@ 3C368CAB3063EF275357ECD4 /* LoginScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenViewModel.swift; sourceTree = ""; }; 3C3ADF21BE301D0DA48F2A7E /* ShareExtensionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionView.swift; sourceTree = ""; }; 3C3E67E09FE5A35D73818C39 /* AppLockScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenModels.swift; sourceTree = ""; }; - 3CCD41CD67DB5DA0D436BFE9 /* VoiceMessageRoomPlaybackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomPlaybackView.swift; sourceTree = ""; }; 3CCE3636E3D01477C8B2E9D0 /* ReportContentScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenModels.swift; sourceTree = ""; }; 3CFD5EB0B0EEA4549FB49784 /* SettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreen.swift; sourceTree = ""; }; 3D1D4A6D451F43A03CACD01D /* PINTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PINTextField.swift; sourceTree = ""; }; @@ -1596,6 +1653,7 @@ 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomLayoutLabelStyle.swift; sourceTree = ""; }; 42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenModels.swift; sourceTree = ""; }; 42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreen.swift; sourceTree = ""; }; + 430C73079A84654BF46A7FF5 /* FileMediaEventsTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMediaEventsTimelineView.swift; sourceTree = ""; }; 434522ED2BDED08759048077 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = ""; }; 436A0D98D372B17EAE9AA999 /* GlobalSearchScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreenModels.swift; sourceTree = ""; }; 43A84EE187D0C772E18A4E39 /* VoiceMessageCacheProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageCacheProtocol.swift; sourceTree = ""; }; @@ -1610,10 +1668,12 @@ 4549FCB53F43DB0B278374BC /* TemplateScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreen.swift; sourceTree = ""; }; 4552D3466B1453F287223ADA /* SwipeRightAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeRightAction.swift; sourceTree = ""; }; 45571C2EBD98ED7E0CEA7AF7 /* RoomRolesAndPermissionsUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsUITests.swift; sourceTree = ""; }; + 45A4B934BA41D6C255900265 /* preview_video.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = preview_video.jpg; sourceTree = ""; }; 45CDF9A107BFE6C79B58D6B5 /* RoomMembersListScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModelProtocol.swift; sourceTree = ""; }; 45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationCenterProtocol.swift; sourceTree = ""; }; 4629710C0337ADD9C8909542 /* ka */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ka; path = ka.lproj/Localizable.strings; sourceTree = ""; }; 466C71A0FED9BFF287613C82 /* RoomDetailsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenModels.swift; sourceTree = ""; }; + 467498BEA681758BE2F80826 /* TimelineMediaPreviewDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewDetailsView.swift; sourceTree = ""; }; 4691B8DE1D51DE152680098A /* HomeScreenSlidingSyncMigrationBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenSlidingSyncMigrationBanner.swift; sourceTree = ""; }; 46A2AD86F7E618F468F6FAF5 /* VoiceMessageRecordingButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecordingButton.swift; sourceTree = ""; }; 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsAppCoordinator.swift; sourceTree = ""; }; @@ -1679,6 +1739,7 @@ 5351EBD7A0B9610548E4B7B2 /* EncryptedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedRoomTimelineItem.swift; sourceTree = ""; }; 536C0E2178949B290776EA4E /* QRCodeLoginServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginServiceProtocol.swift; sourceTree = ""; }; 536E72DCBEEC4A1FE66CFDCE /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; + 53F41CEAAE2BB4E74CDC2278 /* TimelineMediaPreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewViewModel.swift; sourceTree = ""; }; 53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = test_animated_image.gif; sourceTree = ""; }; 542D4F49FABA056DEEEB3400 /* RustTracing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RustTracing.swift; sourceTree = ""; }; 5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsService.swift; sourceTree = ""; }; @@ -1713,6 +1774,7 @@ 5A43964330459965AF048A8C /* LoginScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenViewModelTests.swift; sourceTree = ""; }; 5AEA0B743847CFA5B3C38EE4 /* RoomMembersListScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenCoordinator.swift; sourceTree = ""; }; 5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenCoordinator.swift; sourceTree = ""; }; + 5C1F000589F2CEE6B03ECFAB /* TimelineMediaPreviewViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewViewModelTests.swift; sourceTree = ""; }; 5C7C7CFA6B2A62A685FF6CE3 /* DeveloperOptionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenCoordinator.swift; sourceTree = ""; }; 5CEEAE1BFAACD6C96B6DB731 /* PHGPostHogProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogProtocol.swift; sourceTree = ""; }; 5D26A086A8278D39B5756D6F /* project.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = project.yml; sourceTree = ""; }; @@ -1791,6 +1853,7 @@ 6FA38E813BE14149F173F461 /* PinnedEventsBannerStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsBannerStateTests.swift; sourceTree = ""; }; 6FC5015B9634698BDB8701AF /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = it; path = it.lproj/Localizable.stringsdict; sourceTree = ""; }; 6FC8B21E86B137BE4E91F82A /* ElementCallServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallServiceProtocol.swift; sourceTree = ""; }; + 7033218DA395B003F7AB29A2 /* MediaEventsTimelineScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEventsTimelineScreenModels.swift; sourceTree = ""; }; 7061BE2C0BF427C38AEDEF5E /* SecureBackupRecoveryKeyScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenViewModel.swift; sourceTree = ""; }; 70C86696AC9521F8ED88FBEB /* MediaUploadPreviewScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreen.swift; sourceTree = ""; }; 713B48DBF65DE4B0DD445D66 /* ReportContentScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1838,6 +1901,7 @@ 7B3D16709ADD4F4BCC710B1E /* SecureBackupScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenModels.swift; sourceTree = ""; }; 7B849D2FF2CC12BA411A1651 /* CreateRoomModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomModels.swift; sourceTree = ""; }; 7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowCoordinatorProtocol.swift; sourceTree = ""; }; + 7BBADF8010C813D905C172CE /* SecurityAndPrivacyScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAndPrivacyScreenModels.swift; sourceTree = ""; }; 7C1AF829F12FDC99717082D9 /* RoomRolesAndPermissionsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsScreenViewModel.swift; sourceTree = ""; }; 7C28B70BEFD3676F11D5D51F /* RoomRolesAndPermissionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsScreenCoordinator.swift; sourceTree = ""; }; 7C71B9802433F1B4252291BB /* IdentityConfirmationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1852,6 +1916,7 @@ 7EB58E4E8D6D634C246AD5C2 /* RoomInviterLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomInviterLabel.swift; sourceTree = ""; }; 7EECE8B331CD169790EF284F /* BugReportScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModelTests.swift; sourceTree = ""; }; 7F615A00DB223FF3280204D2 /* UserDiscoveryServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoveryServiceProtocol.swift; sourceTree = ""; }; + 7F957320D0EB7D7B4E30C79D /* KnockRequestProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestProxyMock.swift; sourceTree = ""; }; 7FB2253D36E81E045E1CB432 /* Duration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Duration.swift; sourceTree = ""; }; 7FDF541AE914059942B575B4 /* IdentityConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenModels.swift; sourceTree = ""; }; 8063E65441E771200108C558 /* ReadReceiptsSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadReceiptsSummaryView.swift; sourceTree = ""; }; @@ -1871,6 +1936,7 @@ 82DFA1B7B088D033E0794B82 /* RoomChangeRolesScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenCoordinator.swift; sourceTree = ""; }; 82EE3B877D91030248B1242D /* DeactivateAccountScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreenViewModelProtocol.swift; sourceTree = ""; }; 8319173DD66C07F45DC48848 /* IdentityConfirmedScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreenViewModelProtocol.swift; sourceTree = ""; }; + 832397B5C3D00A4BF52C5F0B /* ShouldScrollOnKeyboardDidShow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShouldScrollOnKeyboardDidShow.swift; sourceTree = ""; }; 837B440C4705E4B899BCB899 /* RoomDetailsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenViewModel.swift; sourceTree = ""; }; 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedCornerShape.swift; sourceTree = ""; }; 83B4E3F1265581683E4997B8 /* RoomSelectionScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSelectionScreenViewModel.swift; sourceTree = ""; }; @@ -1881,6 +1947,7 @@ 84A87D0471D438A233C2CF4A /* RoomMemberDetailsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenViewModel.swift; sourceTree = ""; }; 84AF32E4136FD6F159D86C2C /* RoomDirectorySearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchView.swift; sourceTree = ""; }; 84B7A28A6606D58D1E38C55A /* ExpiringTaskRunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpiringTaskRunnerTests.swift; sourceTree = ""; }; + 8512B82404B1751D0BCC82D2 /* MediaEventsTimelineScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEventsTimelineScreenCoordinator.swift; sourceTree = ""; }; 85149F56BA333619900E2410 /* UserDetailsEditScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsEditScreenViewModelProtocol.swift; sourceTree = ""; }; 851B95BB98649B8E773D6790 /* AppLockService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockService.swift; sourceTree = ""; }; 8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenViewModelTests.swift; sourceTree = ""; }; @@ -1898,6 +1965,7 @@ 86A6F283BC574FDB96ABBB07 /* DeveloperOptionsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenViewModel.swift; sourceTree = ""; }; 86C8CE2630F54D5FE1591786 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/InfoPlist.strings; sourceTree = ""; }; 86D7CD5CA270BFC3EBB450CA /* PinnedEventsTimelineScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineScreenViewModel.swift; sourceTree = ""; }; + 87FC42213E86E8182CFD3A49 /* preview_avatar_user.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = preview_avatar_user.jpg; sourceTree = ""; }; 88410BD213FDF9B28E8B671F /* UserDetailsEditScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDetailsEditScreen.swift; sourceTree = ""; }; 8896CDD20CA2D87EA3B848A1 /* RoomNotificationSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreen.swift; sourceTree = ""; }; 889DEDD63C68ABDA8AD29812 /* VoiceMessageMediaManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageMediaManagerProtocol.swift; sourceTree = ""; }; @@ -1926,6 +1994,7 @@ 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = ""; }; 8E1584F8BCF407BB94F48F04 /* EncryptionResetPasswordScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreen.swift; sourceTree = ""; }; 8EAF4A49F3ACD8BB8B0D2371 /* ClientSDKMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientSDKMock.swift; sourceTree = ""; }; + 8F062DD2CCD95DC33528A16F /* KnockRequestProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestProxy.swift; sourceTree = ""; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = ""; }; 8F6210134203BE1F2DD5C679 /* RoomDirectoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectoryCell.swift; sourceTree = ""; }; 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModelTests.swift; sourceTree = ""; }; @@ -1963,10 +2032,13 @@ 96CE9D6642DD487D8CC90C9C /* landscape_test_image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = landscape_test_image.jpg; sourceTree = ""; }; 97287090CA64DAA95386ECED /* ResolveVerifiedUserSendFailureScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResolveVerifiedUserSendFailureScreen.swift; sourceTree = ""; }; 974AEAF3FE0C577A6C04AD6E /* RoomPermissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPermissions.swift; sourceTree = ""; }; + 976ED77B772F50C4BAD757E7 /* MediaEventsTimelineScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEventsTimelineScreenViewModel.swift; sourceTree = ""; }; 9780389F8A53E4D26E23DD03 /* LoginScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenViewModelProtocol.swift; sourceTree = ""; }; + 978092B01BEAB39F2C4389AE /* SecurityAndPrivacyScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAndPrivacyScreenViewModel.swift; sourceTree = ""; }; 97B2ACA28A854E41AE3AC9AD /* TimelineViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineViewModel.swift; sourceTree = ""; }; 97C8E13A1FBA717B0C277ECC /* ProgressCursorModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressCursorModifier.swift; sourceTree = ""; }; 97CE98208321C4D66E363612 /* ShimmerModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShimmerModifier.swift; sourceTree = ""; }; + 97F2F6B6E56055EF173A2DD3 /* SecurityAndPrivacyScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAndPrivacyScreenCoordinator.swift; sourceTree = ""; }; 981663D961C94270FA035FD0 /* Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = ""; }; 9873076F224E4CE09D8BD47D /* TemplateScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenUITests.swift; sourceTree = ""; }; 989D7380D9C86B3A10D30B13 /* AppLockSetupPINScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModelTests.swift; sourceTree = ""; }; @@ -1991,6 +2063,7 @@ 9C7F7DE62D33C6A26CBFCD72 /* IntegrationTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = IntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = ""; }; 9CF1EE0AA78470C674554262 /* PillTextAttachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillTextAttachment.swift; sourceTree = ""; }; + 9E3B41C36800DD4558D7BDA7 /* VoiceMessageRoomPlaybackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomPlaybackView.swift; sourceTree = ""; }; 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIConstants.swift; sourceTree = ""; }; 9E8F4D7D61B80EBD5CB92F8A /* KnockedRoomProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockedRoomProxyMock.swift; sourceTree = ""; }; 9EB9BA2F30EB8C33226D8FF1 /* UserSessionStoreMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionStoreMock.swift; sourceTree = ""; }; @@ -2009,6 +2082,7 @@ A130A2251A15A7AACC84FD37 /* RoomPollsHistoryScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenViewModelProtocol.swift; sourceTree = ""; }; A16CD2C62CB7DB78A4238485 /* ReportContentScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenCoordinator.swift; sourceTree = ""; }; A16D0F226B1819D017531647 /* BlockedUsersScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenCoordinator.swift; sourceTree = ""; }; + A175D0FDEDBFA44C47FE13AE /* MediaEventsTimelineScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEventsTimelineScreenViewModelProtocol.swift; sourceTree = ""; }; A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationStateMachineTests.swift; sourceTree = ""; }; A232D9156D225BD9FD1D0C43 /* PhotoLibraryPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryPicker.swift; sourceTree = ""; }; A243A6E6207297123E60DE48 /* TimelineItemMacContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMacContextMenu.swift; sourceTree = ""; }; @@ -2042,6 +2116,7 @@ A9E88667D393612FD5D84718 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/SAS.strings; sourceTree = ""; }; A9FAFE1C2149E6AC8156ED2B /* Collection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Collection.swift; sourceTree = ""; }; AA19C32BD97F45847724E09A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Untranslated.strings; sourceTree = ""; }; + AA57E8563C346B13DDE4A6F4 /* TimelineMediaPreviewScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewScreen.swift; sourceTree = ""; }; AAC9344689121887B74877AF /* UnitTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; AACE9B8E1A4AE79A7E2914F6 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = es; path = es.lproj/Localizable.stringsdict; sourceTree = ""; }; AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserProfile+Mock.swift"; sourceTree = ""; }; @@ -2057,6 +2132,7 @@ ACA11F7F50A4A3887A18CA5A /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; ACD7BD6BEE21264F6677904A /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = ""; }; AD0FF64B0E6470F66F42E182 /* EstimatedWaveformView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EstimatedWaveformView.swift; sourceTree = ""; }; + AD3521DF92391551E02004D8 /* VoiceMessageMediaEventsTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageMediaEventsTimelineView.swift; sourceTree = ""; }; AD378D580A41E42560C60E9C /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Localizable.strings; sourceTree = ""; }; AD529C89924EE32CE307F36F /* VisualListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisualListItem.swift; sourceTree = ""; }; AD558A898847C179E4B7A237 /* SecureBackupKeyBackupScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreen.swift; sourceTree = ""; }; @@ -2070,6 +2146,7 @@ AE40D4A5DD857AC16EED945A /* URLSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSession.swift; sourceTree = ""; }; AE52983FAFB4E0998C00EE8A /* CancellableTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CancellableTask.swift; sourceTree = ""; }; AE5DDBEBBA17973ED4638823 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Localizable.stringsdict; sourceTree = ""; }; + AE739A6836E86E3780748477 /* TimelineItemBubbleBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemBubbleBackground.swift; sourceTree = ""; }; AEB5FF7A09B79B0C6B528F7C /* SFNumberedListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SFNumberedListView.swift; sourceTree = ""; }; AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilderTests.swift; sourceTree = ""; }; AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilderTests.swift; sourceTree = ""; }; @@ -2099,6 +2176,7 @@ B43456E73F8A2D52B69B9FB9 /* TemplateScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenViewModel.swift; sourceTree = ""; }; B4427AF4B7FB7EF3E3D424C7 /* QRCodeLoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginService.swift; sourceTree = ""; }; B48B7AD4908C5C374517B892 /* MapAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = MapAssets.xcassets; sourceTree = ""; }; + B4AE42C19EDE64B7CB7BE4D0 /* SecurityAndPrivacyScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAndPrivacyScreen.swift; sourceTree = ""; }; B4CFE236419E830E8946639C /* Analytics+SwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Analytics+SwiftUI.swift"; sourceTree = ""; }; B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyProtocol.swift; sourceTree = ""; }; B53AC78E49A297AC1D72A7CF /* AppMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediator.swift; sourceTree = ""; }; @@ -2107,9 +2185,9 @@ B63B69F9A2BC74DD40DC75C8 /* AdvancedSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModel.swift; sourceTree = ""; }; B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetails.swift; sourceTree = ""; }; B655A536341D2695158C6664 /* AuthenticationClientBuilderFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationClientBuilderFactory.swift; sourceTree = ""; }; + B6A293D06BAB2B7A17D9314B /* VoiceMessageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomTimelineView.swift; sourceTree = ""; }; B6E4AB573FAEBB7B853DD04C /* AppHooks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppHooks.swift; sourceTree = ""; }; B6E89E530A8E92EC44301CA1 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = ""; }; - B70A50C41C5871B4DB905E7E /* VoiceMessageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomTimelineView.swift; sourceTree = ""; }; B73587C2E3CF5998361AE516 /* HomeScreenRoomTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomTests.swift; sourceTree = ""; }; B746EFA112532A7B701FB914 /* RoomNotificationSettingsCustomSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsCustomSectionView.swift; sourceTree = ""; }; B7884BD256C091EB511B2EDF /* AppLockSetupPINScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -2154,6 +2232,7 @@ BFEE91FB8ABB5F5884B6D940 /* WaveformInteractionModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaveformInteractionModifier.swift; sourceTree = ""; }; C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementXAttributeScope.swift; sourceTree = ""; }; C070FD43DC6BF4E50217965A /* LocalizationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationTests.swift; sourceTree = ""; }; + C07851F4EA81AA3339806A7B /* KnockRequestProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestProxyProtocol.swift; sourceTree = ""; }; C08E9043618AE5B0BF7B07E1 /* TemplateScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenViewModelTests.swift; sourceTree = ""; }; C0900BBF0A5D5D775E917C70 /* EventBasedMessageTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedMessageTimelineItemProtocol.swift; sourceTree = ""; }; C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenEmptyStateView.swift; sourceTree = ""; }; @@ -2191,6 +2270,7 @@ C715CFE00686DACA59D836EA /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/SAS.strings; sourceTree = ""; }; C729D95CB4588D4D9AAC3DFA /* RoomChangePermissionsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenModels.swift; sourceTree = ""; }; C75EF87651B00A176AB08E97 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + C75FE3F524B575D53787868C /* TimelineMediaPreviewRedactConfirmationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewRedactConfirmationView.swift; sourceTree = ""; }; C7661EFFCAA307A97D71132A /* HomeScreenRoomList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomList.swift; sourceTree = ""; }; C7D851A10FDA55579960DC61 /* WebRegistrationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebRegistrationScreenCoordinator.swift; sourceTree = ""; }; C830A64609CBD152F06E0457 /* NotificationConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationConstants.swift; sourceTree = ""; }; @@ -2227,6 +2307,7 @@ CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = ""; }; CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = ""; }; D01FD1171FF40E34D707FD00 /* BigIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigIcon.swift; sourceTree = ""; }; + D046ABB22E680F7C5054441B /* SecurityAndPrivacyScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAndPrivacyScreenViewModelProtocol.swift; sourceTree = ""; }; D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoverySection.swift; sourceTree = ""; }; D086854995173E897F993C26 /* AdvancedSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; D09227E671DB30795C43FFFD /* KnockRequestsListScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListScreenViewModel.swift; sourceTree = ""; }; @@ -2274,6 +2355,7 @@ DA2AEC1AB349A341FE13DEC1 /* StartChatScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenUITests.swift; sourceTree = ""; }; DA3D82522494E78746B2214E /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/SAS.strings; sourceTree = ""; }; DAB8D7926A5684E18196B538 /* VoiceMessageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageCache.swift; sourceTree = ""; }; + DADECBBB672497BCD4822468 /* Result.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; DB06F22CFA34885B40976061 /* RoomDetailsEditScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreen.swift; sourceTree = ""; }; DBEDCEC9D908C19C63D24395 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; DC0AEA686E425F86F6BA0404 /* UNNotification+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNNotification+Creator.swift"; sourceTree = ""; }; @@ -2282,6 +2364,7 @@ DCA2D836BD10303F37FAAEED /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; DCAC01A97A43BE07B9E94E43 /* ShareExtensionModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionModels.swift; sourceTree = ""; }; DCF239C619971FDE48132550 /* SecureBackupLogoutConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenModels.swift; sourceTree = ""; }; + DD955A0380C287C418F1A74D /* PhotoLibraryManagerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryManagerMock.swift; sourceTree = ""; }; DD97F9661ABF08CE002054A2 /* AppLockServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceTests.swift; sourceTree = ""; }; DE5127D6EA05B2E45D0A7D59 /* JoinRoomScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenViewModelTests.swift; sourceTree = ""; }; DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaFileHandleProxy.swift; sourceTree = ""; }; @@ -2305,6 +2388,7 @@ E321E840DCC63790049984F4 /* ElementCallServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallServiceMock.swift; sourceTree = ""; }; E34685D186453E429ADEE58E /* ClientProtocolTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProtocolTests.swift; sourceTree = ""; }; E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainController.swift; sourceTree = ""; }; + E3A62FBD3007312311C14DD8 /* TimelineMediaPreviewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewCoordinator.swift; sourceTree = ""; }; E3B97591B2D3D4D67553506D /* AnalyticsClientProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsClientProtocol.swift; sourceTree = ""; }; E4103AB4340F2974D690A12A /* CallScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreen.swift; sourceTree = ""; }; E413F4CBD7BF0588F394A9DD /* RoomDetailsEditScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenViewModel.swift; sourceTree = ""; }; @@ -2327,6 +2411,7 @@ E6E6BDF9D26DB05C88901416 /* RedactedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineItem.swift; sourceTree = ""; }; E6F5D66F158A6662F953733E /* NotificationSettingsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxy.swift; sourceTree = ""; }; E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactory.swift; sourceTree = ""; }; + E7495E1119753B06FF2C2279 /* PhotoLibraryManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryManager.swift; sourceTree = ""; }; E76A706B3EEA32B882DA5E2D /* BlockedUsersScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModelProtocol.swift; sourceTree = ""; }; E78FC546F28E045A560F2963 /* EncryptionKeyProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionKeyProviderProtocol.swift; sourceTree = ""; }; E8294DB9E95C0C0630418466 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; @@ -2418,6 +2503,7 @@ FBC776F301D374A3298C69DA /* AppCoordinatorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinatorProtocol.swift; sourceTree = ""; }; FC83F47D2173B7538AA72E0E /* RoomSummaryProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProviderMock.swift; sourceTree = ""; }; FC853F9B4FBE039D2C16EC6B /* RoomMembersListManageMemberSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListManageMemberSheet.swift; sourceTree = ""; }; + FC9044BE0E4A66F5B963E834 /* AudioFileEventsTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioFileEventsTimelineView.swift; sourceTree = ""; }; FCE93F0CBF0D96B77111C413 /* AppLockFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockFlowCoordinator.swift; sourceTree = ""; }; FD1275D9CE0FFBA6E8E85426 /* UserIndicatorController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorController.swift; sourceTree = ""; }; FDB9C37196A4C79F24CE80C6 /* KeychainControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerTests.swift; sourceTree = ""; }; @@ -2592,6 +2678,7 @@ isa = PBXGroup; children = ( 693E16574C6F7F9FA1015A8C /* Search.swift */, + 832397B5C3D00A4BF52C5F0B /* ShouldScrollOnKeyboardDidShow.swift */, E2DA161C142B7AB8CC40F752 /* Animation */, CE2FBFD64A89F5DBE4EB30DB /* Layout */, E6E1D07163F8752D62DA4A93 /* Styles */, @@ -2896,6 +2983,18 @@ path = View; sourceTree = ""; }; + 26397A1EDB867FD573821532 /* MediaEventsTimelineScreen */ = { + isa = PBXGroup; + children = ( + 8512B82404B1751D0BCC82D2 /* MediaEventsTimelineScreenCoordinator.swift */, + 7033218DA395B003F7AB29A2 /* MediaEventsTimelineScreenModels.swift */, + 976ED77B772F50C4BAD757E7 /* MediaEventsTimelineScreenViewModel.swift */, + A175D0FDEDBFA44C47FE13AE /* MediaEventsTimelineScreenViewModelProtocol.swift */, + DB180A1068D7B85489E13E3F /* View */, + ); + path = MediaEventsTimelineScreen; + sourceTree = ""; + }; 26C16326BCCCED74A85A0F48 /* View */ = { isa = PBXGroup; children = ( @@ -2908,6 +3007,7 @@ isa = PBXGroup; children = ( 01C4C7DB37597D7D8379511A /* Assets.xcassets */, + 17F7A723A46DF5C95BE15EBF /* clear.png */, A0C06C0F6A8621B22BFAEB56 /* Localizations */, 8AEA6A91159FA0D3EAFCCB0D /* Sounds */, ); @@ -3039,6 +3139,7 @@ 2DA4F09CB613C54FDC73AE6A /* ThreadDecorator.swift */, F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */, 1DA7E93C2E148B96EF6A8500 /* TimelineItemAccessibilityModifier.swift */, + AE739A6836E86E3780748477 /* TimelineItemBubbleBackground.swift */, 0A459AE4B6566B2FA99E86B2 /* TimelineItemBubbledStylerView.swift */, 753B4C6C0EDDCBF0708DC384 /* TimelineItemSendInfoLabel.swift */, 6CD4823EAB4B4E8BAB4F6B8C /* TimelineStyle.swift */, @@ -3047,6 +3148,14 @@ path = Style; sourceTree = ""; }; + 31602635E5D50101A3A24D51 /* View */ = { + isa = PBXGroup; + children = ( + B4AE42C19EDE64B7CB7BE4D0 /* SecurityAndPrivacyScreen.swift */, + ); + path = View; + sourceTree = ""; + }; 31CE4DA53232AA534057F912 /* Mocks */ = { isa = PBXGroup; children = ( @@ -3061,10 +3170,12 @@ 3A21027F05874B1BCC3E452B /* InvitedRoomProxyMock.swift */, 867DC9530C42F7B5176BE465 /* JoinedRoomProxyMock.swift */, 9E8F4D7D61B80EBD5CB92F8A /* KnockedRoomProxyMock.swift */, + 7F957320D0EB7D7B4E30C79D /* KnockRequestProxyMock.swift */, 6F65E4BB9E82EB8373207CF8 /* MediaProviderMock.swift */, 8DA1E8F287680C8ED25EDBAC /* NetworkMonitorMock.swift */, 382B50F7E379B3DBBD174364 /* NotificationSettingsProxyMock.swift */, B2AD8A56CD37E23071A2F4BF /* PHGPostHogMock.swift */, + DD955A0380C287C418F1A74D /* PhotoLibraryManagerMock.swift */, D38391154120264910D19528 /* PollMock.swift */, 894EE8F5B399A165BA2A6634 /* RoomDirectorySearchMock.swift */, 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */, @@ -3102,6 +3213,7 @@ 9A028783CFFF861C5E44FFB1 /* BadgeLabel.swift */, C1FA515B3B0D61EF1E907D2D /* BadgeView.swift */, D01FD1171FF40E34D707FD00 /* BigIcon.swift */, + 07934EF08BB39353E4A94272 /* BlurEffectView.swift */, 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */, B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */, C352359663A0E52BA20761EE /* LoadableImage.swift */, @@ -3249,15 +3361,6 @@ path = Helpers; sourceTree = ""; }; - 3A542DF1C3BB67D829DFDC40 /* VoiceMessages */ = { - isa = PBXGroup; - children = ( - 3CCD41CD67DB5DA0D436BFE9 /* VoiceMessageRoomPlaybackView.swift */, - B70A50C41C5871B4DB905E7E /* VoiceMessageRoomTimelineView.swift */, - ); - path = VoiceMessages; - sourceTree = ""; - }; 3AD37D7DDF9904587601239D /* AppLockScreen */ = { isa = PBXGroup; children = ( @@ -3366,6 +3469,8 @@ 0E95B3BDB80531C85CD50AE6 /* InvitedRoomProxy.swift */, 07C6B0B087FE6601C3F77816 /* JoinedRoomProxy.swift */, 858DA81F2ACF484B7CAD6AE4 /* KnockedRoomProxy.swift */, + 8F062DD2CCD95DC33528A16F /* KnockRequestProxy.swift */, + C07851F4EA81AA3339806A7B /* KnockRequestProxyProtocol.swift */, B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */, 40A66E8BC8D9AE4A08EFB2DF /* RoomInfoProxy.swift */, 974AEAF3FE0C577A6C04AD6E /* RoomPermissions.swift */, @@ -3392,6 +3497,11 @@ isa = PBXGroup; children = ( 638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */, + E7495E1119753B06FF2C2279 /* PhotoLibraryManager.swift */, + E3A62FBD3007312311C14DD8 /* TimelineMediaPreviewCoordinator.swift */, + 2A2BB38DF61F5100B8723112 /* TimelineMediaPreviewModels.swift */, + 53F41CEAAE2BB4E74CDC2278 /* TimelineMediaPreviewViewModel.swift */, + 5EC4A8482DA110602FE6DF42 /* View */, ); path = FilePreviewScreen; sourceTree = ""; @@ -3440,6 +3550,7 @@ 077B01C13BBA2996272C5FB5 /* ProcessInfo.swift */, 1DFE0E493FB55E5A62E7852A /* ProposedViewSize.swift */, 7310D8DFE01AF45F0689C3AA /* Publisher.swift */, + DADECBBB672497BCD4822468 /* Result.swift */, 584A61D9C459FAFEF038A7C0 /* Section.swift */, DF17EA323AD0205A6AB621AA /* Snapshotting.swift */, 40B21E611DADDEF00307E7AC /* String.swift */, @@ -3616,6 +3727,19 @@ path = ItemMenu; sourceTree = ""; }; + 50D53998001EC408A51D6509 /* TimelineViews */ = { + isa = PBXGroup; + children = ( + FC9044BE0E4A66F5B963E834 /* AudioFileEventsTimelineView.swift */, + 430C73079A84654BF46A7FF5 /* FileMediaEventsTimelineView.swift */, + 1FF584D757E768EA7776A532 /* ImageMediaEventsTimelineView.swift */, + 13F354AD441E2FD83DED89AF /* SeparatorMediaEventsTimelineView.swift */, + 2B1FB56520A847DD2532D5C8 /* VideoMediaEventsTimelineView.swift */, + AD3521DF92391551E02004D8 /* VoiceMessageMediaEventsTimelineView.swift */, + ); + path = TimelineViews; + sourceTree = ""; + }; 52AA75722911233E40A3B366 /* Scripts */ = { isa = PBXGroup; children = ( @@ -3692,6 +3816,7 @@ 7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */, A07B011547B201A836C03052 /* EncryptionResetFlowCoordinator.swift */, ECB836DD8BE31931F51B8AC9 /* EncryptionSettingsFlowCoordinator.swift */, + 2178B951602AA921A5FD9DC8 /* MediaEventsTimelineFlowCoordinator.swift */, C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */, A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */, 9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */, @@ -3764,6 +3889,17 @@ path = View; sourceTree = ""; }; + 5EC4A8482DA110602FE6DF42 /* View */ = { + isa = PBXGroup; + children = ( + 467498BEA681758BE2F80826 /* TimelineMediaPreviewDetailsView.swift */, + 30856520F3263D0E195710D7 /* TimelineMediaPreviewFileExportPicker.swift */, + C75FE3F524B575D53787868C /* TimelineMediaPreviewRedactConfirmationView.swift */, + AA57E8563C346B13DDE4A6F4 /* TimelineMediaPreviewScreen.swift */, + ); + path = View; + sourceTree = ""; + }; 5F6CB68B44F6C587E463A934 /* View */ = { isa = PBXGroup; children = ( @@ -4057,6 +4193,7 @@ 848F69921527D31CAACB93AF /* SecureBackupLogoutConfirmationScreenViewModelTests.swift */, C0FF08D0BD7D0B4B6877AB7D /* SecureBackupRecoveryKeyScreenViewModelTests.swift */, 40316EFFEAC7B206EE9A55AE /* SecureBackupScreenViewModelTests.swift */, + 0315C328FF40F84276364E66 /* SecurityAndPrivacyScreenViewModelTests.swift */, 277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */, F08776C48FFB47CACF64ED10 /* ServerConfirmationScreenViewModelTests.swift */, E45EBAFF1A83538D54ABDF92 /* ServerSelectionScreenViewModelTests.swift */, @@ -4070,6 +4207,7 @@ 2CEBCB9676FCD1D0F13188DD /* StringTests.swift */, 2AB2C848BB9A7A9B618B7B89 /* TextBasedRoomTimelineTests.swift */, 9AA3AF94A06D319BB37E52DA /* TimelineItemFactoryTests.swift */, + 5C1F000589F2CEE6B03ECFAB /* TimelineMediaPreviewViewModelTests.swift */, 6509708F54FC883604DFDC95 /* TimelineViewModelTests.swift */, 1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */, 76310030C831D4610A705603 /* URLComponentsTests.swift */, @@ -4396,7 +4534,6 @@ F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */, 8C8616254EE40CA8BA5E9BC2 /* VideoRoomTimelineItemContent.swift */, D529B976F8B2AA654D923422 /* VoiceMessageRoomTimelineItem.swift */, - 3A542DF1C3BB67D829DFDC40 /* VoiceMessages */, ); path = Messages; sourceTree = ""; @@ -5166,6 +5303,18 @@ path = RoomDirectorySearchScreen; sourceTree = ""; }; + C59BA103987B953BA374509F /* SecurityAndPrivacyScreen */ = { + isa = PBXGroup; + children = ( + 97F2F6B6E56055EF173A2DD3 /* SecurityAndPrivacyScreenCoordinator.swift */, + 7BBADF8010C813D905C172CE /* SecurityAndPrivacyScreenModels.swift */, + 978092B01BEAB39F2C4389AE /* SecurityAndPrivacyScreenViewModel.swift */, + D046ABB22E680F7C5054441B /* SecurityAndPrivacyScreenViewModelProtocol.swift */, + 31602635E5D50101A3A24D51 /* View */, + ); + path = SecurityAndPrivacyScreen; + sourceTree = ""; + }; C844840F3DD48A154C65AE0C /* View */ = { isa = PBXGroup; children = ( @@ -5238,6 +5387,7 @@ 44ECC9D66400727DFFEE12E8 /* TimelineStartRoomTimelineView.swift */, C9E535B3388755B65C34CD10 /* UnsupportedRoomTimelineView.swift */, ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */, + B6A293D06BAB2B7A17D9314B /* VoiceMessageRoomTimelineView.swift */, ); path = TimelineItemViews; sourceTree = ""; @@ -5359,6 +5509,15 @@ path = RoomChangePermissionsScreen; sourceTree = ""; }; + DB180A1068D7B85489E13E3F /* View */ = { + isa = PBXGroup; + children = ( + 002399C6CB875C4EBB01CBC0 /* MediaEventsTimelineScreen.swift */, + 50D53998001EC408A51D6509 /* TimelineViews */, + ); + path = View; + sourceTree = ""; + }; DD96B3F20F354494DECBC4F7 /* View */ = { isa = PBXGroup; children = ( @@ -5374,6 +5533,10 @@ 78BBDF7A05CF53B5CDC13682 /* landscape_test_video.mov */, BC51BF90469412ABDE658CDD /* portrait_test_image.jpg */, E5E7D4EE7CA295E5039FDA21 /* portrait_test_video.mp4 */, + 12FD5280AF55AB7F50F8E47D /* preview_avatar_room.jpg */, + 87FC42213E86E8182CFD3A49 /* preview_avatar_user.jpg */, + 200626E8353AB2729444F991 /* preview_image.jpg */, + 45A4B934BA41D6C255900265 /* preview_video.jpg */, 53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */, BB576F4118C35E6B5124FA22 /* test_apple_image.heic */, 66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */, @@ -5416,6 +5579,7 @@ children = ( EF1593DD87F974F8509BB619 /* ElementAnimations.swift */, 97CE98208321C4D66E363612 /* ShimmerModifier.swift */, + 018194CAFBE80720FECCEDEE /* ZoomTransition.swift */, ); path = Animation; sourceTree = ""; @@ -5453,6 +5617,7 @@ BF0415BE807CA2BCFC210008 /* KnockRequestsListScreen */, 948DD12A5533BE1BC260E437 /* LocationSharing */, 73E032ADD008D63812791D97 /* LogViewerScreen */, + 26397A1EDB867FD573821532 /* MediaEventsTimelineScreen */, 87E2774157D9C4894BCFF3F8 /* MediaPickerScreen */, 23605DD08620BE6558242469 /* MediaUploadPreviewScreen */, 3348D14DBDB54E72FC67E2F3 /* MessageForwardingScreen */, @@ -5475,6 +5640,7 @@ 679E9837ECA8D6776079D16E /* RoomScreen */, 2E42D43DB6835A58D88B2F91 /* RoomSelectionScreen */, 2565414373E6F68005966B8E /* SecureBackup */, + C59BA103987B953BA374509F /* SecurityAndPrivacyScreen */, 70B74A432C241E56A7ACE610 /* Settings */, EC4545C7E37E8294D3FE6800 /* StartChatScreen */, 15D44FCA9475E660B7F56DB9 /* Timeline */, @@ -5747,6 +5913,7 @@ D53FCCE44F96E0BC411A6CF0 /* TimelineSenderAvatarView.swift */, 93C713D124FE915ABF47A6B7 /* TimelineView.swift */, 81F0325E252B057FAEEE1B2D /* TypingIndicatorView.swift */, + 9E3B41C36800DD4558D7BDA7 /* VoiceMessageRoomPlaybackView.swift */, 505AE6F89590187813390D12 /* ItemMenu */, C13DBC8C4A879A5A9C781BBD /* Polls */, B470504BE2DC95FAC94FDD79 /* ReadReceipts */, @@ -6125,11 +6292,16 @@ 5FCD8AFA364206EE32B909A3 /* Settings.bundle in Resources */, CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */, 2797C9D9BA642370F1C85D78 /* Untranslated.stringsdict in Resources */, + BFDDAF1A36FBC7CF63DCB7DD /* clear.png in Resources */, 147597951DB07123A87AA1D1 /* landscape_test_image.jpg in Resources */, FDC67E8C0EDCB00ABC66C859 /* landscape_test_video.mov in Resources */, E67418DACEDBC29E988E6ACD /* message.caf in Resources */, 12E6D052D055531A6783E21B /* portrait_test_image.jpg in Resources */, 5C61810ED7B7CB48346B1B9D /* portrait_test_video.mp4 in Resources */, + 85BD82E144AB99518A57DDEC /* preview_avatar_room.jpg in Resources */, + 03631FC946FF0BBAD37E22BF /* preview_avatar_user.jpg in Resources */, + 5DB4334CBBA142376FF5FFEC /* preview_image.jpg in Resources */, + C3AFDF6349E54290AA31EC88 /* preview_video.jpg in Resources */, DFF7D6A6C26DDD40D00AE579 /* target.yml in Resources */, 18978C9438206828C1D5AF2A /* test_animated_image.gif in Resources */, 01373C1AC4839604C4FDA404 /* test_apple_image.heic in Resources */, @@ -6174,6 +6346,10 @@ F4582042AA4225CC1E4B8A1E /* landscape_test_video.mov in Resources */, 8F3AD08F2E706AA60F1A1D4D /* portrait_test_image.jpg in Resources */, D97C782FE0005995C36FA04A /* portrait_test_video.mp4 in Resources */, + 3C312A3AEDE58BB1C9BBB07C /* preview_avatar_room.jpg in Resources */, + 1801F1467ABCEA080419E150 /* preview_avatar_user.jpg in Resources */, + D31B34B3902BC597593F3ABB /* preview_image.jpg in Resources */, + 5F35069E13D71DD88633A4B2 /* preview_video.jpg in Resources */, 35E975CFDA60E05362A7CF79 /* target.yml in Resources */, B20484642B41C2D76238BAAA /* test_animated_image.gif in Resources */, A1672EF491FE6F3BBF7878BE /* test_apple_image.heic in Resources */, @@ -6478,6 +6654,7 @@ EB87DF90CF6F8D5D12404C6E /* SecureBackupLogoutConfirmationScreenViewModelTests.swift in Sources */, 06B31F84CE52A7A7C271267C /* SecureBackupRecoveryKeyScreenViewModelTests.swift in Sources */, 1B8E30B35BF8F541C1318F19 /* SecureBackupScreenViewModelTests.swift in Sources */, + CB9FB2BEF313072C705AC9B5 /* SecurityAndPrivacyScreenViewModelTests.swift in Sources */, 53A55748D5F587C9061F98BF /* ServerConfigurationScreenViewStateTests.swift in Sources */, 89658A44C9FC19B58FD1C226 /* ServerConfirmationScreenViewModelTests.swift in Sources */, 67ECD32538F6DAFE38A623F9 /* ServerSelectionScreenViewModelTests.swift in Sources */, @@ -6492,6 +6669,7 @@ E75CE800B3E64D0F7F8E228D /* TemplateScreenViewModelTests.swift in Sources */, 3A7DD0D13B0FB8876D69D829 /* TextBasedRoomTimelineTests.swift in Sources */, 0D4EB2ABAA5FE8CB10FDBCB8 /* TimelineItemFactoryTests.swift in Sources */, + F6BF52CB027393EE03CEC523 /* TimelineMediaPreviewViewModelTests.swift in Sources */, 2F6207CB5C4715FE313B1E95 /* TimelineViewModelTests.swift in Sources */, 282A5F3375DDC774AE09B0C3 /* TracingConfigurationTests.swift in Sources */, 8E650379587C31D7912ED67B /* UNNotification+Creator.swift in Sources */, @@ -6622,6 +6800,7 @@ A6DEC1ADEC8FEEC206A0FA37 /* AttributedStringBuilderProtocol.swift in Sources */, 2DA27D78560D5F79B917E163 /* AudioConverter.swift in Sources */, F3F38062C6CA21CF403C5C90 /* AudioConverterProtocol.swift in Sources */, + 77E33FF0E4A50B555BF3A8AA /* AudioFileEventsTimelineView.swift in Sources */, 46C9F8FE3810A04A005FE16B /* AudioPlayer.swift in Sources */, 086D01E79C8E8D3F004FAF21 /* AudioPlayerProtocol.swift in Sources */, 1471A080552631358D152C18 /* AudioPlayerState.swift in Sources */, @@ -6660,6 +6839,7 @@ 934051B17A884AB0635DF81B /* BlockedUsersScreenViewModel.swift in Sources */, A4B123C635F70DDD4BC2FAC9 /* BlockedUsersScreenViewModelProtocol.swift in Sources */, 5EE1D4E316D66943E97FDCF2 /* BloomView.swift in Sources */, + 54FDA3625AACBD9E438D084D /* BlurEffectView.swift in Sources */, B6DF6B6FA8734B70F9BF261E /* BlurHashDecode.swift in Sources */, E794AB6ABE1FF5AF0573FEA1 /* BlurHashEncode.swift in Sources */, A8FA7671948E3DF27F320026 /* BugReportFlowCoordinator.swift in Sources */, @@ -6788,6 +6968,7 @@ 63E46D18B91D08E15FC04125 /* ExpiringTaskRunner.swift in Sources */, 36206F74DDEBF9BEAF6A6A1F /* ExtensionLogger.swift in Sources */, 5F06AD3C66884CE793AE6119 /* FileManager.swift in Sources */, + EA8D941771E762A5D3D7FA0D /* FileMediaEventsTimelineView.swift in Sources */, D33AC79A50DFC26D2498DD28 /* FileRoomTimelineItem.swift in Sources */, 37D789F24199B32E3FD1AA7B /* FileRoomTimelineItemContent.swift in Sources */, 64EE9D2CF7AD02EE53983CE1 /* FileRoomTimelineView.swift in Sources */, @@ -6831,6 +7012,7 @@ AADE7C2497A7B55D8BED7BD6 /* IdentityConfirmedScreenViewModelProtocol.swift in Sources */, FFD52DCDA6962055A363CC8F /* IdentityResetHandleSDKMock.swift in Sources */, BA31448FBD9697F8CB9A83CD /* ImageCache.swift in Sources */, + 446BCD2D0AE27E0CFD1BDC8F /* ImageMediaEventsTimelineView.swift in Sources */, 7CD16990BA843BE9ED639129 /* ImageRoomTimelineItem.swift in Sources */, B796A25F282C0A340D1B9C12 /* ImageRoomTimelineItemContent.swift in Sources */, E2D57361B835E4D2230960E6 /* ImageRoomTimelineView.swift in Sources */, @@ -6857,6 +7039,9 @@ FD29471C72872F8B7580E3E1 /* KeychainControllerMock.swift in Sources */, CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */, 2748E5574A1031DD05E54FDA /* KnockRequestCell.swift in Sources */, + 83D519C509F0F76EDBB60455 /* KnockRequestProxy.swift in Sources */, + 0AD8EF040A60D62F488C18B5 /* KnockRequestProxyMock.swift in Sources */, + D18B70975644C24F60656C0D /* KnockRequestProxyProtocol.swift in Sources */, D5E8EE8A288EFCCF646860EA /* KnockRequestsBannerView.swift in Sources */, E8B290CBB7E5FF5E3C1B6124 /* KnockRequestsListEmptyStateView.swift in Sources */, AAA551AD8768309024D4907B /* KnockRequestsListScreen.swift in Sources */, @@ -6909,6 +7094,12 @@ BEA646DF302711A753F0D420 /* MapTilerStyleBuilderProtocol.swift in Sources */, 67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */, 8658F5034EAD7357CE7F9AC7 /* MatrixUserShareLink.swift in Sources */, + 84E514915DF0C168B08A3A0A /* MediaEventsTimelineFlowCoordinator.swift in Sources */, + BEC6DFEA506085D3027E353C /* MediaEventsTimelineScreen.swift in Sources */, + C8E1E4E06B7C7A3A8246FC9B /* MediaEventsTimelineScreenCoordinator.swift in Sources */, + B7F58D6903F9D509EDAB9E4F /* MediaEventsTimelineScreenModels.swift in Sources */, + C11D4A49DC29D89CE2BB31B8 /* MediaEventsTimelineScreenViewModel.swift in Sources */, + FD9777315A5D9CDC47458AD1 /* MediaEventsTimelineScreenViewModelProtocol.swift in Sources */, BCC864190651B3A3CF51E4DF /* MediaFileHandleProxy.swift in Sources */, 208C19811613F9A10F8A7B75 /* MediaLoader.swift in Sources */, A2434D4DFB49A68E5CD0F53C /* MediaLoaderProtocol.swift in Sources */, @@ -6987,6 +7178,8 @@ 847DE3A7EB9FCA2C429C6E85 /* PINTextField.swift in Sources */, 7501442D52A65F73DF79FFD4 /* PaginationIndicatorRoomTimelineItem.swift in Sources */, BC7CA1379D7C24F47B1B8B7E /* PaginationIndicatorRoomTimelineView.swift in Sources */, + 5FA1DCE55973862632961D7C /* PhotoLibraryManager.swift in Sources */, + 2D38D39B1789B91AE69F477F /* PhotoLibraryManagerMock.swift in Sources */, 962A4F8AD6312804E2C6BB6E /* PhotoLibraryPicker.swift in Sources */, EE4E2C1922BBF5169E213555 /* PillAttachmentViewProvider.swift in Sources */, 899359A4D1147601F6C4E364 /* PillConstants.swift in Sources */, @@ -7052,6 +7245,7 @@ 9A0326D2375075871D2AB537 /* ResolveVerifiedUserSendFailureScreenViewModel.swift in Sources */, ED3E91E6166E4923791ACA84 /* ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift in Sources */, A494741843F087881299ACF0 /* RestorationToken.swift in Sources */, + 194585F6CD77242B36D4ADF1 /* Result.swift in Sources */, 6E391F7F628D984AF44385D9 /* RoomAttachmentPicker.swift in Sources */, 8587A53DE8EF94FD796DC375 /* RoomAvatarImage.swift in Sources */, F8C87130FD999F7F1076208C /* RoomChangePermissionsScreen.swift in Sources */, @@ -7202,6 +7396,12 @@ DA7E867F5EAFF8E20B2EE3B6 /* SecureBackupScreenModels.swift in Sources */, 7BF368A78E6D9AFD222F25AF /* SecureBackupScreenViewModel.swift in Sources */, AC90434798E7894370E80E66 /* SecureBackupScreenViewModelProtocol.swift in Sources */, + 7254FB2EFDD43BC8BB7A1213 /* SecurityAndPrivacyScreen.swift in Sources */, + 611BEE29B8B622204E1E6B04 /* SecurityAndPrivacyScreenCoordinator.swift in Sources */, + 6B80C24A52411EAF10E06E96 /* SecurityAndPrivacyScreenModels.swift in Sources */, + 7C545FFEC9930F7247352593 /* SecurityAndPrivacyScreenViewModel.swift in Sources */, + 0D617A152D099D94271D3BA8 /* SecurityAndPrivacyScreenViewModelProtocol.swift in Sources */, + 08547E55DD3686A84550996D /* SeparatorMediaEventsTimelineView.swift in Sources */, 14E99D27628B1A6F0CB46FEA /* SeparatorRoomTimelineItem.swift in Sources */, 5341D48F833E3E30F16FA2A3 /* SeparatorRoomTimelineView.swift in Sources */, 2E8C6672D0EE7D5B1BEDB8E2 /* ServerConfirmationScreen.swift in Sources */, @@ -7235,6 +7435,7 @@ 5D99F63CC88BB29383019FC6 /* ShareExtensionModels.swift in Sources */, 1C8BC70A18060677E295A846 /* ShareToMapsAppActivity.swift in Sources */, 274CE3C986841D15FD530BF5 /* ShimmerModifier.swift in Sources */, + 5038E69A5E6A89DE1A345E04 /* ShouldScrollOnKeyboardDidShow.swift in Sources */, 77920AFA8091AC6B9F190C90 /* Signposter.swift in Sources */, F08F7BC07CA9AEF5CD157918 /* Snapshotting.swift in Sources */, 8BC8EF6705A78946C1F22891 /* SoftLogoutScreen.swift in Sources */, @@ -7281,6 +7482,7 @@ 798BF3072137833FBD3F4C96 /* TimelineDeliveryStatusView.swift in Sources */, 109AEB7D33C4497727AFB87F /* TimelineInteractionHandler.swift in Sources */, E6FA87F773424B27614B23E9 /* TimelineItemAccessibilityModifier.swift in Sources */, + F6767F17D538578B370DD805 /* TimelineItemBubbleBackground.swift in Sources */, 79959F8E45C3749997482A7F /* TimelineItemBubbledStylerView.swift in Sources */, A808DC3F72D15C6C5A52317E /* TimelineItemDebugView.swift in Sources */, 877D3CE8680536DB430DE6A2 /* TimelineItemIdentifier.swift in Sources */, @@ -7294,6 +7496,13 @@ 1B88BB631F7FC45A213BB554 /* TimelineItemSender.swift in Sources */, EFBBD44C0A16F017C32D2099 /* TimelineItemStatusView.swift in Sources */, 562EFB9AB62B38830D9AA778 /* TimelineMediaFrame.swift in Sources */, + FE43747C116CA3D8D6B92F5F /* TimelineMediaPreviewCoordinator.swift in Sources */, + 12EC6BC99F373FE5C6EB9B64 /* TimelineMediaPreviewDetailsView.swift in Sources */, + 4ED764A24F2A715C25CF07F1 /* TimelineMediaPreviewFileExportPicker.swift in Sources */, + 77FB08C303F4C74C0E8577E2 /* TimelineMediaPreviewModels.swift in Sources */, + A32384E3D85CA65342D3A908 /* TimelineMediaPreviewRedactConfirmationView.swift in Sources */, + 9826A4DBBEFA7041A9E0EFAD /* TimelineMediaPreviewScreen.swift in Sources */, + 86769B62BAE17601B3AE1B60 /* TimelineMediaPreviewViewModel.swift in Sources */, B818580464CFB5400A3EF6AE /* TimelineModels.swift in Sources */, E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */, 16A1F6C703305FCAF4E14EC6 /* TimelineProxyMock.swift in Sources */, @@ -7364,6 +7573,7 @@ 7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */, 79D57E9AE03A2DC689D14EA2 /* UserSessionStoreMock.swift in Sources */, AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */, + 5C33976A720B64094CBC56B1 /* VideoMediaEventsTimelineView.swift in Sources */, F07D88421A9BC4D03D4A5055 /* VideoRoomTimelineItem.swift in Sources */, 1A83DD22F3E6F76B13B6E2F9 /* VideoRoomTimelineItemContent.swift in Sources */, 2CA61BB208CD82EBDB58CD13 /* VideoRoomTimelineView.swift in Sources */, @@ -7372,6 +7582,7 @@ 1318721F4E5F307586D98112 /* VoiceMessageButton.swift in Sources */, 4681820102DAC8BA586357D4 /* VoiceMessageCache.swift in Sources */, 4F2DF6138E87A4B8C2488CA3 /* VoiceMessageCacheProtocol.swift in Sources */, + 4870F7F72CEBEFDAD1C973A6 /* VoiceMessageMediaEventsTimelineView.swift in Sources */, 386720B603F87D156DB01FB2 /* VoiceMessageMediaManager.swift in Sources */, 9DE801D278AC34737467F937 /* VoiceMessageMediaManagerProtocol.swift in Sources */, F7932A3F075B0D3F24DEECB5 /* VoiceMessagePreviewComposer.swift in Sources */, @@ -7380,9 +7591,9 @@ C405528EB4BBEA93579050EE /* VoiceMessageRecordingButton.swift in Sources */, E0C167D41A48EDB30B447DE3 /* VoiceMessageRecordingComposer.swift in Sources */, 756EA0D663261889EF64E6D4 /* VoiceMessageRecordingView.swift in Sources */, - A9482B967FC85DA611514D35 /* VoiceMessageRoomPlaybackView.swift in Sources */, + 55DF6DEEF2CEEF40F84B53B0 /* VoiceMessageRoomPlaybackView.swift in Sources */, 024E70451A7CD9E4E034D8A9 /* VoiceMessageRoomTimelineItem.swift in Sources */, - 87B4E59A4467F8EC75F82372 /* VoiceMessageRoomTimelineView.swift in Sources */, + 1224084B7E289E0830BA2C54 /* VoiceMessageRoomTimelineView.swift in Sources */, CA12AE0DCD57D49CD96C699A /* WaveformCursorView.swift in Sources */, 63CDC201A5980F304F6D0A1C /* WaveformInteractionModifier.swift in Sources */, B773ACD8881DB18E876D950C /* WaveformSource.swift in Sources */, @@ -7393,6 +7604,7 @@ 66357ECB73B1290E5490A012 /* WebRegistrationScreenViewModelProtocol.swift in Sources */, 08CB4BD12CEEDE6AAE4A18DD /* WindowManager.swift in Sources */, AE5AAD9E32511544FDFA5560 /* WindowManagerProtocol.swift in Sources */, + 80F1B442DB5E2C362ACDD8E2 /* ZoomTransition.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -7824,7 +8036,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 17.6; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; MACOSX_DEPLOYMENT_TARGET = 14.6; - MARKETING_VERSION = 1.9.8; + MARKETING_VERSION = 1.9.10; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCTION_APP_NAME = Element; @@ -7901,7 +8113,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 17.6; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; MACOSX_DEPLOYMENT_TARGET = 14.6; - MARKETING_VERSION = 1.9.8; + MARKETING_VERSION = 1.9.10; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -8215,7 +8427,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.77; + version = 1.0.83; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { @@ -8335,7 +8547,7 @@ repositoryURL = "https://github.com/element-hq/compound-ios"; requirement = { kind = revision; - revision = 901f3f2fc150db82cf8a2c4da53914b31f681b56; + revision = 9325643cb4d22150881c5bf79e1e6e3c5a87ea89; }; }; F76A08D0EA29A07A54F4EB4D /* XCRemoteSwiftPackageReference "swift-collections" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6b6570ef8c..af76e8c09a 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -6,8 +6,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/compound-design-tokens", "state" : { - "revision" : "31b236f02c811704b68e8aae429865fe8eb8d8ba", - "version" : "2.1.1" + "revision" : "a6e96fb4436a4945423a8c068001093af4b7b315", + "version" : "3.0.1" } }, { @@ -15,7 +15,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/compound-ios", "state" : { - "revision" : "901f3f2fc150db82cf8a2c4da53914b31f681b56" + "revision" : "9325643cb4d22150881c5bf79e1e6e3c5a87ea89" } }, { @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "4e01a9482cfefae4f06c6f3a5a33d21a2bf73d84", - "version" : "1.0.77" + "revision" : "0d20974d1c44225596b24af1ec1f36716dd6e512", + "version" : "1.0.83" } }, { @@ -185,8 +185,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/BarredEwe/Prefire", "state" : { - "revision" : "0b7b6e6fe98af7e12b1440ca8fe81b3033ecf873", - "version" : "2.9.0" + "revision" : "172a7f0a95f99f6656f6b2d0531b648c08d26c56", + "version" : "2.10.0" } }, { diff --git a/ElementX/Resources/Localizations/be.lproj/Localizable.strings b/ElementX/Resources/Localizations/be.lproj/Localizable.strings index 4fa69ce0df..73ae934433 100644 --- a/ElementX/Resources/Localizations/be.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/be.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Прагляд у хроніцы"; "action_view_source" = "Прагляд зыходнага кода"; "action_yes" = "Так"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Выйсці і абнавіць"; "banner_migrate_to_native_sliding_sync_description" = "Ваш сервер зараз падтрымлівае новы, хутчэйшы пратакол. Выйдзіце з сістэмы і зноў увайдзіце, каб абнавіць яе. Гэта дапаможа вам пазбегнуць прымусовага выхаду з сістэмы, калі стары пратакол будзе пазней выдалены."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Ваш хатні сервер больш не падтрымлівае стары пратакол. Калі ласка, выйдзіце і ўвайдзіце зноў, каб працягнуць выкарыстанне праграмы."; @@ -138,10 +139,13 @@ "common_creating_room" = "Стварэнне пакоя…"; "common_current_user_left_room" = "Выйшаў з пакоя"; "common_dark" = "Цёмная"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Памылка расшыфроўкі"; "common_developer_options" = "Параметры распрацоўшчыка"; "common_device_id" = "Device ID"; "common_direct_chat" = "Прамы чат"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(Адрэдагавана)"; "common_editing" = "Рэдагаванне"; "common_editing_caption" = "Editing caption"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "Без водступу"; "rich_text_editor_url_placeholder" = "Спасылка"; "rich_text_editor_a11y_add_attachment" = "Дадаць далучэнне"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; "screen_advanced_settings_element_call_base_url" = "Карыстальніцкі URL сервера Element Call"; "screen_advanced_settings_element_call_base_url_description" = "Усталюйце карыстальніцкі асноўны URL для Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "Адрас пазначаны няправільна, пераканайцеся, што вы ўказалі пратакол (http/https) і правільны адрас."; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз."; "screen_media_upload_preview_error_failed_sending" = "Не атрымалася загрузіць медыяфайлы, паспрабуйце яшчэ раз."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Замацаваныя паведамленні"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Увядзіце свае даныя"; "screen_login_title" = "Сардэчна запрашаем!"; "screen_login_title_with_homeserver" = "Увайсці ў %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Не ўдалося выбраць носьбіт, паўтарыце спробу."; "screen_migration_message" = "Гэта аднаразовы працэс, дзякуем за чаканне."; "screen_migration_title" = "Налада ўліковага запісу."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Пры загрузцы налад апавяшчэнняў адбылася памылка."; "screen_room_details_error_muting" = "Не атрымалася адключыць гук у гэтым пакоі, паўтарыце спробу."; "screen_room_details_error_unmuting" = "Не ўдалося ўключыць гук у гэтым пакоі. Паўтарыце спробу."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Уласныя"; "screen_room_details_notification_mode_default" = "Стандартныя"; "screen_room_details_share_room_title" = "Падзяліцца пакоем"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ унеслі невядомую змену ў сяброўства"; "test_language_identifier" = "be"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Выпраўленне непаладак"; "troubleshoot_notifications_screen_action" = "Запусціць тэсты"; "troubleshoot_notifications_screen_action_again" = "Запусціце тэсты яшчэ раз"; diff --git a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings index df5429a5e1..17ad35b2b0 100644 --- a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "View in timeline"; "action_view_source" = "Преглед на източника"; "action_yes" = "Да"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Log Out & Upgrade"; "banner_migrate_to_native_sliding_sync_description" = "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; @@ -138,10 +139,13 @@ "common_creating_room" = "Създаване на стая…"; "common_current_user_left_room" = "Left room"; "common_dark" = "Тъмен"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Грешка при разшифроване"; "common_developer_options" = "Опции за разработчици"; "common_device_id" = "Device ID"; "common_direct_chat" = "Директен чат"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(редактирано)"; "common_editing" = "Редактиране"; "common_editing_caption" = "Editing caption"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "Unindent"; "rich_text_editor_url_placeholder" = "Връзка"; "rich_text_editor_a11y_add_attachment" = "Прикачване на файл"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; "screen_advanced_settings_element_call_base_url" = "Custom Element Call base URL"; "screen_advanced_settings_element_call_base_url_description" = "Set a custom base URL for Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "Invalid URL, please make sure you include the protocol (http/https) and the correct address."; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Failed processing media to upload, please try again."; "screen_media_upload_preview_error_failed_sending" = "Failed uploading media, please try again."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Pinned messages"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Въведете своите данни"; "screen_login_title" = "Добре дошли отново!"; "screen_login_title_with_homeserver" = "Влизане в %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Failed selecting media, please try again."; "screen_migration_message" = "This is a one time process, thanks for waiting."; "screen_migration_title" = "Setting up your account."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "An error occurred when loading notification settings."; "screen_room_details_error_muting" = "Failed muting this room, please try again."; "screen_room_details_error_unmuting" = "Failed unmuting this room, please try again."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Персонализирани"; "screen_room_details_notification_mode_default" = "По подразбиране"; "screen_room_details_share_room_title" = "Споделяне на стаята"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ made an unknown change to their membership"; "test_language_identifier" = "bg"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Troubleshoot"; "troubleshoot_notifications_screen_action" = "Run tests"; "troubleshoot_notifications_screen_action_again" = "Run tests again"; diff --git a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings index 1a5f11e52f..9a6046bdbe 100644 --- a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings @@ -36,10 +36,10 @@ "action_confirm_password" = "Potvrdit heslo"; "action_continue" = "Pokračovat"; "action_copy" = "Kopírovat"; -"action_copy_caption" = "Copy caption"; +"action_copy_caption" = "Kopírovat titulek"; "action_copy_link" = "Kopírovat odkaz"; "action_copy_link_to_message" = "Kopírovat odkaz na zprávu"; -"action_copy_text" = "Copy text"; +"action_copy_text" = "Kopírovat text"; "action_create" = "Vytvořit"; "action_create_a_room" = "Vytvořit místnost"; "action_deactivate" = "Deaktivovat"; @@ -86,7 +86,7 @@ "action_reject" = "Odmítnout"; "action_remove" = "Odstranit"; "action_remove_caption" = "Odstranit titulek"; -"action_remove_message" = "Remove message"; +"action_remove_message" = "Odstranit zprávu"; "action_reply" = "Odpovědět"; "action_reply_in_thread" = "Odpovědět ve vlákně"; "action_report_bug" = "Nahlásit chybu"; @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Zobrazit na časové ose"; "action_view_source" = "Zobrazit zdroj"; "action_yes" = "Ano"; +"action_yes_try_again" = "Ano, zkusit znovu"; "banner_migrate_to_native_sliding_sync_action" = "Odhlásit se a upgradovat"; "banner_migrate_to_native_sliding_sync_description" = "Váš server nyní podporuje nový, rychlejší protokol. Chcete-li upgradovat, odhlaste se a znovu se přihlaste. Pokud to uděláte nyní, pomůže vám vyhnout se nucenému odhlášení, když bude starý protokol později odstraněn."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Váš domovský server již nepodporuje starý protokol. Chcete-li pokračovat v používání aplikace, odhlaste se a znovu se přihlaste."; @@ -138,10 +139,13 @@ "common_creating_room" = "Vytváření místnosti…"; "common_current_user_left_room" = "Opustit místnost"; "common_dark" = "Tmavé"; +"common_date_date_at_time" = "%1$@ v %2$@"; +"common_date_this_month" = "Tento měsíc"; "common_decryption_error" = "Chyba dešifrování"; "common_developer_options" = "Možnosti pro vývojáře"; "common_device_id" = "ID zařízení"; "common_direct_chat" = "Přímý chat"; +"common_downloading" = "Stahování"; "common_edited_suffix" = "(upraveno)"; "common_editing" = "Úpravy"; "common_editing_caption" = "Úprava titulku"; @@ -373,21 +377,38 @@ "screen_join_room_knock_message_description" = "Zpráva (nepovinné)"; "screen_join_room_knock_sent_description" = "Pokud bude váš požadavek přijat, obdržíte pozvánku na vstup do místnosti."; "screen_join_room_knock_sent_title" = "Žádost o vstup odeslána"; -"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Yes, accept all"; -"screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; -"screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; +"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Ano, přijmout všechny"; +"screen_knock_requests_list_accept_all_alert_description" = "Opravdu chcete přijmout všechny žádosti o vstup?"; +"screen_knock_requests_list_accept_all_alert_title" = "Přijmout všechny požadavky"; "screen_knock_requests_list_accept_all_button_title" = "Přijmout vše"; -"screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; -"screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; -"screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; -"screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; -"screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; -"screen_knock_requests_list_decline_alert_title" = "Decline access"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "Nemohli jsme přijmout všechny žádosti. Chcete to zkusit znovu?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Nepodařilo se přijmout všechny žádosti"; +"screen_knock_requests_list_accept_all_loading_title" = "Přijímání všech žádostí o vstup"; +"screen_knock_requests_list_accept_failed_alert_description" = "Tuto žádost jsme nemohli přijmout. Chcete to zkusit znovu?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Žádost se nepodařilo přijmout"; +"screen_knock_requests_list_accept_loading_title" = "Přijímání žádosti o vstup"; +"screen_knock_requests_list_ban_alert_confirm_button_title" = "Ano, odmítnout a vykázat"; +"screen_knock_requests_list_ban_alert_description" = "Opravdu chcete odmítnout a vykázat %1$@? Tento uživatel nebude moci znovu požádat o vstup do této místnosti."; +"screen_knock_requests_list_ban_alert_title" = "Odmítnout a zakázat vstup"; +"screen_knock_requests_list_ban_loading_title" = "Odmítání vstupu a vykázání"; +"screen_knock_requests_list_decline_alert_confirm_button_title" = "Ano, odmítnout"; +"screen_knock_requests_list_decline_alert_description" = "Opravdu chcete odmítnout %1$@ žádost o vstup do této místnosti?"; +"screen_knock_requests_list_decline_alert_title" = "Odmítnout vstup"; "screen_knock_requests_list_decline_and_ban_action_title" = "Odmítnout a vykázat"; +"screen_knock_requests_list_decline_failed_alert_description" = "Tuto žádost jsme nemohli odmítnout. Chcete to zkusit znovu?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Žádost se nepodařilo odmítnout"; +"screen_knock_requests_list_decline_loading_title" = "Odmítání žádosti o vstup"; "screen_knock_requests_list_empty_state_description" = "Když někdo požádá o vstup do místnosti, uvidíte jeho žádost zde."; "screen_knock_requests_list_empty_state_title" = "Žádná čekající žádost o vstup"; +"screen_knock_requests_list_initial_loading_title" = "Načítání žádostí o vstup..."; "screen_knock_requests_list_title" = "Žádosti o vstup"; -"screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; +"screen_media_details_file_format" = "Formát souboru"; +"screen_media_details_filename" = "Název souboru"; +"screen_media_details_redact_confirmation_message" = "Tento soubor bude odstraněn z místnosti a členové k němu nebudou mít přístup."; +"screen_media_details_redact_confirmation_title" = "Smazat soubor?"; +"screen_media_details_uploaded_by" = "Nahrál(a)"; +"screen_media_details_uploaded_on" = "Nahráno"; +"screen_media_upload_preview_caption_warning" = "Titulky nemusí být viditelné pro lidi, kteří používají starší aplikace."; "screen_media_upload_preview_error_failed_processing" = "Nahrání média se nezdařilo, zkuste to prosím znovu."; "screen_media_upload_preview_error_failed_sending" = "Nahrání média se nezdařilo, zkuste to prosím znovu."; "screen_pinned_timeline_empty_state_description" = "Přidržte zprávu a vyberte „%1$@“, kterou chcete zahrnout sem."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "Zobrazit"; "screen_room_details_pinned_events_row_title" = "Připnuté zprávy"; "screen_room_details_requests_to_join_title" = "Žádosti o vstup"; +"screen_room_details_security_and_privacy_title" = "Zabezpečení a soukromí"; "screen_roomlist_knock_event_sent_description" = "Žádost o vstup odeslána"; +"screen_security_and_privacy_ask_to_join_option_description" = "Kdokoli může požádat o vstup do místnosti, ale správce nebo moderátor bude muset žádost přijmout."; +"screen_security_and_privacy_ask_to_join_option_title" = "Požádat o vstup"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Ano, povolit šifrování"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Po aktivaci nelze šifrování místnosti deaktivovat. Historie zpráv bude viditelná pouze pro členy místnosti od doby, kdy byli pozváni nebo od té doby, co do místnosti vstoupili.\nNikdo kromě členů místnosti nebude moci číst zprávy. To může bránit správnému fungování robotů a propojení.\nNedoporučujeme povolovat šifrování pro místnosti, které může kdokoli najít a vstoupit do nich."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Povolit šifrování?"; +"screen_security_and_privacy_encryption_section_footer" = "Jakmile je povoleno, šifrování nelze zakázat."; +"screen_security_and_privacy_encryption_section_title" = "Šifrování"; +"screen_security_and_privacy_encryption_toggle_title" = "Povolit koncové šifrování"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Každý může najít a vstoupit"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Kdokoliv"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "Lidé mohou vstoupit, pouze pokud jsou pozváni"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Pouze pro zvané"; +"screen_security_and_privacy_room_access_section_title" = "Přístup do místnosti"; +"screen_security_and_privacy_title" = "Zabezpečení a soukromí"; "screen_timeline_item_menu_send_failure_changed_identity" = "Zpráva nebyla odeslána, protože ověřená identita uživatele %1$@ se změnila."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Zpráva nebyla odeslána, protože%1$@ neověřil(a) všechna zařízení."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Zpráva nebyla odeslána, protože jste neověřili jedno nebo více zařízení."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Zadejte své údaje"; "screen_login_title" = "Vítejte zpět!"; "screen_login_title_with_homeserver" = "Přihlaste se k %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "Tento soubor bude odstraněn z místnosti a členové k němu nebudou mít přístup."; +"screen_media_browser_delete_confirmation_title" = "Smazat soubor?"; +"screen_media_browser_files_empty_state_subtitle" = "Zde se zobrazí dokumenty, zvukové soubory a hlasové zprávy nahrané do této místnosti."; +"screen_media_browser_files_empty_state_title" = "Zatím nebyly nahrány žádné soubory"; +"screen_media_browser_list_loading_files" = "Načítání souborů..."; +"screen_media_browser_list_loading_media" = "Načítání médií..."; +"screen_media_browser_list_mode_files" = "Soubory"; +"screen_media_browser_list_mode_media" = "Média"; +"screen_media_browser_media_empty_state_subtitle" = "Obrázky a videa nahraná do této místnosti budou zobrazeny zde."; +"screen_media_browser_media_empty_state_title" = "Zatím nebyla nahrána žádná média"; +"screen_media_browser_title" = "Média a soubory"; "screen_media_picker_error_failed_selection" = "Výběr média se nezdařil, zkuste to prosím znovu."; "screen_migration_message" = "Jedná se o jednorázový proces, prosíme o strpení."; "screen_migration_title" = "Nastavení vašeho účtu"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Při načítání nastavení oznámení došlo k chybě."; "screen_room_details_error_muting" = "Ztišení této místnosti se nezdařilo, zkuste to prosím znovu."; "screen_room_details_error_unmuting" = "Nepodařilo se zrušit ztišení této místnosti, zkuste to prosím znovu."; +"screen_room_details_media_gallery_title" = "Média a soubory"; "screen_room_details_notification_mode_custom" = "Vlastní"; "screen_room_details_notification_mode_default" = "Výchozí"; "screen_room_details_share_room_title" = "Sdílet místnost"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ provedl(a) neznámou změnu svého členství"; "test_language_identifier" = "en"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historické zprávy nejsou na tomto zařízení k dispozici"; +"timeline_decryption_failure_historical_event_user_not_joined" = "Nemáte přístup k této zprávě"; +"timeline_decryption_failure_unable_to_decrypt" = "Nelze dešifrovat zprávu"; +"timeline_decryption_failure_withheld_unverified" = "Tato zpráva byla zablokována buď proto, že jste neověřili své zařízení, nebo proto, že odesílatel potřebuje ověřit vaši totožnost."; "troubleshoot_notifications_entry_point_section" = "Odstraňování problémů"; "troubleshoot_notifications_screen_action" = "Spustit testy"; "troubleshoot_notifications_screen_action_again" = "Spustit testy znovu"; diff --git a/ElementX/Resources/Localizations/de.lproj/Localizable.strings b/ElementX/Resources/Localizations/de.lproj/Localizable.strings index 8e410678d5..cb55c8856e 100644 --- a/ElementX/Resources/Localizations/de.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/de.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Im Chatverlauf anzeigen"; "action_view_source" = "Quellcode anzeigen"; "action_yes" = "Ja"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Abmelden und aktualisieren"; "banner_migrate_to_native_sliding_sync_description" = "Dein Server unterstützt jetzt ein neues, schnelleres Protokoll. Melde dich ab und melde dich wieder an, um zu aktualisieren. Wenn du das jetzt tust, vermeidest du eine erzwungene Abmeldung, wenn das alte Protokoll später entfernt wird."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Dein Homeserver unterstützt das alte Protokoll nicht mehr. Bitte logge dich aus und melde dich wieder an, um die App weiter zu nutzen."; @@ -138,10 +139,13 @@ "common_creating_room" = "Raum wird erstellt..."; "common_current_user_left_room" = "Hat den Raum verlassen"; "common_dark" = "Dunkel"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Dekodierungsfehler"; "common_developer_options" = "Entwickleroptionen"; "common_device_id" = "Geräte-ID"; "common_direct_chat" = "Direktnachricht"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(bearbeitet)"; "common_editing" = "Bearbeitung"; "common_editing_caption" = "Bearbeitung der Bildunterschrift"; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Sind Sie sicher, dass Sie alle Beitrittsanfragen akzeptieren möchten?"; "screen_knock_requests_list_accept_all_alert_title" = "Akzeptiere alle Anfragen"; "screen_knock_requests_list_accept_all_button_title" = "Alle akzeptieren"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Ja, ablehnen und sperren"; "screen_knock_requests_list_ban_alert_description" = "Sind Sie sicher, dass Sie %1$@ ablehnen und sperren möchten ? Dieser Benutzer kann keinen erneuten Zugriff auf diesen Raum anfordern."; "screen_knock_requests_list_ban_alert_title" = "Ablehnen und Zugriff verbieten"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Ja, ablehnen"; "screen_knock_requests_list_decline_alert_description" = "Sind Sie sicher, dass Sie die %1$@ Anfrage, diesem Chatroom beizutreten, ablehnen möchten ?"; "screen_knock_requests_list_decline_alert_title" = "Zugriff verweigern"; "screen_knock_requests_list_decline_and_ban_action_title" = "Ablehnen und sperren"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "Falls jemand um Aufnahme in den Raum bittet, können Sie dessen Anfrage hier sehen."; "screen_knock_requests_list_empty_state_title" = "Keine ausstehende Beitrittsanfrage"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Beitrittsanfragen"; +"screen_media_details_file_format" = "Dateiformat"; +"screen_media_details_filename" = "Dateiname"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Hochgeladen von"; +"screen_media_details_uploaded_on" = "Hochgeladen am"; "screen_media_upload_preview_caption_warning" = "Bildunterschriften sind für Nutzer älterer Apps möglicherweise nicht sichtbar."; "screen_media_upload_preview_error_failed_processing" = "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuche es erneut."; "screen_media_upload_preview_error_failed_sending" = "Das Hochladen der Medien ist fehlgeschlagen. Bitte versuche es erneut."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "Ansicht"; "screen_room_details_pinned_events_row_title" = "Fixierte Nachrichten"; "screen_room_details_requests_to_join_title" = "Beitrittsanfragen"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Beitrittsanfrage gesendet"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Nachricht nicht gesendet, weil sich die verifizierte Identität von %1$@ geändert hat."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Nachricht wurde nicht gesendet, weil %1$@ nicht alle Geräte verifiziert hat"; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Die Nachricht wurde nicht gesendet, weil Sie eines oder mehrere Ihrer Geräte nicht verifiziert haben."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Gebe deine Daten ein"; "screen_login_title" = "Willkommen zurück!"; "screen_login_title_with_homeserver" = "Anmelden bei %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Dateien werden geladen…"; +"screen_media_browser_list_loading_media" = "Medien werden geladen…"; +"screen_media_browser_list_mode_files" = "Dateien"; +"screen_media_browser_list_mode_media" = "Medien"; +"screen_media_browser_media_empty_state_subtitle" = "In diesen Chatroom hochgeladene Bilder und Videos werden hier angezeigt."; +"screen_media_browser_media_empty_state_title" = "Noch keine Medien hochgeladen"; +"screen_media_browser_title" = "Medien und Dateien"; "screen_media_picker_error_failed_selection" = "Medienauswahl fehlgeschlagen, bitte versuche es erneut."; "screen_migration_message" = "Dies ist ein einmaliger Vorgang, danke fürs Warten."; "screen_migration_title" = "Dein Konto wird eingerichtet."; @@ -620,7 +667,7 @@ "screen_onboarding_sign_up" = "Konto erstellen"; "screen_onboarding_welcome_message" = "Willkommen beim schnellsten %1$@ aller Zeiten. Optimiert für Geschwindigkeit und Einfachheit."; "screen_onboarding_welcome_subtitle" = "Willkommen zu %1$@. Aufgeladen, für Geschwindigkeit und Einfachheit."; -"screen_onboarding_welcome_title" = "Sei in deinem Element"; +"screen_onboarding_welcome_title" = "Sei in Deinem Element"; "screen_polls_history_empty_ongoing" = "Keine laufenden Umfragen vorhanden."; "screen_polls_history_empty_past" = "Keine vergangenen Umfragen vorhanden."; "screen_polls_history_filter_ongoing" = "Aktuell"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten."; "screen_room_details_error_muting" = "Die Stummschaltung ist fehlgeschlagen, bitte versuche es erneut."; "screen_room_details_error_unmuting" = "Die Deaktivierung der Stummschaltung ist fehlgeschlagen, bitte versuche es erneut."; +"screen_room_details_media_gallery_title" = "Medien und Dateien"; "screen_room_details_notification_mode_custom" = "Benutzerdefiniert"; "screen_room_details_notification_mode_default" = "Standard"; "screen_room_details_share_room_title" = "Teilen"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ hat eine unbekannte Änderung vorgenommen"; "test_language_identifier" = "en"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Der Nachrichtenverlauf ist auf diesem Gerät nicht verfügbar"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Nachricht kann nicht entschlüsselt werden"; +"timeline_decryption_failure_withheld_unverified" = "Diese Nachricht wurde entweder blockiert, weil Ihr Gerät nicht verifiziert ist oder weil der Absender Ihre Identität überprüfen muss."; "troubleshoot_notifications_entry_point_section" = "Fehlerbehebung"; "troubleshoot_notifications_screen_action" = "Tests durchführen"; "troubleshoot_notifications_screen_action_again" = "Tests erneut durchführen"; diff --git a/ElementX/Resources/Localizations/el.lproj/Localizable.strings b/ElementX/Resources/Localizations/el.lproj/Localizable.strings index 4c56b70a3c..96ff133b6b 100644 --- a/ElementX/Resources/Localizations/el.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/el.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Προβολή στο χρονοδιάγραμμα"; "action_view_source" = "Προβολή πηγής"; "action_yes" = "Ναι"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Αποσύνδεση & Αναβάθμιση"; "banner_migrate_to_native_sliding_sync_description" = "Ο διακομιστής σου υποστηρίζει τώρα ένα νέο, ταχύτερο πρωτόκολλο. Αποσυνδέσου και συνδέσου ξανά για αναβάθμιση τώρα. Κάνοντας αυτό τώρα θα σε βοηθήσει να αποφύγεις μια αναγκαστική αποσύνδεση όταν το παλιό πρωτόκολλο καταργηθεί αργότερα."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Ο οικιακός διακομιστής σου δεν υποστηρίζει πλέον το παλιό πρωτόκολλο. Αποσυνδέσου και συνδέσου ξανά για να συνεχίσεις να χρησιμοποιείς την εφαρμογή."; @@ -138,10 +139,13 @@ "common_creating_room" = "Δημιουργία δωματίου..."; "common_current_user_left_room" = "Αποχώρησε από το δωμάτιο"; "common_dark" = "Σκοτεινό"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "Αυτό το μήνα"; "common_decryption_error" = "Σφάλμα αποκρυπτογράφησης"; "common_developer_options" = "Επιλογές προγραμματιστή"; "common_device_id" = "ID συσκευής"; "common_direct_chat" = "Άμεση συνομιλία"; +"common_downloading" = "Γίνεται λήψη"; "common_edited_suffix" = "(επεξεργάστηκε)"; "common_editing" = "Επεξεργάζεται"; "common_editing_caption" = "Η λεζάντα επεξεργάζεται"; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Σίγουρα θες να αποδεχτείς όλα τα αιτήματα συμμετοχής;"; "screen_knock_requests_list_accept_all_alert_title" = "Αποδοχή όλων των αιτημάτων"; "screen_knock_requests_list_accept_all_button_title" = "Αποδοχή όλων"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Αποδοχή όλων των αιτημάτων συμμετοχής"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Γίνεται αποδοχή αιτήματος συμμετοχής"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Ναι, απόρριψη και αποκλεισμός"; "screen_knock_requests_list_ban_alert_description" = "Σίγουρα θες να απορρίψειε και να αποκλείσεις τον χρήστη %1$@; Αυτός ο χρήστης δεν θα μπορεί να ζητήσει πρόσβαση για να συμμετάσχει ξανά σε αυτό το δωμάτιο."; "screen_knock_requests_list_ban_alert_title" = "Απόρριψη και αποκλεισμός πρόσβασης"; +"screen_knock_requests_list_ban_loading_title" = "Γίνεται απόρριψη και αποκλεισμός πρόσβασης"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Ναι, απόρριψη"; "screen_knock_requests_list_decline_alert_description" = "Σίγουρα θες να απορρίψεις το αίτημα του χρήστη %1$@ να συμμετάσχει στο δωμάτιο;"; "screen_knock_requests_list_decline_alert_title" = "Απόρριψη πρόσβασης"; "screen_knock_requests_list_decline_and_ban_action_title" = "Απόρριψη και αποκλεισμός"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Γίνεται απόρριψη αιτήματος συμμετοχής"; "screen_knock_requests_list_empty_state_description" = "Όταν κάποιος θα ζητήσει να συμμετάσχει στο δωμάτιο, θα μπορείς να δεις το αίτημά του εδώ."; "screen_knock_requests_list_empty_state_title" = "Δεν υπάρχει εκκρεμές αίτημα συμμετοχής"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Αιτήματα συμμετοχής"; +"screen_media_details_file_format" = "Μορφή αρχείου"; +"screen_media_details_filename" = "Όνομα αρχείου"; +"screen_media_details_redact_confirmation_message" = "Αυτό το αρχείο θα αφαιρεθεί από το δωμάτιο και τα μέλη δεν θα έχουν πρόσβαση σε αυτό."; +"screen_media_details_redact_confirmation_title" = "Διαγραφή αρχείου;"; +"screen_media_details_uploaded_by" = "Μεταφορτώθηκε από"; +"screen_media_details_uploaded_on" = "Μεταφορτώθηκε στις"; "screen_media_upload_preview_caption_warning" = "Οι λεζάντες ενδέχεται να μην είναι ορατές σε άτομα που χρησιμοποιούν παλαιότερες εφαρμογές."; "screen_media_upload_preview_error_failed_processing" = "Αποτυχία μεταφόρτωσης μέσου, δοκίμασε ξανά."; "screen_media_upload_preview_error_failed_sending" = "Αποτυχία μεταφόρτωσης πολυμέσων, δοκίμασε ξανά."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "Προβολή"; "screen_room_details_pinned_events_row_title" = "Καρφιτσωμένα μηνύματα"; "screen_room_details_requests_to_join_title" = "Αιτήματα συμμετοχής"; +"screen_room_details_security_and_privacy_title" = "Ασφάλεια & απόρρητο"; "screen_roomlist_knock_event_sent_description" = "Το αίτημα συμμετοχής στάλθηκε"; +"screen_security_and_privacy_ask_to_join_option_description" = "Οποιοσδήποτε μπορεί να ζητήσει να συμμετάσχει στο δωμάτιο, αλλά κάποιος διαχειριστής ή συντονιστής θα πρέπει να αποδεχθεί το αίτημα."; +"screen_security_and_privacy_ask_to_join_option_title" = "Αίτημα συμμετοχής"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Ναι, ενεργοποιήστε την κρυπτογράφηση"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Μόλις ενεργοποιηθεί, η κρυπτογράφηση για ένα δωμάτιο δεν μπορεί να απενεργοποιηθεί. Το ιστορικό μηνυμάτων θα είναι ορατό μόνο για τα μέλη του δωματίου από τότε που προσκλήθηκαν ή από τότε που εντάχθηκαν στην αίθουσα.\nΚανείς εκτός από τα μέλη του δωματίου δεν θα μπορεί να διαβάσει μηνύματα. Αυτό μπορεί να αποτρέψει τη σωστή λειτουργία των bots και των γεφυρών.\nΔεν συνιστούμε να ενεργοποιήσεις την κρυπτογράφηση για δωμάτια στα οποία μπορεί κανείς να βρει και να συμμετάσχει."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Ενεργοποίηση κρυπτογράφησης;"; +"screen_security_and_privacy_encryption_section_footer" = "Μόλις ενεργοποιηθεί, η κρυπτογράφηση δεν μπορεί να απενεργοποιηθεί."; +"screen_security_and_privacy_encryption_section_title" = "Κρυπτογράφηση"; +"screen_security_and_privacy_encryption_toggle_title" = "Ενεργοποίηση κρυπτογράφησης από άκρο σε άκρο"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Οποιοσδήποτε μπορεί να βρει και να συμμετάσχει"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Οποιοσδήποτε"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "Τα άτομα μπορούν να συμμετάσχουν μόνο εάν έχουν προσκληθεί"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Μόνο πρόσκληση"; +"screen_security_and_privacy_room_access_section_title" = "Πρόσβαση δωματίου"; +"screen_security_and_privacy_title" = "Ασφάλεια & απόρρητο"; "screen_timeline_item_menu_send_failure_changed_identity" = "Το μήνυμα δεν στάλθηκε επειδή η επαληθευμένη ταυτότητα του χρήστη %1$@ έχει αλλάξει."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Το μήνυμα δεν στάλθηκε επειδή ο χρήστης %1$@ δεν έχει επαληθεύσει όλες τις συσκευές."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Το μήνυμα δεν στάλθηκε επειδή δεν έχεις επαληθεύσει τουλάχιστον μία από τις συσκευές σου."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Εισήγαγε τα στοιχεία σου"; "screen_login_title" = "Καλωσόρισες ξανά!"; "screen_login_title_with_homeserver" = "Συνδέσου στο %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "Αυτό το αρχείο θα αφαιρεθεί από την αίθουσα και τα μέλη δεν θα έχουν πρόσβαση σε αυτό."; +"screen_media_browser_delete_confirmation_title" = "Διαγραφή αρχείου;"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Φόρτωση αρχείων..."; +"screen_media_browser_list_loading_media" = "Φόρτωση πολυμέσων…"; +"screen_media_browser_list_mode_files" = "Αρχεία"; +"screen_media_browser_list_mode_media" = "Πολυμέσα"; +"screen_media_browser_media_empty_state_subtitle" = "Εικόνες και βίντεο που μεταφορτώνονται σε αυτό το δωμάτιο θα εμφανίζονται εδώ."; +"screen_media_browser_media_empty_state_title" = "Δεν έχουν μεταφορτωθεί ακόμα πολυμέσα"; +"screen_media_browser_title" = "Πολυμέσα και αρχεία"; "screen_media_picker_error_failed_selection" = "Αποτυχία επιλογής πολυμέσου, δοκίμασε ξανά."; "screen_migration_message" = "Αυτή είναι μια εφάπαξ διαδικασία, ευχαριστώ που περίμενες."; "screen_migration_title" = "Ρύθμιση του λογαριασμού σου."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Παρουσιάστηκε σφάλμα κατά τη φόρτωση των ρυθμίσεων ειδοποίησης."; "screen_room_details_error_muting" = "Αποτυχία σίγασης αυτού του δωματίου, δοκίμασε ξανά."; "screen_room_details_error_unmuting" = "Αποτυχία κατάργησης σίγασης αυτού του δωματίου, δοκίμασε ξανά."; +"screen_room_details_media_gallery_title" = "Πολυμέσα και αρχεία"; "screen_room_details_notification_mode_custom" = "Προσαρμοσμένο"; "screen_room_details_notification_mode_default" = "Προεπιλογή"; "screen_room_details_share_room_title" = "Κοινή χρήση δωματίου"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "Ο χρήστης %1$@ έκανε μια άγνωστη αλλαγή στην ιδιότητα μέλους του."; "test_language_identifier" = "el"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Τα ιστορικά μηνύματα δεν είναι διαθέσιμα σε αυτήν τη συσκευή"; +"timeline_decryption_failure_historical_event_user_not_joined" = "Δεν έχεις πρόσβαση σε αυτό το μήνυμα"; +"timeline_decryption_failure_unable_to_decrypt" = "Δεν είναι δυνατή η αποκρυπτογράφηση μηνύματος"; +"timeline_decryption_failure_withheld_unverified" = "Αυτό το μήνυμα αποκλείστηκε είτε επειδή δεν επαλήθευσες τη συσκευή σου είτε επειδή ο αποστολέας πρέπει να επαληθεύσει την ταυτότητά σου."; "troubleshoot_notifications_entry_point_section" = "Αντιμετώπιση προβλημάτων"; "troubleshoot_notifications_screen_action" = "Εκτέλεση δοκιμών"; "troubleshoot_notifications_screen_action_again" = "Επανεκτέλεση δοκιμών"; diff --git a/ElementX/Resources/Localizations/en.lproj/InfoPlist.strings b/ElementX/Resources/Localizations/en.lproj/InfoPlist.strings index 47f84ab950..8c69574587 100644 --- a/ElementX/Resources/Localizations/en.lproj/InfoPlist.strings +++ b/ElementX/Resources/Localizations/en.lproj/InfoPlist.strings @@ -2,4 +2,4 @@ "NSFaceIDUsageDescription" = "Face ID is used to access your app."; "NSLocationWhenInUseUsageDescription" = "Grant location access so that Element X can share your location."; "NSMicrophoneUsageDescription" = "To record and send messages with audio, Element X needs to access the microphone."; -"NSPhotoLibraryUsageDescription" = "Allows saving photos and videos to your library."; +"NSPhotoLibraryUsageDescription" = "This lets you save images and videos to your photo library."; diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 9abc9ec077..63ab6a7c3b 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "View in timeline"; "action_view_source" = "View source"; "action_yes" = "Yes"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Log Out & Upgrade"; "banner_migrate_to_native_sliding_sync_description" = "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; @@ -138,10 +139,14 @@ "common_creating_room" = "Creating room…"; "common_current_user_left_room" = "Left room"; "common_dark" = "Dark"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Decryption error"; "common_developer_options" = "Developer options"; "common_device_id" = "Device ID"; "common_direct_chat" = "Direct chat"; +"common_download_failed" = "Download failed"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(edited)"; "common_editing" = "Editing"; "common_editing_caption" = "Editing caption"; @@ -156,6 +161,8 @@ "common_favourite" = "Favourite"; "common_favourited" = "Favourited"; "common_file" = "File"; +"common_file_deleted" = "File deleted"; +"common_file_saved" = "File saved"; "common_forward_message" = "Forward message"; "common_frequently_used" = "Frequently used"; "common_gif" = "GIF"; @@ -270,6 +277,7 @@ "dialog_permission_microphone_description_ios" = "Grant access so you can record and send messages with audio."; "dialog_permission_microphone_title_ios" = "%1$@ needs permission to access your microphone."; "dialog_permission_notification" = "In order to let the application display notifications, please grant the permission in the system settings."; +"dialog_permission_photo_library_title_ios" = "%1$@ does not have access to your photo library."; "dialog_title_confirmation" = "Confirmation"; "dialog_title_warning" = "Warning"; "dialog_unsaved_changes_description_ios" = "Your changes won’t be saved"; @@ -377,16 +385,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Failed processing media to upload, please try again."; "screen_media_upload_preview_error_failed_sending" = "Failed uploading media, please try again."; @@ -412,7 +437,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Pinned messages"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -586,6 +626,18 @@ "screen_login_form_header" = "Enter your details"; "screen_login_title" = "Welcome back!"; "screen_login_title_with_homeserver" = "Sign in to %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_download_error_message" = "Check your internet connection and try again."; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Failed selecting media, please try again."; "screen_migration_message" = "This is a one time process, thanks for waiting."; "screen_migration_title" = "Setting up your account."; @@ -743,6 +795,7 @@ "screen_room_details_error_loading_notification_settings" = "An error occurred when loading notification settings."; "screen_room_details_error_muting" = "Failed muting this room, please try again."; "screen_room_details_error_unmuting" = "Failed unmuting this room, please try again."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Custom"; "screen_room_details_notification_mode_default" = "Default"; "screen_room_details_share_room_title" = "Share room"; @@ -986,6 +1039,11 @@ "state_event_room_unknown_membership_change" = "%1$@ made an unknown change to their membership"; "test_language_identifier" = "en"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_unverified_device" = "You need to verify this device for access to historical messages"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Troubleshoot"; "troubleshoot_notifications_screen_action" = "Run tests"; "troubleshoot_notifications_screen_action_again" = "Run tests again"; diff --git a/ElementX/Resources/Localizations/es.lproj/Localizable.strings b/ElementX/Resources/Localizations/es.lproj/Localizable.strings index 1ac660bde8..a38421a904 100644 --- a/ElementX/Resources/Localizations/es.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/es.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "View in timeline"; "action_view_source" = "Ver Fuente"; "action_yes" = "Sí"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Log Out & Upgrade"; "banner_migrate_to_native_sliding_sync_description" = "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; @@ -138,10 +139,13 @@ "common_creating_room" = "Creando sala…"; "common_current_user_left_room" = "Saliste de la sala"; "common_dark" = "Oscuro"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Error de descifrado"; "common_developer_options" = "Opciones de desarrollador"; "common_device_id" = "Device ID"; "common_direct_chat" = "Chat directo"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(editado)"; "common_editing" = "Edición"; "common_editing_caption" = "Editing caption"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "Quitar sangría"; "rich_text_editor_url_placeholder" = "Enlace"; "rich_text_editor_a11y_add_attachment" = "Adjuntar archivo"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; "screen_advanced_settings_element_call_base_url" = "URL base personalizada de Element Call"; "screen_advanced_settings_element_call_base_url_description" = "Define una URL base personalizada para Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "URL no válida, asegúrate de incluir el protocolo (http/https) y la dirección correcta."; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Error al procesar el contenido multimedia, por favor inténtalo de nuevo."; "screen_media_upload_preview_error_failed_sending" = "Error al subir el contenido multimedia, por favor inténtalo de nuevo."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Pinned messages"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Introduce tus datos"; "screen_login_title" = "¡Hola de nuevo!"; "screen_login_title_with_homeserver" = "Iniciar sesión en %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Error al seleccionar archivos multimedia, por favor inténtalo de nuevo."; "screen_migration_message" = "Este proceso solo se hace una vez, gracias por esperar."; "screen_migration_title" = "Configura tu cuenta"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Se ha producido un error al cargar la configuración de las notificaciones."; "screen_room_details_error_muting" = "No se ha podido silenciar esta sala, inténtalo de nuevo."; "screen_room_details_error_unmuting" = "Error al dejar de silenciar esta sala, por favor inténtalo de nuevo."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Personalizado"; "screen_room_details_notification_mode_default" = "Por defecto"; "screen_room_details_share_room_title" = "Compartir sala"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ realizó un cambio desconocido en su membresía"; "test_language_identifier" = "es"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Troubleshoot"; "troubleshoot_notifications_screen_action" = "Run tests"; "troubleshoot_notifications_screen_action_again" = "Run tests again"; diff --git a/ElementX/Resources/Localizations/et.lproj/Localizable.strings b/ElementX/Resources/Localizations/et.lproj/Localizable.strings index ea7f3cd3f9..7e02880d5e 100644 --- a/ElementX/Resources/Localizations/et.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/et.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Vaata ajajoonel"; "action_view_source" = "Vaata lähtekoodi"; "action_yes" = "Jah"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Logi välja ja uuenda"; "banner_migrate_to_native_sliding_sync_description" = "Sinu koduserver toetab uut ja kiiremat protokolli. Uuendamiseks logi korraks rakendusest välja ja siis tagasi. Mingil hetkel tulevikus vana protokoll eemaldatakse kasutusest ja tehes uuenduse nüüd väldid hilisemat sundkorras uuendust."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Sinu koduserver enam ei toeta vana protokolli. Jätkamaks rakenduse kasutamist palun logi välja ning seejärel tagasi."; @@ -138,10 +139,13 @@ "common_creating_room" = "Loome jututoa…"; "common_current_user_left_room" = "Lahkus jututoast"; "common_dark" = "Tume"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "Sel kuul"; "common_decryption_error" = "Dekrüptimisviga"; "common_developer_options" = "Arendaja valikud"; "common_device_id" = "Seadme tunnus"; "common_direct_chat" = "Otsevestlus"; +"common_downloading" = "Laadime alla"; "common_edited_suffix" = "(muudetud)"; "common_editing" = "Muutmine"; "common_editing_caption" = "Muudame selgitust"; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Kas sa oled kindel, et soovid kõik vastu liitumist soovinud võtta?"; "screen_knock_requests_list_accept_all_alert_title" = "Võta kõik vastu"; "screen_knock_requests_list_accept_all_button_title" = "Nõustu kõigiga"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Jah, keeldu liitumisest ning keela ligipääs"; "screen_knock_requests_list_ban_alert_description" = "Kas sa oled kindel, et soovid kasutajale %1$@ keelata ligipääsu siia jututuppa ning seada talle suhtluskeelu? Seetõttu ta ei saa ka enam hiljem liitumispalvet saata."; "screen_knock_requests_list_ban_alert_title" = "Keeldu liitumisest ja keela ligipääs"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Jah, keeldu"; "screen_knock_requests_list_decline_alert_description" = "Kas sa oled kindel, et soovid kasutajale %1$@ keelata ligipääsu siia jututuppa?"; "screen_knock_requests_list_decline_alert_title" = "Keela ligipääs"; "screen_knock_requests_list_decline_and_ban_action_title" = "Keeldu ja määra suhtluskeeld"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "Kui keegi soovib jututoaga liituda, siis need päringud on kuvatud siin."; "screen_knock_requests_list_empty_state_title" = "Pole ühtegi liitumispalvet"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Liitumispalved"; +"screen_media_details_file_format" = "Failivorming"; +"screen_media_details_filename" = "Failinimi"; +"screen_media_details_redact_confirmation_message" = "Järgnevaga eemaldame selle faili jututoast ja tema liikmed enam ei pääse failile ligi."; +"screen_media_details_redact_confirmation_title" = "Kas kustutame faili?"; +"screen_media_details_uploaded_by" = "Üleslaadija"; +"screen_media_details_uploaded_on" = "Üleslaaditud"; "screen_media_upload_preview_caption_warning" = "Selgitused ja alapealkirjad ei pruugi olla nähtavad vanemate rakenduste kasutajatele."; "screen_media_upload_preview_error_failed_processing" = "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti."; "screen_media_upload_preview_error_failed_sending" = "Meediafaili üleslaadimine ei õnnestunud. Palun proovi uuesti."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "Vaata"; "screen_room_details_pinned_events_row_title" = "Esiletõstetud sõnumid"; "screen_room_details_requests_to_join_title" = "Liitumispalved"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Liitumispäring on saadetud"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Sõnum on saatmata, kuna kasutaja %1$@ verifitseeritud identiteet on muutunud."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Sõnum on saatmata, kuna %1$@ pole verifitseerinud kõiki oma seadmeid."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Kuna sa pole üks või enamgi oma seadet verifitseerinud, siis sinu sõnum on saatmata."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Sisesta oma andmed"; "screen_login_title" = "Tere tulemast tagasi!"; "screen_login_title_with_homeserver" = "Logi sisse serverisse %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "Järgnevaga eemaldame selle faili jututoast ka tema liikmed enam ei pääse failile ligi."; +"screen_media_browser_delete_confirmation_title" = "Kas kustutame faili?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Laadime faile…"; +"screen_media_browser_list_loading_media" = "Laadime meediat…"; +"screen_media_browser_list_mode_files" = "Failid"; +"screen_media_browser_list_mode_media" = "Meedia"; +"screen_media_browser_media_empty_state_subtitle" = "Antud jututuppa üleslaaditud pildid ja videod kuvatakse siin."; +"screen_media_browser_media_empty_state_title" = "Mitte keegi pole veel meediat üles laadinud"; +"screen_media_browser_title" = "Meedia ja failid"; "screen_media_picker_error_failed_selection" = "Meediafaili valimine ei õnnestunud. Palun proovi uuesti."; "screen_migration_message" = "Tänud, et ootad - seda toimingut on vaja teha vaid üks kord."; "screen_migration_title" = "Seadistame sinu kasutajakontot."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Teavituste seadistuste laadimisel tekkis viga."; "screen_room_details_error_muting" = "Selle jututoa summutamine ei õnnestunud. Palun proovi uuesti."; "screen_room_details_error_unmuting" = "Selle jututoa summutamise eemaldamine ei õnnestunud. Palun proovi uuesti."; +"screen_room_details_media_gallery_title" = "Meedia ja failid"; "screen_room_details_notification_mode_custom" = "Kohandatud"; "screen_room_details_notification_mode_default" = "Vaikimisi"; "screen_room_details_share_room_title" = "Jaga jututuba"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ tegi oma liikmelisuses teadmata muutatuse"; "test_language_identifier" = "et"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Vanu sõnumeid ei saa selles seadmes näha"; +"timeline_decryption_failure_historical_event_user_not_joined" = "Sul puudub ligipääs sellele sõnumile"; +"timeline_decryption_failure_unable_to_decrypt" = "Sõnumi dekrüptimine ei õnnestu"; +"timeline_decryption_failure_withheld_unverified" = "Kuna seade on verifitseerimata või saatja pole sind verifitseerinud, siis sõnumi näitamine on blokeeritud."; "troubleshoot_notifications_entry_point_section" = "Veaotsing"; "troubleshoot_notifications_screen_action" = "Käivita testid"; "troubleshoot_notifications_screen_action_again" = "Käivita testid uuesti"; diff --git a/ElementX/Resources/Localizations/fa.lproj/Localizable.strings b/ElementX/Resources/Localizations/fa.lproj/Localizable.strings index 03821d049a..30ac09ff7d 100644 --- a/ElementX/Resources/Localizations/fa.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fa.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "دیدن در خط زمانی"; "action_view_source" = "دیدن منبع"; "action_yes" = "بله"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "خروج و ارتقا"; "banner_migrate_to_native_sliding_sync_description" = "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; @@ -138,10 +139,13 @@ "common_creating_room" = "ایجاد کردن اتاق…"; "common_current_user_left_room" = "اتاق را ترک کرد"; "common_dark" = "تیره"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "خطای رمزگشایی"; "common_developer_options" = "گزینه‌های توسعه دهنده"; "common_device_id" = "Device ID"; "common_direct_chat" = "گپ مستقیم"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(ویراسته)"; "common_editing" = "ویرایش"; "common_editing_caption" = "Editing caption"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "تونرفتگی"; "rich_text_editor_url_placeholder" = "پیوند"; "rich_text_editor_a11y_add_attachment" = "افزودن پیوست"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; "screen_advanced_settings_element_call_base_url" = "نشانی پایهٔ تماس المنتی سفارشی"; "screen_advanced_settings_element_call_base_url_description" = "تنظمی نشانی پایه‌‌ای سفارشی برای تماس المنتی."; "screen_advanced_settings_element_call_base_url_validation_error" = "Invalid URL, please make sure you include the protocol (http/https) and the correct address."; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "پردازش رسانه برای بارگذاری شکست خورد. لطفاً دوباره تلاش کنید."; "screen_media_upload_preview_error_failed_sending" = "بارگذاری رسانه شکست خورد. لطفاً دوباره تلاش کنید."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "پیام‌های سنجاق شده"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "جزییاتتان را وارد کنید"; "screen_login_title" = "خوش برگشتید!"; "screen_login_title_with_homeserver" = "ورود به %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "گزینش رسانه شکست خورد. لطفاً دوباره تلاش کنید."; "screen_migration_message" = "فرایندی یک باره است. ممنون از شکیباییتان."; "screen_migration_title" = "برپایی حسابتان."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "An error occurred when loading notification settings."; "screen_room_details_error_muting" = "Failed muting this room, please try again."; "screen_room_details_error_unmuting" = "Failed unmuting this room, please try again."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "سفارشی"; "screen_room_details_notification_mode_default" = "پیش‌گزیده"; "screen_room_details_share_room_title" = "هم‌رسانی اتاق"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ تغییری نامعلوم در عضویتش داد"; "test_language_identifier" = "fa"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "رفع‌اشکال"; "troubleshoot_notifications_screen_action" = "اجرای آزمون‌ها"; "troubleshoot_notifications_screen_action_again" = "اجرای دوبارهٔ آزمون‌ها"; diff --git a/ElementX/Resources/Localizations/fi.lproj/Localizable.strings b/ElementX/Resources/Localizations/fi.lproj/Localizable.strings index 3c44d7e5ae..685d12793e 100644 --- a/ElementX/Resources/Localizations/fi.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fi.lproj/Localizable.strings @@ -22,7 +22,7 @@ "a11y_voice_message_record" = "Nauhoita ääniviesti."; "a11y_voice_message_stop_recording" = "Lopeta nauhoittaminen"; "action_accept" = "Hyväksy"; -"action_add_caption" = "Add caption"; +"action_add_caption" = "Lisää kuvateksti"; "action_add_to_timeline" = "Lisää aikajanalle"; "action_back" = "Takaisin"; "action_call" = "Soita"; @@ -36,10 +36,10 @@ "action_confirm_password" = "Vahvista salasana"; "action_continue" = "Jatka"; "action_copy" = "Kopioi"; -"action_copy_caption" = "Copy caption"; +"action_copy_caption" = "Kopioi kuvateksti"; "action_copy_link" = "Kopioi linkki"; "action_copy_link_to_message" = "Kopioi linkki viestiin"; -"action_copy_text" = "Copy text"; +"action_copy_text" = "Kopioi teksti"; "action_create" = "Luo"; "action_create_a_room" = "Luo huone"; "action_deactivate" = "Deaktivoi"; @@ -50,7 +50,7 @@ "action_discard" = "Hylkää"; "action_done" = "Valmis"; "action_edit" = "Muokkaa"; -"action_edit_caption" = "Edit caption"; +"action_edit_caption" = "Muokkaa kuvatekstiä"; "action_edit_poll" = "Muokkaa kyselyä"; "action_enable" = "Ota käyttöön"; "action_end_poll" = "Lopeta kysely"; @@ -85,8 +85,8 @@ "action_react" = "Reagoi"; "action_reject" = "Hylkää"; "action_remove" = "Poista"; -"action_remove_caption" = "Remove caption"; -"action_remove_message" = "Remove message"; +"action_remove_caption" = "Poista kuvateksti"; +"action_remove_message" = "Poista viesti"; "action_reply" = "Vastaa"; "action_reply_in_thread" = "Vastaa ketjuun"; "action_report_bug" = "Ilmoita virheestä"; @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Näytä aikajanalla"; "action_view_source" = "Näytä lähde"; "action_yes" = "Kyllä"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Kirjaudu Ulos & Päivitä"; "banner_migrate_to_native_sliding_sync_description" = "Palvelimesi tukee nyt uutta, nopeampaa protokollaa. Kirjaudu ulos ja takaisin sisään päivittääksesi nyt. Jos teet tämän nyt, voit välttää pakotetun uloskirjautumisen, kun vanha protokolla poistetaan myöhemmin."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Kotipalvelimesi ei enää tue vanhaa protokollaa. Kirjaudu ulos ja takaisin sisään jatkaaksesi sovelluksen käyttöä."; @@ -125,7 +126,7 @@ "banner_set_up_recovery_title" = "Ota palautus käyttöön tilisi suojaamiseksi"; "common_about" = "Tietoa"; "common_acceptable_use_policy" = "Hyväksyttävän käytön käytäntö"; -"common_adding_caption" = "Adding caption"; +"common_adding_caption" = "Lisätään kuvatekstiä"; "common_advanced_settings" = "Edistyneet asetukset"; "common_analytics" = "Analytiikka"; "common_appearance" = "Ulkoasu"; @@ -138,13 +139,16 @@ "common_creating_room" = "Luodaan huonetta..."; "common_current_user_left_room" = "Poistuit huoneesta"; "common_dark" = "Tumma"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Salauksen purkuvirhe"; "common_developer_options" = "Kehittäjän asetukset"; "common_device_id" = "Laitteen tunnus"; "common_direct_chat" = "Yksityinen keskustelu"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(muokattu)"; "common_editing" = "Muokataan viestiä"; -"common_editing_caption" = "Editing caption"; +"common_editing_caption" = "Muokataan kuvatekstiä"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Salaus"; "common_encryption_enabled" = "Salaus käytössä"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "Poista sisennys"; "rich_text_editor_url_placeholder" = "Linkki"; "rich_text_editor_a11y_add_attachment" = "Lisää liite"; -"rich_text_editor_composer_caption_placeholder" = "Valinnainen kuvateksti..."; +"rich_text_editor_composer_caption_placeholder" = "Lisää kuvateksti"; "screen_advanced_settings_element_call_base_url" = "Mukautettu Element Call URL-osoite"; "screen_advanced_settings_element_call_base_url_description" = "Aseta mukautettu URL-osoite Element Callille."; "screen_advanced_settings_element_call_base_url_validation_error" = "Virheellinen URL-osoite. Varmista, että sisällytät protokollan (http/https) ja oikean osoitteen."; @@ -373,21 +377,38 @@ "screen_join_room_knock_message_description" = "Viesti (valinnainen)"; "screen_join_room_knock_sent_description" = "Saat kutsun liittyä huoneeseen, jos pyyntösi hyväksytään."; "screen_join_room_knock_sent_title" = "Liittymispyyntö lähetetty"; -"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Yes, accept all"; -"screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; -"screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; -"screen_knock_requests_list_accept_all_button_title" = "Accept all"; -"screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; -"screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; -"screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; -"screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; -"screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; -"screen_knock_requests_list_decline_alert_title" = "Decline access"; -"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; -"screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; -"screen_knock_requests_list_empty_state_title" = "No pending request to join"; -"screen_knock_requests_list_title" = "Requests to join"; -"screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; +"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Kyllä, hyväksy kaikki"; +"screen_knock_requests_list_accept_all_alert_description" = "Haluatko varmasti hyväksyä kaikki liittymispyynnöt?"; +"screen_knock_requests_list_accept_all_alert_title" = "Hyväksy kaikki pyynnöt"; +"screen_knock_requests_list_accept_all_button_title" = "Hyväksy kaikki"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; +"screen_knock_requests_list_ban_alert_confirm_button_title" = "Kyllä, hylkää ja anna porttikielto"; +"screen_knock_requests_list_ban_alert_description" = "Haluatko varmasti hylätä käyttäjän %1$@ pyynnön liittyä huoneeseen ja antaa hänelle porttikiellon? Hän ei voi enää pyytää lupaa liittyä tähän huoneeseen."; +"screen_knock_requests_list_ban_alert_title" = "Hylkää ja anna porttikielto"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; +"screen_knock_requests_list_decline_alert_confirm_button_title" = "Kyllä, hylkää"; +"screen_knock_requests_list_decline_alert_description" = "Haluatko varmasti hylätä käyttäjän %1$@ pyynnön liittyä tähän huoneeseen?"; +"screen_knock_requests_list_decline_alert_title" = "Hylkää pyyntö"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Hylkää ja anna porttikielto"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; +"screen_knock_requests_list_empty_state_description" = "Kun joku pyytää liittyä huoneeseen, näet hänen pyyntönsä täällä."; +"screen_knock_requests_list_empty_state_title" = "Ei odottavia liittymispyyntöjä"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; +"screen_knock_requests_list_title" = "Liittymispyynnöt"; +"screen_media_details_file_format" = "Tiedostomuoto"; +"screen_media_details_filename" = "Tiedostonimi"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Lähettäjä:"; +"screen_media_details_uploaded_on" = "Lähetetty"; +"screen_media_upload_preview_caption_warning" = "Kuvatekstit eivät välttämättä näy ihmisille, jotka käyttävät vanhempia sovelluksia."; "screen_media_upload_preview_error_failed_processing" = "Median käsittely epäonnistui, yritä uudelleen."; "screen_media_upload_preview_error_failed_sending" = "Median lähettäminen epäonnistui, yritä uudelleen."; "screen_pinned_timeline_empty_state_description" = "Paina viestiä ja valitse “%1$@” lisätäksesi sen tänne."; @@ -402,17 +423,32 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Yksi tai useampi laitteistasi on vahvistamaton. Voit lähettää viestin silti tai peruuttaa sen toistaiseksi ja yrittää uudelleen myöhemmin, kun olet vahvistanut kaikki laitteesi."; "screen_resolve_send_failure_you_unsigned_device_title" = "Viestiäsi ei lähetetty, koska et ole vahvistanut yhtä tai useampaa laitettasi."; "screen_room_mentions_at_room_subtitle" = "Ilmoita koko huoneelle"; -"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; +"screen_room_multiple_knock_requests_view_all_button_title" = "Näytä kaikki"; "screen_room_pinned_banner_indicator" = "%1$@ / %2$@"; "screen_room_pinned_banner_indicator_description" = "Kiinnitetty viesti %1$@"; "screen_room_pinned_banner_loading_description" = "Viestiä ladataan..."; "screen_room_pinned_banner_view_all_button_title" = "Näytä kaikki"; -"screen_room_single_knock_request_accept_button_title" = "Accept"; -"screen_room_single_knock_request_title" = "%1$@ wants to join this room"; -"screen_room_single_knock_request_view_button_title" = "View"; +"screen_room_single_knock_request_accept_button_title" = "Hyväksy"; +"screen_room_single_knock_request_title" = "%1$@ haluaa liittyä tähän huoneeseen"; +"screen_room_single_knock_request_view_button_title" = "Näytä"; "screen_room_details_pinned_events_row_title" = "Kiinnitetyt viestit"; -"screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_requests_to_join_title" = "Liittymispyynnöt"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Liittymispyyntö lähetetty"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Viestiä ei lähetetty, koska käyttäjän %1$@ vahvistettu identiteetti on muuttunut."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Viestiä ei lähetetty, koska %1$@ ei ole vahvistanut kaikkia laitteitaan."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Viestiä ei lähetetty, koska et ole vahvistanut yhtä tai useampaa laitettasi."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Syötä tietosi"; "screen_login_title" = "Tervetuloa takaisin!"; "screen_login_title_with_homeserver" = "Kirjaudu sisään %1$@ -palvelimelle"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Ladataan tiedostoja..."; +"screen_media_browser_list_loading_media" = "Ladataan mediaa..."; +"screen_media_browser_list_mode_files" = "Tiedostot"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Tähän huoneeseen lähetetyt kuvat ja videot näytetään täällä."; +"screen_media_browser_media_empty_state_title" = "Mediaa ei ole vielä lähetetty"; +"screen_media_browser_title" = "Media ja tiedostot"; "screen_media_picker_error_failed_selection" = "Median valinta epäonnistui, yritä uudelleen."; "screen_migration_message" = "Tämä on kertaluonteinen prosessi, kiitos odottamisesta."; "screen_migration_title" = "Tiliä määritetään."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Ilmoitusasetuksia ladattaessa tapahtui virhe."; "screen_room_details_error_muting" = "Tämän huoneen mykistäminen epäonnistui, yritä uudelleen."; "screen_room_details_error_unmuting" = "Tämän huoneen mykistyksen poistaminen epäonnistui, yritä uudelleen."; +"screen_room_details_media_gallery_title" = "Media ja tiedostot"; "screen_room_details_notification_mode_custom" = "Mukautettu"; "screen_room_details_notification_mode_default" = "Oletus"; "screen_room_details_share_room_title" = "Jaa huone"; @@ -779,7 +827,7 @@ "screen_room_member_list_manage_member_user_info" = "Näytä profiili"; "screen_room_member_list_mode_banned" = "Porttikiellot"; "screen_room_member_list_mode_members" = "Jäsenet"; -"screen_room_member_list_pending_header_title" = "Kutsutut"; +"screen_room_member_list_pending_header_title" = "Kutsuttu"; "screen_room_member_list_removing_user" = "Poistetaan käyttäjää %1$@ huoneesta..."; "screen_room_member_list_role_administrator" = "Ylläpitäjä"; "screen_room_member_list_role_moderator" = "Valvoja"; @@ -860,7 +908,7 @@ "screen_session_verification_compare_numbers_subtitle" = "Varmista, että alla olevat numerot vastaavat toisessa istunnossa näkyviä numeroita."; "screen_session_verification_compare_numbers_title" = "Vertaa numeroita"; "screen_session_verification_complete_subtitle" = "Uusi kirjautumisesi on nyt vahvistettu. Sillä on pääsy salattuihin viesteihisi, ja muut käyttäjät näkevät sen luotettuna."; -"screen_session_verification_enter_recovery_key" = "Käytä palautusavainta"; +"screen_session_verification_enter_recovery_key" = "Syötä palautusavain"; "screen_session_verification_failed_subtitle" = "Joko pyyntö aikakatkaistiin, pyyntö hylättiin tai vahvistus ei täsmännyt."; "screen_session_verification_open_existing_session_subtitle" = "Vahvista, että se olet sinä, jotta näet aiemmat salatut viestisi."; "screen_session_verification_open_existing_session_title" = "Avaa laite, jossa olet jo kirjautuneena"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ teki tuntemattoman muutoksen jäsenyyteensä"; "test_language_identifier" = "fi"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Viestihistoria ei ole saatavilla tällä laitteella"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Viestin salauksen purkaminen ei onnistu"; +"timeline_decryption_failure_withheld_unverified" = "Tämä viesti estettiin, koska laitettasi ei ole vahvistettu tai koska lähettäjän on vahvistettava identiteettisi."; "troubleshoot_notifications_entry_point_section" = "Vianmääritys"; "troubleshoot_notifications_screen_action" = "Suorita testit"; "troubleshoot_notifications_screen_action_again" = "Suorita testit uudelleen"; @@ -1049,7 +1101,7 @@ "screen_blocked_users_unblock_alert_description" = "Näet jälleen kaikki heidän lähettämänsä viestit."; "screen_blocked_users_unblock_alert_title" = "Poista käyttäjän esto"; "screen_bug_report_rash_logs_alert_title" = "%1$@ kaatui edellisellä käyttökerralla. Haluatko jakaa virheraportin kanssamme?"; -"screen_chat_backup_recovery_action_confirm" = "Käytä palautusavainta"; +"screen_chat_backup_recovery_action_confirm" = "Syötä palautusavain"; "screen_chat_backup_recovery_action_setup" = "Ota palautus käyttöön"; "screen_create_poll_cancel_confirmation_content_ios" = "Muutoksiasi ei tallenneta"; "screen_create_room_add_people_title" = "Kutsu ihmisiä"; diff --git a/ElementX/Resources/Localizations/fi.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/fi.lproj/Localizable.stringsdict index 2b6e31e2ea..77970718a8 100644 --- a/ElementX/Resources/Localizations/fi.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/fi.lproj/Localizable.stringsdict @@ -237,9 +237,9 @@ NSStringFormatValueTypeKey d one - %1$@ +%2$d other want to join this room + %1$@ +%2$d muu haluavat liittyä tähän huoneeseen other - %1$@ +%2$d others want to join this room + %1$@ +%2$d muuta haluavat liittyä tähän huoneeseen screen_room_timeline_state_changes diff --git a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings index 2a9b6b1165..7d2af68eb0 100644 --- a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Voir dans la discussion"; "action_view_source" = "Afficher la source"; "action_yes" = "Oui"; +"action_yes_try_again" = "Oui, réessayez"; "banner_migrate_to_native_sliding_sync_action" = "Déconnecter et mettre à niveau"; "banner_migrate_to_native_sliding_sync_description" = "Votre serveur prend désormais en charge un nouveau protocole plus rapide. Déconnectez-vous, puis reconnectez-vous pour effectuer la mise à niveau dès maintenant. En le faisant tout de suite, vous éviterez une déconnexion forcée lorsque l'ancien protocole sera supprimé."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Votre serveur d’accueil ne prend plus en charge l'ancien protocole. Veuillez vous déconnecter puis vous reconnecter pour continuer à utiliser l'application."; @@ -138,10 +139,13 @@ "common_creating_room" = "Création du salon…"; "common_current_user_left_room" = "Quitter le salon"; "common_dark" = "Sombre"; +"common_date_date_at_time" = "%1$@ à %2$@"; +"common_date_this_month" = "Ce mois-ci"; "common_decryption_error" = "Erreur de déchiffrement"; "common_developer_options" = "Options pour les développeurs"; "common_device_id" = "Identifiant de session"; "common_direct_chat" = "Discussion à deux"; +"common_downloading" = "En cours de téléchargement"; "common_edited_suffix" = "(modifié)"; "common_editing" = "Édition"; "common_editing_caption" = "Modification de la légende"; @@ -215,7 +219,7 @@ "common_shared_location" = "Position partagée"; "common_signing_out" = "Déconnexion"; "common_something_went_wrong" = "Une erreur s'est produite"; -"common_starting_chat" = "Création de la discussion..."; +"common_starting_chat" = "Création de la discussion…"; "common_sticker" = "Autocollant"; "common_success" = "Succès"; "common_suggestions" = "Suggestions"; @@ -244,7 +248,7 @@ "common_verify_identity" = "Vérifier l'identité"; "common_video" = "Vidéo"; "common_voice_message" = "Message vocal"; -"common_waiting" = "En attente..."; +"common_waiting" = "En attente…"; "common_waiting_for_decryption_key" = "En attente de la clé de déchiffrement"; "common.copied_to_clipboard" = "Copié dans le presse-papiers"; "common.do_not_show_this_again" = "Ne plus afficher"; @@ -256,7 +260,7 @@ "common_unable_to_decrypt_verification_violation" = "L'identité vérifiée de l'expéditeur a changé"; "confirm_recovery_key_banner_message" = "Confirmez votre clé de récupération pour conserver l’accès à votre stockage de clés et à l’historique des messages."; "confirm_recovery_key_banner_primary_button_title" = "Saisissez votre clé de récupération"; -"confirm_recovery_key_banner_secondary_button_title" = "Clé de récupération oubliée?"; +"confirm_recovery_key_banner_secondary_button_title" = "Clé de récupération oubliée ?"; "confirm_recovery_key_banner_title" = "Le stockage de vos clés n'est pas synchronisé"; "crash_detection_dialog_content" = "%1$@ s’est arrêté la dernière fois qu’il a été utilisé. Souhaitez-vous partager un rapport d’incident avec nous ?"; "crypto_identity_change_pin_violation" = "L'identité de %1$@ semble avoir changé. %2$@"; @@ -273,7 +277,7 @@ "dialog_title_confirmation" = "Confirmation"; "dialog_title_warning" = "Attention"; "dialog_unsaved_changes_description_ios" = "Vos modifications ne seront pas enregistrées"; -"dialog_unsaved_changes_title" = "Enregistrer les changements?"; +"dialog_unsaved_changes_title" = "Enregistrer les changements ?"; "emoji_picker_category_activity" = "Activités"; "emoji_picker_category_flags" = "Drapeaux"; "emoji_picker_category_foods" = "Nourriture et boissons"; @@ -302,7 +306,7 @@ "full_screen_intent_banner_title" = "Améliorez votre expérience d'appel"; "invite_friends_rich_title" = "🔐️ Rejoignez-moi sur %1$@"; "invite_friends_text" = "Salut, parle-moi sur %1$@ : %2$@"; -"leave_conversation_alert_subtitle" = "Êtes-vous sûr de vouloir quitter cette discussion? Vous ne pourrez pas la rejoindre à nouveau sans y être invité."; +"leave_conversation_alert_subtitle" = "Êtes-vous sûr de vouloir quitter cette discussion ? Vous ne pourrez pas la rejoindre à nouveau sans y être invité."; "leave_room_alert_empty_subtitle" = "Êtes-vous sûr de vouloir quitter ce salon ? Vous êtes la seule personne ici. Si vous partez, personne ne pourra rejoindre le salon à l’avenir, y compris vous."; "leave_room_alert_private_subtitle" = "Êtes-vous sûr de vouloir quitter ce salon ? Ce salon n’est pas public et vous ne pourrez pas le rejoindre sans invitation."; "leave_room_alert_subtitle" = "Êtes-vous sûr de vouloir quitter le salon ?"; @@ -316,7 +320,7 @@ "notification_inline_reply_failed" = "** Échec de l’envoi - veuillez ouvrir le salon"; "notification_invite_body" = "Vous a invité(e) à discuter"; "notification_invite_body_with_sender" = "%1$@ vous a invité à discuter"; -"notification_mentioned_you_body" = "Mentionné(e): %1$@"; +"notification_mentioned_you_body" = "Mentionné(e) : %1$@"; "notification_new_messages" = "Nouveaux messages"; "notification_reaction_body" = "A réagi avec %1$@"; "notification_room_invite_body" = "Vous a invité(e) à rejoindre le salon"; @@ -330,11 +334,11 @@ "notification_unread_notified_messages_in_room" = "%1$@ dans %2$@"; "notification_unread_notified_messages_in_room_and_invitation" = "%1$@ dans %2$@ et %3$@"; "preference_rageshake" = "Rageshake pour signaler un problème"; -"rageshake_detection_dialog_content" = "Vous semblez secouez votre téléphone avec frustration. Souhaitez-vous ouvrir le formulaire pour reporter un problème?"; +"rageshake_detection_dialog_content" = "Vous semblez secouez votre téléphone avec frustration. Souhaitez-vous ouvrir le formulaire pour reporter un problème ?"; "rich_text_editor_bullet_list" = "Afficher une liste à puces"; "rich_text_editor_close_formatting_options" = "Fermer les options de formatage"; "rich_text_editor_code_block" = "Afficher le bloc de code"; -"rich_text_editor_composer_placeholder" = "Message..."; +"rich_text_editor_composer_placeholder" = "Message…"; "rich_text_editor_create_link" = "Créer un lien"; "rich_text_editor_edit_link" = "Modifier le lien"; "rich_text_editor_format_bold" = "Appliquer le format gras"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "Décaler vers la gauche"; "rich_text_editor_url_placeholder" = "Lien"; "rich_text_editor_a11y_add_attachment" = "Ajouter une pièce jointe"; -"rich_text_editor_composer_caption_placeholder" = "Légende facultative..."; +"rich_text_editor_composer_caption_placeholder" = "Légende facultative…"; "screen_advanced_settings_element_call_base_url" = "URL de base pour Element Call personnalisée"; "screen_advanced_settings_element_call_base_url_description" = "Configurer une URL de base pour Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "URL invalide, assurez-vous d’inclure le protocol (http/https) et l’adresse correcte."; @@ -368,25 +372,42 @@ "screen_create_room_room_visibility_section_title" = "Visibilité du salon"; "screen_join_room_cancel_knock_action" = "Annuler la demande"; "screen_join_room_cancel_knock_alert_confirmation" = "Oui, annuler"; -"screen_join_room_cancel_knock_alert_description" = "Êtes-vous sûr de vouloir annuler votre demande d'accès à ce salon?"; +"screen_join_room_cancel_knock_alert_description" = "Êtes-vous sûr de vouloir annuler votre demande d'accès à ce salon ?"; "screen_join_room_cancel_knock_alert_title" = "Annuler la demande d'adhésion"; "screen_join_room_knock_message_description" = "Message (facultatif)"; "screen_join_room_knock_sent_description" = "Vous recevrez une invitation à rejoindre le salon si votre demande est acceptée."; "screen_join_room_knock_sent_title" = "Demande de rejoindre le salon envoyée"; "screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Oui, tout accepter"; -"screen_knock_requests_list_accept_all_alert_description" = "Êtes-vous sûr de vouloir accepter toutes les demandes pour rejoindre le salon ?"; +"screen_knock_requests_list_accept_all_alert_description" = "Êtes-vous sûr de vouloir accepter toutes les demandes pour rejoindre le salon ?"; "screen_knock_requests_list_accept_all_alert_title" = "Tout accepter"; "screen_knock_requests_list_accept_all_button_title" = "Tout accepter"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "Toutes les demandes n'ont pas pu être acceptées. Voulez-vous réessayer ?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Toutes les demandes n'ont pas été acceptées"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepter toutes les demandes à rejoindre"; +"screen_knock_requests_list_accept_failed_alert_description" = "La demande n'a pas pu être acceptée. Voulez-vous réessayer ?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Impossible d'accepter la demande"; +"screen_knock_requests_list_accept_loading_title" = "Accepter la demande à rejoindre"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Oui, rejeter et bannir"; -"screen_knock_requests_list_ban_alert_description" = "Êtes-vous sûr de vouloir rejeter la demande et bannir %1$@? Cet utilisateur ne pourra pas demander à nouveau à rejoindre ce salon."; +"screen_knock_requests_list_ban_alert_description" = "Êtes-vous sûr de vouloir rejeter la demande et bannir %1$@ ? Cet utilisateur ne pourra pas demander à nouveau à rejoindre ce salon."; "screen_knock_requests_list_ban_alert_title" = "Refuser et interdire l'accès"; +"screen_knock_requests_list_ban_loading_title" = "En cours de traitement…"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Oui, refuser"; -"screen_knock_requests_list_decline_alert_description" = "Êtes-vous sûr de vouloir refuser la demande de %1$@ à rejoindre le salon?"; +"screen_knock_requests_list_decline_alert_description" = "Êtes-vous sûr de vouloir refuser la demande de %1$@ à rejoindre le salon ?"; "screen_knock_requests_list_decline_alert_title" = "Refuser l'accès"; "screen_knock_requests_list_decline_and_ban_action_title" = "Refuser et bannir"; +"screen_knock_requests_list_decline_failed_alert_description" = "Nous n'avons pas pu refuser cette demande. Voulez-vous réessayer ?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Echec"; +"screen_knock_requests_list_decline_loading_title" = "Traitement en cours…"; "screen_knock_requests_list_empty_state_description" = "Lorsque quelqu'un demandera à rejoindre le salon, vous pourrez voir sa demande ici."; "screen_knock_requests_list_empty_state_title" = "Personne ne demande à rejoindre le salon"; +"screen_knock_requests_list_initial_loading_title" = "Chargement..."; "screen_knock_requests_list_title" = "Demandes en attente"; +"screen_media_details_file_format" = "Format du fichier"; +"screen_media_details_filename" = "Nom du fichier"; +"screen_media_details_redact_confirmation_message" = "Ce fichier sera supprimé du salon et les membres n'y auront plus accès."; +"screen_media_details_redact_confirmation_title" = "Supprimer le fichier ?"; +"screen_media_details_uploaded_by" = "Envoyé par"; +"screen_media_details_uploaded_on" = "Envoyé le"; "screen_media_upload_preview_caption_warning" = "Les légendes peuvent ne pas être visibles pour les utilisateurs d'anciennes applications."; "screen_media_upload_preview_error_failed_processing" = "Échec du traitement des médias à télécharger, veuillez réessayer."; "screen_media_upload_preview_error_failed_sending" = "Échec du téléchargement du média, veuillez réessayer."; @@ -405,14 +426,29 @@ "screen_room_multiple_knock_requests_view_all_button_title" = "Tout afficher"; "screen_room_pinned_banner_indicator" = "%1$@ sur %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Messages épinglés"; -"screen_room_pinned_banner_loading_description" = "Chargement du message..."; +"screen_room_pinned_banner_loading_description" = "Chargement du message…"; "screen_room_pinned_banner_view_all_button_title" = "Voir tout"; "screen_room_single_knock_request_accept_button_title" = "Accepter"; "screen_room_single_knock_request_title" = "%1$@ souhaite rejoindre ce salon"; "screen_room_single_knock_request_view_button_title" = "Voir"; "screen_room_details_pinned_events_row_title" = "Messages épinglés"; "screen_room_details_requests_to_join_title" = "Demandes en attente"; +"screen_room_details_security_and_privacy_title" = "Sécurité & confidentialité"; "screen_roomlist_knock_event_sent_description" = "Demande d'adhésion envoyée"; +"screen_security_and_privacy_ask_to_join_option_description" = "N'importe qui peut demander à rejoindre le salon, mais un administrateur ou un modérateur devra accepter la demande."; +"screen_security_and_privacy_ask_to_join_option_title" = "Demander à rejoindre"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Oui, activer le chiffrement"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Une fois activé, le chiffrement d'un salon ne peut pas être désactivé. L'historique des messages ne sera visible que pour les membres depuis qu'ils ont été invités ou depuis qu'ils ont rejoint le salon.\nPersonne d'autre que les membres du salon ne pourra lire les messages. Cela peut empêcher les bots et les bridges de fonctionner correctement.\nNous ne recommandons pas d'activer le chiffrement pour les salons que tout le monde peut trouver et rejoindre."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Activer le chiffrement ?"; +"screen_security_and_privacy_encryption_section_footer" = "Une fois activé, le chiffrement ne peut pas être désactivé."; +"screen_security_and_privacy_encryption_section_title" = "Chiffrement"; +"screen_security_and_privacy_encryption_toggle_title" = "Activer le chiffrement de bout en bout"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Tout le monde peut le trouver et le rejoindre"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Tout le monde"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "Le salon ne peut être joint que par les personnes invitées"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Sur invitation uniquement"; +"screen_security_and_privacy_room_access_section_title" = "Accès au salon"; +"screen_security_and_privacy_title" = "Sécurité & confidentialité"; "screen_timeline_item_menu_send_failure_changed_identity" = "Le message n'a pas été envoyé car l'identité vérifiée de %1$@ a changé."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Le message n'a pas été envoyé car %1$@ n'a pas vérifié tous ses appareils."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message non envoyé car vous n'avez pas vérifié tous vos appareils."; @@ -443,15 +479,15 @@ "screen_app_lock_biometric_authentication" = "l'authentification biométrique"; "screen_app_lock_biometric_unlock" = "déverrouillage biométrique"; "screen_app_lock_biometric_unlock_reason_ios" = "Veuillez vous authentification pour accéder à l’application"; -"screen_app_lock_forgot_pin" = "Code PIN oublié?"; +"screen_app_lock_forgot_pin" = "Code PIN oublié ?"; "screen_app_lock_settings_change_pin" = "Modifier le code PIN"; "screen_app_lock_settings_enable_biometric_unlock" = "Autoriser le déverrouillage biométrique"; "screen_app_lock_settings_enable_face_id_ios" = "Autoriser Face ID"; "screen_app_lock_settings_enable_optic_id_ios" = "Autoriser Optic ID"; "screen_app_lock_settings_enable_touch_id_ios" = "Autoriser Touch ID"; "screen_app_lock_settings_remove_pin" = "Supprimer le code PIN"; -"screen_app_lock_settings_remove_pin_alert_message" = "Êtes-vous certain de vouloir supprimer le code PIN?"; -"screen_app_lock_settings_remove_pin_alert_title" = "Supprimer le code PIN?"; +"screen_app_lock_settings_remove_pin_alert_message" = "Êtes-vous certain de vouloir supprimer le code PIN ?"; +"screen_app_lock_settings_remove_pin_alert_title" = "Supprimer le code PIN ?"; "screen_app_lock_setup_biometric_unlock_allow_title" = "Autoriser %1$@"; "screen_app_lock_setup_biometric_unlock_skip" = "Je préfère utiliser le code PIN"; "screen_app_lock_setup_biometric_unlock_subtitle" = "Gagnez du temps en utilisant %1$@ pour déverrouiller l’application à chaque fois."; @@ -500,7 +536,7 @@ "screen_chat_backup_recovery_action_change" = "Changer la clé de récupération"; "screen_chat_backup_recovery_action_change_description" = "Récupérez votre identité cryptographique et l'historique de vos messages à l'aide d'une clé de récupération si vous avez perdu tous vos appareils existants."; "screen_chat_backup_recovery_action_confirm_description" = "Le stockage de vos clés est actuellement désynchronisé."; -"screen_chat_backup_recovery_action_setup_description" = "Accédez à vos messages chiffrés si vous perdez tous vos appareils ou que vous êtes déconnectés de %1$@ partout."; +"screen_chat_backup_recovery_action_setup_description" = "Accédez à vos messages chiffrés si vous perdez tous vos appareils ou que vous êtes déconnecté de %1$@ partout."; "screen_create_account_title" = "Créer un compte"; "screen_create_new_recovery_key_list_item_1" = "Ouvrez %1$@ sur un ordinateur"; "screen_create_new_recovery_key_list_item_2" = "Connectez-vous à nouveau à votre compte"; @@ -527,7 +563,7 @@ "screen_deactivate_account_confirmation_dialog_content" = "Veuillez confirmer que vous souhaitez désactiver votre compte. Cette action ne peut pas être annulée."; "screen_deactivate_account_delete_all_messages" = "Supprimer tous mes messages"; "screen_deactivate_account_delete_all_messages_notice" = "Attention : les futurs utilisateurs pourraient voir des conversations incomplètes."; -"screen_deactivate_account_description" = "La désactivation de votre compte est %1$@, cela va:"; +"screen_deactivate_account_description" = "La désactivation de votre compte est %1$@, cela va :"; "screen_deactivate_account_description_bold_part" = "irréversible"; "screen_deactivate_account_list_item_1" = "%1$@ votre compte (vous ne pourrez plus vous reconnecter et votre identifiant ne pourra pas être réutilisé)."; "screen_deactivate_account_list_item_1_bold_part" = "Désactiver définitivement"; @@ -535,13 +571,13 @@ "screen_deactivate_account_list_item_3" = "Supprimer les informations de votre compte du serveur d'identité."; "screen_deactivate_account_list_item_4" = "Rendre vos messages invisibles aux futurs membres des salons si vous choisissez de les supprimer. Vos messages seront toujours visibles pour les utilisateurs qui les ont déjà récupérés."; "screen_deactivate_account_title" = "Désactiver votre compte"; -"screen_edit_poll_delete_confirmation" = "Êtes-vous certain de vouloir supprimer ce sondage?"; +"screen_edit_poll_delete_confirmation" = "Êtes-vous certain de vouloir supprimer ce sondage ?"; "screen_edit_profile_display_name" = "Pseudonyme"; "screen_edit_profile_display_name_placeholder" = "Votre pseudonyme"; "screen_edit_profile_error" = "Une erreur inconnue s’est produite et les informations n’ont pas pu être modifiées."; "screen_edit_profile_error_title" = "Impossible de mettre à jour le profil"; "screen_edit_profile_title" = "Modifier le profil"; -"screen_edit_profile_updating_details" = "Mise à jour du profil..."; +"screen_edit_profile_updating_details" = "Mise à jour du profil…"; "screen_encryption_reset_action_continue_reset" = "Continuer la réinitialisation"; "screen_encryption_reset_bullet_1" = "Les détails de votre compte, vos contacts, vos préférences et votre liste de discussions seront conservés"; "screen_encryption_reset_bullet_2" = "Vous perdrez l’historique de vos messages"; @@ -569,15 +605,15 @@ "screen_join_room_space_not_supported_title" = "Les Spaces ne sont pas encore pris en charge"; "screen_join_room_subtitle_knock" = "Cliquez ci-dessous et un administrateur sera prévenu. Une fois votre demande approuvée, pour pourrez rejoindre la discussion."; "screen_join_room_subtitle_no_preview" = "Vous devez être un membre du salon pour pouvoir lire l'historique des messages."; -"screen_join_room_title_knock" = "Vous souhaitez rejoindre ce salon?"; +"screen_join_room_title_knock" = "Vous souhaitez rejoindre ce salon ?"; "screen_join_room_title_no_preview" = "La prévisualisation n'est pas disponible"; "screen_key_backup_disable_confirmation_action_turn_off" = "Désactiver"; "screen_key_backup_disable_confirmation_description" = "Vous perdrez vos messages chiffrés si vous vous déconnectez de toutes vos sessions."; -"screen_key_backup_disable_confirmation_title" = "Êtes-vous certain de vouloir désactiver la sauvegarde?"; -"screen_key_backup_disable_description" = "Désactiver la sauvegarde supprimera votre clé de récupération actuelle et désactivera d’autres mesures de sécurité. Dans ce cas:"; +"screen_key_backup_disable_confirmation_title" = "Êtes-vous certain de vouloir désactiver la sauvegarde ?"; +"screen_key_backup_disable_description" = "Désactiver la sauvegarde supprimera votre clé de récupération actuelle et désactivera d’autres mesures de sécurité. Dans ce cas :"; "screen_key_backup_disable_description_point_1" = "Pas d’accès à l’historique des discussions chiffrées sur vos nouveaux appareils"; -"screen_key_backup_disable_description_point_2" = "Perte de l’accès à vos messages chiffrés si vous êtes déconnectés de %1$@ partout"; -"screen_key_backup_disable_title" = "Êtes-vous certain de vouloir désactiver la sauvegarde?"; +"screen_key_backup_disable_description_point_2" = "Perte de l’accès à vos messages chiffrés si vous êtes déconnecté de %1$@ partout"; +"screen_key_backup_disable_title" = "Êtes-vous certain de vouloir désactiver la sauvegarde ?"; "screen_login_error_deactivated_account" = "Ce compte a été désactivé."; "screen_login_error_invalid_credentials" = "Nom d’utilisateur et/ou mot de passe incorrects"; "screen_login_error_invalid_user_id" = "Il ne s’agit pas d’un identifiant utilisateur valide. Format attendu : « @user:homeserver.org »"; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Saisissez vos identifiants\n(sous la forme paul.lagent-beta.gouv.fr)"; // Tchap "screen_login_title" = "Content de vous revoir !"; "screen_login_title_with_homeserver" = "Connectez-vous à %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "Ce fichier sera supprimé du salon et les membres n'y auront plus accès."; +"screen_media_browser_delete_confirmation_title" = "Supprimer le fichier ?"; +"screen_media_browser_files_empty_state_subtitle" = "Les documents, les fichiers audio et les messages vocaux envoyés dans ce salon seront affichés ici."; +"screen_media_browser_files_empty_state_title" = "Aucun fichier n'a encore été envoyé"; +"screen_media_browser_list_loading_files" = "Chargement des fichiers…"; +"screen_media_browser_list_loading_media" = "Chargement des médias…"; +"screen_media_browser_list_mode_files" = "Fichiers"; +"screen_media_browser_list_mode_media" = "Média"; +"screen_media_browser_media_empty_state_subtitle" = "Les images et vidéos envoyées dans ce salon seront affichées ici."; +"screen_media_browser_media_empty_state_title" = "Aucun média n'a encore été envoyé dans ce salon"; +"screen_media_browser_title" = "Médias et fichiers"; "screen_media_picker_error_failed_selection" = "Échec de la sélection du média, veuillez réessayer."; "screen_migration_message" = "Il s’agit d’une opération ponctuelle, merci d’attendre quelques instants."; "screen_migration_title" = "Configuration de votre compte."; @@ -669,14 +716,14 @@ "screen_recovery_key_change_description" = "Obtenez une nouvelle clé de récupération dans le cas où vous avez oublié l’ancienne. Après le changement, l’ancienne clé ne sera plus utilisable."; "screen_recovery_key_change_generate_key" = "Générer une nouvelle clé"; "screen_recovery_key_change_success" = "Clé de récupération modifée"; -"screen_recovery_key_change_title" = "Changer la clé de récupération?"; +"screen_recovery_key_change_title" = "Changer la clé de récupération ?"; "screen_recovery_key_confirm_create_new_recovery_key" = "Créer une nouvelle clé de récupération"; -"screen_recovery_key_confirm_description" = "Assurez vous que personne d'autre ne regarde votre écran!"; +"screen_recovery_key_confirm_description" = "Assurez vous que personne d'autre ne regarde votre écran !"; "screen_recovery_key_confirm_error_content" = "Veuillez réessayer pour confirmer l'accès à votre stockage de clés."; "screen_recovery_key_confirm_error_title" = "Clé de récupération incorrecte"; "screen_recovery_key_confirm_key_description" = "Si vous avez une clé de sécurité ou une phrase de sécurité, cela fonctionnera également."; "screen_recovery_key_confirm_key_placeholder" = "Saisissez la clé ici…"; -"screen_recovery_key_confirm_lost_recovery_key" = "Clé de récupération perdue?"; +"screen_recovery_key_confirm_lost_recovery_key" = "Clé de récupération perdue ?"; "screen_recovery_key_confirm_success" = "Clé de récupération confirmée"; "screen_recovery_key_copied_to_clipboard" = "Clé de récupération copiée"; "screen_recovery_key_generating_key" = "Génération…"; @@ -685,7 +732,7 @@ "screen_recovery_key_save_key_description" = "Taper pour copier la clé"; "screen_recovery_key_save_title" = "Sauvegarder la clé"; "screen_recovery_key_setup_confirmation_description" = "La clé ne pourra plus être affichée après cette étape."; -"screen_recovery_key_setup_confirmation_title" = "Avez-vous sauvegardé votre clé de récupération?"; +"screen_recovery_key_setup_confirmation_title" = "Avez-vous sauvegardé votre clé de récupération ?"; "screen_recovery_key_setup_description" = "Votre sauvegarde est protégée par votre clé de récupération. Si vous avez besoin d’une nouvelle clé après la configuration, vous pourrez en créer une nouvelle en cliquant sur \"Changer la clé de récupération\"."; "screen_recovery_key_setup_generate_key" = "Générer la clé de récupération"; "screen_recovery_key_setup_generate_key_description" = "Ne partagez cela avec personne !"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Une erreur s’est produite lors du chargement des paramètres de notification."; "screen_room_details_error_muting" = "Échec de la mise en sourdine de ce salon, veuillez réessayer."; "screen_room_details_error_unmuting" = "Échec de la désactivation de la mise en sourdine de ce salon, veuillez réessayer."; +"screen_room_details_media_gallery_title" = "Médias et fichiers"; "screen_room_details_notification_mode_custom" = "Personnalisé"; "screen_room_details_notification_mode_default" = "Défaut"; "screen_room_details_share_room_title" = "Partager le salon"; @@ -766,7 +814,7 @@ "screen_room_member_details_verify_button_title" = "Vérifier %1$@"; "screen_room_member_list_ban_member_confirmation_action" = "Bannir"; "screen_room_member_list_ban_member_confirmation_description" = "L‘utilisateur ne pourra pas rejoindre le salon à nouveau, même si il est invité."; -"screen_room_member_list_ban_member_confirmation_title" = "Êtes-vous certain de vouloir bannir ce membre?"; +"screen_room_member_list_ban_member_confirmation_title" = "Êtes-vous certain de vouloir bannir ce membre ?"; "screen_room_member_list_banned_empty" = "Il n’y a pas d’utilisateur banni dans ce salon."; "screen_room_member_list_banning_user" = "Bannissement de %1$@"; "screen_room_member_list_manage_member_ban" = "Retirer et bannir ce membre"; @@ -810,7 +858,7 @@ "screen_room_roles_and_permissions_permissions_header" = "Autorisations"; "screen_room_roles_and_permissions_reset" = "Réinitialisation des autorisations"; "screen_room_roles_and_permissions_reset_confirm_description" = "La réinitialisation des autorisations entraîne la perte des réglages actuels."; -"screen_room_roles_and_permissions_reset_confirm_title" = "Réinitialisation des autorisations?"; +"screen_room_roles_and_permissions_reset_confirm_title" = "Réinitialisation des autorisations ?"; "screen_room_roles_and_permissions_roles_header" = "Rôles"; "screen_room_roles_and_permissions_room_details" = "Détails du salon"; "screen_room_roles_and_permissions_title" = "Rôles et autorisations"; @@ -844,7 +892,7 @@ "screen_roomlist_filter_rooms" = "Salons"; "screen_roomlist_filter_rooms_empty_state_title" = "Vous n’êtes membre d’aucun salon"; "screen_roomlist_filter_unreads" = "Non-lus"; -"screen_roomlist_filter_unreads_empty_state_title" = "Félicitations!\nVous n’avez plus de messages non-lus!"; +"screen_roomlist_filter_unreads_empty_state_title" = "Félicitations !\nVous n’avez plus de messages non-lus !"; "screen_roomlist_main_space_title" = "Conversations"; "screen_roomlist_mark_as_read" = "Marquer comme lu"; "screen_roomlist_mark_as_unread" = "Marquer comme non lu"; @@ -866,7 +914,7 @@ "screen_session_verification_open_existing_session_title" = "Ouvrir une session existante"; "screen_session_verification_positive_button_canceled" = "Réessayer la vérification"; "screen_session_verification_positive_button_initial" = "Je suis prêt.e"; -"screen_session_verification_positive_button_verifying_ongoing" = "En attente de correspondance"; +"screen_session_verification_positive_button_verifying_ongoing" = "En attente de correspondance…"; "screen_session_verification_ready_subtitle" = "Comparer un groupe unique d’Emojis."; "screen_session_verification_request_accepted_subtitle" = "Comparez les emoji uniques en veillant à ce qu’ils apparaissent dans le même ordre."; "screen_session_verification_request_details_timestamp" = "Connecté"; @@ -896,7 +944,7 @@ "screen_signed_out_subtitle" = "La déconnexion peut être due à une des raisons ci-dessous. Veuillez vous connecter à nouveau pour continuer à utiliser %@."; "screen_signed_out_title" = "Vous avez été déconnecté"; "screen_signout_confirmation_dialog_content" = "Êtes-vous sûr de vouloir vous déconnecter ?"; -"screen_signout_in_progress_dialog_content" = "Déconnexion..."; +"screen_signout_in_progress_dialog_content" = "Déconnexion…"; "screen_signout_key_backup_disabled_subtitle" = "Vous êtes en train de vous déconnecter de votre dernière session. Si vous vous déconnectez maintenant, vous perdrez l’accès à l’historique de vos discussions chiffrées."; "screen_signout_key_backup_disabled_title" = "Vous avez désactivé la sauvegarde"; "screen_signout_key_backup_offline_subtitle" = "Vos clés étaient en cours de sauvegarde lorsque vous avez perdu la connexion au réseau. Il faudrait rétablir cette connexion afin de pouvoir terminer la sauvegarde avant de vous déconnecter."; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ a effectué un changement inconnu à son adhésion"; "test_language_identifier" = "fr"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Les anciens messages ne sont pas disponibles sur cet appareil"; +"timeline_decryption_failure_historical_event_user_not_joined" = "Vous n'avez pas accès à ce message"; +"timeline_decryption_failure_unable_to_decrypt" = "Impossible de déchiffrer le message"; +"timeline_decryption_failure_withheld_unverified" = "Ce message a été bloqué soit parce que vous n'avez pas vérifié votre session, soit parce que l'expéditeur doit vérifier votre identité."; "troubleshoot_notifications_entry_point_section" = "Dépannage"; "troubleshoot_notifications_screen_action" = "Exécuter les tests"; "troubleshoot_notifications_screen_action_again" = "Relancer les tests"; @@ -1007,7 +1059,7 @@ "troubleshoot_notifications_test_display_notification_description" = "Vérifier que l’application peut afficher des notifications."; "troubleshoot_notifications_test_display_notification_failure" = "Vous n’avez pas cliqué sur la notification."; "troubleshoot_notifications_test_display_notification_permission_failure" = "Impossible d'afficher la notification."; -"troubleshoot_notifications_test_display_notification_success" = "Vous avez cliqué sur la notification!"; +"troubleshoot_notifications_test_display_notification_success" = "Vous avez cliqué sur la notification !"; "troubleshoot_notifications_test_display_notification_title" = "Affichage des notifications"; "troubleshoot_notifications_test_display_notification_waiting" = "Veuillez cliquer sur la notification pour continuer le test."; "troubleshoot_notifications_test_firebase_availability_description" = "Vérification que Firebase est disponible."; @@ -1079,7 +1131,7 @@ "screen_room_change_role_section_administrators" = "Administrateurs"; "screen_room_change_role_section_moderators" = "Modérateurs"; "screen_room_change_role_section_users" = "Membres"; -"screen_room_change_role_unsaved_changes_title" = "Enregistrer les changements?"; +"screen_room_change_role_unsaved_changes_title" = "Enregistrer les changements ?"; "screen_room_details_invite_people_title" = "Inviter des amis"; "screen_room_details_leave_conversation_title" = "Quitter la discussion"; "screen_room_details_leave_room_title" = "Quitter le salon"; @@ -1099,5 +1151,5 @@ "screen_signout_confirmation_dialog_title" = "Se déconnecter"; "screen_signout_key_backup_offline_title" = "Vos clés sont en cours de sauvegarde"; "screen_signout_preference_item" = "Se déconnecter"; -"screen_signout_save_recovery_key_title" = "Avez-vous sauvegardé votre clé de récupération?"; +"screen_signout_save_recovery_key_title" = "Avez-vous sauvegardé votre clé de récupération ?"; "troubleshoot_notifications_entry_point_title" = "Dépanner les notifications"; diff --git a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings index f6f5b11a1f..d9413d843b 100644 --- a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings @@ -22,7 +22,7 @@ "a11y_voice_message_record" = "Hangüzenet felvétele."; "a11y_voice_message_stop_recording" = "Rögzítés leállítása"; "action_accept" = "Elfogadás"; -"action_add_caption" = "Add caption"; +"action_add_caption" = "Felirat hozzáadása"; "action_add_to_timeline" = "Hozzáadás az idővonalhoz"; "action_back" = "Vissza"; "action_call" = "Hívás"; @@ -36,10 +36,10 @@ "action_confirm_password" = "Jelszó megerősítése"; "action_continue" = "Folytatás"; "action_copy" = "Másolás"; -"action_copy_caption" = "Copy caption"; +"action_copy_caption" = "Felirat másolása"; "action_copy_link" = "Hivatkozás másolása"; "action_copy_link_to_message" = "Üzenetre mutató hivatkozás másolása"; -"action_copy_text" = "Copy text"; +"action_copy_text" = "Szöveg másolása"; "action_create" = "Létrehozás"; "action_create_a_room" = "Szoba létrehozása"; "action_deactivate" = "Deaktiválás"; @@ -50,7 +50,7 @@ "action_discard" = "Elvetés"; "action_done" = "Kész"; "action_edit" = "Szerkesztés"; -"action_edit_caption" = "Edit caption"; +"action_edit_caption" = "Felirat szerkesztése"; "action_edit_poll" = "Szavazás szerkesztése"; "action_enable" = "Engedélyezés"; "action_end_poll" = "Szavazás lezárása"; @@ -85,8 +85,8 @@ "action_react" = "Reakció"; "action_reject" = "Elutasítás"; "action_remove" = "Eltávolítás"; -"action_remove_caption" = "Remove caption"; -"action_remove_message" = "Remove message"; +"action_remove_caption" = "Felirat eltávolítása"; +"action_remove_message" = "Üzenet eltávolítása"; "action_reply" = "Válasz"; "action_reply_in_thread" = "Válasz az üzenetszálban"; "action_report_bug" = "Hiba jelentése"; @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Megtekintés az idővonalon"; "action_view_source" = "Forrás megtekintése"; "action_yes" = "Igen"; +"action_yes_try_again" = "Igen, újrapróbálkozás"; "banner_migrate_to_native_sliding_sync_action" = "Kijelentkezés és frissítés"; "banner_migrate_to_native_sliding_sync_description" = "A kiszolgálója mostantól egy új, gyorsabb protokollt támogat. A frissítéshez jelentkezzen ki, majd jelentkezzen be újra. Ha ezt most megteszi, elkerülheti a kényszerített kijelentkeztetést a régi protokollt eltávolításakor."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "A Matrix-kiszolgáló már nem támogatja a régi protokollt. Az alkalmazás további használatához jelentkezzen ki és be."; @@ -125,7 +126,7 @@ "banner_set_up_recovery_title" = "Helyreállítás beállítása"; "common_about" = "Névjegy"; "common_acceptable_use_policy" = "Elfogadható használatra vonatkozó szabályzat"; -"common_adding_caption" = "Adding caption"; +"common_adding_caption" = "Felirat hozzáadása"; "common_advanced_settings" = "Speciális beállítások"; "common_analytics" = "Elemzések"; "common_appearance" = "Megjelenítés"; @@ -138,13 +139,16 @@ "common_creating_room" = "Szoba létrehozása…"; "common_current_user_left_room" = "Elhagyta a szobát"; "common_dark" = "Sötét"; +"common_date_date_at_time" = "%1$@ itt: %2$@"; +"common_date_this_month" = "Ebben a hónapban"; "common_decryption_error" = "Visszafejtési hiba"; "common_developer_options" = "Fejlesztői beállítások"; "common_device_id" = "Eszközazonosító"; "common_direct_chat" = "Közvetlen csevegés"; +"common_downloading" = "Letöltés"; "common_edited_suffix" = "(szerkesztve)"; "common_editing" = "Szerkesztés"; -"common_editing_caption" = "Editing caption"; +"common_editing_caption" = "Felirat szerkesztése"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Titkosítás"; "common_encryption_enabled" = "Titkosítás engedélyezve"; @@ -233,7 +237,7 @@ "common_unable_to_invite_title" = "Nem sikerült elküldeni a meghívót (meghívókat)"; "common_unlock" = "Feloldás"; "common_unmute" = "Némítás feloldása"; -"common_unsupported_call" = "Unsupported call"; +"common_unsupported_call" = "Nem támogatott hívás"; "common_unsupported_event" = "Nem támogatott esemény"; "common_username" = "Felhasználónév"; "common_verification_cancelled" = "Az ellenőrzés megszakítva"; @@ -361,8 +365,8 @@ "screen_create_room_room_access_section_header" = "Szobahozzáférés"; "screen_create_room_room_access_section_knocking_option_description" = "Bárki kérheti, hogy csatlakozzon a szobához, de egy adminisztrátornak vagy moderátornak el kell fogadnia a kérést"; "screen_create_room_room_access_section_knocking_option_title" = "Csatlakozás kérése"; -"screen_create_room_room_address_invalid_symbols_error_description" = "Some characters are not allowed. Only letters, digits and the following symbols are supported ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"; -"screen_create_room_room_address_not_available_error_description" = "This room address already exists. Please try editing the room address field or change the room name"; +"screen_create_room_room_address_invalid_symbols_error_description" = "Egyes karakterek nem engedélyezettek. Csak a betűk, a számjegyek és a következő szimbólumok támogatottak: $ & '() * +/; =? @ [] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Ez a szobacím már létezik. Próbálja meg szerkeszteni a szobacím mezőt, vagy módosítsa a szoba nevét."; "screen_create_room_room_address_section_footer" = "Ahhoz, hogy ez a szoba látható legyen a nyilvános szobák címtárában, meg kell adnia a szoba címét."; "screen_create_room_room_address_section_title" = "Szoba címe"; "screen_create_room_room_visibility_section_title" = "Szoba láthatósága"; @@ -373,21 +377,38 @@ "screen_join_room_knock_message_description" = "Üzenet (nem kötelező)"; "screen_join_room_knock_sent_description" = "Ha a kérését elfogadják, meghívót kap a szobához való csatlakozáshoz."; "screen_join_room_knock_sent_title" = "Csatlakozási kérés elküldve"; -"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Yes, accept all"; -"screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; -"screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; -"screen_knock_requests_list_accept_all_button_title" = "Accept all"; -"screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; -"screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; -"screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; -"screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; -"screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; -"screen_knock_requests_list_decline_alert_title" = "Decline access"; -"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; -"screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; -"screen_knock_requests_list_empty_state_title" = "No pending request to join"; -"screen_knock_requests_list_title" = "Requests to join"; -"screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; +"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Igen, az összes elfogadása"; +"screen_knock_requests_list_accept_all_alert_description" = "Biztos, hogy elfogadja az összes csatlakozási kérelmet?"; +"screen_knock_requests_list_accept_all_alert_title" = "Minden kérés elfogadása"; +"screen_knock_requests_list_accept_all_button_title" = "Összes elfogadása"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "Nem sikerült az összes kérés fogadása. Újra megpróbálja?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Nem sikerült az összes kérés elfogadása"; +"screen_knock_requests_list_accept_all_loading_title" = "Összes csatlakozási kérés elfogadása"; +"screen_knock_requests_list_accept_failed_alert_description" = "Nem sikerült elfogadni a kérést. Megpróbálja újra?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Nem sikerült elfogadni a kérést"; +"screen_knock_requests_list_accept_loading_title" = "Csatlakozási kérés elfogadása"; +"screen_knock_requests_list_ban_alert_confirm_button_title" = "Igen, elutasítás és kitiltás"; +"screen_knock_requests_list_ban_alert_description" = "Biztos, hogy elutasítja %1$@ kérését és ki is tiltja? Többé nem fogja tudni azt kérni, hogy csatlakozhasson ehhez a szobához."; +"screen_knock_requests_list_ban_alert_title" = "A hozzáférés elutasítása és kitiltás"; +"screen_knock_requests_list_ban_loading_title" = "A hozzáférés megtagadása és kitiltás"; +"screen_knock_requests_list_decline_alert_confirm_button_title" = "Igen, elutasítás"; +"screen_knock_requests_list_decline_alert_description" = "Biztos, hogy elutasítja %1$@ kérését, hogy csatlakozzon a szobához?"; +"screen_knock_requests_list_decline_alert_title" = "Hozzáférés elutasítása"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Elutasítás és kitiltás"; +"screen_knock_requests_list_decline_failed_alert_description" = "Nem sikerült elutasítani a kérést. Megpróbálja újra?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Nem sikerült elutasítani a kérést"; +"screen_knock_requests_list_decline_loading_title" = "Csatlakozási kérés elutasítása"; +"screen_knock_requests_list_empty_state_description" = "Ha valaki csatlakozni kíván a szobához, itt láthatja a kérését."; +"screen_knock_requests_list_empty_state_title" = "Nincs függőben lévő csatlakozási kérelem"; +"screen_knock_requests_list_initial_loading_title" = "Csatlakozási kérések betöltése…"; +"screen_knock_requests_list_title" = "Csatlakozási kérelmek"; +"screen_media_details_file_format" = "Fájlformátum"; +"screen_media_details_filename" = "Fájlnév"; +"screen_media_details_redact_confirmation_message" = "Ez a fájl el lesz távolítva a szobából, és a tagok nem férhetnek hozzá."; +"screen_media_details_redact_confirmation_title" = "Törli a fájlt?"; +"screen_media_details_uploaded_by" = "Feltöltötte:"; +"screen_media_details_uploaded_on" = "Feltöltve:"; +"screen_media_upload_preview_caption_warning" = "Előfordulhat, hogy a feliratok nem láthatók a régebbi alkalmazásokat használók számára."; "screen_media_upload_preview_error_failed_processing" = "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra."; "screen_media_upload_preview_error_failed_sending" = "Nem sikerült a média feltöltése, próbálja újra."; "screen_pinned_timeline_empty_state_description" = "Nyomjon hosszan az üzenetre, és válassza a „%1$@” lehetőséget, hogy itt szerepeljen."; @@ -402,17 +423,32 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Egy vagy több eszköze nincs ellenőrizve. Így is elküldheti az üzenetet, vagy egyelőre megszakíthatja, és később, az összes eszköz ellenőrzése után újrapróbálkozhat."; "screen_resolve_send_failure_you_unsigned_device_title" = "Az üzenet nem lett elküldve, mert egy vagy több eszközét nem ellenőrizte"; "screen_room_mentions_at_room_subtitle" = "Az egész szoba értesítése"; -"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; +"screen_room_multiple_knock_requests_view_all_button_title" = "Összes megtekintése"; "screen_room_pinned_banner_indicator" = "%1$@ / %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ kitűzött üzenet"; "screen_room_pinned_banner_loading_description" = "Üzenet betöltése…"; "screen_room_pinned_banner_view_all_button_title" = "Összes megtekintése"; -"screen_room_single_knock_request_accept_button_title" = "Accept"; -"screen_room_single_knock_request_title" = "%1$@ wants to join this room"; -"screen_room_single_knock_request_view_button_title" = "View"; +"screen_room_single_knock_request_accept_button_title" = "Elfogadás"; +"screen_room_single_knock_request_title" = "%1$@ szeretne csatlakozni ehhez a szobához"; +"screen_room_single_knock_request_view_button_title" = "Megtekintés"; "screen_room_details_pinned_events_row_title" = "Kitűzött üzenetek"; -"screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_requests_to_join_title" = "Csatlakozási kérelem"; +"screen_room_details_security_and_privacy_title" = "Biztonság és adatvédelem"; "screen_roomlist_knock_event_sent_description" = "Csatlakozási kérés elküldve"; +"screen_security_and_privacy_ask_to_join_option_description" = "Bárki kérheti, hogy csatlakozzon a szobához, de egy adminisztrátornak vagy moderátornak el kell fogadnia a kérést."; +"screen_security_and_privacy_ask_to_join_option_title" = "Csatlakozás kérése"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Igen, engedélyezze a titkosítást"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Az engedélyezés után a szoba titkosítása nem tiltható le. Az üzenetek előzményei csak a szobatagok számára láthatók, amikor meghívást kaptak, vagy mióta csatlakoztak a szobához.\nA szobatagokon kívül senki sem tudja olvasni az üzeneteket. Ez megakadályozhatja a botok és a hidak megfelelő működését.\nNem javasoljuk a titkosítás engedélyezését az olyan szobákban, amelyeket bárki megtalálhat és csatlakozhat."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Engedélyezi a titkosítást?"; +"screen_security_and_privacy_encryption_section_footer" = "Engedélyezés után a titkosítás nem tiltható le."; +"screen_security_and_privacy_encryption_section_title" = "Titkosítás"; +"screen_security_and_privacy_encryption_toggle_title" = "Végpontok közötti titkosítás engedélyezése"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Bárki megtalálhatja és csatlakozhat"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Bárki"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "Az emberek csak akkor csatlakozhatnak, ha meghívást kapnak"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Csak meghívással"; +"screen_security_and_privacy_room_access_section_title" = "Szobahozzáférés"; +"screen_security_and_privacy_title" = "Biztonság és adatvédelem"; "screen_timeline_item_menu_send_failure_changed_identity" = "Az üzenet nem lett elküldve, mert %1$@ ellenőrzött személyazonossága megváltozott."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Az üzenet nem lett elküldve, mert %1$@ nem ellenőrizte az összes eszközét."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Az üzenet nem lett elküldve, mert egy vagy több eszközét nem ellenőrizte."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Adja meg adatait"; "screen_login_title" = "Örülünk, hogy visszatért!"; "screen_login_title_with_homeserver" = "Bejelentkezés ide: %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "Ez a fájl el lesz távolítva a szobából, és a tagok nem férhetnek hozzá."; +"screen_media_browser_delete_confirmation_title" = "Törli a fájlt?"; +"screen_media_browser_files_empty_state_subtitle" = "A szobába feltöltött dokumentumok, hangfájlok és hangüzenetek itt jelennek meg."; +"screen_media_browser_files_empty_state_title" = "Még nincsenek fájlok feltöltve"; +"screen_media_browser_list_loading_files" = "Fájlok betöltése…"; +"screen_media_browser_list_loading_media" = "Média betöltése…"; +"screen_media_browser_list_mode_files" = "Fájlok"; +"screen_media_browser_list_mode_media" = "Média"; +"screen_media_browser_media_empty_state_subtitle" = "Az ebbe a szobába feltöltött képek és videók itt jelennek meg."; +"screen_media_browser_media_empty_state_title" = "Még nincs feltöltött média"; +"screen_media_browser_title" = "Média és fájlok"; "screen_media_picker_error_failed_selection" = "Nem sikerült kiválasztani a médiát, próbálja újra."; "screen_migration_message" = "Ez egy egyszeri folyamat, köszönjük a türelmét."; "screen_migration_title" = "A fiók beállítása."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Hiba történt az értesítési beállítások betöltésekor."; "screen_room_details_error_muting" = "Nem sikerült elnémítani ezt a szobát, próbálja újra."; "screen_room_details_error_unmuting" = "Nem sikerült feloldani a szoba némítását, próbálja újra."; +"screen_room_details_media_gallery_title" = "Média és fájlok"; "screen_room_details_notification_mode_custom" = "Egyéni"; "screen_room_details_notification_mode_default" = "Alapértelmezett"; "screen_room_details_share_room_title" = "Szoba megosztása"; @@ -817,7 +865,7 @@ "screen_room_timeline_add_reaction" = "Emodzsi hozzáadása"; "screen_room_timeline_beginning_of_room" = "Ez a(z) %1$@ kezdete."; "screen_room_timeline_beginning_of_room_no_name" = "Ez a beszélgetés kezdete."; -"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; +"screen_room_timeline_legacy_call" = "Nem támogatott hívás. Kérdezze meg, hogy a hívó fél tudja-e használni az új Element X alkalmazást."; "screen_room_timeline_less_reactions" = "Kevesebb megjelenítése"; "screen_room_timeline_message_copied" = "Üzenet másolva"; "screen_room_timeline_no_permission_to_post" = "Nincs jogosultsága arra, hogy bejegyzést tegyen közzé ebben a szobában"; @@ -878,10 +926,10 @@ "screen_session_verification_request_title" = "Ellenőrzés kérve"; "screen_session_verification_they_dont_match" = "Nem egyeznek"; "screen_session_verification_they_match" = "Megegyeznek"; -"screen_session_verification_use_another_device_subtitle" = "Make sure you have the app open in the other device before starting verification from here."; -"screen_session_verification_use_another_device_title" = "Open the app on another verified device"; -"screen_session_verification_waiting_another_device_subtitle" = "You should see a popup on the other device. Start the verification from there now."; -"screen_session_verification_waiting_another_device_title" = "Start verification on the other device"; +"screen_session_verification_use_another_device_subtitle" = "Győződjön meg róla, hogy az alkalmazás nyitva van a másik eszközön, mielőtt innen elindítja az ellenőrzést."; +"screen_session_verification_use_another_device_title" = "Nyissa meg az alkalmazást egy másik ellenőrzött eszközön"; +"screen_session_verification_waiting_another_device_subtitle" = "A másik eszközön egy felugró ablaknak kell megjelennie. Kezdje el az ellenőrzést onnan."; +"screen_session_verification_waiting_another_device_title" = "Ellenőrzés megkezdése a másik eszközön"; "screen_session_verification_waiting_to_accept_subtitle" = "A folytatáshoz fogadja el az ellenőrzési folyamat indítási kérését a másik munkamenetében."; "screen_session_verification_waiting_to_accept_title" = "Várakozás a kérés elfogadására"; "screen_share_location_title" = "Hely megosztása"; @@ -946,8 +994,8 @@ "state_event_room_invite_you" = "%1$@ meghívta"; "state_event_room_join" = "%1$@ csatlakozott a szobához"; "state_event_room_join_by_you" = "Csatlakozott a szobához"; -"state_event_room_knock" = "%1$@ kérte, hogy csatlakozhasson"; -"state_event_room_knock_accepted" = "%1$@ engedélyezte, hogy %2$@ csatlakozhasson"; +"state_event_room_knock" = "%1$@ kéri, hogy csatlakozhasson"; +"state_event_room_knock_accepted" = "%1$@ hozzáférést kapott a következőhöz: %2$@"; "state_event_room_knock_accepted_by_you" = "Engedélyezte, hogy %1$@ csatlakozhasson"; "state_event_room_knock_by_you" = "Kérte, hogy csatlakozhasson"; "state_event_room_knock_denied" = "%1$@ elutasította %2$@ kérését, hogy csatlakozhasson"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ ismeretlen változást hajtott végre a tagságában"; "test_language_identifier" = "hu"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "A korábbi üzenetek nem érhetők el ezen az eszközön"; +"timeline_decryption_failure_historical_event_user_not_joined" = "Nincs hozzáférése ehhez az üzenethez"; +"timeline_decryption_failure_unable_to_decrypt" = "Nem sikerült visszafejteni az üzenetet"; +"timeline_decryption_failure_withheld_unverified" = "Ez az üzenet azért lett blokkolva, mert vagy nem ellenőrizte az eszközt, vagy a feladónak ellenőriznie kell az Ön személyazonosságát."; "troubleshoot_notifications_entry_point_section" = "Hibaelhárítás"; "troubleshoot_notifications_screen_action" = "Tesztek futtatása"; "troubleshoot_notifications_screen_action_again" = "Tesztek újbóli futtatása"; diff --git a/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict index beebf83762..405c3a6404 100644 --- a/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict @@ -237,9 +237,9 @@ NSStringFormatValueTypeKey d one - %1$@ +%2$d other want to join this room + %1$@ és még %2$d felhasználó szeretne csatlakozni ehhez a szobához other - %1$@ +%2$d others want to join this room + %1$@ és még %2$d felhasználó szeretne csatlakozni ehhez a szobához screen_room_timeline_state_changes diff --git a/ElementX/Resources/Localizations/id.lproj/Localizable.strings b/ElementX/Resources/Localizations/id.lproj/Localizable.strings index 7f654be975..a6f4cf6edb 100644 --- a/ElementX/Resources/Localizations/id.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/id.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Lihat di lini masa"; "action_view_source" = "Tampilkan sumber"; "action_yes" = "Ya"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Keluar & Tingkatkan"; "banner_migrate_to_native_sliding_sync_description" = "Server Anda kini mendukung protokol baru yang lebih cepat. Keluar dan masuk lagi untuk memperbarui sekarang. Melakukan hal ini sekarang akan membantu Anda menghindari keluar paksa saat protokol lama dihapus nantinya."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Homeserver Anda tidak lagi mendukung protokol lama. Silakan keluar dan masuk kembali untuk terus menggunakan aplikasi."; @@ -138,10 +139,13 @@ "common_creating_room" = "Membuat ruangan..."; "common_current_user_left_room" = "Keluar dari ruangan"; "common_dark" = "Gelap"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Kesalahan dekripsi"; "common_developer_options" = "Opsi pengembang"; "common_device_id" = "ID Perangkat"; "common_direct_chat" = "Obrolan langsung"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(disunting)"; "common_editing" = "Penyuntingan"; "common_editing_caption" = "Editing caption"; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Gagal memproses media untuk diunggah, silakan coba lagi."; "screen_media_upload_preview_error_failed_sending" = "Gagal mengunggah media, silakan coba lagi."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Pesan yang disematkan"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Permintaan untuk bergabung dikirim"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Pesan tidak terkirim karena identitas terverifikasi %1$@ telah berubah."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Pesan tidak terkirim karena %1$@ belum memverifikasi semua perangkat."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Pesan tidak terkirim karena Anda belum memverifikasi satu atau beberapa perangkat Anda."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Masukkan detail Anda"; "screen_login_title" = "Selamat datang kembali!"; "screen_login_title_with_homeserver" = "Masuk ke %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Gagal memilih media, silakan coba lagi."; "screen_migration_message" = "Ini adalah proses satu kali, terima kasih telah menunggu."; "screen_migration_title" = "Menyiapkan akun Anda."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Terjadi kesalahan saat memuat pengaturan notifikasi."; "screen_room_details_error_muting" = "Gagal membisukan ruangan ini, silakan coba lagi."; "screen_room_details_error_unmuting" = "Gagal membunyikan ruangan ini, silakan coba lagi."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Khusus"; "screen_room_details_notification_mode_default" = "Bawaan"; "screen_room_details_share_room_title" = "Bagikan ruangan"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ membuat perubahan keanggotaan yang tidak diketahui"; "test_language_identifier" = "id"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Pemecahan masalah"; "troubleshoot_notifications_screen_action" = "Jalankan tes"; "troubleshoot_notifications_screen_action_again" = "Jalankan tes lagi"; diff --git a/ElementX/Resources/Localizations/it.lproj/Localizable.strings b/ElementX/Resources/Localizations/it.lproj/Localizable.strings index 33309394d1..3775ef7fb9 100644 --- a/ElementX/Resources/Localizations/it.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/it.lproj/Localizable.strings @@ -22,7 +22,7 @@ "a11y_voice_message_record" = "Registra un messaggio vocale."; "a11y_voice_message_stop_recording" = "Ferma la registrazione"; "action_accept" = "Accetta"; -"action_add_caption" = "Add caption"; +"action_add_caption" = "Aggiungi didascalia"; "action_add_to_timeline" = "Aggiungi alla conversazione"; "action_back" = "Indietro"; "action_call" = "Chiama"; @@ -36,10 +36,10 @@ "action_confirm_password" = "Conferma password"; "action_continue" = "Continua"; "action_copy" = "Copia"; -"action_copy_caption" = "Copy caption"; +"action_copy_caption" = "Copia didascalia"; "action_copy_link" = "Copia collegamento"; "action_copy_link_to_message" = "Copia collegamento al messaggio"; -"action_copy_text" = "Copy text"; +"action_copy_text" = "Copia testo"; "action_create" = "Crea"; "action_create_a_room" = "Crea una stanza"; "action_deactivate" = "Disattiva"; @@ -50,7 +50,7 @@ "action_discard" = "Annulla"; "action_done" = "Fine"; "action_edit" = "Modifica"; -"action_edit_caption" = "Edit caption"; +"action_edit_caption" = "Modifica didascalia"; "action_edit_poll" = "Modifica sondaggio"; "action_enable" = "Attiva"; "action_end_poll" = "Termina sondaggio"; @@ -58,7 +58,7 @@ "action_forgot_password" = "Password dimenticata?"; "action_forward" = "Inoltra"; "action_go_back" = "Indietro"; -"action_ignore" = "Ignore"; +"action_ignore" = "Ignora"; "action_invite" = "Invita"; "action_invite_friends" = "Invita persone"; "action_invite_friends_to_app" = "Invita persone su %1$@"; @@ -79,14 +79,14 @@ "action_ok" = "OK"; "action_open_settings" = "Impostazioni"; "action_open_with" = "Apri con"; -"action_pin" = "Pin"; +"action_pin" = "Fissa"; "action_quick_reply" = "Risposta rapida"; "action_quote" = "Citazione"; "action_react" = "Reagisci"; "action_reject" = "Rifiuta"; "action_remove" = "Rimuovi"; -"action_remove_caption" = "Remove caption"; -"action_remove_message" = "Remove message"; +"action_remove_caption" = "Rimuovi didascalia"; +"action_remove_message" = "Rimuovi messaggio"; "action_reply" = "Rispondi"; "action_reply_in_thread" = "Rispondi nella discussione"; "action_report_bug" = "Segnala un problema"; @@ -101,7 +101,7 @@ "action_send_message" = "Invia messaggio"; "action_share" = "Condividi"; "action_share_link" = "Condividi collegamento"; -"action_show" = "Show"; +"action_show" = "Mostra"; "action_sign_in_again" = "Accedi di nuovo"; "action_signout" = "Disconnetti"; "action_signout_anyway" = "Disconnetti comunque"; @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Visualizza nella conversazione"; "action_view_source" = "Vedi codice sorgente"; "action_yes" = "Sì"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Esci e aggiorna"; "banner_migrate_to_native_sliding_sync_description" = "Il tuo server ora supporta un nuovo protocollo più veloce. Esci e rientra per effettuare l'aggiornamento. Se lo fai ora, eviterai una disconnessione forzata quando il vecchio protocollo verrà rimosso in seguito."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Il tuo homeserver non supporta più il vecchio protocollo. Esci e rientra per continuare a usare l'app."; @@ -125,7 +126,7 @@ "banner_set_up_recovery_title" = "Configura il ripristino"; "common_about" = "Informazioni"; "common_acceptable_use_policy" = "Regole sull'utilizzo consentito"; -"common_adding_caption" = "Adding caption"; +"common_adding_caption" = "Aggiunta didascalia"; "common_advanced_settings" = "Impostazioni avanzate"; "common_analytics" = "Statistiche di utilizzo"; "common_appearance" = "Aspetto"; @@ -138,15 +139,18 @@ "common_creating_room" = "Creazione stanza…"; "common_current_user_left_room" = "Hai lasciato la stanza"; "common_dark" = "Scuro"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Errore di decrittazione"; "common_developer_options" = "Opzioni sviluppatore"; -"common_device_id" = "Device ID"; +"common_device_id" = "ID dispositivo"; "common_direct_chat" = "Conversazione diretta"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(modificato)"; "common_editing" = "Modifica in corso"; -"common_editing_caption" = "Editing caption"; +"common_editing_caption" = "Modifica didascalia"; "common_emote" = "* %1$@ %2$@"; -"common_encryption" = "Encryption"; +"common_encryption" = "Crittografia"; "common_encryption_enabled" = "Crittografia abilitata"; "common_enter_your_pin" = "Inserisci il PIN"; "common_error" = "Errore"; @@ -157,7 +161,7 @@ "common_favourited" = "Preferita"; "common_file" = "File"; "common_forward_message" = "Inoltra messaggio"; -"common_frequently_used" = "Frequently used"; +"common_frequently_used" = "Usati di frequente"; "common_gif" = "GIF"; "common_image" = "Immagine"; "common_in_reply_to" = "In risposta a %1$@"; @@ -233,15 +237,15 @@ "common_unable_to_invite_title" = "Impossibile inviare inviti"; "common_unlock" = "Sblocca"; "common_unmute" = "Annulla silenzioso"; -"common_unsupported_call" = "Unsupported call"; +"common_unsupported_call" = "Chiamata non supportata"; "common_unsupported_event" = "Evento non supportato"; "common_username" = "Nome utente"; "common_verification_cancelled" = "Verifica annullata"; "common_verification_complete" = "Verifica completata"; -"common_verification_failed" = "Verification failed"; -"common_verified" = "Verified"; +"common_verification_failed" = "Verifica fallita"; +"common_verified" = "Verificato"; "common_verify_device" = "Verifica dispositivo"; -"common_verify_identity" = "Verify identity"; +"common_verify_identity" = "Verifica l'identità"; "common_video" = "Video"; "common_voice_message" = "Messaggio vocale"; "common_waiting" = "In attesa…"; @@ -252,15 +256,15 @@ "common.pinned" = "Fissato"; "common.send_to" = "Invia a"; "common.you" = "Tu"; -"common_unable_to_decrypt_insecure_device" = "Sent from an insecure device"; -"common_unable_to_decrypt_verification_violation" = "Sender's verified identity has changed"; -"confirm_recovery_key_banner_message" = "Il backup della chat non è attualmente sincronizzato. Devi confermare la chiave di recupero per mantenere l'accesso al backup della chat."; -"confirm_recovery_key_banner_primary_button_title" = "Enter your recovery key"; -"confirm_recovery_key_banner_secondary_button_title" = "Forgot your recovery key?"; -"confirm_recovery_key_banner_title" = "Inserisci la chiave di recupero"; +"common_unable_to_decrypt_insecure_device" = "Inviato da un dispositivo non sicuro"; +"common_unable_to_decrypt_verification_violation" = "L'identità verificata del mittente è cambiata"; +"confirm_recovery_key_banner_message" = "Conferma la chiave di recupero per mantenere l'accesso all'archiviazione delle chiavi e alla cronologia dei messaggi."; +"confirm_recovery_key_banner_primary_button_title" = "Inserisci la tua chiave di recupero"; +"confirm_recovery_key_banner_secondary_button_title" = "Hai dimenticato la chiave di recupero?"; +"confirm_recovery_key_banner_title" = "L'archiviazione delle chiavi non è sincronizzata"; "crash_detection_dialog_content" = "%1$@ si è chiuso inaspettatamente l'ultima volta che è stato usato. Vuoi condividere con noi un rapporto sull'arresto anomalo?"; "crypto_identity_change_pin_violation" = "L'identità di %1$@ sembra essere cambiata. %2$@"; -"crypto_identity_change_pin_violation_new" = "%1$@’s %2$@ identity appears to have changed. %3$@"; +"crypto_identity_change_pin_violation_new" = "L'identità di %1$@ %2$@ sembra essere cambiata. %3$@"; "crypto_identity_change_pin_violation_new_user_id" = "(%1$@)"; "dialog_permission_camera" = "Per permettere all'applicazione di usare la fotocamera, concedi l'autorizzazione nelle impostazioni di sistema."; "dialog_permission_generic" = "Concedi l'autorizzazione nelle impostazioni di sistema."; @@ -352,42 +356,59 @@ "rich_text_editor_unindent" = "Rientro a sinistra"; "rich_text_editor_url_placeholder" = "Collegamento"; "rich_text_editor_a11y_add_attachment" = "Aggiungi allegato"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Aggiungi una didascalia"; "screen_advanced_settings_element_call_base_url" = "URL base di Element Call personalizzato"; "screen_advanced_settings_element_call_base_url_description" = "Imposta un URL di base personalizzato per Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "URL non valido, assicurati di includere il protocollo (http/https) e l'indirizzo corretto."; -"screen_create_room_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_room_access_section_header" = "Room Access"; -"screen_create_room_room_access_section_knocking_option_description" = "Anyone can ask to join the room but an administrator or a moderator will have to accept the request"; -"screen_create_room_room_access_section_knocking_option_title" = "Ask to join"; -"screen_create_room_room_address_invalid_symbols_error_description" = "Some characters are not allowed. Only letters, digits and the following symbols are supported ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"; -"screen_create_room_room_address_not_available_error_description" = "This room address already exists. Please try editing the room address field or change the room name"; -"screen_create_room_room_address_section_footer" = "In order for this room to be visible in the public room directory, you will need a room address."; -"screen_create_room_room_address_section_title" = "Room address"; -"screen_create_room_room_visibility_section_title" = "Room visibility"; -"screen_join_room_cancel_knock_action" = "Cancel request"; -"screen_join_room_cancel_knock_alert_confirmation" = "Yes, cancel"; -"screen_join_room_cancel_knock_alert_description" = "Are you sure that you want to cancel your request to join this room?"; -"screen_join_room_cancel_knock_alert_title" = "Cancel request to join"; -"screen_join_room_knock_message_description" = "Message (optional)"; -"screen_join_room_knock_sent_description" = "You will receive an invite to join the room if your request is accepted."; -"screen_join_room_knock_sent_title" = "Request to join sent"; -"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Yes, accept all"; -"screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; -"screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; -"screen_knock_requests_list_accept_all_button_title" = "Accept all"; -"screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; -"screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; -"screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; -"screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; -"screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; -"screen_knock_requests_list_decline_alert_title" = "Decline access"; -"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; -"screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; -"screen_knock_requests_list_empty_state_title" = "No pending request to join"; -"screen_knock_requests_list_title" = "Requests to join"; -"screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; +"screen_create_room_room_access_section_anyone_option_description" = "Chiunque può entrare in questa stanza"; +"screen_create_room_room_access_section_anyone_option_title" = "Chiunque"; +"screen_create_room_room_access_section_header" = "Accesso alla stanza"; +"screen_create_room_room_access_section_knocking_option_description" = "Chiunque può chiedere di entrare nella stanza, ma un amministratore o un moderatore dovrà accettare la richiesta"; +"screen_create_room_room_access_section_knocking_option_title" = "Chiedi di entrare"; +"screen_create_room_room_address_invalid_symbols_error_description" = "Alcuni caratteri non sono consentiti. Sono supportate solo lettere, cifre e i seguenti simboli ! $ & '() * +/; =? @ [] - . _"; +"screen_create_room_room_address_not_available_error_description" = "L'indirizzo di questa stanza esiste già. Prova a modificare il campo dell'indirizzo o a cambiare il nome della stanza"; +"screen_create_room_room_address_section_footer" = "Affinché questa stanza sia visibile nell'elenco delle stanze pubbliche, è necessario un indirizzo della stanza."; +"screen_create_room_room_address_section_title" = "Indirizzo della stanza"; +"screen_create_room_room_visibility_section_title" = "Visibilità della stanza"; +"screen_join_room_cancel_knock_action" = "Cancella richiesta"; +"screen_join_room_cancel_knock_alert_confirmation" = "Sì, annulla"; +"screen_join_room_cancel_knock_alert_description" = "Sei sicuro di voler annullare la tua richiesta di accesso a questa stanza?"; +"screen_join_room_cancel_knock_alert_title" = "Annulla la richiesta di accesso"; +"screen_join_room_knock_message_description" = "Messaggio (opzionale)"; +"screen_join_room_knock_sent_description" = "Riceverai un invito a entrare nella stanza se la tua richiesta viene accettata."; +"screen_join_room_knock_sent_title" = "Richiesta di accesso inviata"; +"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Sì, accetta tutte"; +"screen_knock_requests_list_accept_all_alert_description" = "Sei sicuro di voler accettare tutte le richieste di accesso?"; +"screen_knock_requests_list_accept_all_alert_title" = "Accetta tutte le richieste"; +"screen_knock_requests_list_accept_all_button_title" = "Accetta tutte"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; +"screen_knock_requests_list_ban_alert_confirm_button_title" = "Sì, rifiuta e blocca"; +"screen_knock_requests_list_ban_alert_description" = "Sei sicuro di voler rifiutare e bloccare %1$@? Questo utente non potrà richiedere nuovamente l'accesso per entrare in questa stanza."; +"screen_knock_requests_list_ban_alert_title" = "Rifiuta e blocca l'accesso"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; +"screen_knock_requests_list_decline_alert_confirm_button_title" = "Sì, rifiuta"; +"screen_knock_requests_list_decline_alert_description" = "Sei sicuro di voler rifiutare la richiesta di %1$@ ad entrare in a questa stanza?"; +"screen_knock_requests_list_decline_alert_title" = "Rifiuta l'accesso"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Rifiuta e blocca"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; +"screen_knock_requests_list_empty_state_description" = "Quando qualcuno ti chiederà di entrare nella stanza, potrai vedere la sua richiesta qui."; +"screen_knock_requests_list_empty_state_title" = "Nessuna richiesta di accesso in sospeso"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; +"screen_knock_requests_list_title" = "Richieste di accesso"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; +"screen_media_upload_preview_caption_warning" = "Le didascalie potrebbero non essere visibili agli utenti di app meno recenti."; "screen_media_upload_preview_error_failed_processing" = "Elaborazione del file multimediale da caricare fallita, riprova."; "screen_media_upload_preview_error_failed_sending" = "Caricamento del file multimediale fallito, riprova."; "screen_pinned_timeline_empty_state_description" = "Premi su un messaggio e scegli “%1$@” per includerlo qui."; @@ -402,17 +423,32 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Uno o più dispositivi non sono verificati. Puoi inviare il messaggio comunque, oppure annullarlo e riprovare più tardi dopo aver verificato tutti i tuoi dispositivi."; "screen_resolve_send_failure_you_unsigned_device_title" = "Il tuo messaggio non è stato inviato perché non hai verificato uno o più dispositivi."; "screen_room_mentions_at_room_subtitle" = "Notifica l'intera stanza"; -"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; +"screen_room_multiple_knock_requests_view_all_button_title" = "Visualizza tutte"; "screen_room_pinned_banner_indicator" = "%1$@ di %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Messaggi fissati"; "screen_room_pinned_banner_loading_description" = "Caricamento messaggio…"; "screen_room_pinned_banner_view_all_button_title" = "Mostra tutti"; -"screen_room_single_knock_request_accept_button_title" = "Accept"; -"screen_room_single_knock_request_title" = "%1$@ wants to join this room"; -"screen_room_single_knock_request_view_button_title" = "View"; +"screen_room_single_knock_request_accept_button_title" = "Accetta"; +"screen_room_single_knock_request_title" = "%1$@ vuole entrare in questa stanza"; +"screen_room_single_knock_request_view_button_title" = "Visualizza"; "screen_room_details_pinned_events_row_title" = "Messaggi fissati"; -"screen_room_details_requests_to_join_title" = "Requests to join"; -"screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_room_details_requests_to_join_title" = "Richieste di accesso"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; +"screen_roomlist_knock_event_sent_description" = "Richiesta di accesso inviata"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Messaggio non inviato perché l'identità verificata di %1$@ è cambiata."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Messaggio non inviato perché %1$@ non ha verificato tutti i dispositivi."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Messaggio non inviato perché non hai verificato uno o più dispositivi."; @@ -424,8 +460,8 @@ "screen_account_provider_signup_title" = "Stai per creare un account su %@"; "screen_advanced_settings_developer_mode" = "Modalità sviluppatore"; "screen_advanced_settings_developer_mode_description" = "Attiva per avere accesso alle funzionalità per sviluppatori."; -"screen_advanced_settings_media_compression_description" = "Upload photos and videos faster and reduce data usage"; -"screen_advanced_settings_media_compression_title" = "Optimise media quality"; +"screen_advanced_settings_media_compression_description" = "Carica foto e video più velocemente e riduci l'utilizzo dei dati"; +"screen_advanced_settings_media_compression_title" = "Ottimizza la qualità dei contenuti multimediali"; "screen_advanced_settings_rich_text_editor_description" = "Disattiva l'editor di testo avanzato per scrivere manualmente in Markdown"; "screen_advanced_settings_send_read_receipts" = "Ricevute di visualizzazione"; "screen_advanced_settings_send_read_receipts_description" = "Se disattivato, le tue ricevute di visualizzazione non verranno inviate a nessuno. Riceverai comunque ricevute di visualizzazione da altri utenti."; @@ -492,14 +528,14 @@ "screen_change_server_title" = "Seleziona il tuo server"; "screen_chat_backup_key_backup_action_disable" = "Disattiva il backup"; "screen_chat_backup_key_backup_action_enable" = "Attiva il backup"; -"screen_chat_backup_key_backup_description" = "Il backup ti garantisce di non perdere la cronologia dei messaggi. %1$@."; -"screen_chat_backup_key_backup_title" = "Backup"; -"screen_chat_backup_key_storage_disabled_error" = "Key storage must be turned on to set up recovery."; -"screen_chat_backup_key_storage_toggle_description" = "Upload keys from this device"; -"screen_chat_backup_key_storage_toggle_title" = "Allow key storage"; +"screen_chat_backup_key_backup_description" = "Archivia la tua identità crittografica e le chiavi dei messaggi in modo sicuro sul server. Ciò ti consentirà di visualizzare la cronologia dei messaggi su tutti i nuovi dispositivi. %1$@."; +"screen_chat_backup_key_backup_title" = "Archiviazione chiavi"; +"screen_chat_backup_key_storage_disabled_error" = "L'archiviazione delle chiavi deve essere attivata per configurare il ripristino."; +"screen_chat_backup_key_storage_toggle_description" = "Carica le chiavi da questo dispositivo"; +"screen_chat_backup_key_storage_toggle_title" = "Consenti l'archiviazione delle chiavi"; "screen_chat_backup_recovery_action_change" = "Cambia la chiave di recupero"; -"screen_chat_backup_recovery_action_change_description" = "Recover your cryptographic identity and message history with a recovery key if you’ve lost all your existing devices."; -"screen_chat_backup_recovery_action_confirm_description" = "Il backup delle conversazioni non è attualmente sincronizzato."; +"screen_chat_backup_recovery_action_change_description" = "Recupera la tua identità crittografica e la cronologia dei messaggi con una chiave di recupero se hai perso tutti i dispositivi esistenti."; +"screen_chat_backup_recovery_action_confirm_description" = "L'archiviazione delle chiavi non è sincronizzata."; "screen_chat_backup_recovery_action_setup_description" = "Ottieni l'accesso ai tuoi messaggi cifrati se perdi tutti i tuoi dispositivi o se sei disconnesso da %1$@ ovunque."; "screen_create_account_title" = "Crea account"; "screen_create_new_recovery_key_list_item_1" = "Apri %1$@ in un dispositivo desktop"; @@ -519,10 +555,10 @@ "screen_create_poll_title" = "Crea sondaggio"; "screen_create_room_action_create_room" = "Nuova stanza"; "screen_create_room_error_creating_room" = "Si è verificato un errore durante la creazione della stanza"; -"screen_create_room_private_option_description" = "I messaggi in questa stanza sono cifrati. La crittografia non può essere disattivata in seguito."; -"screen_create_room_private_option_title" = "Stanza privata (solo su invito)"; -"screen_create_room_public_option_description" = "I messaggi non sono cifrati e chiunque può leggerli. Puoi attivare la crittografia in un secondo momento."; -"screen_create_room_public_option_title" = "Stanza pubblica (chiunque)"; +"screen_create_room_private_option_description" = "Solo le persone invitate possono accedere a questa stanza. Tutti i messaggi sono cifrati end-to-end."; +"screen_create_room_private_option_title" = "Stanza privata"; +"screen_create_room_public_option_description" = "Chiunque può trovare questa stanza.\nPuoi modificarlo in qualsiasi momento nelle impostazioni della stanza."; +"screen_create_room_public_option_title" = "Stanza pubblica"; "screen_create_room_topic_label" = "Argomento (facoltativo)"; "screen_deactivate_account_confirmation_dialog_content" = "Conferma di voler disattivare il tuo account. Questa azione è irreversibile."; "screen_deactivate_account_delete_all_messages" = "Elimina tutti i miei messaggi"; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Inserisci i tuoi dati"; "screen_login_title" = "Bentornato!"; "screen_login_title_with_homeserver" = "Accedi a %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "File"; +"screen_media_browser_list_mode_media" = "Contenuti multimediali"; +"screen_media_browser_media_empty_state_subtitle" = "Le immagini e i video caricati in questa stanza verranno mostrati qui."; +"screen_media_browser_media_empty_state_title" = "Nessun file multimediale ancora caricato"; +"screen_media_browser_title" = "File e contenuti multimediali"; "screen_media_picker_error_failed_selection" = "Selezione del file multimediale fallita, riprova."; "screen_migration_message" = "Si tratta di una procedura che si effettua una sola volta, grazie per l'attesa."; "screen_migration_title" = "Configurazione del tuo account."; @@ -653,7 +700,7 @@ "screen_qr_code_login_initial_state_item_3" = "Seleziona %1$@"; "screen_qr_code_login_initial_state_item_3_action" = "\"Collega un nuovo dispositivo\""; "screen_qr_code_login_initial_state_item_4" = "Scansiona il codice QR con questo dispositivo"; -"screen_qr_code_login_initial_state_subtitle" = "Only available if your account provider supports it."; +"screen_qr_code_login_initial_state_subtitle" = "Disponibile solo se il provider del tuo account lo supporta."; "screen_qr_code_login_initial_state_title" = "Apri %1$@ su un altro dispositivo per ottenere il codice QR"; "screen_qr_code_login_invalid_scan_state_description" = "Usa il codice QR mostrato sull'altro dispositivo."; "screen_qr_code_login_invalid_scan_state_subtitle" = "Codice QR sbagliato"; @@ -672,7 +719,7 @@ "screen_recovery_key_change_title" = "Cambiare la chiave di recupero?"; "screen_recovery_key_confirm_create_new_recovery_key" = "Crea una nuova chiave di recupero"; "screen_recovery_key_confirm_description" = "Assicurati che nessuno possa vedere questa schermata!"; -"screen_recovery_key_confirm_error_content" = "Riprova per confermare l'accesso al backup della chat."; +"screen_recovery_key_confirm_error_content" = "Riprova per confermare l'accesso all'archivio delle chiavi."; "screen_recovery_key_confirm_error_title" = "Chiave di recupero errata"; "screen_recovery_key_confirm_key_description" = "Se hai una chiave di sicurezza o una password, andrà bene anche questo."; "screen_recovery_key_confirm_key_placeholder" = "Inserisci..."; @@ -681,14 +728,14 @@ "screen_recovery_key_copied_to_clipboard" = "Chiave di recupero copiata"; "screen_recovery_key_generating_key" = "Generazione…"; "screen_recovery_key_save_action" = "Salva la chiave di recupero"; -"screen_recovery_key_save_description" = "Annota la chiave di recupero in un posto sicuro o salvala in un gestore di password."; +"screen_recovery_key_save_description" = "Annota questa chiave di recupero in un posto sicuro, come un gestore di password, una nota cifrata o una cassaforte fisica."; "screen_recovery_key_save_key_description" = "Tocca per copiare la chiave di recupero"; "screen_recovery_key_save_title" = "Salva la tua chiave di recupero"; "screen_recovery_key_setup_confirmation_description" = "Dopo questo passaggio non potrai accedere alla nuova chiave di recupero."; "screen_recovery_key_setup_confirmation_title" = "Hai salvato la chiave di recupero?"; "screen_recovery_key_setup_description" = "Il backup della chat è protetto da una chiave di recupero. Se hai bisogno di una nuova chiave di recupero dopo la configurazione, puoi ricrearla selezionando \"Cambia chiave di recupero\"."; "screen_recovery_key_setup_generate_key" = "Genera la tua chiave di recupero"; -"screen_recovery_key_setup_generate_key_description" = "Assicurati di conservare la chiave di recupero in un posto sicuro"; +"screen_recovery_key_setup_generate_key_description" = "Non condividerla con nessuno!"; "screen_recovery_key_setup_success" = "Configurazione del recupero completata"; "screen_recovery_key_setup_title" = "Configura il recupero"; "screen_report_content_block_user_hint" = "Seleziona se vuoi nascondere tutti i messaggi attuali e futuri di questo utente"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Si è verificato un errore durante il caricamento delle impostazioni di notifica."; "screen_room_details_error_muting" = "Impostazione del silenzioso fallita per questa stanza, riprova."; "screen_room_details_error_unmuting" = "Disattivazione del silenzioso di questa stanza fallita, riprova."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Personalizzato"; "screen_room_details_notification_mode_default" = "Predefinito"; "screen_room_details_share_room_title" = "Condividi stanza"; @@ -762,8 +810,8 @@ "screen_room_member_details_unblock_alert_action" = "Sblocca"; "screen_room_member_details_unblock_alert_description" = "Potrai vedere di nuovo tutti i suoi messaggi."; "screen_room_member_details_unblock_user" = "Sblocca utente"; -"screen_room_member_details_verify_button_subtitle" = "Use the web app to verify this user."; -"screen_room_member_details_verify_button_title" = "Verify %1$@"; +"screen_room_member_details_verify_button_subtitle" = "Usa l'app web per verificare questo utente."; +"screen_room_member_details_verify_button_title" = "Verifica %1$@"; "screen_room_member_list_ban_member_confirmation_action" = "Escludi"; "screen_room_member_list_ban_member_confirmation_description" = "Non potrà entrare nuovamente in questa stanza se invitato."; "screen_room_member_list_ban_member_confirmation_title" = "Vuoi davvero escludere questo membro?"; @@ -817,7 +865,7 @@ "screen_room_timeline_add_reaction" = "Aggiungi emoji"; "screen_room_timeline_beginning_of_room" = "Questo è l'inizio di %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Questo è l'inizio della conversazione."; -"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; +"screen_room_timeline_legacy_call" = "Chiamata non supportata. Chiedi se il chiamante può utilizzare la nuova app Element X."; "screen_room_timeline_less_reactions" = "Mostra meno"; "screen_room_timeline_message_copied" = "Messaggio copiato"; "screen_room_timeline_no_permission_to_post" = "Non sei autorizzato a postare in questa stanza"; @@ -861,7 +909,7 @@ "screen_session_verification_compare_numbers_title" = "Confronta i numeri"; "screen_session_verification_complete_subtitle" = "La tua nuova sessione è ora verificata. Ha accesso ai tuoi messaggi crittografati e gli altri utenti la vedranno come attendibile."; "screen_session_verification_enter_recovery_key" = "Inserisci la chiave di recupero"; -"screen_session_verification_failed_subtitle" = "Either the request timed out, the request was denied, or there was a verification mismatch."; +"screen_session_verification_failed_subtitle" = "La richiesta è scaduta, è stata rifiutata o c'è stata una mancata corrispondenza nella verifica."; "screen_session_verification_open_existing_session_subtitle" = "Dimostra la tua identità per accedere alla cronologia dei messaggi crittografati."; "screen_session_verification_open_existing_session_title" = "Apri una sessione esistente"; "screen_session_verification_positive_button_canceled" = "Riprova la verifica"; @@ -869,19 +917,19 @@ "screen_session_verification_positive_button_verifying_ongoing" = "In attesa di un riscontro"; "screen_session_verification_ready_subtitle" = "Confronta un set unico di emoji."; "screen_session_verification_request_accepted_subtitle" = "Confronta le emoji uniche, assicurandoti che appaiano nello stesso ordine."; -"screen_session_verification_request_details_timestamp" = "Signed in"; -"screen_session_verification_request_failure_title" = "Verification failed"; -"screen_session_verification_request_footer" = "Only continue if you initiated this verification."; -"screen_session_verification_request_subtitle" = "Verify the other device to keep your message history secure."; -"screen_session_verification_request_success_subtitle" = "Now you can read or send messages securely on your other device."; -"screen_session_verification_request_success_title" = "Device verified"; -"screen_session_verification_request_title" = "Verification requested"; +"screen_session_verification_request_details_timestamp" = "Accesso effettuato"; +"screen_session_verification_request_failure_title" = "Verifica fallita"; +"screen_session_verification_request_footer" = "Continua solo se tu hai avviato questa verifica."; +"screen_session_verification_request_subtitle" = "Verifica l'altro dispositivo per proteggere la cronologia dei messaggi."; +"screen_session_verification_request_success_subtitle" = "Ora puoi leggere o inviare messaggi in modo sicuro sull'altro dispositivo."; +"screen_session_verification_request_success_title" = "Dispositivo verificato"; +"screen_session_verification_request_title" = "Richiesta di verifica"; "screen_session_verification_they_dont_match" = "Non corrispondono"; "screen_session_verification_they_match" = "Corrispondono"; -"screen_session_verification_use_another_device_subtitle" = "Make sure you have the app open in the other device before starting verification from here."; -"screen_session_verification_use_another_device_title" = "Open the app on another verified device"; -"screen_session_verification_waiting_another_device_subtitle" = "You should see a popup on the other device. Start the verification from there now."; -"screen_session_verification_waiting_another_device_title" = "Start verification on the other device"; +"screen_session_verification_use_another_device_subtitle" = "Assicurati di avere l'app aperta sull'altro dispositivo prima di iniziare la verifica da qui."; +"screen_session_verification_use_another_device_title" = "Apri l'app su un altro dispositivo verificato"; +"screen_session_verification_waiting_another_device_subtitle" = "Dovresti vedere un popup sull'altro dispositivo. Inizia subito la verifica da lì."; +"screen_session_verification_waiting_another_device_title" = "Avvia la verifica sull'altro dispositivo"; "screen_session_verification_waiting_to_accept_subtitle" = "Accetta la richiesta di avviare il processo di verifica nell'altra sessione per continuare."; "screen_session_verification_waiting_to_accept_title" = "In attesa di accettare la richiesta"; "screen_share_location_title" = "Condividi posizione"; @@ -946,8 +994,8 @@ "state_event_room_invite_you" = "%1$@ ti ha invitato"; "state_event_room_join" = "%1$@ si è unito alla stanza"; "state_event_room_join_by_you" = "Ti sei unito alla stanza"; -"state_event_room_knock" = "%1$@ ha chiesto di unirsi"; -"state_event_room_knock_accepted" = "%1$@ ha permesso a %2$@ di unirsi"; +"state_event_room_knock" = "%1$@ ha richiesto di entrare"; +"state_event_room_knock_accepted" = "%1$@ ha permesso a %2$@ di entrare"; "state_event_room_knock_accepted_by_you" = "Hai permesso a %1$@ di partecipare"; "state_event_room_knock_by_you" = "Hai richiesto di unirti"; "state_event_room_knock_denied" = "%1$@ ha rifiutato la richiesta di unirsi di %2$@"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ ha apportato una modifica sconosciuta alla propria presenza nella stanza"; "test_language_identifier" = "it"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "La cronologia messaggi non è disponibile su questo dispositivo"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Impossibile decifrare il messaggio"; +"timeline_decryption_failure_withheld_unverified" = "Questo messaggio è stato bloccato perché il dispositivo non è verificato o perché il mittente deve verificare la tua identità."; "troubleshoot_notifications_entry_point_section" = "Risoluzione dei problemi"; "troubleshoot_notifications_screen_action" = "Esegui i test"; "troubleshoot_notifications_screen_action_again" = "Esegui nuovamente i test"; @@ -1067,8 +1119,8 @@ "screen_login_subtitle" = "Matrix è una rete aperta per comunicazioni sicure e decentralizzate."; "screen_notification_settings_mentions_section_title" = "Menzioni"; "screen_qr_code_login_invalid_scan_state_retry_button" = "Riprova"; -"screen_recovery_key_change_generate_key_description" = "Assicurati di conservare la chiave di recupero in un posto sicuro"; -"screen_recovery_key_confirm_title" = "Enter your recovery key"; +"screen_recovery_key_change_generate_key_description" = "Non condividerla con nessuno!"; +"screen_recovery_key_confirm_title" = "Inserisci la tua chiave di recupero"; "screen_report_content_block_user" = "Blocca utente"; "screen_reset_encryption_password_placeholder" = "Inserisci..."; "screen_room_attachment_source_camera_photo" = "Scatta foto"; @@ -1094,7 +1146,7 @@ "screen_room_timeline_reactions_show_less" = "Mostra meno"; "screen_roomlist_filter_people" = "Persone"; "screen_server_confirmation_change_server" = "Cambia fornitore dell'account"; -"screen_session_verification_request_failure_subtitle" = "Either the request timed out, the request was denied, or there was a verification mismatch."; +"screen_session_verification_request_failure_subtitle" = "La richiesta è scaduta, è stata rifiutata o c'è stata una mancata corrispondenza nella verifica."; "screen_signout_confirmation_dialog_submit" = "Disconnetti"; "screen_signout_confirmation_dialog_title" = "Disconnetti"; "screen_signout_key_backup_offline_title" = "Il backup delle chiavi è ancora in corso"; diff --git a/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict index f84b37ef64..e14512de8d 100644 --- a/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict @@ -237,9 +237,9 @@ NSStringFormatValueTypeKey d one - %1$@ +%2$d other want to join this room + %1$@ +%2$d vogliono entrare in questa stanza other - %1$@ +%2$d others want to join this room + %1$@ +%2$d vogliono entrare in questa stanza screen_room_timeline_state_changes diff --git a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings index bfd0efcef3..7b4c8f6b63 100644 --- a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "View in timeline"; "action_view_source" = "წყაროს ნახვა"; "action_yes" = "დიახ"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Log Out & Upgrade"; "banner_migrate_to_native_sliding_sync_description" = "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; @@ -138,10 +139,13 @@ "common_creating_room" = "ოთახის შექმნა..."; "common_current_user_left_room" = "დატოვა ოთახი"; "common_dark" = "მუქი"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "გაშიფვრის შეცდომა"; "common_developer_options" = "დეველოპერის პარამეტრები"; "common_device_id" = "Device ID"; "common_direct_chat" = "პირდაპირი ჩატი"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(რედაქტირებულია)"; "common_editing" = "რედაქტირება"; "common_editing_caption" = "Editing caption"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "აბზაცის გარეშე"; "rich_text_editor_url_placeholder" = "Ბმული"; "rich_text_editor_a11y_add_attachment" = "დაამატეთ დანართი"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; "screen_advanced_settings_element_call_base_url" = "მორგებული Element-ის ზარის საბაზისო URL"; "screen_advanced_settings_element_call_base_url_description" = "დააყენეთ საბაზისო URL Element-ის ზარებისათვის."; "screen_advanced_settings_element_call_base_url_validation_error" = "არასწორი URL, გთხოვთ, დარწმუნდეთ, რომ შეიტანეთ პროტოკოლი (http/https) და სწორი მისამართი."; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "მედიის ატვირთვა ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა."; "screen_media_upload_preview_error_failed_sending" = "მედიის ატვირთვა ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Pinned messages"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "შეიყვანეთ თქვენი დეტალები"; "screen_login_title" = "კეთილი იყოს თქვენი მობრძანება!"; "screen_login_title_with_homeserver" = "შესვლა %1$@-ში"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "მედიის შერჩევა ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა."; "screen_migration_message" = "ეს არის ერთჯერადი პროცესი, მადლობა ლოდინისთვის."; "screen_migration_title" = "თქვენი ანგარიშის კონფიგურაცია"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "შეტყობინებების პარამეტრების ჩატვირთვისას მოხდა შეცდომა."; "screen_room_details_error_muting" = "ამ ოთახის დადუმება ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა."; "screen_room_details_error_unmuting" = "ამ ოთახის დადუმების მოხსნა ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "მორგებული"; "screen_room_details_notification_mode_default" = "ნაგულისხმევი"; "screen_room_details_share_room_title" = "ოთახის გაზიარება"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ უცნობი ცვლილება შეიტანა თავის წევრობაში"; "test_language_identifier" = "ka"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Troubleshoot"; "troubleshoot_notifications_screen_action" = "Run tests"; "troubleshoot_notifications_screen_action_again" = "Run tests again"; diff --git a/ElementX/Resources/Localizations/nl.lproj/Localizable.strings b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings index 4c633456bb..6d3b0ede16 100644 --- a/ElementX/Resources/Localizations/nl.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Bekijk in tijdlijn"; "action_view_source" = "Bron weergeven"; "action_yes" = "Ja"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Uitloggen & Upgraden"; "banner_migrate_to_native_sliding_sync_description" = "Je server ondersteunt nu een nieuw, sneller protocol. Log uit en log opnieuw in om nu te upgraden. Als je dit nu doet, voorkom je dat je geforceerd uitlogt wordt wanneer het oude protocol later wordt verwijderd."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Je homeserver ondersteunt het oude protocol niet meer. Log uit en log opnieuw in om de app te blijven gebruiken."; @@ -138,10 +139,13 @@ "common_creating_room" = "Kamer maken..."; "common_current_user_left_room" = "Heeft de kamer verlaten"; "common_dark" = "Donker"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Decryptie fout"; "common_developer_options" = "Ontwikkelaarsopties"; "common_device_id" = "Device ID"; "common_direct_chat" = "Directe chat"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(bewerkt)"; "common_editing" = "Bewerken"; "common_editing_caption" = "Editing caption"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "Inspringing ongedaan maken"; "rich_text_editor_url_placeholder" = "Link"; "rich_text_editor_a11y_add_attachment" = "Bijlage toevoegen"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; "screen_advanced_settings_element_call_base_url" = "Aangepaste basis-URL voor Element Call"; "screen_advanced_settings_element_call_base_url_description" = "Stel een aangepaste basis-URL in voor Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "Ongeldige URL, zorg ervoor dat je het protocol (http/https) en het juiste adres invult."; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Het verwerken van media voor uploaden is mislukt. Probeer het opnieuw."; "screen_media_upload_preview_error_failed_sending" = "Het uploaden van media is mislukt. Probeer het opnieuw."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Vastgezette berichten"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Bericht niet verzonden omdat %1$@'s geverifieerde identiteit is gewijzigd."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Bericht niet verzonden omdat %1$@ niet alle apparaten heeft geverifieerd."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Bericht is niet verzonden omdat je een of meerdere apparaten niet geverifieerd hebt"; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Vul je gegevens in"; "screen_login_title" = "Welkom terug!"; "screen_login_title_with_homeserver" = "Inloggen bij %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Het selecteren van media is mislukt. Probeer het opnieuw."; "screen_migration_message" = "Dit is een eenmalig proces, bedankt voor het wachten."; "screen_migration_title" = "Je account instellen."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Er is een fout opgetreden bij het laden van de meldingsinstellingen."; "screen_room_details_error_muting" = "Het dempen van deze kamer is mislukt. Probeer het opnieuw."; "screen_room_details_error_unmuting" = "Het dempen opheffen voor deze kamer is mislukt. Probeer het opnieuw."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Aangepast"; "screen_room_details_notification_mode_default" = "Standaard"; "screen_room_details_share_room_title" = "Kamer delen"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ heeft een onbekende lidmaatschapswijziging"; "test_language_identifier" = "en"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Problemen oplossen"; "troubleshoot_notifications_screen_action" = "Tests uitvoeren"; "troubleshoot_notifications_screen_action_again" = "Tests opnieuw uitvoeren"; diff --git a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings index 37b1f45f85..2dc5cd0462 100644 --- a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Wyświetl na osi czasu"; "action_view_source" = "Wyświetl źródło"; "action_yes" = "Tak"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Wyloguj się i zaktualizuj"; "banner_migrate_to_native_sliding_sync_description" = "Twój serwer obsługuje teraz nowy, szybszy protokół. Wyloguj się i zaloguj ponownie, aby uaktualnić teraz. Zrobienie tego teraz pomoże uniknąć wymuszonego wylogowania, gdy stary protokół zostanie później usunięty."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Twój serwer domowy już nie wspiera starego protokołu. Zaloguj się ponownie, aby kontynuować korzystanie z aplikacji."; @@ -127,7 +128,7 @@ "common_acceptable_use_policy" = "Polityka użytkowania"; "common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Ustawienia zaawansowane"; -"common_analytics" = "Analityka"; +"common_analytics" = "Dane analityczne"; "common_appearance" = "Wygląd"; "common_audio" = "Dźwięk"; "common_blocked_users" = "Zablokowani użytkownicy"; @@ -138,10 +139,13 @@ "common_creating_room" = "Tworzenie pokoju..."; "common_current_user_left_room" = "Opuścił pokój"; "common_dark" = "Ciemny"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Błąd deszyfrowania"; "common_developer_options" = "Opcje programisty"; "common_device_id" = "ID urządzenia"; "common_direct_chat" = "Czat prywatny"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(edytowane)"; "common_editing" = "Edytowanie"; "common_editing_caption" = "Editing caption"; @@ -260,7 +264,7 @@ "confirm_recovery_key_banner_title" = "Wprowadź swój klucz przywracania"; "crash_detection_dialog_content" = "%1$@ uległ awarii podczas ostatniego użycia. Czy chcesz przesłać nam raport o awarii?"; "crypto_identity_change_pin_violation" = "Tożsamość %1$@ mogła ulec zmianie. %2$@"; -"crypto_identity_change_pin_violation_new" = "%1$@’s %2$@ identity appears to have changed. %3$@"; +"crypto_identity_change_pin_violation_new" = "Wygląda na to, że tożsamość %1$@ %2$@ uległa zmianie. %3$@"; "crypto_identity_change_pin_violation_new_user_id" = "(%1$@)"; "dialog_permission_camera" = "Aby umożliwić aplikacji korzystanie z aparatu, prosimy o udzielenie zezwolenia w ustawieniach systemowych."; "dialog_permission_generic" = "Proszę nadać uprawnienia w ustawieniach systemowych."; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "Bez wcięcia"; "rich_text_editor_url_placeholder" = "Link"; "rich_text_editor_a11y_add_attachment" = "Dodaj załącznik"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; "screen_advanced_settings_element_call_base_url" = "Własny bazowy URL dla połączeń Element"; "screen_advanced_settings_element_call_base_url_description" = "Ustaw własny bazowy URL dla połączeń Element"; "screen_advanced_settings_element_call_base_url_validation_error" = "Nieprawidłowy adres URL, upewnij się, że zawiera protokół (http/https) i poprawny adres."; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Przetwarzanie multimediów do przesłania nie powiodło się, spróbuj ponownie."; "screen_media_upload_preview_error_failed_sending" = "Przesyłanie multimediów nie powiodło się, spróbuj ponownie."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Przypięte wiadomości"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Wysłano prośbę o dołączenie"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Wiadomość nie została wysłana, ponieważ tożsamość %1$@ uległa zmianie."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Wiadomość nie została wysłana, ponieważ %1$@ nie zweryfikował wszystkich urządzeń."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Wiadomość nie została wysłana, ponieważ nie zweryfikowałeś jednego lub więcej swoich urządzeń."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Wprowadź swoje dane"; "screen_login_title" = "Witaj ponownie!"; "screen_login_title_with_homeserver" = "Zaloguj się do %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Nie udało się wybrać multimediów. Spróbuj ponownie."; "screen_migration_message" = "Jest to jednorazowy proces, dziękujemy za czekanie."; "screen_migration_title" = "Konfigurowanie Twojego konta."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Wystąpił błąd podczas ładowania ustawień powiadomień."; "screen_room_details_error_muting" = "Wyciszenie tego pokoju nie powiodło się, spróbuj ponownie."; "screen_room_details_error_unmuting" = "Nie udało się wyłączyć wyciszenia tego pokoju. Spróbuj ponownie."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Niestandardowy"; "screen_room_details_notification_mode_default" = "Domyślny"; "screen_room_details_share_room_title" = "Udostępnij pokój"; @@ -856,7 +904,7 @@ "screen_server_confirmation_title_register" = "Zamierzasz utworzyć konto na %1$@"; "screen_session_verification_cancelled_subtitle" = "Coś tu nie gra. Albo upłynął limit czasu, albo żądanie zostało odrzucone."; "screen_session_verification_compare_emojis_subtitle" = "Upewnij się, że emoji poniżej pasują do tych pokazanych na innej sesji."; -"screen_session_verification_compare_emojis_title" = "Porównaj emotki"; +"screen_session_verification_compare_emojis_title" = "Porównaj emoji"; "screen_session_verification_compare_numbers_subtitle" = "Upewnij się, że liczby poniżej pasują do tych wyświetlanych na innej sesji."; "screen_session_verification_compare_numbers_title" = "Porównaj liczby"; "screen_session_verification_complete_subtitle" = "Twoja nowa sesja jest teraz zweryfikowana. Ma ona dostęp do Twoich zaszyfrowanych wiadomości, a inni użytkownicy będą widzieć ją jako zaufaną."; @@ -868,7 +916,7 @@ "screen_session_verification_positive_button_initial" = "Jestem gotowy(a)"; "screen_session_verification_positive_button_verifying_ongoing" = "Oczekiwanie na dopasowanie"; "screen_session_verification_ready_subtitle" = "Porównaj unikalny zestaw emoji."; -"screen_session_verification_request_accepted_subtitle" = "Porównaj unikalne emoji, upewniając się, że pojawiły się w tej samej kolejności."; +"screen_session_verification_request_accepted_subtitle" = "Porównaj unikalny zestaw emoji i upewnij się, że są w tej samej kolejności."; "screen_session_verification_request_details_timestamp" = "Zalogowano"; "screen_session_verification_request_failure_title" = "Weryfikacja nie powiodła się"; "screen_session_verification_request_footer" = "Kontynuuj tylko, jeśli to Ty zainicjowałeś tę weryfikację."; @@ -883,7 +931,7 @@ "screen_session_verification_waiting_another_device_subtitle" = "You should see a popup on the other device. Start the verification from there now."; "screen_session_verification_waiting_another_device_title" = "Start verification on the other device"; "screen_session_verification_waiting_to_accept_subtitle" = "Zaakceptuj prośbę o rozpoczęcie procesu weryfikacji w innej sesji, aby kontynuować."; -"screen_session_verification_waiting_to_accept_title" = "Oczekiwanie na zaakceptowanie żądania"; +"screen_session_verification_waiting_to_accept_title" = "Oczekiwanie na zaakceptowanie prośby"; "screen_share_location_title" = "Udostępnij lokalizację"; "screen_share_my_location_action" = "Udostępnij moją lokalizację"; "screen_share_open_apple_maps" = "Otwórz w Apple Maps"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ dokonał nieznanej zmiany w swoim członkostwie"; "test_language_identifier" = "pl"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Rozwiązywanie problemów"; "troubleshoot_notifications_screen_action" = "Uruchom testy"; "troubleshoot_notifications_screen_action_again" = "Uruchom testy ponownie"; diff --git a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings index ea5cd6ded4..370ac34243 100644 --- a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "View in timeline"; "action_view_source" = "Ver fonte"; "action_yes" = "Sim"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Log Out & Upgrade"; "banner_migrate_to_native_sliding_sync_description" = "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; @@ -138,10 +139,13 @@ "common_creating_room" = "Criando sala…"; "common_current_user_left_room" = "Saiu da sala"; "common_dark" = "Escuro"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Erro de descriptografia"; "common_developer_options" = "Opções do desenvolvedor"; "common_device_id" = "Device ID"; "common_direct_chat" = "Conversa privada"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(editado)"; "common_editing" = "Editando"; "common_editing_caption" = "Editing caption"; @@ -352,9 +356,9 @@ "rich_text_editor_unindent" = "Desidentar"; "rich_text_editor_url_placeholder" = "Link"; "rich_text_editor_a11y_add_attachment" = "Adicionar anexo"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; -"screen_advanced_settings_element_call_base_url" = "Custom Element Call base URL"; -"screen_advanced_settings_element_call_base_url_description" = "Set a custom base URL for Element Call."; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; +"screen_advanced_settings_element_call_base_url" = "URL base do Element Call personalizado"; +"screen_advanced_settings_element_call_base_url_description" = "Defina um URL base personalizado para Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "URL inválida, por favor verifique se o protocolo (http/https) e o endereço correto estão presentes."; "screen_create_room_room_access_section_anyone_option_description" = "Anyone can join this room"; "screen_create_room_room_access_section_anyone_option_title" = "Anyone"; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Falha ao processar mídia para upload. Tente novamente."; "screen_media_upload_preview_error_failed_sending" = "Falha ao enviar mídia. Tente novamente."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Pinned messages"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -492,14 +528,14 @@ "screen_change_server_title" = "Selecione seu servidor"; "screen_chat_backup_key_backup_action_disable" = "Desativar o backup"; "screen_chat_backup_key_backup_action_enable" = "Ativar o backup"; -"screen_chat_backup_key_backup_description" = "O backup garante que você não perca seu histórico de mensagens. %1$@."; +"screen_chat_backup_key_backup_description" = "Armazene sua identidade criptográfica e chaves de mensagem com segurança no servidor. Isso permitirá que você visualize seu histórico de mensagens em quaisquer novos dispositivos.%1$@ ."; "screen_chat_backup_key_backup_title" = "Armazenamento de chaves"; "screen_chat_backup_key_storage_disabled_error" = "Key storage must be turned on to set up recovery."; "screen_chat_backup_key_storage_toggle_description" = "Upload keys from this device"; "screen_chat_backup_key_storage_toggle_title" = "Allow key storage"; "screen_chat_backup_recovery_action_change" = "Alterar chave de recuperação"; "screen_chat_backup_recovery_action_change_description" = "Recover your cryptographic identity and message history with a recovery key if you’ve lost all your existing devices."; -"screen_chat_backup_recovery_action_confirm_description" = "Seu backup das conversas está atualmente fora de sincronia."; +"screen_chat_backup_recovery_action_confirm_description" = "Seu armazenamento de chaves está fora de sincronia no momento."; "screen_chat_backup_recovery_action_setup_description" = "Tenha acesso às suas mensagens criptografadas se você perder todos os seus dispositivos ou for desconectado do %1$@ em qualquer lugar."; "screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Open %1$@ in a desktop device"; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Insira seus dados"; "screen_login_title" = "Bem-vindo de volta!"; "screen_login_title_with_homeserver" = "Iniciar sessão em %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Falha ao selecionar a mídia, tente novamente."; "screen_migration_message" = "Este é um processo único, obrigado por esperar."; "screen_migration_title" = "Configurando sua conta."; @@ -681,14 +728,14 @@ "screen_recovery_key_copied_to_clipboard" = "Chave de recuperação copiada"; "screen_recovery_key_generating_key" = "Gerando..."; "screen_recovery_key_save_action" = "Salvar chave de recuperação"; -"screen_recovery_key_save_description" = "Anote sua chave de recuperação em algum lugar seguro ou salve-a em um gerenciador de senhas."; +"screen_recovery_key_save_description" = "Anote essa chave de recuperação em algum lugar seguro, como um gerenciador de senhas, uma nota criptografada ou um cofre físico."; "screen_recovery_key_save_key_description" = "Toque para copiar a chave de recuperação"; "screen_recovery_key_save_title" = "Salve sua chave de recuperação"; "screen_recovery_key_setup_confirmation_description" = "Você não poderá acessar sua nova chave de recuperação após essa etapa."; "screen_recovery_key_setup_confirmation_title" = "Você salvou sua chave de recuperação?"; "screen_recovery_key_setup_description" = "Seu backup das conversas é protegido por uma chave de recuperação. Se precisar de uma nova chave de recuperação após a configuração, você pode recriá-la selecionando “Alterar chave de recuperação”."; "screen_recovery_key_setup_generate_key" = "Gere sua chave de recuperação"; -"screen_recovery_key_setup_generate_key_description" = "Certifique-se de que você pode armazenar sua chave de recuperação em algum lugar seguro"; +"screen_recovery_key_setup_generate_key_description" = "Não compartilhe isso com ninguém!"; "screen_recovery_key_setup_success" = "Configuração de recuperação bem-sucedida"; "screen_recovery_key_setup_title" = "Configurar a recuperação"; "screen_report_content_block_user_hint" = "Marque se você deseja ocultar todas as mensagens atuais e futuras desse usuário"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Ocorreu um erro ao carregar as configurações de notificação."; "screen_room_details_error_muting" = "Falha ao silenciar esta sala, tente novamente."; "screen_room_details_error_unmuting" = "Falha ao ativar o som desta sala. Tente novamente."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Personalizado"; "screen_room_details_notification_mode_default" = "Padrão"; "screen_room_details_share_room_title" = "Compartilhar sala"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ fez uma alteração desconhecida em sua associação"; "test_language_identifier" = "pt-br"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Troubleshoot"; "troubleshoot_notifications_screen_action" = "Execute testes"; "troubleshoot_notifications_screen_action_again" = "Run tests again"; @@ -1067,7 +1119,7 @@ "screen_login_subtitle" = "A Matrix é uma rede aberta para comunicação segura e descentralizada."; "screen_notification_settings_mentions_section_title" = "Menções"; "screen_qr_code_login_invalid_scan_state_retry_button" = "Tente novamente"; -"screen_recovery_key_change_generate_key_description" = "Certifique-se de que você pode armazenar sua chave de recuperação em algum lugar seguro"; +"screen_recovery_key_change_generate_key_description" = "Não compartilhe isso com ninguém!"; "screen_recovery_key_confirm_title" = "Enter your recovery key"; "screen_report_content_block_user" = "Bloquear usuário"; "screen_reset_encryption_password_placeholder" = "Inserir..."; diff --git a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings index e0453d96d1..e6c9938f47 100644 --- a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Ver na cronologia"; "action_view_source" = "Ver fonte"; "action_yes" = "Sim"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Sair & Atualizar"; "banner_migrate_to_native_sliding_sync_description" = "O teu servidor suporta agora um protocolo novo e mais rápido. Termina a sessão e volta a iniciar sessão para atualizar agora. Se o fizeres agora, evitarás um fim de sessão forçado quando o protocolo antigo for removido mais tarde."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Seu homeserver não suporta mais o protocolo antigo. Termine sessão e volte a iniciar sessão para continuar a utilizar a aplicação."; @@ -138,10 +139,13 @@ "common_creating_room" = "A criar sala…"; "common_current_user_left_room" = "Saíste da sala"; "common_dark" = "Escuro"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Erro de decifragem"; "common_developer_options" = "Opções de programador"; "common_device_id" = "ID do dispositivo"; "common_direct_chat" = "Conversa direta"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(editada)"; "common_editing" = "A editar"; "common_editing_caption" = "Editing caption"; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Falha ao processar multimédia para carregamento, por favor tente novamente."; "screen_media_upload_preview_error_failed_sending" = "Falhar ao carregar multimédia, por favor tente novamente."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Mensagens afixadas"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Pedido de adesão enviado"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Mensagem não enviada porque a identidade verificada de %1$@ foi alterada."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Mensagem não enviada porque %1$@ não verificou todos os dispositivos."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Mensagem não enviada porque não verificou um ou mais dos seus dispositivos."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Insere o teus detalhes"; "screen_login_title" = "Bem-vindo(a) de volta!"; "screen_login_title_with_homeserver" = "Iniciar sessão em %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Falha ao selecionar multimédia, por favor tente novamente."; "screen_migration_message" = "Este processo só acontece uma única vez, obrigado por esperares."; "screen_migration_title" = "A configurar a tua conta…"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Erro ao carregar as configurações de notificação."; "screen_room_details_error_muting" = "Não foi possível silenciar esta sala, por favor tenta novamente."; "screen_room_details_error_unmuting" = "Não foi possível dessilenciar esta sala, por favor tenta novamente."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Personalizado"; "screen_room_details_notification_mode_default" = "Predefinição"; "screen_room_details_share_room_title" = "Partilhar sala"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ efetuou uma alteração desconhecida à sua participação na sala"; "test_language_identifier" = "pt"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Resolução de problemas"; "troubleshoot_notifications_screen_action" = "Correr testes"; "troubleshoot_notifications_screen_action_again" = "Correr testes novamente"; diff --git a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings index dbbeb1b50a..7cdf53620d 100644 --- a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "View in timeline"; "action_view_source" = "Vedeți sursă"; "action_yes" = "Da"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Log Out & Upgrade"; "banner_migrate_to_native_sliding_sync_description" = "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; @@ -138,10 +139,13 @@ "common_creating_room" = "Se creează camera…"; "common_current_user_left_room" = "Ați parăsit camera"; "common_dark" = "Întunecat"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Eroare de decriptare"; "common_developer_options" = "Opțiuni programator"; "common_device_id" = "Device ID"; "common_direct_chat" = "Chat direct"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(editat)"; "common_editing" = "Editare"; "common_editing_caption" = "Editing caption"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "Dez-identare"; "rich_text_editor_url_placeholder" = "Link"; "rich_text_editor_a11y_add_attachment" = "Adăugați un atașament"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; "screen_advanced_settings_element_call_base_url" = "Adresa URL de bază Element Call"; "screen_advanced_settings_element_call_base_url_description" = "Setați o adresă URL de bază personalizată pentru Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "URL invalid, vă rugăm să vă asigurați că includeți protocolul (http/https) și adresa corectă."; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Procesarea datelor media a eșuat, vă rugăm să încercați din nou."; "screen_media_upload_preview_error_failed_sending" = "Încărcarea fișierelor media a eșuat, încercați din nou."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Pinned messages"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Introduceți detaliile"; "screen_login_title" = "Bine ați revenit!"; "screen_login_title_with_homeserver" = "Conectați-vă la %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Selectarea fișierelor media a eșuat, încercați din nou."; "screen_migration_message" = "Acesta este un proces care se desfășoară o singură dată, vă mulțumim pentru așteptare."; "screen_migration_title" = "Contul dumneavoastră se configurează"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "A apărut o eroare la încărcarea setărilor pentru notificari."; "screen_room_details_error_muting" = "Dezactivarea notificarilor pentru această cameră a eșuat, încercați din nou."; "screen_room_details_error_unmuting" = "Activarea notificarilor pentru această cameră a eșuat, încercați din nou."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Personalizat"; "screen_room_details_notification_mode_default" = "Implicit"; "screen_room_details_share_room_title" = "Partajați camera"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ a făcut o modificare necunoscută asupra calității sale de membru"; "test_language_identifier" = "ro"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Depanare"; "troubleshoot_notifications_screen_action" = "Rulați testele"; "troubleshoot_notifications_screen_action_again" = "Rulați din nou testele"; diff --git a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings index 1e29541697..07832649c8 100644 --- a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Просмотр в хронологии"; "action_view_source" = "Показать источник"; "action_yes" = "Да"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Выйти и обновить"; "banner_migrate_to_native_sliding_sync_description" = "Теперь ваш сервер поддерживает новый, более быстрый протокол. Чтобы обновить его прямо сейчас, выйдите и войдите в свою учётную запись снова. Сделав это сейчас, вы сможете избежать принудительного выхода из системы при последующем удалении старого протокола."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Ваш домашний сервер больше не поддерживает старый протокол. Пожалуйста, выйдите и войдите в свою учётную запись снова, чтобы продолжить использование приложения."; @@ -138,10 +139,13 @@ "common_creating_room" = "Создание комнаты…"; "common_current_user_left_room" = "Покинул комнату"; "common_dark" = "Тёмное"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Ошибка расшифровки"; "common_developer_options" = "Для разработчика"; "common_device_id" = "Идентификатор устройства"; "common_direct_chat" = "Личный чат"; +"common_downloading" = "Загрузка"; "common_edited_suffix" = "(изменено)"; "common_editing" = "Редактирование"; "common_editing_caption" = "Редактирование подписи"; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Вы действительно хотите принять все заявки на присоединение?"; "screen_knock_requests_list_accept_all_alert_title" = "Принять все запросы"; "screen_knock_requests_list_accept_all_button_title" = "Принять всё"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Да, отклонить и запретить"; "screen_knock_requests_list_ban_alert_description" = "Вы уверен, что хочешь отклонить и запретить %1$@? Этот пользователь больше не сможет запросить доступ к этой комнате."; "screen_knock_requests_list_ban_alert_title" = "Отклонить и запретить доступ"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Да, отклонить"; "screen_knock_requests_list_decline_alert_description" = "Вы уверены, что хотите отклонить %1$@ запрос на присоединение к этой комнате?"; "screen_knock_requests_list_decline_alert_title" = "Отклонить доступ"; "screen_knock_requests_list_decline_and_ban_action_title" = "Отклонить и запретить"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "Вы сможете увидеть запрос, когда кто-то попросит присоединиться к комнате."; "screen_knock_requests_list_empty_state_title" = "Нет ожидающих запросов на присоединение"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Запросы на присоединение"; +"screen_media_details_file_format" = "Формат файла"; +"screen_media_details_filename" = "Имя файла"; +"screen_media_details_redact_confirmation_message" = "Этот файл будет удален из комнаты и у участников не будет к нему доступа."; +"screen_media_details_redact_confirmation_title" = "Удалить файл?"; +"screen_media_details_uploaded_by" = "Загружено"; +"screen_media_details_uploaded_on" = "Загружено на"; "screen_media_upload_preview_caption_warning" = "Подпись может быть не видна пользователям старых приложений."; "screen_media_upload_preview_error_failed_processing" = "Не удалось обработать медиафайл для загрузки, попробуйте еще раз."; "screen_media_upload_preview_error_failed_sending" = "Не удалось загрузить медиафайлы, попробуйте еще раз."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "Просмотр"; "screen_room_details_pinned_events_row_title" = "Закрепленные сообщения"; "screen_room_details_requests_to_join_title" = "Запросы на вступление"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Запрос на присоединение отправлен"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Сообщение не отправлено, потому что верифицированная личность %1$@ изменилась."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Сообщение не отправлено, потому что %1$@ не проверил одно или несколько устройств."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Сообщение не отправлено, поскольку вы не подтвердили одно или несколько своих устройств."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Введите свои данные"; "screen_login_title" = "Рады видеть вас снова!"; "screen_login_title_with_homeserver" = "Войти в %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "Этот файл будет удален из комнаты и участники не будут иметь к нему доступ."; +"screen_media_browser_delete_confirmation_title" = "Удалить файл?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Загрузка файлов..."; +"screen_media_browser_list_loading_media" = "Загрузка медиа…"; +"screen_media_browser_list_mode_files" = "Файлы"; +"screen_media_browser_list_mode_media" = "Медиа"; +"screen_media_browser_media_empty_state_subtitle" = "Здесь будут показаны изображения и видео, загруженные в данную комнату."; +"screen_media_browser_media_empty_state_title" = "Пока что нет загруженных медиафайлов"; +"screen_media_browser_title" = "Медиа и файлы"; "screen_media_picker_error_failed_selection" = "Не удалось выбрать носитель, попробуйте еще раз."; "screen_migration_message" = "Это одноразовый процесс, спасибо, что подождали."; "screen_migration_title" = "Настройка учетной записи."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Произошла ошибка при загрузке настроек уведомлений."; "screen_room_details_error_muting" = "Не удалось отключить звук в этой комнате, попробуйте еще раз."; "screen_room_details_error_unmuting" = "Не удалось включить звук в эту комнату, попробуйте еще раз."; +"screen_room_details_media_gallery_title" = "Медиа и файлы"; "screen_room_details_notification_mode_custom" = "Пользовательский"; "screen_room_details_notification_mode_default" = "По умолчанию"; "screen_room_details_share_room_title" = "Поделиться комнатой"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ внес неизвестное изменение для своих участников"; "test_language_identifier" = "ru"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "На этом устройстве недоступна история сообщений"; +"timeline_decryption_failure_historical_event_user_not_joined" = "У вас нет доступа к этому сообщению"; +"timeline_decryption_failure_unable_to_decrypt" = "Не удалось расшифровать сообщение"; +"timeline_decryption_failure_withheld_unverified" = "Это сообщение было заблокировано по причине того, что вы не подтвердили свое устройство, либо отправителю необходимо подтвердить вашу личность."; "troubleshoot_notifications_entry_point_section" = "Устранение неполадок"; "troubleshoot_notifications_screen_action" = "Выполнение тестов"; "troubleshoot_notifications_screen_action_again" = "Повторное выполнение тестов"; diff --git a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings index 367a13aa32..3e714bab58 100644 --- a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Zobraziť na časovej osi"; "action_view_source" = "Zobraziť zdroj"; "action_yes" = "Áno"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Odhlásiť sa a aktualizovať"; "banner_migrate_to_native_sliding_sync_description" = "Váš server teraz podporuje nový, rýchlejší protokol. Odhláste sa a prihláste sa znova, aby ste mohli aktualizovať. Ak to urobíte teraz, pomôže vám vyhnúť sa nútenému odhláseniu, keď sa starý protokol neskôr odstráni."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Váš domovský server už nepodporuje starý protokol. Ak chcete pokračovať v používaní aplikácie, odhláste sa a znova sa prihláste."; @@ -138,10 +139,13 @@ "common_creating_room" = "Vytváranie miestnosti..."; "common_current_user_left_room" = "Opustil/a miestnosť"; "common_dark" = "Tmavý"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Chyba dešifrovania"; "common_developer_options" = "Možnosti pre vývojárov"; "common_device_id" = "ID zariadenia"; "common_direct_chat" = "Priama konverzácia"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(upravené)"; "common_editing" = "Upravuje sa"; "common_editing_caption" = "Úprava titulku"; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Prijať všetky"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Odmietnuť a zakázať"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "Keď niekto požiada, aby sa pripojil k miestnosti, jeho žiadosť si môžete pozrieť tu."; "screen_knock_requests_list_empty_state_title" = "Žiadna čakajúca žiadosť o pripojenie"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Žiadosti o pripojenie"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova."; "screen_media_upload_preview_error_failed_sending" = "Nepodarilo sa nahrať médiá, skúste to prosím znova."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "Zobraziť"; "screen_room_details_pinned_events_row_title" = "Pripnuté správy"; "screen_room_details_requests_to_join_title" = "Žiadosti o vstup"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Žiadosť o vstup odoslaná"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Správa nebola odoslaná, pretože sa zmenila overená totožnosť používateľa %1$@."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Správa nebola odoslaná, pretože %1$@ neoveril/a všetky zariadenia."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Správa nebola odoslaná, pretože ste neoverili jedno alebo viac svojich zariadení."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Zadajte svoje údaje"; "screen_login_title" = "Vitajte späť!"; "screen_login_title_with_homeserver" = "Prihlásiť sa do %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Nepodarilo sa vybrať médium, skúste to prosím znova."; "screen_migration_message" = "Ide o jednorazový proces, ďakujeme za trpezlivosť."; "screen_migration_title" = "Nastavenie vášho účtu."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Pri načítaní nastavení oznámení došlo k chybe."; "screen_room_details_error_muting" = "Nepodarilo sa stlmiť túto miestnosť, skúste to prosím znova."; "screen_room_details_error_unmuting" = "Nepodarilo sa zrušiť stlmenie tejto miestnosti, skúste to prosím znova."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Vlastné"; "screen_room_details_notification_mode_default" = "Predvolené"; "screen_room_details_share_room_title" = "Zdieľať miestnosť"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ urobil/a neznámu zmenu svojho členstva"; "test_language_identifier" = "sk"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Riešenie problémov"; "troubleshoot_notifications_screen_action" = "Spustiť testy"; "troubleshoot_notifications_screen_action_again" = "Spustiť testy znova"; diff --git a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings index 12ccf743e0..f3b8f4d96d 100644 --- a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Visa i tidslinjen"; "action_view_source" = "Visa källkod"; "action_yes" = "Ja"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Log Out & Upgrade"; "banner_migrate_to_native_sliding_sync_description" = "Din server stöder nu ett nytt, snabbare protokoll. Logga ut och logga in igen för att uppgradera nu. Om du gör detta nu hjälper du dig att undvika en tvingad utloggning när det gamla protokollet tas bort senare."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; @@ -138,10 +139,13 @@ "common_creating_room" = "Skapar rum …"; "common_current_user_left_room" = "Lämnade rummet"; "common_dark" = "Mörkt"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Avkrypteringsfel"; "common_developer_options" = "Utvecklaralternativ"; "common_device_id" = "Device ID"; "common_direct_chat" = "Direktchatt"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(redigerad)"; "common_editing" = "Redigerar"; "common_editing_caption" = "Editing caption"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "Ta bort indrag"; "rich_text_editor_url_placeholder" = "Länk"; "rich_text_editor_a11y_add_attachment" = "Lägg till bilaga"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; "screen_advanced_settings_element_call_base_url" = "Anpassad bas-URL för Element Call"; "screen_advanced_settings_element_call_base_url_description" = "Ange en anpassad bas-URL för Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "Ogiltig URL, se till att du inkluderar protokollet (http/https) och rätt adress."; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Misslyckades att bearbeta media för uppladdning, vänligen pröva igen."; "screen_media_upload_preview_error_failed_sending" = "Misslyckades att ladda upp media, vänligen pröva igen."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Fästa meddelanden"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Ange dina uppgifter"; "screen_login_title" = "Välkommen tillbaka!"; "screen_login_title_with_homeserver" = "Logga in på %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Misslyckades att välja media, vänligen pröva igen."; "screen_migration_message" = "Detta är en engångsprocess, tack för att du väntar."; "screen_migration_title" = "Konfigurerar ditt konto"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Ett fel uppstod vid laddning av aviseringsinställningar."; "screen_room_details_error_muting" = "Misslyckades att tysta det här rummet, vänligen pröva igen."; "screen_room_details_error_unmuting" = "Misslyckades att avtysta det här rummet, vänligen pröva igen."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Anpassad"; "screen_room_details_notification_mode_default" = "Förval"; "screen_room_details_share_room_title" = "Dela rum"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ gjorde en okänd ändring till deras medlemsskap."; "test_language_identifier" = "sv"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Felsök"; "troubleshoot_notifications_screen_action" = "Kör tester"; "troubleshoot_notifications_screen_action_again" = "Kör tester igen"; diff --git a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings index b2b8377d92..32c75c1eab 100644 --- a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "Переглянути на шкалі часу"; "action_view_source" = "Переглянути джерело"; "action_yes" = "Так"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Вийти та оновити"; "banner_migrate_to_native_sliding_sync_description" = "Ваш сервер тепер підтримує новий, швидший протокол. Вийдіть із системи та увійдіть знову, щоб оновити систему зараз. Якщо ви зробите це зараз, це допоможе вам уникнути примусового виходу з системи, коли старий протокол буде видалено пізніше."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Ваш домашній сервер більше не підтримує старий протокол. Будь ласка, вийдіть і увійдіть знову, щоб продовжити використання програми."; @@ -138,10 +139,13 @@ "common_creating_room" = "Створення кімнати..."; "common_current_user_left_room" = "Виходить з кімнати"; "common_dark" = "Темна"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Помилка розшифрування"; "common_developer_options" = "Налаштування розробника"; "common_device_id" = "Ідентифікатор пристрою"; "common_direct_chat" = "Особиста бесіда"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(відредаговано)"; "common_editing" = "Редагування"; "common_editing_caption" = "Editing caption"; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Не вдалося обробити медіафайл для завантаження, спробуйте ще раз."; "screen_media_upload_preview_error_failed_sending" = "Не вдалося завантажити медіафайл, спробуйте ще раз."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Закріплені повідомлення"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Запит на приєднання надіслано"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Повідомлення не надіслано, оскільки підтверджена особистість %1$@ змінилася."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Повідомлення не надіслано, оскільки %1$@ перевірив не всі пристрої."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Повідомлення не надіслано, оскільки ви не підтвердили один або кілька своїх пристроїв."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Введіть свої дані"; "screen_login_title" = "З поверненням!"; "screen_login_title_with_homeserver" = "Увійти в %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Не вдалося вибрати медіафайл, спробуйте ще раз."; "screen_migration_message" = "Це одноразовий процес, дякую за очікування."; "screen_migration_title" = "Налаштування облікового запису."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Виникла помилка при завантаженні налаштувань сповіщень."; "screen_room_details_error_muting" = "Не вдалося вимкнути цю кімнату. Будь ласка, спробуйте ще раз."; "screen_room_details_error_unmuting" = "Не вдалося ввімкнути звук цієї кімнати. Повторіть спробу."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Власні"; "screen_room_details_notification_mode_default" = "Типово"; "screen_room_details_share_room_title" = "Поділитися кімнатою"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ вносить невідомі зміни щодо свого членства"; "test_language_identifier" = "uk"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Усунення несправностей"; "troubleshoot_notifications_screen_action" = "Запустити тести"; "troubleshoot_notifications_screen_action_again" = "Запустити тести знову"; diff --git a/ElementX/Resources/Localizations/uz.lproj/Localizable.strings b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings index 858a6e471e..fd82c2b82b 100644 --- a/ElementX/Resources/Localizations/uz.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "View in timeline"; "action_view_source" = "Manbani korish"; "action_yes" = "Ha"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Log Out & Upgrade"; "banner_migrate_to_native_sliding_sync_description" = "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; @@ -138,10 +139,13 @@ "common_creating_room" = "Xona yaratilmoqda…"; "common_current_user_left_room" = "Xonani tark etdi"; "common_dark" = "Dark"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "Shifrni ochish xatosi"; "common_developer_options" = "Dasturchi variantlari"; "common_device_id" = "Device ID"; "common_direct_chat" = "Direct chat"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(tahrirlangan)"; "common_editing" = "Tahrirlash"; "common_editing_caption" = "Editing caption"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "Paragrafni bekor qilish"; "rich_text_editor_url_placeholder" = "Havola"; "rich_text_editor_a11y_add_attachment" = "Biriktirma qo'shing"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; "screen_advanced_settings_element_call_base_url" = "Maxsus element qo‘ng‘iroqlar bazasi URL manzili"; "screen_advanced_settings_element_call_base_url_description" = "Element qo'ng'irog'iga maxsus asosiy url or'natish"; "screen_advanced_settings_element_call_base_url_validation_error" = "Invalid URL, please make sure you include the protocol (http/https) and the correct address."; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Mediani yuklab bo‘lmadi, qayta urinib ko‘ring."; "screen_media_upload_preview_error_failed_sending" = "Media yuklanmadi, qayta urinib ko‘ring."; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Pinned messages"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "Tafsilotlaringizni kiriting"; "screen_login_title" = "Qaytib kelganingizdan xursandmiz!"; "screen_login_title_with_homeserver" = "Kirish%1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Media tanlash jarayonida xatolik yuz berdi, qayta urinib ko'ring"; "screen_migration_message" = "Bu bir martalik jarayon, kutganingiz uchun rahmat."; "screen_migration_title" = "Hisobingiz sozlanmoqda."; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "Bildirishnoma sozlamalarini yuklashda xatolik yuz berdi."; "screen_room_details_error_muting" = "Bu xona ovozini o‘chirib bo‘lmadi, qayta urinib ko‘ring."; "screen_room_details_error_unmuting" = "Bu xonaning ovozi yoqilmadi, qayta urinib ko‘ring."; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "Maxsus"; "screen_room_details_notification_mode_default" = "Standart"; "screen_room_details_share_room_title" = "Xonani baham ko'ring"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ aʼzoligiga nomaʼlum oʻzgarishlar kiritdi"; "test_language_identifier" = "en"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Troubleshoot"; "troubleshoot_notifications_screen_action" = "Run tests"; "troubleshoot_notifications_screen_action_again" = "Run tests again"; diff --git a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings index a4ae040a24..f200a09b9d 100644 --- a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "在时间轴中查看"; "action_view_source" = "查看源码"; "action_yes" = "是"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "登出并升级"; "banner_migrate_to_native_sliding_sync_description" = "您的服务器现在支持更快的新协议。现在登出并重新登录以进行升级。现在这样做可以帮助您避免在以后删除旧协议时被强制登出。"; "banner_migrate_to_native_sliding_sync_force_logout_title" = "您的服务器不再支持旧协议。请登出并重新登录以继续使用此应用。"; @@ -138,10 +139,13 @@ "common_creating_room" = "正在创建聊天室..."; "common_current_user_left_room" = "离开聊天室"; "common_dark" = "深色"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "解密错误"; "common_developer_options" = "开发者选项"; "common_device_id" = "设备 ID"; "common_direct_chat" = "私聊"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(已编辑)"; "common_editing" = "编辑中"; "common_editing_caption" = "Editing caption"; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "处理要上传的媒体失败,请重试。"; "screen_media_upload_preview_error_failed_sending" = "上传媒体失败,请重试。"; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "置顶消息"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "加入请求已发送"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "消息未发送,因为 %1$@ 的已验证身份已经发生改变。"; "screen_timeline_item_menu_send_failure_unsigned_device" = "消息未发送,因为%1$@尚未验证所有设备。"; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "消息未发送,因为您有尚未验证的设备。"; @@ -586,6 +622,17 @@ "screen_login_form_header" = "输入您的详细信息"; "screen_login_title" = "欢迎回来!"; "screen_login_title_with_homeserver" = "登录到 %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "选择媒体失败,请重试。"; "screen_migration_message" = "这是一个一次性的过程,感谢您的等待。"; "screen_migration_title" = "设置您的账户。"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "加载通知设置时出错。"; "screen_room_details_error_muting" = "无法将此聊天室静音,请重试。"; "screen_room_details_error_unmuting" = "无法取消此聊天室的静音,请重试。"; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "自定义"; "screen_room_details_notification_mode_default" = "默认"; "screen_room_details_share_room_title" = "分享聊天室"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ 对其成员资格进行了未知更改"; "test_language_identifier" = "zh-Hans"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "排查问题"; "troubleshoot_notifications_screen_action" = "运行测试"; "troubleshoot_notifications_screen_action_again" = "再次运行测试"; diff --git a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings index 543bf88bbb..937717ff03 100644 --- a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "View in timeline"; "action_view_source" = "檢視原始碼"; "action_yes" = "是"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Log Out & Upgrade"; "banner_migrate_to_native_sliding_sync_description" = "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; @@ -138,10 +139,13 @@ "common_creating_room" = "正在建立聊天室..."; "common_current_user_left_room" = "已離開聊天室"; "common_dark" = "深色"; +"common_date_date_at_time" = "%1$@ at %2$@"; +"common_date_this_month" = "This month"; "common_decryption_error" = "解密錯誤"; "common_developer_options" = "開發者選項"; "common_device_id" = "Device ID"; "common_direct_chat" = "私訊"; +"common_downloading" = "Downloading"; "common_edited_suffix" = "(已編輯)"; "common_editing" = "編輯中"; "common_editing_caption" = "Editing caption"; @@ -352,7 +356,7 @@ "rich_text_editor_unindent" = "減少縮排"; "rich_text_editor_url_placeholder" = "連結"; "rich_text_editor_a11y_add_attachment" = "新增附件"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Add a caption"; "screen_advanced_settings_element_call_base_url" = "Custom Element Call base URL"; "screen_advanced_settings_element_call_base_url_description" = "Set a custom base URL for Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "Invalid URL, please make sure you include the protocol (http/https) and the correct address."; @@ -377,16 +381,33 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; +"screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; +"screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; "screen_knock_requests_list_ban_alert_title" = "Decline and ban from accessing"; +"screen_knock_requests_list_ban_loading_title" = "Declining and banning access"; "screen_knock_requests_list_decline_alert_confirm_button_title" = "Yes, decline"; "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; +"screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; +"screen_knock_requests_list_initial_loading_title" = "Loading requests to join…"; "screen_knock_requests_list_title" = "Requests to join"; +"screen_media_details_file_format" = "File format"; +"screen_media_details_filename" = "File name"; +"screen_media_details_redact_confirmation_message" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_details_redact_confirmation_title" = "Delete file?"; +"screen_media_details_uploaded_by" = "Uploaded by"; +"screen_media_details_uploaded_on" = "Uploaded on"; "screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; "screen_media_upload_preview_error_failed_processing" = "Failed processing media to upload, please try again."; "screen_media_upload_preview_error_failed_sending" = "無法上傳媒體檔案,請稍後再試。"; @@ -412,7 +433,22 @@ "screen_room_single_knock_request_view_button_title" = "View"; "screen_room_details_pinned_events_row_title" = "Pinned messages"; "screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_security_and_privacy_title" = "Security & privacy"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request."; +"screen_security_and_privacy_ask_to_join_option_title" = "Ask to join"; +"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption"; +"screen_security_and_privacy_enable_encryption_alert_description" = "Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.\nNo one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.\nWe do not recommend enabling encryption for rooms that anyone can find and join."; +"screen_security_and_privacy_enable_encryption_alert_title" = "Enable encryption?"; +"screen_security_and_privacy_encryption_section_footer" = "Once enabled, encryption cannot be disabled."; +"screen_security_and_privacy_encryption_section_title" = "Encryption"; +"screen_security_and_privacy_encryption_toggle_title" = "Enable end-to-end encryption"; +"screen_security_and_privacy_room_access_anyone_option_description" = "Anyone can find and join"; +"screen_security_and_privacy_room_access_anyone_option_title" = "Anyone"; +"screen_security_and_privacy_room_access_invite_only_option_description" = "People can only join if they are invited"; +"screen_security_and_privacy_room_access_invite_only_option_title" = "Invite only"; +"screen_security_and_privacy_room_access_section_title" = "Room access"; +"screen_security_and_privacy_title" = "Security & privacy"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified all devices."; "screen_timeline_item_menu_send_failure_you_unsigned_device" = "Message not sent because you have not verified one or more of your devices."; @@ -586,6 +622,17 @@ "screen_login_form_header" = "輸入您的詳細資料"; "screen_login_title" = "歡迎回來!"; "screen_login_title_with_homeserver" = "登入 %1$@"; +"screen_media_browser_delete_confirmation_subtitle" = "This file will be removed from the room and members won’t have access to it."; +"screen_media_browser_delete_confirmation_title" = "Delete file?"; +"screen_media_browser_files_empty_state_subtitle" = "Documents, audio files, and voice messages uploaded to this room will be shown here."; +"screen_media_browser_files_empty_state_title" = "No files uploaded yet"; +"screen_media_browser_list_loading_files" = "Loading files…"; +"screen_media_browser_list_loading_media" = "Loading media…"; +"screen_media_browser_list_mode_files" = "Files"; +"screen_media_browser_list_mode_media" = "Media"; +"screen_media_browser_media_empty_state_subtitle" = "Images and videos uploaded to this room will be shown here."; +"screen_media_browser_media_empty_state_title" = "No media uploaded yet"; +"screen_media_browser_title" = "Media and files"; "screen_media_picker_error_failed_selection" = "Failed selecting media, please try again."; "screen_migration_message" = "這是一次性的程序,感謝您耐心等候。"; "screen_migration_title" = "正在設定您的帳號。"; @@ -743,6 +790,7 @@ "screen_room_details_error_loading_notification_settings" = "載入通知設定時發生錯誤。"; "screen_room_details_error_muting" = "無法關閉聊天室通知,請再試一次。"; "screen_room_details_error_unmuting" = "無法開啟聊天室通知,請再試一次。"; +"screen_room_details_media_gallery_title" = "Media and files"; "screen_room_details_notification_mode_custom" = "自訂"; "screen_room_details_notification_mode_default" = "預設"; "screen_room_details_share_room_title" = "分享聊天室"; @@ -986,6 +1034,10 @@ "state_event_room_unknown_membership_change" = "%1$@ made an unknown change to their membership"; "test_language_identifier" = "zh-tw"; "test_untranslated_default_language_identifier" = "en"; +"timeline_decryption_failure_historical_event_no_key_backup" = "Historical messages are not available on this device"; +"timeline_decryption_failure_historical_event_user_not_joined" = "You don't have access to this message"; +"timeline_decryption_failure_unable_to_decrypt" = "Unable to decrypt message"; +"timeline_decryption_failure_withheld_unverified" = "This message was blocked either because you did not verify your device or because the sender needs to verify your identity."; "troubleshoot_notifications_entry_point_section" = "Troubleshoot"; "troubleshoot_notifications_screen_action" = "Run tests"; "troubleshoot_notifications_screen_action_again" = "Run tests again"; diff --git a/ElementX/Resources/clear.png b/ElementX/Resources/clear.png new file mode 100644 index 0000000000..07fc8418cb Binary files /dev/null and b/ElementX/Resources/clear.png differ diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index b01beac1f3..4ac9ddc664 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -1047,7 +1047,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg .actionsPublisher .filter(\.isSyncUpdate) .collect(.byTimeOrCount(DispatchQueue.main, .seconds(10), 10)) - .sink(receiveValue: { [weak self] _ in + .sink { [weak self] _ in guard let self else { return } MXLog.info("Background app refresh finished") backgroundRefreshSyncObserver?.cancel() @@ -1058,6 +1058,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg MXLog.info("Marking Background app refresh task as complete.") task.setTaskCompleted(success: true) } - }) + } } } diff --git a/ElementX/Sources/Application/AppSettings.swift b/ElementX/Sources/Application/AppSettings.swift index 2c240e9642..7126fd626a 100644 --- a/ElementX/Sources/Application/AppSettings.swift +++ b/ElementX/Sources/Application/AppSettings.swift @@ -13,6 +13,7 @@ protocol CommonSettingsProtocol { var logLevel: TracingConfiguration.LogLevel { get } var enableOnlySignedDeviceIsolationMode: Bool { get } var hideTimelineMedia: Bool { get } + var eventCacheEnabled: Bool { get } } /// Store Element specific app settings. @@ -27,6 +28,8 @@ final class AppSettings { case hasRunNotificationPermissionsOnboarding case hasRunIdentityConfirmationOnboarding + case frequentlyUsedSystemEmojis + case enableNotifications case enableInAppNotifications case pusherProfileTag @@ -39,7 +42,6 @@ final class AppSettings { case hideTimelineMedia case elementCallBaseURLOverride - case elementCallEncryptionEnabled // Feature flags case slidingSyncDiscovery @@ -47,7 +49,7 @@ final class AppSettings { case fuzzyRoomListSearchEnabled case enableOnlySignedDeviceIsolationMode case knockingEnabled - case createMediaCaptionsEnabled + case eventCacheEnabled } private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier @@ -245,6 +247,9 @@ final class AppSettings { @UserPreference(key: UserDefaultsKeys.hasRunIdentityConfirmationOnboarding, defaultValue: false, storageType: .userDefaults(store)) var hasRunIdentityConfirmationOnboarding + @UserPreference(key: UserDefaultsKeys.frequentlyUsedSystemEmojis, defaultValue: [FrequentlyUsedEmoji](), storageType: .userDefaults(store)) + var frequentlyUsedSystemEmojis + // MARK: - Home Screen @UserPreference(key: UserDefaultsKeys.hideUnreadMessagesBadge, defaultValue: false, storageType: .userDefaults(store)) @@ -302,9 +307,6 @@ final class AppSettings { @UserPreference(key: UserDefaultsKeys.knockingEnabled, defaultValue: false, storageType: .userDefaults(store)) var knockingEnabled - @UserPreference(key: UserDefaultsKeys.createMediaCaptionsEnabled, defaultValue: false, storageType: .userDefaults(store)) - var createMediaCaptionsEnabled - #endif // MARK: - Shared @@ -318,6 +320,9 @@ final class AppSettings { @UserPreference(key: UserDefaultsKeys.hideTimelineMedia, defaultValue: false, storageType: .userDefaults(store)) var hideTimelineMedia + + @UserPreference(key: UserDefaultsKeys.eventCacheEnabled, defaultValue: false, storageType: .userDefaults(store)) + var eventCacheEnabled } extension AppSettings: CommonSettingsProtocol { } diff --git a/ElementX/Sources/Application/Application.swift b/ElementX/Sources/Application/Application.swift index ad1f9823fe..fe2fb27a54 100644 --- a/ElementX/Sources/Application/Application.swift +++ b/ElementX/Sources/Application/Application.swift @@ -42,11 +42,11 @@ struct Application: App { openURLInSystemBrowser($0) } } - .onContinueUserActivity("INStartVideoCallIntent", perform: { userActivity in + .onContinueUserActivity("INStartVideoCallIntent") { userActivity in // `INStartVideoCallIntent` is to be replaced with `INStartCallIntent` // but calls from Recents still send it ¯\_(ツ)_/¯ appCoordinator.handleUserActivity(userActivity) - }) + } .task { appCoordinator.start() } diff --git a/ElementX/Sources/FlowCoordinators/MediaEventsTimelineFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/MediaEventsTimelineFlowCoordinator.swift new file mode 100644 index 0000000000..bcb14f3e99 --- /dev/null +++ b/ElementX/Sources/FlowCoordinators/MediaEventsTimelineFlowCoordinator.swift @@ -0,0 +1,131 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import Foundation + +enum MediaEventsTimelineFlowCoordinatorAction { + case viewInRoomTimeline(TimelineItemIdentifier) + case finished +} + +class MediaEventsTimelineFlowCoordinator: FlowCoordinatorProtocol { + private let navigationStackCoordinator: NavigationStackCoordinator + private let userSession: UserSessionProtocol + private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol + private let roomProxy: JoinedRoomProxyProtocol + private let userIndicatorController: UserIndicatorControllerProtocol + private let appMediator: AppMediatorProtocol + private let emojiProvider: EmojiProviderProtocol + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + private var cancellables = Set() + + init(navigationStackCoordinator: NavigationStackCoordinator, + userSession: UserSessionProtocol, + roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol, + roomProxy: JoinedRoomProxyProtocol, + userIndicatorController: UserIndicatorControllerProtocol, + appMediator: AppMediatorProtocol, + emojiProvider: EmojiProviderProtocol) { + self.navigationStackCoordinator = navigationStackCoordinator + self.userSession = userSession + self.roomTimelineControllerFactory = roomTimelineControllerFactory + self.roomProxy = roomProxy + self.userIndicatorController = userIndicatorController + self.appMediator = appMediator + self.emojiProvider = emojiProvider + } + + func start() { + Task { await presentMediaEventsTimeline() } + } + + func handleAppRoute(_ appRoute: AppRoute, animated: Bool) { + fatalError() + } + + func clearRoute(animated: Bool) { + fatalError() + } + + // MARK: - Private + + private func presentMediaEventsTimeline() async { + let timelineItemFactory = RoomTimelineItemFactory(userID: userSession.clientProxy.userID, + attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), + stateEventStringBuilder: RoomStateEventStringBuilder(userID: userSession.clientProxy.userID)) + + guard case let .success(mediaTimelineController) = await roomTimelineControllerFactory.buildMessageFilteredRoomTimelineController(allowedMessageTypes: [.image, .video], + roomProxy: roomProxy, + timelineItemFactory: timelineItemFactory, + mediaProvider: userSession.mediaProvider) else { + MXLog.error("Failed presenting media timeline") + return + } + + guard case let .success(filesTimelineController) = await roomTimelineControllerFactory.buildMessageFilteredRoomTimelineController(allowedMessageTypes: [.file, .audio], + roomProxy: roomProxy, + timelineItemFactory: timelineItemFactory, + mediaProvider: userSession.mediaProvider) else { + MXLog.error("Failed presenting media timeline") + return + } + + let parameters = MediaEventsTimelineScreenCoordinatorParameters(roomProxy: roomProxy, + mediaTimelineController: mediaTimelineController, + filesTimelineController: filesTimelineController, + mediaProvider: userSession.mediaProvider, + mediaPlayerProvider: MediaPlayerProvider(), + voiceMessageMediaManager: userSession.voiceMessageMediaManager, + appMediator: appMediator, + emojiProvider: emojiProvider, + userIndicatorController: userIndicatorController) + + let coordinator = MediaEventsTimelineScreenCoordinator(parameters: parameters) + + coordinator.actions + .sink { [weak self] action in + switch action { + case .viewItem(let previewContext): + self?.presentMediaPreview(for: previewContext) + } + } + .store(in: &cancellables) + + navigationStackCoordinator.push(coordinator) { [weak self] in + self?.actionsSubject.send(.finished) + } + } + + private func presentMediaPreview(for previewContext: TimelineMediaPreviewContext) { + let parameters = TimelineMediaPreviewCoordinatorParameters(context: previewContext, + mediaProvider: userSession.mediaProvider, + userIndicatorController: userIndicatorController, + appMediator: appMediator) + + let coordinator = TimelineMediaPreviewCoordinator(parameters: parameters) + coordinator.actionsPublisher + .sink { [weak self] action in + switch action { + case .viewInRoomTimeline(let itemID): + self?.navigationStackCoordinator.pop(animated: false) + self?.actionsSubject.send(.viewInRoomTimeline(itemID)) + self?.navigationStackCoordinator.setFullScreenCoverCoordinator(nil) + case .dismiss: + self?.navigationStackCoordinator.setFullScreenCoverCoordinator(nil) + } + } + .store(in: &cancellables) + + navigationStackCoordinator.setFullScreenCoverCoordinator(coordinator) + } +} diff --git a/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift index fcaf4fb7dc..6ee1d0182d 100644 --- a/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift @@ -65,9 +65,9 @@ class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol { attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)) - guard let timelineController = await roomTimelineControllerFactory.buildRoomPinnedTimelineController(roomProxy: roomProxy, - timelineItemFactory: timelineItemFactory, - mediaProvider: userSession.mediaProvider) else { + guard let timelineController = await roomTimelineControllerFactory.buildPinnedEventsRoomTimelineController(roomProxy: roomProxy, + timelineItemFactory: timelineItemFactory, + mediaProvider: userSession.mediaProvider) else { fatalError("This can never fail because we allow this view to be presented only when the timeline is fully loaded and not nil") } diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index 5e2d4ce3ae..8c632fc600 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -50,11 +50,6 @@ struct FocusEvent: Hashable { let shouldSetPin: Bool } -private enum PinnedEventsTimelineSource: Hashable { - case room - case details(isRoot: Bool) -} - private enum PresentationAction: Hashable { case eventFocus(FocusEvent) case share(ShareExtensionPayload) @@ -102,6 +97,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { // periphery:ignore - used to avoid deallocation private var pinnedEventsTimelineFlowCoordinator: PinnedEventsTimelineFlowCoordinator? // periphery:ignore - used to avoid deallocation + private var mediaEventsTimelineFlowCoordinator: MediaEventsTimelineFlowCoordinator? + // periphery:ignore - used to avoid deallocation private var childRoomFlowCoordinator: RoomFlowCoordinator? private let stateMachine: StateMachine = .init(state: .initial) @@ -149,7 +146,6 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { fatalError("This flow coordinator expect a route") } - // swiftlint:disable:next cyclomatic_complexity func handleAppRoute(_ appRoute: AppRoute, animated: Bool) { guard stateMachine.state != .complete else { fatalError("This flow coordinator is `finished` ☠️") @@ -352,16 +348,12 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { case (.pollForm, .dismissPollForm): return .room case (.room, .presentPinnedEventsTimeline): - return .pinnedEventsTimeline(previousState: .room) - case (.roomDetails(let isRoot), .presentPinnedEventsTimeline): - return .pinnedEventsTimeline(previousState: .details(isRoot: isRoot)) + return .pinnedEventsTimeline(previousState: fromState) + case (.roomDetails, .presentPinnedEventsTimeline): + return .pinnedEventsTimeline(previousState: fromState) case (.pinnedEventsTimeline(let previousState), .dismissPinnedEventsTimeline): - switch previousState { - case .room: - return .room - case .details(let isRoot): - return .roomDetails(isRoot: isRoot) - } + return previousState + case (.roomDetails, .presentPollsHistory): return .pollsHistory case (.pollsHistory, .dismissPollsHistory): @@ -378,7 +370,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { return .resolveSendFailure case (.resolveSendFailure, .dismissResolveSendFailure): return .room - // Child flow + case (_, .startChildFlow(let roomID, _, _)): return .presentingChild(childRoomID: roomID, previousState: fromState) case (.presentingChild(_, let previousState), .dismissChildFlow): @@ -387,6 +379,17 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { return .knockRequestsList(previousState: fromState) case (.knockRequestsList(let previousState), .dismissKnockRequestsListScreen): return previousState + + case (.roomDetails, .presentMediaEventsTimeline): + return .mediaEventsTimeline(previousState: fromState) + case (.mediaEventsTimeline(let previousState), .dismissMediaEventsTimeline): + return previousState + + case (.roomDetails, .presentSecurityAndPrivacyScreen): + return .securityAndPrivacy(previousState: fromState) + case (.securityAndPrivacy(let previousState), .dismissSecurityAndPrivacyScreen): + return previousState + default: return nil } @@ -522,8 +525,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { break case (.room, .presentPinnedEventsTimeline, .pinnedEventsTimeline): - presentPinnedEventsTimeline() - + startPinnedEventsTimelineFlow() case (.pinnedEventsTimeline, .dismissPinnedEventsTimeline, .room): break @@ -534,8 +536,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { break case (.roomDetails, .presentPinnedEventsTimeline, .pinnedEventsTimeline): - presentPinnedEventsTimeline() - + startPinnedEventsTimelineFlow() case (.pinnedEventsTimeline, .dismissPinnedEventsTimeline, .roomDetails): break @@ -578,6 +579,16 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { case (.knockRequestsList, .dismissKnockRequestsListScreen, .room): break + case (.roomDetails, .presentMediaEventsTimeline, .mediaEventsTimeline): + Task { await self.startMediaEventsTimelineFlow() } + case (.mediaEventsTimeline, .dismissMediaEventsTimeline, .roomDetails): + break + + case (.roomDetails, .presentSecurityAndPrivacyScreen, .securityAndPrivacy): + presentSecurityAndPrivacyScreen() + case (.securityAndPrivacy, .dismissSecurityAndPrivacyScreen, .roomDetails): + break + // Child flow case (_, .startChildFlow(let roomID, let via, let entryPoint), .presentingChild): Task { await self.startChildFlow(for: roomID, via: via, entryPoint: entryPoint) } @@ -854,6 +865,10 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { stateMachine.tryEvent(.presentPinnedEventsTimeline) case .presentKnockingRequestsListScreen: stateMachine.tryEvent(.presentKnockRequestsListScreen) + case .presentMediaEventsTimeline: + stateMachine.tryEvent(.presentMediaEventsTimeline) + case .presentSecurityAndPrivacyScreen: + stateMachine.tryEvent(.presentSecurityAndPrivacyScreen) } } .store(in: &cancellables) @@ -901,7 +916,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } private func presentKnockRequestsList() { - let parameters = KnockRequestsListScreenCoordinatorParameters(roomProxy: roomProxy, mediaProvider: userSession.mediaProvider) + let parameters = KnockRequestsListScreenCoordinatorParameters(roomProxy: roomProxy, + mediaProvider: userSession.mediaProvider, + userIndicatorController: userIndicatorController) let coordinator = KnockRequestsListScreenCoordinator(parameters: parameters) navigationStackCoordinator.push(coordinator) { [weak self] in @@ -1438,65 +1455,45 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { coordinator.start() } - private func presentPinnedEventsTimeline() { - let stackCoordinator = NavigationStackCoordinator() - let coordinator = PinnedEventsTimelineFlowCoordinator(navigationStackCoordinator: stackCoordinator, - userSession: userSession, - roomTimelineControllerFactory: roomTimelineControllerFactory, - roomProxy: roomProxy, - userIndicatorController: userIndicatorController, - appMediator: appMediator, - emojiProvider: emojiProvider) - + private func presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, sendHandle: SendHandleProxy) { + let coordinator = ResolveVerifiedUserSendFailureScreenCoordinator(parameters: .init(failure: failure, + sendHandle: sendHandle, + roomProxy: roomProxy, + userIndicatorController: userIndicatorController)) coordinator.actionsPublisher.sink { [weak self] action in - guard let self else { - return - } + guard let self else { return } switch action { - case .finished: - navigationStackCoordinator.setSheetCoordinator(nil) - case .displayUser(let userID): - navigationStackCoordinator.setSheetCoordinator(nil) - stateMachine.tryEvent(.presentRoomMemberDetails(userID: userID)) - case .forwardedMessageToRoom(let roomID): - navigationStackCoordinator.setSheetCoordinator(nil) - stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room)) - case .displayRoomScreenWithFocussedPin(let eventID): + case .dismiss: navigationStackCoordinator.setSheetCoordinator(nil) - stateMachine.tryEvent(.presentRoom(presentationAction: .eventFocus(.init(eventID: eventID, shouldSetPin: true)))) } } .store(in: &cancellables) - pinnedEventsTimelineFlowCoordinator = coordinator - navigationStackCoordinator.setSheetCoordinator(stackCoordinator) { [weak self] in - self?.stateMachine.tryEvent(.dismissPinnedEventsTimeline) + navigationStackCoordinator.setSheetCoordinator(coordinator) { [weak self] in + self?.stateMachine.tryEvent(.dismissResolveSendFailure) } - coordinator.start() } - private func presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, sendHandle: SendHandleProxy) { - let coordinator = ResolveVerifiedUserSendFailureScreenCoordinator(parameters: .init(failure: failure, - sendHandle: sendHandle, - roomProxy: roomProxy, - userIndicatorController: userIndicatorController)) + private func presentSecurityAndPrivacyScreen() { + let coordinator = SecurityAndPrivacyScreenCoordinator(parameters: .init(roomProxy: roomProxy)) + coordinator.actionsPublisher.sink { [weak self] action in guard let self else { return } switch action { - case .dismiss: - navigationStackCoordinator.setSheetCoordinator(nil) + case .done: + break } } .store(in: &cancellables) - navigationStackCoordinator.setSheetCoordinator(coordinator) { [weak self] in - self?.stateMachine.tryEvent(.dismissResolveSendFailure) + navigationStackCoordinator.push(coordinator) { [weak self] in + self?.stateMachine.tryEvent(.dismissSecurityAndPrivacyScreen) } } - // MARK: - Child Flow + // MARK: - Other flows private func startChildFlow(for roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint) async { let coordinator = await RoomFlowCoordinator(roomID: roomID, @@ -1534,6 +1531,78 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { coordinator.handleAppRoute(.share(payload), animated: true) } } + + private func startPinnedEventsTimelineFlow() { + let stackCoordinator = NavigationStackCoordinator() + + let flowCoordinator = PinnedEventsTimelineFlowCoordinator(navigationStackCoordinator: stackCoordinator, + userSession: userSession, + roomTimelineControllerFactory: roomTimelineControllerFactory, + roomProxy: roomProxy, + userIndicatorController: userIndicatorController, + appMediator: appMediator, + emojiProvider: emojiProvider) + + flowCoordinator.actionsPublisher.sink { [weak self] action in + guard let self else { + return + } + + switch action { + case .finished: + navigationStackCoordinator.setSheetCoordinator(nil) + case .displayUser(let userID): + navigationStackCoordinator.setSheetCoordinator(nil) + stateMachine.tryEvent(.presentRoomMemberDetails(userID: userID)) + case .forwardedMessageToRoom(let roomID): + navigationStackCoordinator.setSheetCoordinator(nil) + stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room)) + case .displayRoomScreenWithFocussedPin(let eventID): + navigationStackCoordinator.setSheetCoordinator(nil) + stateMachine.tryEvent(.presentRoom(presentationAction: .eventFocus(.init(eventID: eventID, shouldSetPin: true)))) + } + } + .store(in: &cancellables) + + pinnedEventsTimelineFlowCoordinator = flowCoordinator + + navigationStackCoordinator.setSheetCoordinator(stackCoordinator) { [weak self] in + self?.stateMachine.tryEvent(.dismissPinnedEventsTimeline) + } + + flowCoordinator.start() + } + + private func startMediaEventsTimelineFlow() async { + let flowCoordinator = MediaEventsTimelineFlowCoordinator(navigationStackCoordinator: navigationStackCoordinator, + userSession: userSession, + roomTimelineControllerFactory: roomTimelineControllerFactory, + roomProxy: roomProxy, + userIndicatorController: userIndicatorController, + appMediator: appMediator, + emojiProvider: emojiProvider) + + flowCoordinator.actionsPublisher.sink { [weak self] action in + guard let self else { return } + + switch action { + case .viewInRoomTimeline(let itemID): + guard let eventID = itemID.eventID else { + MXLog.error("Unable to present room timeline for event \(itemID)") + return + } + stateMachine.tryEvent(.presentRoom(presentationAction: .eventFocus(.init(eventID: eventID, shouldSetPin: false))), + userInfo: EventUserInfo(animated: false)) // No animation so the timeline visible when the preview animates away. + case .finished: + stateMachine.tryEvent(.dismissMediaEventsTimeline) + } + } + .store(in: &cancellables) + + mediaEventsTimelineFlowCoordinator = flowCoordinator + + flowCoordinator.start() + } } private extension RoomFlowCoordinator { @@ -1571,9 +1640,11 @@ private extension RoomFlowCoordinator { case pollsHistory case pollsHistoryForm case rolesAndPermissions - case pinnedEventsTimeline(previousState: PinnedEventsTimelineSource) + case pinnedEventsTimeline(previousState: State) case resolveSendFailure case knockRequestsList(previousState: State) + case mediaEventsTimeline(previousState: State) + case securityAndPrivacy(previousState: State) /// A child flow is in progress. case presentingChild(childRoomID: String, previousState: State) @@ -1649,22 +1720,16 @@ private extension RoomFlowCoordinator { case presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, sendHandle: SendHandleProxy) case dismissResolveSendFailure - // Child room flow events case startChildFlow(roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint) case dismissChildFlow case presentKnockRequestsListScreen case dismissKnockRequestsListScreen - } -} - -private extension Result { - var isFailure: Bool { - switch self { - case .success: - return false - case .failure: - return true - } + + case presentMediaEventsTimeline + case dismissMediaEventsTimeline + + case presentSecurityAndPrivacyScreen + case dismissSecurityAndPrivacyScreen } } diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index 311924d905..27cde34f76 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -5,6 +5,7 @@ // Please see LICENSE in the repository root for full details. // +import AnalyticsEvents import AVKit import Combine import MatrixRustSDK @@ -369,20 +370,25 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { timeToDecryptMs = -1 } - switch info.cause { - case .unknown: - analytics.trackError(context: nil, domain: .E2EE, name: .OlmKeysNotSentError, timeToDecryptMillis: timeToDecryptMs) - case .unknownDevice: - analytics.trackError(context: nil, domain: .E2EE, name: .ExpectedSentByInsecureDevice, timeToDecryptMillis: timeToDecryptMs) - case .unsignedDevice: - analytics.trackError(context: nil, domain: .E2EE, name: .ExpectedSentByInsecureDevice, timeToDecryptMillis: timeToDecryptMs) - case .verificationViolation: - analytics.trackError(context: nil, domain: .E2EE, name: .ExpectedVerificationViolation, timeToDecryptMillis: timeToDecryptMs) - case .sentBeforeWeJoined: - analytics.trackError(context: nil, domain: .E2EE, name: .ExpectedDueToMembership, timeToDecryptMillis: timeToDecryptMs) - case .historicalMessage: - analytics.trackError(context: nil, domain: .E2EE, name: .HistoricalMessage, timeToDecryptMillis: timeToDecryptMs) + let errorName: AnalyticsEvent.Error.Name = switch info.cause { + case .unknown: .OlmKeysNotSentError + case .unknownDevice, .unsignedDevice: .ExpectedSentByInsecureDevice + case .verificationViolation: .ExpectedVerificationViolation + case .sentBeforeWeJoined: .ExpectedDueToMembership + case .historicalMessageAndBackupIsDisabled, .historicalMessageAndDeviceIsUnverified: .HistoricalMessage + case .withheldForUnverifiedOrInsecureDevice: .RoomKeysWithheldForUnverifiedDevice + case .withheldBySender: .OlmKeysNotSentError } + + analytics.trackError(context: nil, + domain: .E2EE, + name: errorName, + timeToDecryptMillis: timeToDecryptMs, + eventLocalAgeMillis: Int(truncatingIfNeeded: info.eventLocalAgeMillis), + isFederated: info.ownHomeserver != info.senderHomeserver, + isMatrixDotOrg: info.ownHomeserver == "matrix.org", + userTrustsOwnIdentity: info.userTrustsOwnIdentity, + wasVisibleToUser: nil) } .store(in: &cancellables) diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index cb7e231c6d..5fcbeb9425 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -270,6 +270,8 @@ internal enum L10n { internal static var actionViewSource: String { return L10n.tr("Localizable", "action_view_source") } /// Yes internal static var actionYes: String { return L10n.tr("Localizable", "action_yes") } + /// Yes, try again + internal static var actionYesTryAgain: String { return L10n.tr("Localizable", "action_yes_try_again") } /// Log Out & Upgrade internal static var bannerMigrateToNativeSlidingSyncAction: String { return L10n.tr("Localizable", "banner_migrate_to_native_sliding_sync_action") } /// Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later. @@ -314,6 +316,12 @@ internal enum L10n { internal static var commonCurrentUserLeftRoom: String { return L10n.tr("Localizable", "common_current_user_left_room") } /// Dark internal static var commonDark: String { return L10n.tr("Localizable", "common_dark") } + /// %1$@ at %2$@ + internal static func commonDateDateAtTime(_ p1: Any, _ p2: Any) -> String { + return L10n.tr("Localizable", "common_date_date_at_time", String(describing: p1), String(describing: p2)) + } + /// This month + internal static var commonDateThisMonth: String { return L10n.tr("Localizable", "common_date_this_month") } /// Decryption error internal static var commonDecryptionError: String { return L10n.tr("Localizable", "common_decryption_error") } /// Developer options @@ -322,6 +330,10 @@ internal enum L10n { internal static var commonDeviceId: String { return L10n.tr("Localizable", "common_device_id") } /// Direct chat internal static var commonDirectChat: String { return L10n.tr("Localizable", "common_direct_chat") } + /// Download failed + internal static var commonDownloadFailed: String { return L10n.tr("Localizable", "common_download_failed") } + /// Downloading + internal static var commonDownloading: String { return L10n.tr("Localizable", "common_downloading") } /// (edited) internal static var commonEditedSuffix: String { return L10n.tr("Localizable", "common_edited_suffix") } /// Editing @@ -352,6 +364,10 @@ internal enum L10n { internal static var commonFavourited: String { return L10n.tr("Localizable", "common_favourited") } /// File internal static var commonFile: String { return L10n.tr("Localizable", "common_file") } + /// File deleted + internal static var commonFileDeleted: String { return L10n.tr("Localizable", "common_file_deleted") } + /// File saved + internal static var commonFileSaved: String { return L10n.tr("Localizable", "common_file_saved") } /// Forward message internal static var commonForwardMessage: String { return L10n.tr("Localizable", "common_forward_message") } /// Frequently used @@ -596,6 +612,10 @@ internal enum L10n { } /// In order to let the application display notifications, please grant the permission in the system settings. internal static var dialogPermissionNotification: String { return L10n.tr("Localizable", "dialog_permission_notification") } + /// %1$@ does not have access to your photo library. + internal static func dialogPermissionPhotoLibraryTitleIos(_ p1: Any) -> String { + return L10n.tr("Localizable", "dialog_permission_photo_library_title_ios", String(describing: p1)) + } /// Confirmation internal static var dialogTitleConfirmation: String { return L10n.tr("Localizable", "dialog_title_confirmation") } /// Error @@ -1312,6 +1332,18 @@ internal enum L10n { internal static var screenKnockRequestsListAcceptAllAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_alert_title") } /// Accept all internal static var screenKnockRequestsListAcceptAllButtonTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_button_title") } + /// We couldn’t accept all requests. Would you like to try again? + internal static var screenKnockRequestsListAcceptAllFailedAlertDescription: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_failed_alert_description") } + /// Failed to accept all requests + internal static var screenKnockRequestsListAcceptAllFailedAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_failed_alert_title") } + /// Accepting all requests to join + internal static var screenKnockRequestsListAcceptAllLoadingTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_loading_title") } + /// We couldn’t accept this request. Would you like to try again? + internal static var screenKnockRequestsListAcceptFailedAlertDescription: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_failed_alert_description") } + /// Failed to accept request + internal static var screenKnockRequestsListAcceptFailedAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_failed_alert_title") } + /// Accepting request to join + internal static var screenKnockRequestsListAcceptLoadingTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_loading_title") } /// Yes, decline and ban internal static var screenKnockRequestsListBanAlertConfirmButtonTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_ban_alert_confirm_button_title") } /// Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again. @@ -1320,6 +1352,8 @@ internal enum L10n { } /// Decline and ban from accessing internal static var screenKnockRequestsListBanAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_ban_alert_title") } + /// Declining and banning access + internal static var screenKnockRequestsListBanLoadingTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_ban_loading_title") } /// Yes, decline internal static var screenKnockRequestsListDeclineAlertConfirmButtonTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_alert_confirm_button_title") } /// Are you sure you want to decline %1$@ request to join this room? @@ -1330,10 +1364,18 @@ internal enum L10n { internal static var screenKnockRequestsListDeclineAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_alert_title") } /// Decline and ban internal static var screenKnockRequestsListDeclineAndBanActionTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_and_ban_action_title") } + /// We couldn’t decline this request. Would you like to try again? + internal static var screenKnockRequestsListDeclineFailedAlertDescription: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_failed_alert_description") } + /// Failed to decline request + internal static var screenKnockRequestsListDeclineFailedAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_failed_alert_title") } + /// Declining request to join + internal static var screenKnockRequestsListDeclineLoadingTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_loading_title") } /// When somebody will ask to join the room, you’ll be able to see their request here. internal static var screenKnockRequestsListEmptyStateDescription: String { return L10n.tr("Localizable", "screen_knock_requests_list_empty_state_description") } /// No pending request to join internal static var screenKnockRequestsListEmptyStateTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_empty_state_title") } + /// Loading requests to join… + internal static var screenKnockRequestsListInitialLoadingTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_initial_loading_title") } /// Requests to join internal static var screenKnockRequestsListTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_title") } /// This account has been deactivated. @@ -1356,6 +1398,42 @@ internal enum L10n { internal static func screenLoginTitleWithHomeserver(_ p1: Any) -> String { return L10n.tr("Localizable", "screen_login_title_with_homeserver", String(describing: p1)) } + /// This file will be removed from the room and members won’t have access to it. + internal static var screenMediaBrowserDeleteConfirmationSubtitle: String { return L10n.tr("Localizable", "screen_media_browser_delete_confirmation_subtitle") } + /// Delete file? + internal static var screenMediaBrowserDeleteConfirmationTitle: String { return L10n.tr("Localizable", "screen_media_browser_delete_confirmation_title") } + /// Check your internet connection and try again. + internal static var screenMediaBrowserDownloadErrorMessage: String { return L10n.tr("Localizable", "screen_media_browser_download_error_message") } + /// Documents, audio files, and voice messages uploaded to this room will be shown here. + internal static var screenMediaBrowserFilesEmptyStateSubtitle: String { return L10n.tr("Localizable", "screen_media_browser_files_empty_state_subtitle") } + /// No files uploaded yet + internal static var screenMediaBrowserFilesEmptyStateTitle: String { return L10n.tr("Localizable", "screen_media_browser_files_empty_state_title") } + /// Loading files… + internal static var screenMediaBrowserListLoadingFiles: String { return L10n.tr("Localizable", "screen_media_browser_list_loading_files") } + /// Loading media… + internal static var screenMediaBrowserListLoadingMedia: String { return L10n.tr("Localizable", "screen_media_browser_list_loading_media") } + /// Files + internal static var screenMediaBrowserListModeFiles: String { return L10n.tr("Localizable", "screen_media_browser_list_mode_files") } + /// Media + internal static var screenMediaBrowserListModeMedia: String { return L10n.tr("Localizable", "screen_media_browser_list_mode_media") } + /// Images and videos uploaded to this room will be shown here. + internal static var screenMediaBrowserMediaEmptyStateSubtitle: String { return L10n.tr("Localizable", "screen_media_browser_media_empty_state_subtitle") } + /// No media uploaded yet + internal static var screenMediaBrowserMediaEmptyStateTitle: String { return L10n.tr("Localizable", "screen_media_browser_media_empty_state_title") } + /// Media and files + internal static var screenMediaBrowserTitle: String { return L10n.tr("Localizable", "screen_media_browser_title") } + /// File format + internal static var screenMediaDetailsFileFormat: String { return L10n.tr("Localizable", "screen_media_details_file_format") } + /// File name + internal static var screenMediaDetailsFilename: String { return L10n.tr("Localizable", "screen_media_details_filename") } + /// This file will be removed from the room and members won’t have access to it. + internal static var screenMediaDetailsRedactConfirmationMessage: String { return L10n.tr("Localizable", "screen_media_details_redact_confirmation_message") } + /// Delete file? + internal static var screenMediaDetailsRedactConfirmationTitle: String { return L10n.tr("Localizable", "screen_media_details_redact_confirmation_title") } + /// Uploaded by + internal static var screenMediaDetailsUploadedBy: String { return L10n.tr("Localizable", "screen_media_details_uploaded_by") } + /// Uploaded on + internal static var screenMediaDetailsUploadedOn: String { return L10n.tr("Localizable", "screen_media_details_uploaded_on") } /// Failed selecting media, please try again. internal static var screenMediaPickerErrorFailedSelection: String { return L10n.tr("Localizable", "screen_media_picker_error_failed_selection") } /// Captions might not be visible to people using older apps. @@ -1778,6 +1856,8 @@ internal enum L10n { internal static var screenRoomDetailsLeaveConversationTitle: String { return L10n.tr("Localizable", "screen_room_details_leave_conversation_title") } /// Leave room internal static var screenRoomDetailsLeaveRoomTitle: String { return L10n.tr("Localizable", "screen_room_details_leave_room_title") } + /// Media and files + internal static var screenRoomDetailsMediaGalleryTitle: String { return L10n.tr("Localizable", "screen_room_details_media_gallery_title") } /// Custom internal static var screenRoomDetailsNotificationModeCustom: String { return L10n.tr("Localizable", "screen_room_details_notification_mode_custom") } /// Default @@ -1792,6 +1872,8 @@ internal enum L10n { internal static var screenRoomDetailsRolesAndPermissions: String { return L10n.tr("Localizable", "screen_room_details_roles_and_permissions") } /// Room name internal static var screenRoomDetailsRoomNameLabel: String { return L10n.tr("Localizable", "screen_room_details_room_name_label") } + /// Security & privacy + internal static var screenRoomDetailsSecurityAndPrivacyTitle: String { return L10n.tr("Localizable", "screen_room_details_security_and_privacy_title") } /// Security internal static var screenRoomDetailsSecurityTitle: String { return L10n.tr("Localizable", "screen_room_details_security_title") } /// Share room @@ -2084,6 +2166,36 @@ internal enum L10n { internal static var screenRoomlistMarkAsUnread: String { return L10n.tr("Localizable", "screen_roomlist_mark_as_unread") } /// Browse all rooms internal static var screenRoomlistRoomDirectoryButtonTitle: String { return L10n.tr("Localizable", "screen_roomlist_room_directory_button_title") } + /// Anyone can ask to join the room but an administrator or moderator will have to accept the request. + internal static var screenSecurityAndPrivacyAskToJoinOptionDescription: String { return L10n.tr("Localizable", "screen_security_and_privacy_ask_to_join_option_description") } + /// Ask to join + internal static var screenSecurityAndPrivacyAskToJoinOptionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_ask_to_join_option_title") } + /// Yes, enable encryption + internal static var screenSecurityAndPrivacyEnableEncryptionAlertConfirmButtonTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_enable_encryption_alert_confirm_button_title") } + /// Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room. + /// No one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly. + /// We do not recommend enabling encryption for rooms that anyone can find and join. + internal static var screenSecurityAndPrivacyEnableEncryptionAlertDescription: String { return L10n.tr("Localizable", "screen_security_and_privacy_enable_encryption_alert_description") } + /// Enable encryption? + internal static var screenSecurityAndPrivacyEnableEncryptionAlertTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_enable_encryption_alert_title") } + /// Once enabled, encryption cannot be disabled. + internal static var screenSecurityAndPrivacyEncryptionSectionFooter: String { return L10n.tr("Localizable", "screen_security_and_privacy_encryption_section_footer") } + /// Encryption + internal static var screenSecurityAndPrivacyEncryptionSectionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_encryption_section_title") } + /// Enable end-to-end encryption + internal static var screenSecurityAndPrivacyEncryptionToggleTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_encryption_toggle_title") } + /// Anyone can find and join + internal static var screenSecurityAndPrivacyRoomAccessAnyoneOptionDescription: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_anyone_option_description") } + /// Anyone + internal static var screenSecurityAndPrivacyRoomAccessAnyoneOptionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_anyone_option_title") } + /// People can only join if they are invited + internal static var screenSecurityAndPrivacyRoomAccessInviteOnlyOptionDescription: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_invite_only_option_description") } + /// Invite only + internal static var screenSecurityAndPrivacyRoomAccessInviteOnlyOptionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_invite_only_option_title") } + /// Room access + internal static var screenSecurityAndPrivacyRoomAccessSectionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_section_title") } + /// Security & privacy + internal static var screenSecurityAndPrivacyTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_title") } /// Change account provider internal static var screenServerConfirmationChangeServer: String { return L10n.tr("Localizable", "screen_server_confirmation_change_server") } /// A private server for Element employees. @@ -2490,6 +2602,16 @@ internal enum L10n { internal static var testLanguageIdentifier: String { return L10n.tr("Localizable", "test_language_identifier") } /// en internal static var testUntranslatedDefaultLanguageIdentifier: String { return L10n.tr("Localizable", "test_untranslated_default_language_identifier") } + /// Historical messages are not available on this device + internal static var timelineDecryptionFailureHistoricalEventNoKeyBackup: String { return L10n.tr("Localizable", "timeline_decryption_failure_historical_event_no_key_backup") } + /// You need to verify this device for access to historical messages + internal static var timelineDecryptionFailureHistoricalEventUnverifiedDevice: String { return L10n.tr("Localizable", "timeline_decryption_failure_historical_event_unverified_device") } + /// You don't have access to this message + internal static var timelineDecryptionFailureHistoricalEventUserNotJoined: String { return L10n.tr("Localizable", "timeline_decryption_failure_historical_event_user_not_joined") } + /// Unable to decrypt message + internal static var timelineDecryptionFailureUnableToDecrypt: String { return L10n.tr("Localizable", "timeline_decryption_failure_unable_to_decrypt") } + /// This message was blocked either because you did not verify your device or because the sender needs to verify your identity. + internal static var timelineDecryptionFailureWithheldUnverified: String { return L10n.tr("Localizable", "timeline_decryption_failure_withheld_unverified") } /// Troubleshoot internal static var troubleshootNotificationsEntryPointSection: String { return L10n.tr("Localizable", "troubleshoot_notifications_entry_point_section") } /// Troubleshoot notifications diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 576eff68fd..1857b7f4a3 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -8,6 +8,7 @@ import Combine import Foundation import LocalAuthentication import MatrixRustSDK +import Photos import SwiftUI class AnalyticsClientMock: AnalyticsClientProtocol { var isRunning: Bool { @@ -5974,6 +5975,11 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol { set(value) { underlyingIdentityStatusChangesPublisher = value } } var underlyingIdentityStatusChangesPublisher: CurrentValuePublisher<[IdentityStatusChange], Never>! + var knockRequestsStatePublisher: CurrentValuePublisher { + get { return underlyingKnockRequestsStatePublisher } + set(value) { underlyingKnockRequestsStatePublisher = value } + } + var underlyingKnockRequestsStatePublisher: CurrentValuePublisher! var timeline: TimelineProxyProtocol { get { return underlyingTimeline } set(value) { underlyingTimeline = value } @@ -6147,6 +6153,76 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol { return timelineFocusedOnEventEventIDNumberOfEventsReturnValue } } + //MARK: - messageFilteredTimeline + + var messageFilteredTimelineAllowedMessageTypesUnderlyingCallsCount = 0 + var messageFilteredTimelineAllowedMessageTypesCallsCount: Int { + get { + if Thread.isMainThread { + return messageFilteredTimelineAllowedMessageTypesUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = messageFilteredTimelineAllowedMessageTypesUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + messageFilteredTimelineAllowedMessageTypesUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + messageFilteredTimelineAllowedMessageTypesUnderlyingCallsCount = newValue + } + } + } + } + var messageFilteredTimelineAllowedMessageTypesCalled: Bool { + return messageFilteredTimelineAllowedMessageTypesCallsCount > 0 + } + var messageFilteredTimelineAllowedMessageTypesReceivedAllowedMessageTypes: [RoomMessageEventMessageType]? + var messageFilteredTimelineAllowedMessageTypesReceivedInvocations: [[RoomMessageEventMessageType]] = [] + + var messageFilteredTimelineAllowedMessageTypesUnderlyingReturnValue: Result! + var messageFilteredTimelineAllowedMessageTypesReturnValue: Result! { + get { + if Thread.isMainThread { + return messageFilteredTimelineAllowedMessageTypesUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = messageFilteredTimelineAllowedMessageTypesUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + messageFilteredTimelineAllowedMessageTypesUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + messageFilteredTimelineAllowedMessageTypesUnderlyingReturnValue = newValue + } + } + } + } + var messageFilteredTimelineAllowedMessageTypesClosure: (([RoomMessageEventMessageType]) async -> Result)? + + func messageFilteredTimeline(allowedMessageTypes: [RoomMessageEventMessageType]) async -> Result { + messageFilteredTimelineAllowedMessageTypesCallsCount += 1 + messageFilteredTimelineAllowedMessageTypesReceivedAllowedMessageTypes = allowedMessageTypes + DispatchQueue.main.async { + self.messageFilteredTimelineAllowedMessageTypesReceivedInvocations.append(allowedMessageTypes) + } + if let messageFilteredTimelineAllowedMessageTypesClosure = messageFilteredTimelineAllowedMessageTypesClosure { + return await messageFilteredTimelineAllowedMessageTypesClosure(allowedMessageTypes) + } else { + return messageFilteredTimelineAllowedMessageTypesReturnValue + } + } //MARK: - redact var redactUnderlyingCallsCount = 0 @@ -9540,6 +9616,284 @@ class KeychainControllerMock: KeychainControllerProtocol { removePINCodeBiometricStateClosure?() } } +class KnockRequestProxyMock: KnockRequestProxyProtocol { + var eventID: String { + get { return underlyingEventID } + set(value) { underlyingEventID = value } + } + var underlyingEventID: String! + var userID: String { + get { return underlyingUserID } + set(value) { underlyingUserID = value } + } + var underlyingUserID: String! + var displayName: String? + var avatarURL: URL? + var reason: String? + var formattedTimestamp: String? + var isSeen: Bool { + get { return underlyingIsSeen } + set(value) { underlyingIsSeen = value } + } + var underlyingIsSeen: Bool! + + //MARK: - accept + + var acceptUnderlyingCallsCount = 0 + var acceptCallsCount: Int { + get { + if Thread.isMainThread { + return acceptUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = acceptUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + acceptUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + acceptUnderlyingCallsCount = newValue + } + } + } + } + var acceptCalled: Bool { + return acceptCallsCount > 0 + } + + var acceptUnderlyingReturnValue: Result! + var acceptReturnValue: Result! { + get { + if Thread.isMainThread { + return acceptUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = acceptUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + acceptUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + acceptUnderlyingReturnValue = newValue + } + } + } + } + var acceptClosure: (() async -> Result)? + + func accept() async -> Result { + acceptCallsCount += 1 + if let acceptClosure = acceptClosure { + return await acceptClosure() + } else { + return acceptReturnValue + } + } + //MARK: - decline + + var declineUnderlyingCallsCount = 0 + var declineCallsCount: Int { + get { + if Thread.isMainThread { + return declineUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = declineUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + declineUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + declineUnderlyingCallsCount = newValue + } + } + } + } + var declineCalled: Bool { + return declineCallsCount > 0 + } + + var declineUnderlyingReturnValue: Result! + var declineReturnValue: Result! { + get { + if Thread.isMainThread { + return declineUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = declineUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + declineUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + declineUnderlyingReturnValue = newValue + } + } + } + } + var declineClosure: (() async -> Result)? + + func decline() async -> Result { + declineCallsCount += 1 + if let declineClosure = declineClosure { + return await declineClosure() + } else { + return declineReturnValue + } + } + //MARK: - ban + + var banUnderlyingCallsCount = 0 + var banCallsCount: Int { + get { + if Thread.isMainThread { + return banUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = banUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + banUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + banUnderlyingCallsCount = newValue + } + } + } + } + var banCalled: Bool { + return banCallsCount > 0 + } + + var banUnderlyingReturnValue: Result! + var banReturnValue: Result! { + get { + if Thread.isMainThread { + return banUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = banUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + banUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + banUnderlyingReturnValue = newValue + } + } + } + } + var banClosure: (() async -> Result)? + + func ban() async -> Result { + banCallsCount += 1 + if let banClosure = banClosure { + return await banClosure() + } else { + return banReturnValue + } + } + //MARK: - markAsSeen + + var markAsSeenUnderlyingCallsCount = 0 + var markAsSeenCallsCount: Int { + get { + if Thread.isMainThread { + return markAsSeenUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = markAsSeenUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + markAsSeenUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + markAsSeenUnderlyingCallsCount = newValue + } + } + } + } + var markAsSeenCalled: Bool { + return markAsSeenCallsCount > 0 + } + + var markAsSeenUnderlyingReturnValue: Result! + var markAsSeenReturnValue: Result! { + get { + if Thread.isMainThread { + return markAsSeenUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = markAsSeenUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + markAsSeenUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + markAsSeenUnderlyingReturnValue = newValue + } + } + } + } + var markAsSeenClosure: (() async -> Result)? + + func markAsSeen() async -> Result { + markAsSeenCallsCount += 1 + if let markAsSeenClosure = markAsSeenClosure { + return await markAsSeenClosure() + } else { + return markAsSeenReturnValue + } + } +} class KnockedRoomProxyMock: KnockedRoomProxyProtocol { var info: BaseRoomInfoProxyProtocol { get { return underlyingInfo } @@ -11974,6 +12328,79 @@ class PHGPostHogMock: PHGPostHogProtocol { screenPropertiesClosure?(screenTitle, properties) } } +class PhotoLibraryManagerMock: PhotoLibraryManagerProtocol { + + //MARK: - addResource + + var addResourceAtUnderlyingCallsCount = 0 + var addResourceAtCallsCount: Int { + get { + if Thread.isMainThread { + return addResourceAtUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = addResourceAtUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + addResourceAtUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + addResourceAtUnderlyingCallsCount = newValue + } + } + } + } + var addResourceAtCalled: Bool { + return addResourceAtCallsCount > 0 + } + var addResourceAtReceivedArguments: (type: PHAssetResourceType, url: URL)? + var addResourceAtReceivedInvocations: [(type: PHAssetResourceType, url: URL)] = [] + + var addResourceAtUnderlyingReturnValue: Result! + var addResourceAtReturnValue: Result! { + get { + if Thread.isMainThread { + return addResourceAtUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = addResourceAtUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + addResourceAtUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + addResourceAtUnderlyingReturnValue = newValue + } + } + } + } + var addResourceAtClosure: ((PHAssetResourceType, URL) async -> Result)? + + func addResource(_ type: PHAssetResourceType, at url: URL) async -> Result { + addResourceAtCallsCount += 1 + addResourceAtReceivedArguments = (type: type, url: url) + DispatchQueue.main.async { + self.addResourceAtReceivedInvocations.append((type: type, url: url)) + } + if let addResourceAtClosure = addResourceAtClosure { + return await addResourceAtClosure(type, url) + } else { + return addResourceAtReturnValue + } + } +} class PollInteractionHandlerMock: PollInteractionHandlerProtocol { //MARK: - sendPollResponse @@ -12602,17 +13029,17 @@ class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol { return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReturnValue } } - //MARK: - buildRoomPinnedTimelineController + //MARK: - buildPinnedEventsRoomTimelineController - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = 0 - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount: Int { + var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = 0 + var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount: Int { get { if Thread.isMainThread { - return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount + return buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount + returnValue = buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount } return returnValue! @@ -12620,29 +13047,99 @@ class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol { } set { if Thread.isMainThread { - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue + buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue + buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue } } } } - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCalled: Bool { - return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount > 0 + var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCalled: Bool { + return buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount > 0 } - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)? - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = [] + var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)? + var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = [] - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue: RoomTimelineControllerProtocol? - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue: RoomTimelineControllerProtocol? { + var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue: RoomTimelineControllerProtocol? + var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue: RoomTimelineControllerProtocol? { get { if Thread.isMainThread { - return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue + return buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue } else { var returnValue: RoomTimelineControllerProtocol?? = nil DispatchQueue.main.sync { - returnValue = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue + returnValue = buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue + } + } + } + } + var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure: ((JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) async -> RoomTimelineControllerProtocol?)? + + func buildPinnedEventsRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol? { + buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount += 1 + buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments = (roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider) + DispatchQueue.main.async { + self.buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations.append((roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)) + } + if let buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure = buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure { + return await buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure(roomProxy, timelineItemFactory, mediaProvider) + } else { + return buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue + } + } + //MARK: - buildMessageFilteredRoomTimelineController + + var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = 0 + var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderCallsCount: Int { + get { + if Thread.isMainThread { + return buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue + } + } + } + } + var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderCalled: Bool { + return buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderCallsCount > 0 + } + var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReceivedArguments: (allowedMessageTypes: [RoomMessageEventMessageType], roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)? + var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations: [(allowedMessageTypes: [RoomMessageEventMessageType], roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = [] + + var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue: Result! + var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReturnValue: Result! { + get { + if Thread.isMainThread { + return buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue } return returnValue! @@ -12650,26 +13147,26 @@ class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol { } set { if Thread.isMainThread { - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue + buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue + buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue } } } } - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure: ((JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) async -> RoomTimelineControllerProtocol?)? + var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderClosure: (([RoomMessageEventMessageType], JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) async -> Result)? - func buildRoomPinnedTimelineController(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol? { - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount += 1 - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments = (roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider) + func buildMessageFilteredRoomTimelineController(allowedMessageTypes: [RoomMessageEventMessageType], roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) async -> Result { + buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderCallsCount += 1 + buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReceivedArguments = (allowedMessageTypes: allowedMessageTypes, roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider) DispatchQueue.main.async { - self.buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations.append((roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)) + self.buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations.append((allowedMessageTypes: allowedMessageTypes, roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)) } - if let buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure { - return await buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure(roomProxy, timelineItemFactory, mediaProvider) + if let buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderClosure = buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderClosure { + return await buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderClosure(allowedMessageTypes, roomProxy, timelineItemFactory, mediaProvider) } else { - return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue + return buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReturnValue } } } @@ -13653,15 +14150,15 @@ class TimelineProxyMock: TimelineProxyProtocol { } //MARK: - retryDecryption - var retryDecryptionForUnderlyingCallsCount = 0 - var retryDecryptionForCallsCount: Int { + var retryDecryptionSessionIDsUnderlyingCallsCount = 0 + var retryDecryptionSessionIDsCallsCount: Int { get { if Thread.isMainThread { - return retryDecryptionForUnderlyingCallsCount + return retryDecryptionSessionIDsUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = retryDecryptionForUnderlyingCallsCount + returnValue = retryDecryptionSessionIDsUnderlyingCallsCount } return returnValue! @@ -13669,28 +14166,28 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - retryDecryptionForUnderlyingCallsCount = newValue + retryDecryptionSessionIDsUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - retryDecryptionForUnderlyingCallsCount = newValue + retryDecryptionSessionIDsUnderlyingCallsCount = newValue } } } } - var retryDecryptionForCalled: Bool { - return retryDecryptionForCallsCount > 0 + var retryDecryptionSessionIDsCalled: Bool { + return retryDecryptionSessionIDsCallsCount > 0 } - var retryDecryptionForReceivedSessionID: String? - var retryDecryptionForReceivedInvocations: [String] = [] - var retryDecryptionForClosure: ((String) async -> Void)? + var retryDecryptionSessionIDsReceivedSessionIDs: [String]? + var retryDecryptionSessionIDsReceivedInvocations: [[String]?] = [] + var retryDecryptionSessionIDsClosure: (([String]?) async -> Void)? - func retryDecryption(for sessionID: String) async { - retryDecryptionForCallsCount += 1 - retryDecryptionForReceivedSessionID = sessionID + func retryDecryption(sessionIDs: [String]?) async { + retryDecryptionSessionIDsCallsCount += 1 + retryDecryptionSessionIDsReceivedSessionIDs = sessionIDs DispatchQueue.main.async { - self.retryDecryptionForReceivedInvocations.append(sessionID) + self.retryDecryptionSessionIDsReceivedInvocations.append(sessionIDs) } - await retryDecryptionForClosure?(sessionID) + await retryDecryptionSessionIDsClosure?(sessionIDs) } //MARK: - paginateBackwards diff --git a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift index 9c76fc5c50..f4e206858a 100644 --- a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift @@ -5832,6 +5832,77 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } } + //MARK: - useEventCachePersistentStorage + + var useEventCachePersistentStorageValueUnderlyingCallsCount = 0 + open var useEventCachePersistentStorageValueCallsCount: Int { + get { + if Thread.isMainThread { + return useEventCachePersistentStorageValueUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = useEventCachePersistentStorageValueUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + useEventCachePersistentStorageValueUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + useEventCachePersistentStorageValueUnderlyingCallsCount = newValue + } + } + } + } + open var useEventCachePersistentStorageValueCalled: Bool { + return useEventCachePersistentStorageValueCallsCount > 0 + } + open var useEventCachePersistentStorageValueReceivedValue: Bool? + open var useEventCachePersistentStorageValueReceivedInvocations: [Bool] = [] + + var useEventCachePersistentStorageValueUnderlyingReturnValue: ClientBuilder! + open var useEventCachePersistentStorageValueReturnValue: ClientBuilder! { + get { + if Thread.isMainThread { + return useEventCachePersistentStorageValueUnderlyingReturnValue + } else { + var returnValue: ClientBuilder? = nil + DispatchQueue.main.sync { + returnValue = useEventCachePersistentStorageValueUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + useEventCachePersistentStorageValueUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + useEventCachePersistentStorageValueUnderlyingReturnValue = newValue + } + } + } + } + open var useEventCachePersistentStorageValueClosure: ((Bool) -> ClientBuilder)? + + open override func useEventCachePersistentStorage(value: Bool) -> ClientBuilder { + useEventCachePersistentStorageValueCallsCount += 1 + useEventCachePersistentStorageValueReceivedValue = value + DispatchQueue.main.async { + self.useEventCachePersistentStorageValueReceivedInvocations.append(value) + } + if let useEventCachePersistentStorageValueClosure = useEventCachePersistentStorageValueClosure { + return useEventCachePersistentStorageValueClosure(value) + } else { + return useEventCachePersistentStorageValueReturnValue + } + } + //MARK: - userAgent var userAgentUserAgentUnderlyingCallsCount = 0 @@ -7867,6 +7938,189 @@ open class InReplyToDetailsSDKMock: MatrixRustSDK.InReplyToDetails { } } } +open class KnockRequestActionsSDKMock: MatrixRustSDK.KnockRequestActions { + init() { + super.init(noPointer: .init()) + } + + public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + fatalError("init(unsafeFromRawPointer:) has not been implemented") + } + + fileprivate var pointer: UnsafeMutableRawPointer! + + //MARK: - accept + + open var acceptThrowableError: Error? + var acceptUnderlyingCallsCount = 0 + open var acceptCallsCount: Int { + get { + if Thread.isMainThread { + return acceptUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = acceptUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + acceptUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + acceptUnderlyingCallsCount = newValue + } + } + } + } + open var acceptCalled: Bool { + return acceptCallsCount > 0 + } + open var acceptClosure: (() async throws -> Void)? + + open override func accept() async throws { + if let error = acceptThrowableError { + throw error + } + acceptCallsCount += 1 + try await acceptClosure?() + } + + //MARK: - decline + + open var declineReasonThrowableError: Error? + var declineReasonUnderlyingCallsCount = 0 + open var declineReasonCallsCount: Int { + get { + if Thread.isMainThread { + return declineReasonUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = declineReasonUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + declineReasonUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + declineReasonUnderlyingCallsCount = newValue + } + } + } + } + open var declineReasonCalled: Bool { + return declineReasonCallsCount > 0 + } + open var declineReasonReceivedReason: String? + open var declineReasonReceivedInvocations: [String?] = [] + open var declineReasonClosure: ((String?) async throws -> Void)? + + open override func decline(reason: String?) async throws { + if let error = declineReasonThrowableError { + throw error + } + declineReasonCallsCount += 1 + declineReasonReceivedReason = reason + DispatchQueue.main.async { + self.declineReasonReceivedInvocations.append(reason) + } + try await declineReasonClosure?(reason) + } + + //MARK: - declineAndBan + + open var declineAndBanReasonThrowableError: Error? + var declineAndBanReasonUnderlyingCallsCount = 0 + open var declineAndBanReasonCallsCount: Int { + get { + if Thread.isMainThread { + return declineAndBanReasonUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = declineAndBanReasonUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + declineAndBanReasonUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + declineAndBanReasonUnderlyingCallsCount = newValue + } + } + } + } + open var declineAndBanReasonCalled: Bool { + return declineAndBanReasonCallsCount > 0 + } + open var declineAndBanReasonReceivedReason: String? + open var declineAndBanReasonReceivedInvocations: [String?] = [] + open var declineAndBanReasonClosure: ((String?) async throws -> Void)? + + open override func declineAndBan(reason: String?) async throws { + if let error = declineAndBanReasonThrowableError { + throw error + } + declineAndBanReasonCallsCount += 1 + declineAndBanReasonReceivedReason = reason + DispatchQueue.main.async { + self.declineAndBanReasonReceivedInvocations.append(reason) + } + try await declineAndBanReasonClosure?(reason) + } + + //MARK: - markAsSeen + + open var markAsSeenThrowableError: Error? + var markAsSeenUnderlyingCallsCount = 0 + open var markAsSeenCallsCount: Int { + get { + if Thread.isMainThread { + return markAsSeenUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = markAsSeenUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + markAsSeenUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + markAsSeenUnderlyingCallsCount = newValue + } + } + } + } + open var markAsSeenCalled: Bool { + return markAsSeenCallsCount > 0 + } + open var markAsSeenClosure: (() async throws -> Void)? + + open override func markAsSeen() async throws { + if let error = markAsSeenThrowableError { + throw error + } + markAsSeenCallsCount += 1 + try await markAsSeenClosure?() + } +} open class LazyTimelineItemProviderSDKMock: MatrixRustSDK.LazyTimelineItemProvider { init() { super.init(noPointer: .init()) @@ -8248,6 +8502,71 @@ open class MediaSourceSDKMock: MatrixRustSDK.MediaSource { { } + //MARK: - toJson + + var toJsonUnderlyingCallsCount = 0 + open var toJsonCallsCount: Int { + get { + if Thread.isMainThread { + return toJsonUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = toJsonUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + toJsonUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + toJsonUnderlyingCallsCount = newValue + } + } + } + } + open var toJsonCalled: Bool { + return toJsonCallsCount > 0 + } + + var toJsonUnderlyingReturnValue: String! + open var toJsonReturnValue: String! { + get { + if Thread.isMainThread { + return toJsonUnderlyingReturnValue + } else { + var returnValue: String? = nil + DispatchQueue.main.sync { + returnValue = toJsonUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + toJsonUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + toJsonUnderlyingReturnValue = newValue + } + } + } + } + open var toJsonClosure: (() -> String)? + + open override func toJson() -> String { + toJsonCallsCount += 1 + if let toJsonClosure = toJsonClosure { + return toJsonClosure() + } else { + return toJsonReturnValue + } + } + //MARK: - url var urlUnderlyingCallsCount = 0 @@ -10816,6 +11135,46 @@ open class RoomSDKMock: MatrixRustSDK.Room { try await clearComposerDraftClosure?() } + //MARK: - clearEventCacheStorage + + open var clearEventCacheStorageThrowableError: Error? + var clearEventCacheStorageUnderlyingCallsCount = 0 + open var clearEventCacheStorageCallsCount: Int { + get { + if Thread.isMainThread { + return clearEventCacheStorageUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = clearEventCacheStorageUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + clearEventCacheStorageUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + clearEventCacheStorageUnderlyingCallsCount = newValue + } + } + } + } + open var clearEventCacheStorageCalled: Bool { + return clearEventCacheStorageCallsCount > 0 + } + open var clearEventCacheStorageClosure: (() async throws -> Void)? + + open override func clearEventCacheStorage() async throws { + if let error = clearEventCacheStorageThrowableError { + throw error + } + clearEventCacheStorageCallsCount += 1 + try await clearEventCacheStorageClosure?() + } + //MARK: - discardRoomKey open var discardRoomKeyThrowableError: Error? @@ -12813,6 +13172,81 @@ open class RoomSDKMock: MatrixRustSDK.Room { } } + //MARK: - messageFilteredTimeline + + open var messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeThrowableError: Error? + var messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeUnderlyingCallsCount = 0 + open var messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeCallsCount: Int { + get { + if Thread.isMainThread { + return messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeUnderlyingCallsCount = newValue + } + } + } + } + open var messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeCalled: Bool { + return messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeCallsCount > 0 + } + open var messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeReceivedArguments: (internalIdPrefix: String?, allowedMessageTypes: [RoomMessageEventMessageType], dateDividerMode: DateDividerMode)? + open var messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeReceivedInvocations: [(internalIdPrefix: String?, allowedMessageTypes: [RoomMessageEventMessageType], dateDividerMode: DateDividerMode)] = [] + + var messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeUnderlyingReturnValue: Timeline! + open var messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeReturnValue: Timeline! { + get { + if Thread.isMainThread { + return messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeUnderlyingReturnValue + } else { + var returnValue: Timeline? = nil + DispatchQueue.main.sync { + returnValue = messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeUnderlyingReturnValue = newValue + } + } + } + } + open var messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeClosure: ((String?, [RoomMessageEventMessageType], DateDividerMode) async throws -> Timeline)? + + open override func messageFilteredTimeline(internalIdPrefix: String?, allowedMessageTypes: [RoomMessageEventMessageType], dateDividerMode: DateDividerMode) async throws -> Timeline { + if let error = messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeThrowableError { + throw error + } + messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeCallsCount += 1 + messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeReceivedArguments = (internalIdPrefix: internalIdPrefix, allowedMessageTypes: allowedMessageTypes, dateDividerMode: dateDividerMode) + DispatchQueue.main.async { + self.messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeReceivedInvocations.append((internalIdPrefix: internalIdPrefix, allowedMessageTypes: allowedMessageTypes, dateDividerMode: dateDividerMode)) + } + if let messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeClosure = messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeClosure { + return try await messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeClosure(internalIdPrefix, allowedMessageTypes, dateDividerMode) + } else { + return messageFilteredTimelineInternalIdPrefixAllowedMessageTypesDateDividerModeReturnValue + } + } + //MARK: - ownUserId var ownUserIdUnderlyingCallsCount = 0 @@ -13420,6 +13854,52 @@ open class RoomSDKMock: MatrixRustSDK.Room { try await sendCallNotificationIfNeededClosure?() } + //MARK: - sendRaw + + open var sendRawEventTypeContentThrowableError: Error? + var sendRawEventTypeContentUnderlyingCallsCount = 0 + open var sendRawEventTypeContentCallsCount: Int { + get { + if Thread.isMainThread { + return sendRawEventTypeContentUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = sendRawEventTypeContentUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + sendRawEventTypeContentUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + sendRawEventTypeContentUnderlyingCallsCount = newValue + } + } + } + } + open var sendRawEventTypeContentCalled: Bool { + return sendRawEventTypeContentCallsCount > 0 + } + open var sendRawEventTypeContentReceivedArguments: (eventType: String, content: String)? + open var sendRawEventTypeContentReceivedInvocations: [(eventType: String, content: String)] = [] + open var sendRawEventTypeContentClosure: ((String, String) async throws -> Void)? + + open override func sendRaw(eventType: String, content: String) async throws { + if let error = sendRawEventTypeContentThrowableError { + throw error + } + sendRawEventTypeContentCallsCount += 1 + sendRawEventTypeContentReceivedArguments = (eventType: eventType, content: content) + DispatchQueue.main.async { + self.sendRawEventTypeContentReceivedInvocations.append((eventType: eventType, content: content)) + } + try await sendRawEventTypeContentClosure?(eventType, content) + } + //MARK: - setIsFavourite open var setIsFavouriteIsFavouriteTagOrderThrowableError: Error? @@ -13721,6 +14201,81 @@ open class RoomSDKMock: MatrixRustSDK.Room { } } + //MARK: - subscribeToKnockRequests + + open var subscribeToKnockRequestsListenerThrowableError: Error? + var subscribeToKnockRequestsListenerUnderlyingCallsCount = 0 + open var subscribeToKnockRequestsListenerCallsCount: Int { + get { + if Thread.isMainThread { + return subscribeToKnockRequestsListenerUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = subscribeToKnockRequestsListenerUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + subscribeToKnockRequestsListenerUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + subscribeToKnockRequestsListenerUnderlyingCallsCount = newValue + } + } + } + } + open var subscribeToKnockRequestsListenerCalled: Bool { + return subscribeToKnockRequestsListenerCallsCount > 0 + } + open var subscribeToKnockRequestsListenerReceivedListener: KnockRequestsListener? + open var subscribeToKnockRequestsListenerReceivedInvocations: [KnockRequestsListener] = [] + + var subscribeToKnockRequestsListenerUnderlyingReturnValue: TaskHandle! + open var subscribeToKnockRequestsListenerReturnValue: TaskHandle! { + get { + if Thread.isMainThread { + return subscribeToKnockRequestsListenerUnderlyingReturnValue + } else { + var returnValue: TaskHandle? = nil + DispatchQueue.main.sync { + returnValue = subscribeToKnockRequestsListenerUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + subscribeToKnockRequestsListenerUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + subscribeToKnockRequestsListenerUnderlyingReturnValue = newValue + } + } + } + } + open var subscribeToKnockRequestsListenerClosure: ((KnockRequestsListener) async throws -> TaskHandle)? + + open override func subscribeToKnockRequests(listener: KnockRequestsListener) async throws -> TaskHandle { + if let error = subscribeToKnockRequestsListenerThrowableError { + throw error + } + subscribeToKnockRequestsListenerCallsCount += 1 + subscribeToKnockRequestsListenerReceivedListener = listener + DispatchQueue.main.async { + self.subscribeToKnockRequestsListenerReceivedInvocations.append(listener) + } + if let subscribeToKnockRequestsListenerClosure = subscribeToKnockRequestsListenerClosure { + return try await subscribeToKnockRequestsListenerClosure(listener) + } else { + return subscribeToKnockRequestsListenerReturnValue + } + } + //MARK: - subscribeToRoomInfoUpdates var subscribeToRoomInfoUpdatesListenerUnderlyingCallsCount = 0 diff --git a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift index d8acfaf791..30edf80776 100644 --- a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift @@ -30,6 +30,7 @@ struct JoinedRoomProxyMockConfiguration { var timelineStartReached = false var members: [RoomMemberProxyMock] = .allMembers + var knockRequestsState: KnockRequestsState = .loaded([]) var ownUserID = RoomMemberProxyMock.mockMe.userID var inviter: RoomMemberProxyProtocol? @@ -57,6 +58,7 @@ extension JoinedRoomProxyMock { infoPublisher = CurrentValueSubject(.init(roomInfo: .init(configuration))).asCurrentValuePublisher() membersPublisher = CurrentValueSubject(configuration.members).asCurrentValuePublisher() + knockRequestsStatePublisher = CurrentValueSubject(configuration.knockRequestsState).asCurrentValuePublisher() typingMembersPublisher = CurrentValueSubject([]).asCurrentValuePublisher() identityStatusChangesPublisher = CurrentValueSubject([]).asCurrentValuePublisher() @@ -92,7 +94,7 @@ extension JoinedRoomProxyMock { } canUserInviteUserIDReturnValue = .success(configuration.canUserInvite) canUserRedactOtherUserIDReturnValue = .success(false) - canUserRedactOwnUserIDReturnValue = .success(false) + canUserRedactOwnUserIDReturnValue = .success(true) canUserKickUserIDClosure = { [weak self] userID in .success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user) } diff --git a/ElementX/Sources/Mocks/KnockRequestProxyMock.swift b/ElementX/Sources/Mocks/KnockRequestProxyMock.swift new file mode 100644 index 0000000000..9b34c2759a --- /dev/null +++ b/ElementX/Sources/Mocks/KnockRequestProxyMock.swift @@ -0,0 +1,35 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Foundation + +struct KnockRequestProxyMockConfiguration { + let eventID: String + let userID: String + var displayName: String? + var avatarURL: URL? + var timestamp: String? + var reason: String? + var isSeen = false +} + +extension KnockRequestProxyMock { + convenience init(_ configuration: KnockRequestProxyMockConfiguration) { + self.init() + eventID = configuration.eventID + userID = configuration.userID + displayName = configuration.displayName + avatarURL = configuration.avatarURL + reason = configuration.reason + formattedTimestamp = configuration.timestamp + isSeen = configuration.isSeen + acceptReturnValue = .success(()) + declineReturnValue = .success(()) + banReturnValue = .success(()) + markAsSeenReturnValue = .success(()) + } +} diff --git a/ElementX/Sources/Mocks/MediaProviderMock.swift b/ElementX/Sources/Mocks/MediaProviderMock.swift index c2ae134960..fe9984f8b4 100644 --- a/ElementX/Sources/Mocks/MediaProviderMock.swift +++ b/ElementX/Sources/Mocks/MediaProviderMock.swift @@ -10,6 +10,7 @@ import SwiftUI extension MediaProviderMock { struct Configuration { } + // swiftlint:disable:next cyclomatic_complexity convenience init(configuration: Configuration) { self.init() @@ -18,9 +19,26 @@ extension MediaProviderMock { return nil } - // At some stage it would be nice to return different images, but for now they can be the same. - if mediaSource?.url == .mockMXCImage || mediaSource?.url == .mockMXCAvatar { - return Asset.Images.appLogo.image + if mediaSource?.url == .mockMXCImage { + if let url = Bundle.main.url(forResource: "preview_image", withExtension: "jpg"), + let data = try? Data(contentsOf: url) { + return UIImage(data: data) + } + } else if mediaSource?.url == .mockMXCVideo { + if let url = Bundle.main.url(forResource: "preview_video", withExtension: "jpg"), + let data = try? Data(contentsOf: url) { + return UIImage(data: data) + } + } else if mediaSource?.url == .mockMXCAvatar { + if let url = Bundle.main.url(forResource: "preview_avatar_room", withExtension: "jpg"), + let data = try? Data(contentsOf: url) { + return UIImage(data: data) + } + } else if mediaSource?.url == .mockMXCUserAvatar { + if let url = Bundle.main.url(forResource: "preview_avatar_user", withExtension: "jpg"), + let data = try? Data(contentsOf: url) { + return UIImage(data: data) + } } return UIImage(systemName: "photo") @@ -43,7 +61,13 @@ extension MediaProviderMock { return .success(data) } - loadFileFromSourceFilenameReturnValue = .failure(.failedRetrievingFile) + loadFileFromSourceFilenameClosure = { _, _ in + guard let url = Bundle.main.url(forResource: "preview_image", withExtension: "jpg") else { + return .failure(.failedRetrievingFile) + } + + return .success(.unmanaged(url: url)) + } loadImageRetryingOnReconnectionSizeClosure = { _, _ in Task { diff --git a/ElementX/Sources/Mocks/PhotoLibraryManagerMock.swift b/ElementX/Sources/Mocks/PhotoLibraryManagerMock.swift new file mode 100644 index 0000000000..dc8046a1f2 --- /dev/null +++ b/ElementX/Sources/Mocks/PhotoLibraryManagerMock.swift @@ -0,0 +1,21 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Foundation + +extension PhotoLibraryManagerMock { + struct Configuration { + var authorizationDenied = false + } + + // swiftlint:disable:next cyclomatic_complexity + convenience init(_ configuration: Configuration) { + self.init() + + addResourceAtReturnValue = configuration.authorizationDenied ? .failure(PhotoLibraryManagerError.notAuthorized) : .success(()) + } +} diff --git a/ElementX/Sources/Mocks/PollMock.swift b/ElementX/Sources/Mocks/PollMock.swift index 821550f415..4c1f5995a3 100644 --- a/ElementX/Sources/Mocks/PollMock.swift +++ b/ElementX/Sources/Mocks/PollMock.swift @@ -85,7 +85,7 @@ extension PollRoomTimelineItem { .init(id: .randomEvent, poll: poll, body: "poll", - timestamp: "Now", + timestamp: .mock, isOutgoing: isOutgoing, isEditable: isEditable, canBeRepliedTo: true, diff --git a/ElementX/Sources/Mocks/RoomMemberProxyMock.swift b/ElementX/Sources/Mocks/RoomMemberProxyMock.swift index 8c81c727e1..e6571ff3b6 100644 --- a/ElementX/Sources/Mocks/RoomMemberProxyMock.swift +++ b/ElementX/Sources/Mocks/RoomMemberProxyMock.swift @@ -43,14 +43,14 @@ extension RoomMemberProxyMock { static var mockMe: RoomMemberProxyMock { RoomMemberProxyMock(with: .init(userID: "@me:matrix.org", displayName: "Me", - avatarURL: .mockMXCAvatar, + avatarURL: .mockMXCUserAvatar, membership: .join)) } static var mockMeAdmin: RoomMemberProxyMock { RoomMemberProxyMock(with: .init(userID: "@me:matrix.org", displayName: "Me", - avatarURL: .mockMXCAvatar, + avatarURL: .mockMXCUserAvatar, membership: .join, powerLevel: 100, role: .administrator)) @@ -83,7 +83,7 @@ extension RoomMemberProxyMock { static var mockDan: RoomMemberProxyMock { RoomMemberProxyMock(with: .init(userID: "@dan:matrix.org", displayName: "Dan", - avatarURL: .mockMXCAvatar, + avatarURL: .mockMXCUserAvatar, membership: .join)) } diff --git a/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift b/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift index 7c71582868..4a70c0167a 100644 --- a/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift +++ b/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift @@ -71,7 +71,7 @@ extension Array where Element == RoomSummary { static let mockRooms: [Element] = [ RoomSummary(roomListItem: RoomListItemSDKMock(), id: "1", - joinRequestType: nil, + knockRequestType: nil, name: "Foundation 🔭🪐🌌", isDirect: false, avatarURL: nil, @@ -88,7 +88,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "2", - joinRequestType: nil, + knockRequestType: nil, name: "Foundation and Empire", isDirect: false, avatarURL: .mockMXCAvatar, @@ -105,7 +105,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "3", - joinRequestType: nil, + knockRequestType: nil, name: "Second Foundation", isDirect: false, avatarURL: nil, @@ -122,7 +122,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "4", - joinRequestType: nil, + knockRequestType: nil, name: "Foundation's Edge", isDirect: false, avatarURL: nil, @@ -139,7 +139,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "5", - joinRequestType: nil, + knockRequestType: nil, name: "Foundation and Earth", isDirect: true, avatarURL: nil, @@ -156,7 +156,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "6", - joinRequestType: nil, + knockRequestType: nil, name: "Prelude to Foundation", isDirect: true, avatarURL: nil, @@ -173,7 +173,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "0", - joinRequestType: nil, + knockRequestType: nil, name: "Unknown", isDirect: false, avatarURL: nil, @@ -223,7 +223,7 @@ extension Array where Element == RoomSummary { static let mockInvites: [Element] = [ RoomSummary(roomListItem: RoomListItemSDKMock(), id: "someAwesomeRoomId1", - joinRequestType: .invite(inviter: RoomMemberProxyMock.mockCharlie), + knockRequestType: .invite(inviter: RoomMemberProxyMock.mockCharlie), name: "First room", isDirect: false, avatarURL: .mockMXCAvatar, @@ -240,7 +240,7 @@ extension Array where Element == RoomSummary { isFavourite: false), RoomSummary(roomListItem: RoomListItemSDKMock(), id: "someAwesomeRoomId2", - joinRequestType: .invite(inviter: RoomMemberProxyMock.mockCharlie), + knockRequestType: .invite(inviter: RoomMemberProxyMock.mockCharlie), name: "Second room", isDirect: true, avatarURL: nil, diff --git a/ElementX/Sources/Other/Avatars.swift b/ElementX/Sources/Other/Avatars.swift index 96fc58aaaa..e97b3dae66 100644 --- a/ElementX/Sources/Other/Avatars.swift +++ b/ElementX/Sources/Other/Avatars.swift @@ -75,6 +75,7 @@ enum UserAvatarSizeOnScreen { case knockingUsersBannerStack case knockingUserBanner case knockingUserList + case mediaPreviewDetails var value: CGFloat { switch self { @@ -110,6 +111,8 @@ enum UserAvatarSizeOnScreen { return 32 case .knockingUserList: return 52 + case .mediaPreviewDetails: + return 32 } } } diff --git a/ElementX/Sources/Other/Extensions/ClientBuilder.swift b/ElementX/Sources/Other/Extensions/ClientBuilder.swift index 6ca8cb335a..2b90d963b9 100644 --- a/ElementX/Sources/Other/Extensions/ClientBuilder.swift +++ b/ElementX/Sources/Other/Extensions/ClientBuilder.swift @@ -15,13 +15,15 @@ extension ClientBuilder { slidingSync: ClientBuilderSlidingSync, sessionDelegate: ClientSessionDelegate, appHooks: AppHooks, - enableOnlySignedDeviceIsolationMode: Bool) -> ClientBuilder { + enableOnlySignedDeviceIsolationMode: Bool, + eventCacheEnabled: Bool) -> ClientBuilder { var builder = ClientBuilder() .crossProcessStoreLocksHolderName(holderName: InfoPlistReader.main.bundleIdentifier) .enableOidcRefreshLock() .setSessionDelegate(sessionDelegate: sessionDelegate) .userAgent(userAgent: UserAgentBuilder.makeASCIIUserAgent()) .requestConfig(config: .init(retryLimit: 0, timeout: 30000, maxConcurrentRequests: nil, retryTimeout: nil)) + .useEventCachePersistentStorage(value: eventCacheEnabled) builder = switch slidingSync { case .restored: builder diff --git a/ElementX/Sources/Other/Extensions/Date.swift b/ElementX/Sources/Other/Extensions/Date.swift index 791e57dc52..14ef23bdfc 100644 --- a/ElementX/Sources/Other/Extensions/Date.swift +++ b/ElementX/Sources/Other/Extensions/Date.swift @@ -32,4 +32,14 @@ extension Date { return formatted(.dateTime.year().day().month()) } } + + /// The date formatted as just the time, for use in timeline items specifically. + func formattedTime() -> String { + formatted(date: .omitted, time: .shortened) + } + + /// A fixed date used for mocks, previews etc. + static var mock: Date { + DateComponents(calendar: .current, year: 2007, month: 1, day: 9, hour: 9, minute: 41).date ?? .now + } } diff --git a/ElementX/Sources/Other/Extensions/PlatformViewVersionPredicate.swift b/ElementX/Sources/Other/Extensions/PlatformViewVersionPredicate.swift index 879af5a8ea..61900a3e08 100644 --- a/ElementX/Sources/Other/Extensions/PlatformViewVersionPredicate.swift +++ b/ElementX/Sources/Other/Extensions/PlatformViewVersionPredicate.swift @@ -10,18 +10,24 @@ import SwiftUIIntrospect extension PlatformViewVersionPredicate { static var supportedVersions: Self { - .iOS(.v16, .v17, .v18) + .iOS(.v17, .v18) } } extension PlatformViewVersionPredicate { static var supportedVersions: Self { - .iOS(.v16, .v17, .v18) + .iOS(.v17, .v18) } } extension PlatformViewVersionPredicate { static var supportedVersions: Self { - .iOS(.v16, .v17, .v18) + .iOS(.v17, .v18) + } +} + +extension PlatformViewVersionPredicate { + static var supportedVersions: Self { + .iOS(.v17, .v18) } } diff --git a/ElementX/Sources/Other/Extensions/Result.swift b/ElementX/Sources/Other/Extensions/Result.swift new file mode 100644 index 0000000000..2c1b9eecff --- /dev/null +++ b/ElementX/Sources/Other/Extensions/Result.swift @@ -0,0 +1,17 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +extension Result { + var isFailure: Bool { + switch self { + case .success: + return false + case .failure: + return true + } + } +} diff --git a/ElementX/Sources/Other/Extensions/URL.swift b/ElementX/Sources/Other/Extensions/URL.swift index 0c026ef129..1c7a5a93a8 100644 --- a/ElementX/Sources/Other/Extensions/URL.swift +++ b/ElementX/Sources/Other/Extensions/URL.swift @@ -103,9 +103,10 @@ extension URL: @retroactive ExpressibleByStringLiteral { // MARK: Mocks - static var mockMXCAudio: URL { "mxc://matrix.org/1234567890FiLe" } + static var mockMXCAudio: URL { "mxc://matrix.org/1234567890AuDiO" } static var mockMXCFile: URL { "mxc://matrix.org/1234567890FiLe" } static var mockMXCImage: URL { "mxc://matrix.org/1234567890ImAgE" } static var mockMXCVideo: URL { "mxc://matrix.org/1234567890ViDeO" } static var mockMXCAvatar: URL { "mxc://matrix.org/1234567890AvAtAr" } + static var mockMXCUserAvatar: URL { "mxc://matrix.org/1234567890AvAtArUsEr" } } diff --git a/ElementX/Sources/Other/SwiftUI/Animation/ZoomTransition.swift b/ElementX/Sources/Other/SwiftUI/Animation/ZoomTransition.swift new file mode 100644 index 0000000000..4094542f6a --- /dev/null +++ b/ElementX/Sources/Other/SwiftUI/Animation/ZoomTransition.swift @@ -0,0 +1,30 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import SwiftUI + +extension View { + /// A convenience modifier to conditionally apply `.navigationTransition(.zoom(…))` when available. + @ViewBuilder + func zoomTransition(sourceID: some Hashable, in namespace: Namespace.ID) -> some View { + if #available(iOS 18.0, *) { + navigationTransition(.zoom(sourceID: sourceID, in: namespace)) + } else { + self + } + } + + /// A convenience modifier to conditionally apply `.matchedTransitionSource(…)` when available. + @ViewBuilder + func zoomTransitionSource(id: some Hashable, in namespace: Namespace.ID) -> some View { + if #available(iOS 18.0, *) { + matchedTransitionSource(id: id, in: namespace) + } else { + self + } + } +} diff --git a/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift b/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift index c715f5fc93..cd5bb6399c 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift @@ -29,4 +29,9 @@ extension View { } } } + + @ViewBuilder + func mediaGalleryTimelineAspectRatio(imageInfo: ImageInfoProxy?) -> some View { + aspectRatio(imageInfo?.aspectRatio, contentMode: .fill) + } } diff --git a/ElementX/Sources/Other/SwiftUI/ShouldScrollOnKeyboardDidShow.swift b/ElementX/Sources/Other/SwiftUI/ShouldScrollOnKeyboardDidShow.swift new file mode 100644 index 0000000000..58736ca900 --- /dev/null +++ b/ElementX/Sources/Other/SwiftUI/ShouldScrollOnKeyboardDidShow.swift @@ -0,0 +1,24 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import SwiftUI + +extension View { + /// Adds a scroll view reader to the view and scrolls to the provided id if the condition is true, so far it only works properly if the item is the last in the scroll view. + func shouldScrollOnKeyboardDidShow(_ shouldScroll: Bool, to id: any Hashable) -> some View { + ScrollViewReader { scrollView in + onReceive(NotificationCenter.default.publisher(for: UIApplication.keyboardDidShowNotification)) { _ in + guard shouldScroll else { return } + // Scroll to the footer of the alias when the keyboard appears + withAnimation { + // We could improve this in the future by also providing the anchor as an argument + scrollView.scrollTo(id, anchor: .top) + } + } + } + } +} diff --git a/ElementX/Sources/Other/SwiftUI/Views/BlurEffectView.swift b/ElementX/Sources/Other/SwiftUI/Views/BlurEffectView.swift new file mode 100644 index 0000000000..008bee983e --- /dev/null +++ b/ElementX/Sources/Other/SwiftUI/Views/BlurEffectView.swift @@ -0,0 +1,22 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import SwiftUI + +/// A view that renders a `UIBlurEffect` as there is a larger range of +/// effects available compared to using SwiftUI's `Material` type. +struct BlurEffectView: UIViewRepresentable { + var style: UIBlurEffect.Style + + func makeUIView(context: Context) -> UIVisualEffectView { + UIVisualEffectView(effect: UIBlurEffect(style: style)) + } + + func updateUIView(_ uiView: UIVisualEffectView, context: Context) { + uiView.effect = UIBlurEffect(style: style) + } +} diff --git a/ElementX/Sources/Other/VoiceMessage/VoiceMessageButton.swift b/ElementX/Sources/Other/VoiceMessage/VoiceMessageButton.swift index d0fffff0f8..b99628bd64 100644 --- a/ElementX/Sources/Other/VoiceMessage/VoiceMessageButton.swift +++ b/ElementX/Sources/Other/VoiceMessage/VoiceMessageButton.swift @@ -106,12 +106,12 @@ struct VoiceMessageButton_Previews: PreviewProvider, TestablePreview { static var previews: some View { VStack(spacing: 8) { HStack(spacing: 8) { - VoiceMessageButton(state: .paused, size: .small, action: { }) - VoiceMessageButton(state: .paused, size: .medium, action: { }) + VoiceMessageButton(state: .paused, size: .small) { } + VoiceMessageButton(state: .paused, size: .medium) { } } HStack(spacing: 8) { - VoiceMessageButton(state: .playing, size: .small, action: { }) - VoiceMessageButton(state: .playing, size: .medium, action: { }) + VoiceMessageButton(state: .playing, size: .small) { } + VoiceMessageButton(state: .playing, size: .medium) { } } } .padding() diff --git a/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift b/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift index e9090cabd4..6926820380 100644 --- a/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift +++ b/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift @@ -38,7 +38,7 @@ struct BlockedUsersScreen: View { // kind: .button(action: { context.send(viewAction: .unblockUser(user)) })) ListRow(label: .avatar(title: user.displayName ?? MatrixIdFromString(user.userID).userDisplayName?.displayName ?? user.userID, icon: avatar(for: user)), details: .isWaiting(context.viewState.processingUserID == user.userID), - kind: .button(action: { context.send(viewAction: .unblockUser(user)) })) + kind: .button { context.send(viewAction: .unblockUser(user)) }) } } } diff --git a/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift b/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift index 2cd0d5559a..9a54f78e5d 100644 --- a/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift +++ b/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift @@ -26,7 +26,6 @@ struct CallScreen: View { Image(systemSymbol: .chevronBackward) .fontWeight(.semibold) } - // .padding(.leading, -8) // Fixes the button alignment, but harder to tap. } } } diff --git a/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModel.swift b/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModel.swift index 1e750d7911..5723d8fcb2 100644 --- a/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModel.swift +++ b/ElementX/Sources/Screens/CreatePollScreen/PollFormScreenViewModel.swift @@ -34,14 +34,14 @@ class PollFormScreenViewModel: PollFormScreenViewModelType, PollFormScreenViewMo title: L10n.screenEditPollDeleteConfirmationTitle, message: L10n.screenEditPollDeleteConfirmation, primaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil), - secondaryButton: .init(title: L10n.actionOk, action: { self.actionsSubject.send(.delete) })) + secondaryButton: .init(title: L10n.actionOk) { self.actionsSubject.send(.delete) }) case .cancel: if state.formContentHasChanged { state.bindings.alertInfo = .init(id: .init(), title: L10n.screenCreatePollCancelConfirmationTitleIos, message: L10n.screenCreatePollCancelConfirmationContentIos, primaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil), - secondaryButton: .init(title: L10n.actionOk, action: { self.actionsSubject.send(.cancel) })) + secondaryButton: .init(title: L10n.actionOk) { self.actionsSubject.send(.cancel) }) } else { actionsSubject.send(.cancel) } diff --git a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift index 22f8dbd78b..3fed4c0a37 100644 --- a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift +++ b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift @@ -15,6 +15,7 @@ struct CreateRoomScreen: View { private enum Focus { case name case topic + case alias } private var aliasBinding: Binding { @@ -52,6 +53,7 @@ struct CreateRoomScreen: View { .toolbar { toolbar } .readFrame($frame) .alert(item: $context.alertInfo) + .shouldScrollOnKeyboardDidShow(focus == .alias, to: Focus.alias) } private var roomSection: some View { @@ -193,10 +195,11 @@ struct CreateRoomScreen: View { Text("#") .font(.compound.bodyLG) .foregroundStyle(.compound.textSecondary) - TextField("", text: aliasBinding) .textInputAutocapitalization(.never) .autocorrectionDisabled() + .textContentType(.URL) + .focused($focus, equals: .alias) .tint(.compound.iconAccentTertiary) .font(.compound.bodyLG) .foregroundStyle(.compound.textPrimary) @@ -209,6 +212,7 @@ struct CreateRoomScreen: View { .environment(\.layoutDirection, .leftToRight) .errorBackground(!context.viewState.aliasErrors.isEmpty) }) + .id(Focus.alias) } header: { Text(L10n.screenCreateRoomRoomAddressSectionTitle) .compoundListSectionHeader() diff --git a/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenViewModel.swift b/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenViewModel.swift index 09e5ee076e..21450bac08 100644 --- a/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenViewModel.swift +++ b/ElementX/Sources/Screens/DeactivateAccountScreen/DeactivateAccountScreenViewModel.swift @@ -43,9 +43,9 @@ class DeactivateAccountScreenViewModel: DeactivateAccountScreenViewModelType, De state.bindings.alertInfo = .init(id: .confirmation, title: L10n.screenDeactivateAccountTitle, message: L10n.screenDeactivateAccountConfirmationDialogContent, - primaryButton: .init(title: L10n.actionDeactivate, action: { + primaryButton: .init(title: L10n.actionDeactivate) { Task { await self.deactivateAccount() } - }), + }, secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) } diff --git a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift index a81c2f112c..21eb50490f 100644 --- a/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift +++ b/ElementX/Sources/Screens/EncryptionReset/EncryptionResetScreen/EncryptionResetScreenViewModel.swift @@ -38,10 +38,10 @@ class EncryptionResetScreenViewModel: EncryptionResetScreenViewModelType, Encryp state.bindings.alertInfo = .init(id: UUID(), title: L10n.screenResetEncryptionConfirmationAlertTitle, message: L10n.screenResetEncryptionConfirmationAlertSubtitle, - primaryButton: .init(title: L10n.screenResetEncryptionConfirmationAlertAction, role: .destructive, action: { [weak self] in + primaryButton: .init(title: L10n.screenResetEncryptionConfirmationAlertAction, role: .destructive) { [weak self] in guard let self else { return } Task { await self.startResetFlow() } - })) + }) case .cancel: actionsSubject.send(.cancel) } diff --git a/ElementX/Sources/Screens/FilePreviewScreen/PhotoLibraryManager.swift b/ElementX/Sources/Screens/FilePreviewScreen/PhotoLibraryManager.swift new file mode 100644 index 0000000000..d4b37015dc --- /dev/null +++ b/ElementX/Sources/Screens/FilePreviewScreen/PhotoLibraryManager.swift @@ -0,0 +1,37 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Photos + +enum PhotoLibraryManagerError: Error { + case notAuthorized + case unknown(Error) +} + +// sourcery: AutoMockable +protocol PhotoLibraryManagerProtocol { + func addResource(_ type: PHAssetResourceType, at url: URL) async -> Result +} + +struct PhotoLibraryManager: PhotoLibraryManagerProtocol { + func addResource(_ type: PHAssetResourceType, at url: URL) async -> Result { + do { + try await PHPhotoLibrary.shared().performChanges { + let request = PHAssetCreationRequest.forAsset() + let options = PHAssetResourceCreationOptions() + request.addResource(with: type, fileURL: url, options: options) + } + return .success(()) + } catch { + if (error as NSError).code == PHPhotosError.accessUserDenied.rawValue { + return .failure(.notAuthorized) + } else { + return .failure(.unknown(error)) + } + } + } +} diff --git a/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewCoordinator.swift b/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewCoordinator.swift new file mode 100644 index 0000000000..4fb04d1bbe --- /dev/null +++ b/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewCoordinator.swift @@ -0,0 +1,81 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import SwiftUI + +struct TimelineMediaPreviewContext { + /// The initial item to preview from the provided timeline. + /// This item's `id` will be used as the navigation transition's `sourceID`. + let item: EventBasedMessageTimelineItemProtocol + /// The timeline that the preview comes from, to allow for swiping to other media. + let viewModel: TimelineViewModelProtocol + /// The namespace that the navigation transition's `sourceID` should be defined in. + let namespace: Namespace.ID + /// A closure to be called whenever a different preview item is shown. It should also + /// be called *after* the preview has been dismissed, with an ID of `nil`. + /// + /// This helps work around a bug caused by the flipped scrollview where the zoomed + /// thumbnail starts off upside down while loading the preview screen. + var itemIDHandler: ((TimelineItemIdentifier?) -> Void)? +} + +struct TimelineMediaPreviewCoordinatorParameters { + let context: TimelineMediaPreviewContext + let mediaProvider: MediaProviderProtocol + let userIndicatorController: UserIndicatorControllerProtocol + let appMediator: AppMediatorProtocol +} + +enum TimelineMediaPreviewCoordinatorAction { + case viewInRoomTimeline(TimelineItemIdentifier) + case dismiss +} + +final class TimelineMediaPreviewCoordinator: CoordinatorProtocol { + private let parameters: TimelineMediaPreviewCoordinatorParameters + private let viewModel: TimelineMediaPreviewViewModel + + private var cancellables = Set() + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(parameters: TimelineMediaPreviewCoordinatorParameters) { + self.parameters = parameters + + viewModel = TimelineMediaPreviewViewModel(context: parameters.context, + mediaProvider: parameters.mediaProvider, + photoLibraryManager: PhotoLibraryManager(), + userIndicatorController: parameters.userIndicatorController, + appMediator: parameters.appMediator) + } + + func start() { + viewModel.actions.sink { [weak self] action in + MXLog.info("Coordinator: received view model action: \(action)") + + guard let self else { return } + switch action { + case .viewInRoomTimeline(let itemID): + actionsSubject.send(.viewInRoomTimeline(itemID)) + case .dismiss: + actionsSubject.send(.dismiss) + } + } + .store(in: &cancellables) + } + + func toPresentable() -> AnyView { + // Calling the completion onDisappear isn't ideal, but we don't push away from the screen so it should be + // a good enough approximation of didDismiss, given that the only other option is our navigation callbacks + // which are essentially willDismiss callbacks and happen too early for this particular completion handler. + AnyView(TimelineMediaPreviewScreen(context: viewModel.context, itemIDHandler: parameters.context.itemIDHandler)) + } +} diff --git a/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewModels.swift b/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewModels.swift new file mode 100644 index 0000000000..84b8c40c12 --- /dev/null +++ b/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewModels.swift @@ -0,0 +1,206 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import QuickLook +import SwiftUI + +enum TimelineMediaPreviewViewModelAction: Equatable { + case viewInRoomTimeline(TimelineItemIdentifier) + case dismiss +} + +struct TimelineMediaPreviewViewState: BindableState { + /// All of the items in the timeline that can be previewed. + var previewItems: [TimelineMediaPreviewItem] + /// The index of the initial item inside of `previewItems` that is to be shown. + let initialItemIndex: Int + + /// The media item that is currently being previewed. + var currentItem: TimelineMediaPreviewItem + /// All of the available actions for the current item. + var currentItemActions: TimelineItemMenuActions? + + /// The namespace used for the zoom transition. + let transitionNamespace: Namespace.ID + /// A publisher that the view model uses to signal to the QLPreviewController when the current item has been loaded. + let fileLoadedPublisher = PassthroughSubject() + + var bindings = TimelineMediaPreviewViewStateBindings() +} + +struct TimelineMediaPreviewViewStateBindings { + /// A binding that will present the Details view for the specified item. + var mediaDetailsItem: TimelineMediaPreviewItem? + /// A binding that will present a confirmation to redact the specified item. + var redactConfirmationItem: TimelineMediaPreviewItem? + /// A binding that will present a document picker to export the specified file. + var fileToExport: TimelineMediaPreviewFileExportPicker.File? + + var alertInfo: AlertInfo? +} + +enum TimelineMediaPreviewAlertType { + case authorizationRequired +} + +/// Wraps a media file and title to be previewed with QuickLook. +class TimelineMediaPreviewItem: NSObject, QLPreviewItem, Identifiable { + let timelineItem: EventBasedMessageTimelineItemProtocol + var fileHandle: MediaFileHandleProxy? + var downloadError: Error? + + init(timelineItem: EventBasedMessageTimelineItemProtocol) { + self.timelineItem = timelineItem + } + + init?(roomTimelineItemViewState: RoomTimelineItemViewState) { + switch roomTimelineItemViewState.type { + case .audio(let audioRoomTimelineItem): + timelineItem = audioRoomTimelineItem + case .file(let fileRoomTimelineItem): + timelineItem = fileRoomTimelineItem + case .image(let imageRoomTimelineItem): + timelineItem = imageRoomTimelineItem + case .video(let videoRoomTimelineItem): + timelineItem = videoRoomTimelineItem + default: + return nil + } + } + + // MARK: Identifiable + + var id: TimelineItemIdentifier { timelineItem.id } + + // MARK: QLPreviewItem + + var previewItemURL: URL? { + // Falling back to a clear image allows the presentation animation to work when + // the item is in the event cache and just needs to be loaded from the store. + fileHandle?.url ?? Bundle.main.url(forResource: "clear", withExtension: "png") + } + + var previewItemTitle: String? { + filename + } + + // MARK: Event details + + var sender: TimelineItemSender { + timelineItem.sender + } + + var timestamp: Date { + timelineItem.timestamp + } + + // MARK: Media details + + var mediaSource: MediaSourceProxy? { + switch timelineItem { + case let audioItem as AudioRoomTimelineItem: + audioItem.content.source + case let fileItem as FileRoomTimelineItem: + fileItem.content.source + case let imageItem as ImageRoomTimelineItem: + imageItem.content.imageInfo.source + case let videoItem as VideoRoomTimelineItem: + videoItem.content.videoInfo.source + default: + nil + } + } + + var thumbnailMediaSource: MediaSourceProxy? { + switch timelineItem { + case let fileItem as FileRoomTimelineItem: + fileItem.content.thumbnailSource + case let imageItem as ImageRoomTimelineItem: + imageItem.content.thumbnailInfo?.source + case let videoItem as VideoRoomTimelineItem: + videoItem.content.thumbnailInfo?.source + default: + nil + } + } + + var filename: String? { + switch timelineItem { + case let audioItem as AudioRoomTimelineItem: + audioItem.content.filename + case let fileItem as FileRoomTimelineItem: + fileItem.content.filename + case let imageItem as ImageRoomTimelineItem: + imageItem.content.filename + case let videoItem as VideoRoomTimelineItem: + videoItem.content.filename + default: + nil + } + } + + var fileSize: Double? { + previewItemURL.flatMap { try? FileManager.default.sizeForItem(at: $0) } ?? expectedFileSize + } + + private var expectedFileSize: Double? { + let fileSize: UInt? = switch timelineItem { + case let audioItem as AudioRoomTimelineItem: + audioItem.content.fileSize + case let fileItem as FileRoomTimelineItem: + fileItem.content.fileSize + case let imageItem as ImageRoomTimelineItem: + imageItem.content.imageInfo.fileSize + case let videoItem as VideoRoomTimelineItem: + videoItem.content.videoInfo.fileSize + default: + nil + } + + return fileSize.map(Double.init) + } + + var caption: String? { + timelineItem.mediaCaption + } + + var contentType: String? { + switch timelineItem { + case let audioItem as AudioRoomTimelineItem: + audioItem.content.contentType?.localizedDescription + case let fileItem as FileRoomTimelineItem: + fileItem.content.contentType?.localizedDescription + case let imageItem as ImageRoomTimelineItem: + imageItem.content.contentType?.localizedDescription + case let videoItem as VideoRoomTimelineItem: + videoItem.content.contentType?.localizedDescription + default: + nil + } + } + + var blurhash: String? { + switch timelineItem { + case let imageItem as ImageRoomTimelineItem: + imageItem.content.blurhash + case let videoItem as VideoRoomTimelineItem: + videoItem.content.blurhash + default: + nil + } + } +} + +enum TimelineMediaPreviewViewAction { + case updateCurrentItem(TimelineMediaPreviewItem) + case saveCurrentItem + case showCurrentItemDetails + case menuAction(TimelineItemMenuAction, item: TimelineMediaPreviewItem) + case redactConfirmation(item: TimelineMediaPreviewItem) + case dismiss +} diff --git a/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewViewModel.swift b/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewViewModel.swift new file mode 100644 index 0000000000..d944a7cf3e --- /dev/null +++ b/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewViewModel.swift @@ -0,0 +1,180 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import Foundation + +typealias TimelineMediaPreviewViewModelType = StateStoreViewModel + +class TimelineMediaPreviewViewModel: TimelineMediaPreviewViewModelType { + private let timelineViewModel: TimelineViewModelProtocol + private let currentItemIDHandler: ((TimelineItemIdentifier?) -> Void)? + private let mediaProvider: MediaProviderProtocol + private let photoLibraryManager: PhotoLibraryManagerProtocol + private let userIndicatorController: UserIndicatorControllerProtocol + private let appMediator: AppMediatorProtocol + + private let actionsSubject: PassthroughSubject = .init() + var actions: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(context: TimelineMediaPreviewContext, + mediaProvider: MediaProviderProtocol, + photoLibraryManager: PhotoLibraryManagerProtocol, + userIndicatorController: UserIndicatorControllerProtocol, + appMediator: AppMediatorProtocol) { + timelineViewModel = context.viewModel + currentItemIDHandler = context.itemIDHandler + self.mediaProvider = mediaProvider + self.photoLibraryManager = photoLibraryManager + self.userIndicatorController = userIndicatorController + self.appMediator = appMediator + + let previewItems = timelineViewModel.context.viewState.timelineState.itemViewStates.compactMap(TimelineMediaPreviewItem.init) + let initialItemIndex = previewItems.firstIndex { $0.id == context.item.id } ?? 0 + let currentItem = previewItems[initialItemIndex] + + super.init(initialViewState: TimelineMediaPreviewViewState(previewItems: previewItems, + initialItemIndex: initialItemIndex, + currentItem: currentItem, + transitionNamespace: context.namespace), + mediaProvider: mediaProvider) + + rebuildCurrentItemActions() + + timelineViewModel.context.$viewState.map(\.canCurrentUserRedactSelf) + .merge(with: timelineViewModel.context.$viewState.map(\.canCurrentUserRedactOthers)) + .sink { [weak self] _ in + self?.rebuildCurrentItemActions() + } + .store(in: &cancellables) + } + + override func process(viewAction: TimelineMediaPreviewViewAction) { + switch viewAction { + case .updateCurrentItem(let item): + Task { await updateCurrentItem(item) } + case .saveCurrentItem: + Task { await saveCurrentItem() } + case .showCurrentItemDetails: + state.bindings.mediaDetailsItem = state.currentItem + case .menuAction(let action, let item): + switch action { + case .viewInRoomTimeline: + actionsSubject.send(.viewInRoomTimeline(item.id)) + case .redact: + state.bindings.redactConfirmationItem = item + default: + MXLog.error("Received unexpected action: \(action)") + } + case .redactConfirmation(let item): + redactItem(item) + case .dismiss: + actionsSubject.send(.dismiss) + } + } + + private func updateCurrentItem(_ previewItem: TimelineMediaPreviewItem) async { + previewItem.downloadError = nil // Clear any existing error. + state.currentItem = previewItem + currentItemIDHandler?(previewItem.id) + + rebuildCurrentItemActions() + + if previewItem.fileHandle == nil, let source = previewItem.mediaSource { + switch await mediaProvider.loadFileFromSource(source, filename: previewItem.filename) { + case .success(let handle): + previewItem.fileHandle = handle + state.fileLoadedPublisher.send(previewItem.id) + case .failure(let error): + MXLog.error("Failed loading media: \(error)") + context.objectWillChange.send() // Manually trigger the SwiftUI view update. + previewItem.downloadError = error + } + } + } + + private func rebuildCurrentItemActions() { + let timelineContext = timelineViewModel.context + let provider = TimelineItemMenuActionProvider(timelineItem: state.currentItem.timelineItem, + canCurrentUserRedactSelf: timelineContext.viewState.canCurrentUserRedactSelf, + canCurrentUserRedactOthers: timelineContext.viewState.canCurrentUserRedactOthers, + canCurrentUserPin: timelineContext.viewState.canCurrentUserPin, + pinnedEventIDs: timelineContext.viewState.pinnedEventIDs, + isDM: timelineContext.viewState.isEncryptedOneToOneRoom, + isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled, + timelineKind: timelineContext.viewState.timelineKind, + emojiProvider: timelineContext.viewState.emojiProvider) + state.currentItemActions = provider.makeActions() + } + + private func saveCurrentItem() async { + guard let fileURL = state.currentItem.fileHandle?.url else { + MXLog.error("Unable to save an item without a URL, the button shouldn't be visible.") + return + } + + do { + switch state.currentItem.timelineItem { + case is AudioRoomTimelineItem, is FileRoomTimelineItem: + state.bindings.fileToExport = .init(url: fileURL) + return // Don't show the indicator. + case is ImageRoomTimelineItem: + try await photoLibraryManager.addResource(.photo, at: fileURL).get() + case is VideoRoomTimelineItem: + try await photoLibraryManager.addResource(.video, at: fileURL).get() + default: + break + } + + showSavedIndicator() + } catch PhotoLibraryManagerError.notAuthorized { + MXLog.error("Not authorised to save item to photo library") + state.bindings.alertInfo = .init(id: .authorizationRequired, + title: L10n.dialogPermissionPhotoLibraryTitleIos(InfoPlistReader.main.bundleDisplayName), + primaryButton: .init(title: L10n.commonSettings) { self.appMediator.openAppSettings() }, + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) + } catch { + MXLog.error("Failed saving item: \(error)") + showErrorIndicator() + } + } + + private func redactItem(_ item: TimelineMediaPreviewItem) { + timelineViewModel.context.send(viewAction: .handleTimelineItemMenuAction(itemID: item.id, action: .redact)) + state.bindings.redactConfirmationItem = nil + state.bindings.mediaDetailsItem = nil + actionsSubject.send(.dismiss) + showRedactedIndicator() + } + + // MARK: - Indicators + + private func showRedactedIndicator() { + userIndicatorController.submitIndicator(UserIndicator(id: statusIndicatorID, + type: .toast, + title: L10n.commonFileDeleted, + iconName: "checkmark")) + } + + private func showSavedIndicator() { + userIndicatorController.submitIndicator(UserIndicator(id: statusIndicatorID, + type: .toast, + title: L10n.commonFileSaved, + iconName: "checkmark")) + } + + private func showErrorIndicator() { + userIndicatorController.submitIndicator(UserIndicator(id: statusIndicatorID, + type: .toast, + title: L10n.errorUnknown, + iconName: "xmark")) + } + + private var statusIndicatorID: String { "\(Self.self)-Status" } +} diff --git a/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewDetailsView.swift b/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewDetailsView.swift new file mode 100644 index 0000000000..9320acd2c1 --- /dev/null +++ b/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewDetailsView.swift @@ -0,0 +1,194 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct TimelineMediaPreviewDetailsView: View { + let item: TimelineMediaPreviewItem + @ObservedObject var context: TimelineMediaPreviewViewModel.Context + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 0) { + details + actions + } + .frame(maxWidth: .infinity, alignment: .leading) + } + .presentationDetents([.medium]) + .presentationDragIndicator(.visible) + .padding(.top, 19) // For the drag indicator + .presentationBackground(.compound.bgCanvasDefault) + .preferredColorScheme(.dark) + .sheet(item: $context.redactConfirmationItem) { item in + TimelineMediaPreviewRedactConfirmationView(item: item, context: context) + } + } + + private var details: some View { + VStack(alignment: .leading, spacing: 24) { + DetailsRow(title: L10n.screenMediaDetailsUploadedBy) { + HStack(spacing: 8) { + LoadableAvatarImage(url: item.sender.avatarURL, + name: item.sender.displayName, + contentID: item.sender.id, + avatarSize: .user(on: .mediaPreviewDetails), + mediaProvider: context.mediaProvider) + + VStack(alignment: .leading, spacing: 0) { + if let displayName = item.sender.displayName { + Text(displayName) + .font(.compound.bodyMDSemibold) + .foregroundStyle(.compound.decorativeColor(for: item.sender.id).text) + } + + Text(item.sender.id) + .font(.compound.bodySM) + .foregroundStyle(.compound.textSecondary) + } + } + } + + DetailsRow(title: L10n.screenMediaDetailsUploadedOn) { + Text(item.timestamp.formatted(date: .abbreviated, time: .shortened)) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textPrimary) + } + + DetailsRow(title: L10n.screenMediaDetailsFilename) { + Text(item.filename ?? "") + .font(.compound.bodyMD) + .foregroundStyle(.compound.textPrimary) + } + + if let contentType = item.contentType { + DetailsRow(title: L10n.screenMediaDetailsFileFormat) { + Group { + if let fileSize = item.fileSize { + Text(contentType) + Text(" – ") + Text(UInt(fileSize).formatted(.byteCount(style: .file))) + } else { + Text(contentType) + } + } + .font(.compound.bodyMD) + .foregroundStyle(.compound.textPrimary) + } + } + } + .padding(.top, 24) + .padding(.bottom, 32) + .padding(.horizontal, 16) + } + + @ViewBuilder + private var actions: some View { + if let actions = context.viewState.currentItemActions { + VStack(spacing: 0) { + if !actions.actions.isEmpty { + Divider() + .background(Color.compound.bgSubtlePrimary) + } + + ForEach(actions.actions, id: \.self) { action in + Button(role: action.isDestructive ? .destructive : nil) { + context.send(viewAction: .menuAction(action, item: item)) + } label: { + action.label + } + .buttonStyle(.menuSheet) + } + + if !actions.secondaryActions.isEmpty { + Divider() + .background(Color.compound.bgSubtlePrimary) + } + + ForEach(actions.secondaryActions, id: \.self) { action in + Button(role: action.isDestructive ? .destructive : nil) { + context.send(viewAction: .menuAction(action, item: item)) + } label: { + action.label + } + .buttonStyle(.menuSheet) + } + } + } + } + + private struct DetailsRow: View { + let title: String + let content: () -> Content + + var body: some View { + VStack(alignment: .leading, spacing: 8) { + Text(title) + .font(.compound.bodyXS) + .foregroundStyle(.compound.textSecondary) + .textCase(.uppercase) + + content() + } + } + } +} + +// MARK: - Previews + +import UniformTypeIdentifiers + +struct TimelineMediaPreviewDetailsView_Previews: PreviewProvider, TestablePreview { + @Namespace private static var previewNamespace + + static let viewModel = makeViewModel(contentType: .jpeg, isOutgoing: true) + static let unknownTypeViewModel = makeViewModel() + static let presentedOnRoomViewModel = makeViewModel(isPresentedOnRoomScreen: true) + + static var previews: some View { + TimelineMediaPreviewDetailsView(item: viewModel.state.currentItem, + context: viewModel.context) + .previewDisplayName("Image") + .snapshotPreferences(delay: 0.1) + TimelineMediaPreviewDetailsView(item: unknownTypeViewModel.state.currentItem, + context: unknownTypeViewModel.context) + .previewDisplayName("Unknown type") + .snapshotPreferences(delay: 0.1) + + TimelineMediaPreviewDetailsView(item: presentedOnRoomViewModel.state.currentItem, + context: presentedOnRoomViewModel.context) + .previewDisplayName("Incoming on Room") + .snapshotPreferences(delay: 0.1) + } + + static func makeViewModel(contentType: UTType? = nil, isOutgoing: Bool = false, isPresentedOnRoomScreen: Bool = false) -> TimelineMediaPreviewViewModel { + let item = ImageRoomTimelineItem(id: .randomEvent, + timestamp: .mock, + isOutgoing: isOutgoing, + isEditable: true, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "@alice:matrix.org", + displayName: "Alice", + avatarURL: .mockMXCUserAvatar), + content: .init(filename: "Amazing Image.jpeg", + imageInfo: .mockImage, + thumbnailInfo: .mockThumbnail, + contentType: contentType)) + + let timelineKind = TimelineKind.media(isPresentedOnRoomScreen ? .roomScreen : .mediaFilesScreen) + let timelineController = MockRoomTimelineController(timelineKind: timelineKind) + timelineController.timelineItems = [item] + return TimelineMediaPreviewViewModel(context: .init(item: item, + viewModel: TimelineViewModel.mock(timelineKind: timelineKind, + timelineController: timelineController), + namespace: previewNamespace), + mediaProvider: MediaProviderMock(configuration: .init()), + photoLibraryManager: PhotoLibraryManagerMock(.init()), + userIndicatorController: UserIndicatorControllerMock(), + appMediator: AppMediatorMock()) + } +} diff --git a/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewFileExportPicker.swift b/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewFileExportPicker.swift new file mode 100644 index 0000000000..134c8aea25 --- /dev/null +++ b/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewFileExportPicker.swift @@ -0,0 +1,23 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import SwiftUI + +struct TimelineMediaPreviewFileExportPicker: UIViewControllerRepresentable { + struct File: Identifiable { + let url: URL + var id: String { url.absoluteString } + } + + let file: File + + func makeUIViewController(context: Context) -> UIDocumentPickerViewController { + UIDocumentPickerViewController(forExporting: [file.url], asCopy: true) + } + + func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) { } +} diff --git a/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewRedactConfirmationView.swift b/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewRedactConfirmationView.swift new file mode 100644 index 0000000000..0a13fd059b --- /dev/null +++ b/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewRedactConfirmationView.swift @@ -0,0 +1,152 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct TimelineMediaPreviewRedactConfirmationView: View { + @Environment(\.dismiss) private var dismiss + + let item: TimelineMediaPreviewItem + @ObservedObject var context: TimelineMediaPreviewViewModel.Context + + var body: some View { + ScrollView { + VStack(spacing: 0) { + header + preview + buttons + } + } + .presentationDetents([.medium]) + .presentationDragIndicator(.visible) + .padding(.top, 19) // For the drag indicator + .presentationBackground(.compound.bgCanvasDefault) + .preferredColorScheme(.dark) + } + + private var header: some View { + VStack(spacing: 16) { + BigIcon(icon: \.delete, style: .alertSolid) + + VStack(spacing: 8) { + Text(L10n.screenMediaDetailsRedactConfirmationTitle) + .font(.compound.headingMDBold) + .foregroundStyle(.compound.textPrimary) + .multilineTextAlignment(.center) + + Text(L10n.screenMediaDetailsRedactConfirmationMessage) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textSecondary) + .multilineTextAlignment(.center) + } + } + .padding(.top, 24) + .padding(.bottom, 32) + .padding(.horizontal, 24) + } + + @ViewBuilder + private var preview: some View { + HStack(spacing: 12) { + if let mediaSource = item.thumbnailMediaSource { + Color.clear + .scaledFrame(size: 40) + .background { + LoadableImage(mediaSource: mediaSource, + mediaType: .timelineItem(uniqueID: item.id.uniqueID.id), + blurhash: item.blurhash, + mediaProvider: context.mediaProvider) { + Color.compound.bgSubtleSecondary + } + .aspectRatio(contentMode: .fill) + } + .clipShape(RoundedRectangle(cornerRadius: 8)) + } + + VStack(alignment: .leading, spacing: 4) { + Text(item.filename ?? "") + .font(.compound.bodyMD) + .foregroundStyle(.compound.textPrimary) + + if let contentType = item.contentType { + Group { + if let fileSize = item.fileSize { + Text(contentType) + Text(" – ") + Text(UInt(fileSize).formatted(.byteCount(style: .file))) + } else { + Text(contentType) + } + } + .font(.compound.bodySM) + .foregroundStyle(.compound.textSecondary) + } + } + } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 24) + .padding(.bottom, 40) + } + + private var buttons: some View { + VStack(spacing: 16) { + Button(L10n.actionRemove, role: .destructive) { + context.send(viewAction: .redactConfirmation(item: item)) + } + .buttonStyle(.compound(.primary)) + + Button { + dismiss() + } label: { + Text(L10n.actionCancel) + .padding(.vertical, 14) + } + .buttonStyle(.compound(.plain)) + } + .padding(.bottom, 16) + .padding(.horizontal, 16) + } +} + +// MARK: - Previews + +import UniformTypeIdentifiers + +struct TimelineMediaPreviewRedactConfirmationView_Previews: PreviewProvider, TestablePreview { + @Namespace private static var previewNamespace + static let viewModel = makeViewModel(contentType: .jpeg) + + static var previews: some View { + TimelineMediaPreviewRedactConfirmationView(item: viewModel.state.currentItem, context: viewModel.context) + } + + static func makeViewModel(contentType: UTType? = nil) -> TimelineMediaPreviewViewModel { + let item = ImageRoomTimelineItem(id: .randomEvent, + timestamp: .mock, + isOutgoing: false, + isEditable: true, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "@alice:matrix.org", + displayName: "Alice", + avatarURL: .mockMXCUserAvatar), + content: .init(filename: "Amazing Image.jpeg", + imageInfo: .mockImage, + thumbnailInfo: .mockThumbnail, + contentType: contentType)) + + let timelineController = MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen)) + timelineController.timelineItems = [item] + return TimelineMediaPreviewViewModel(context: .init(item: item, + viewModel: TimelineViewModel.mock(timelineKind: timelineController.timelineKind, + timelineController: timelineController), + namespace: previewNamespace), + mediaProvider: MediaProviderMock(configuration: .init()), + photoLibraryManager: PhotoLibraryManagerMock(.init()), + userIndicatorController: UserIndicatorControllerMock(), + appMediator: AppMediatorMock()) + } +} diff --git a/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewScreen.swift b/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewScreen.swift new file mode 100644 index 0000000000..bde0f7ea6c --- /dev/null +++ b/ElementX/Sources/Screens/FilePreviewScreen/View/TimelineMediaPreviewScreen.swift @@ -0,0 +1,304 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import Compound +import QuickLook +import SwiftUI + +struct TimelineMediaPreviewScreen: View { + @ObservedObject var context: TimelineMediaPreviewViewModel.Context + var itemIDHandler: ((TimelineItemIdentifier?) -> Void)? + + @State private var isFullScreen = false + private var toolbarVisibility: Visibility { isFullScreen ? .hidden : .visible } + + private var currentItem: TimelineMediaPreviewItem { context.viewState.currentItem } + + var body: some View { + NavigationStack { + quickLookPreview + } + .introspect(.navigationStack, on: .supportedVersions) { + // Fixes a bug where the QuickLook view overrides the .toolbarBackground(.visible) after it loads the real item. + $0.navigationBar.scrollEdgeAppearance = $0.navigationBar.standardAppearance + $0.toolbar.scrollEdgeAppearance = $0.toolbar.standardAppearance + } + .sheet(item: $context.mediaDetailsItem) { item in + TimelineMediaPreviewDetailsView(item: item, context: context) + } + .sheet(item: $context.fileToExport) { file in + TimelineMediaPreviewFileExportPicker(file: file) + .preferredColorScheme(.dark) + } + .alert(item: $context.alertInfo) + .preferredColorScheme(.dark) + .onDisappear { + itemIDHandler?(nil) + } + .zoomTransition(sourceID: currentItem.id, in: context.viewState.transitionNamespace) + } + + var quickLookPreview: some View { + Color.clear // A completely clear view breaks any SwiftUI gestures (such as drag to dismiss). + .background { QuickLookView(viewModelContext: context).ignoresSafeArea() } // Not the root view to stop QL hijacking the toolbar. + .overlay(alignment: .topTrailing) { fullScreenButton } + .overlay { downloadStatusIndicator } + .toolbar { toolbar } + .toolbar(toolbarVisibility, for: .navigationBar) + .toolbar(toolbarVisibility, for: .bottomBar) + .toolbarBackground(.visible, for: .navigationBar) // The toolbar's scrollEdgeAppearance isn't aware of the quicklook view 🤷‍♂️ + .toolbarBackground(.visible, for: .bottomBar) + .navigationBarTitleDisplayMode(.inline) + .safeAreaInset(edge: .bottom, spacing: 0) { caption } + } + + private var fullScreenButton: some View { + Button { + withAnimation { isFullScreen.toggle() } + } label: { + CompoundIcon(isFullScreen ? \.collapse : \.expand, size: .xSmall, relativeTo: .compound.bodyLG) + .padding(6) + .background(.thinMaterial, in: Circle()) + } + .tint(.compound.textActionPrimary) + .padding(.top, 12) + .padding(.trailing, 14) + } + + @ViewBuilder + private var downloadStatusIndicator: some View { + if currentItem.downloadError != nil { + VStack(spacing: 24) { + CompoundIcon(\.error, size: .custom(48), relativeTo: .compound.headingLG) + .foregroundStyle(.compound.iconCriticalPrimary) + .padding(.vertical, 24.5) + .padding(.horizontal, 28.5) + + VStack(spacing: 2) { + Text(L10n.commonDownloadFailed) + .font(.compound.headingMDBold) + .foregroundStyle(.compound.textPrimary) + .multilineTextAlignment(.center) + Text(L10n.screenMediaBrowserDownloadErrorMessage) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textPrimary) + .multilineTextAlignment(.center) + } + } + .padding(.horizontal, 24) + .padding(.vertical, 40) + .background(.compound.bgSubtlePrimary, in: RoundedRectangle(cornerRadius: 14)) + } else if currentItem.fileHandle == nil { + ProgressView() + .controlSize(.large) + .tint(.compound.iconPrimary) + } + } + + @ViewBuilder + private var caption: some View { + if let caption = currentItem.caption, !isFullScreen { + Text(caption) + .font(.compound.bodyLG) + .foregroundStyle(.compound.textPrimary) + .lineLimit(5) + .frame(maxWidth: .infinity, alignment: .leading) + .fixedSize(horizontal: false, vertical: true) + .padding(16) + .background { + BlurEffectView(style: .systemChromeMaterial) // Darkest material available, matches the bottom bar when content is beneath. + } + .transition(.move(edge: .bottom).combined(with: .opacity)) + } + } + + @ToolbarContentBuilder + private var toolbar: some ToolbarContent { + ToolbarItem(placement: .cancellationAction) { + Button { context.send(viewAction: .dismiss) } label: { + Image(systemSymbol: .chevronBackward) + .fontWeight(.semibold) + } + .tint(.compound.textActionPrimary) // These fix a bug where the light tint is shown when foregrounding the app. + } + + ToolbarItem(placement: .principal) { + toolbarHeader + } + + ToolbarItem(placement: .primaryAction) { + Button { context.send(viewAction: .showCurrentItemDetails) } label: { + CompoundIcon(\.info) + } + .tint(.compound.textActionPrimary) + } + + ToolbarItem(placement: .bottomBar) { + bottomBarContent + .tint(.compound.textActionPrimary) + } + } + + private var toolbarHeader: some View { + VStack(spacing: 0) { + Text(currentItem.sender.displayName ?? currentItem.sender.id) + .font(.compound.bodySMSemibold) + .foregroundStyle(.compound.textPrimary) + Text(currentItem.timestamp.formatted(date: .abbreviated, time: .omitted)) + .font(.compound.bodyXS) + .foregroundStyle(.compound.textPrimary) + .textCase(.uppercase) + } + } + + private var bottomBarContent: some View { + HStack(spacing: 8) { + if let url = currentItem.fileHandle?.url { + ShareLink(item: url, subject: nil, message: currentItem.caption.map(Text.init)) { + CompoundIcon(\.shareIos) + } + + Spacer() + + Button { context.send(viewAction: .saveCurrentItem) } label: { + CompoundIcon(\.downloadIos) + } + } + } + } +} + +// MARK: - QuickLook + +private struct QuickLookView: UIViewControllerRepresentable { + let viewModelContext: TimelineMediaPreviewViewModel.Context + + func makeUIViewController(context: Context) -> PreviewController { + let fileLoadedPublisher = viewModelContext.viewState.fileLoadedPublisher.eraseToAnyPublisher() + let controller = PreviewController(coordinator: context.coordinator, fileLoadedPublisher: fileLoadedPublisher) + controller.currentPreviewItemIndex = viewModelContext.viewState.initialItemIndex + return controller + } + + func updateUIViewController(_ uiViewController: PreviewController, context: Context) { } + + func makeCoordinator() -> Coordinator { + Coordinator(viewModelContext: viewModelContext) + } + + // MARK: Coordinator + + class Coordinator: NSObject, QLPreviewControllerDataSource, QLPreviewControllerDelegate { + private let viewModelContext: TimelineMediaPreviewViewModel.Context + + init(viewModelContext: TimelineMediaPreviewViewModel.Context) { + self.viewModelContext = viewModelContext + } + + func updateCurrentItem(_ item: TimelineMediaPreviewItem) { + viewModelContext.send(viewAction: .updateCurrentItem(item)) + } + + func numberOfPreviewItems(in controller: QLPreviewController) -> Int { + viewModelContext.viewState.previewItems.count + } + + func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem { + viewModelContext.viewState.previewItems[index] + } + } + + // MARK: UIKit + + class PreviewController: QLPreviewController { + private var cancellables: Set = [] + + init(coordinator: Coordinator, fileLoadedPublisher: AnyPublisher) { + super.init(nibName: nil, bundle: nil) + + dataSource = coordinator + delegate = coordinator + + // Observation of currentPreviewItem doesn't work, so use the index instead. + publisher(for: \.currentPreviewItemIndex) + .sink { [weak self] _ in + guard let self, let currentPreviewItem = currentPreviewItem as? TimelineMediaPreviewItem else { return } + coordinator.updateCurrentItem(currentPreviewItem) + } + .store(in: &cancellables) + + fileLoadedPublisher + .sink { [weak self] itemID in + guard let self, (currentPreviewItem as? TimelineMediaPreviewItem)?.id == itemID else { return } + refreshCurrentPreviewItem() + } + .store(in: &cancellables) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + } +} + +// MARK: - Previews + +struct TimelineMediaPreviewScreen_Previews: PreviewProvider { + @Namespace private static var namespace + + static let viewModel = makeViewModel() + static let downloadingViewModel = makeViewModel(isDownloading: true) + static let downloadErrorViewModel = makeViewModel(isDownloadError: true) + + static var previews: some View { + TimelineMediaPreviewScreen(context: viewModel.context) + .previewDisplayName("Normal") + TimelineMediaPreviewScreen(context: downloadingViewModel.context) + .previewDisplayName("Downloading") + TimelineMediaPreviewScreen(context: downloadErrorViewModel.context) + .previewDisplayName("Download Error") + } + + static func makeViewModel(isDownloading: Bool = false, isDownloadError: Bool = false) -> TimelineMediaPreviewViewModel { + let item = FileRoomTimelineItem(id: .randomEvent, + timestamp: .mock, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "", displayName: "Sally Sanderson"), + content: .init(filename: "Important document.pdf", + caption: "A caption goes right here.", + source: try? .init(url: .mockMXCFile, mimeType: nil), + fileSize: 3 * 1024 * 1024, + thumbnailSource: nil, + contentType: .pdf)) + + let timelineController = MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen)) + timelineController.timelineItems = [item] + + let mediaProvider = MediaProviderMock(configuration: .init()) + + if isDownloading { + mediaProvider.loadFileFromSourceFilenameClosure = { _, _ in + try? await Task.sleep(for: .seconds(3600)) + return .failure(.failedRetrievingFile) + } + } else if isDownloadError { + mediaProvider.loadFileFromSourceFilenameClosure = { _, _ in .failure(.failedRetrievingFile) } + } + + return TimelineMediaPreviewViewModel(context: .init(item: item, + viewModel: TimelineViewModel.mock(timelineKind: timelineController.timelineKind, + timelineController: timelineController), + namespace: namespace), + mediaProvider: mediaProvider, + photoLibraryManager: PhotoLibraryManagerMock(.init()), + userIndicatorController: UserIndicatorControllerMock(), + appMediator: AppMediatorMock()) + } +} diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift index 7671b37748..3e5c6aefc8 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift @@ -219,13 +219,13 @@ extension HomeScreenRoom { let hasUnreadMessages = hideUnreadMessagesBadge ? false : summary.hasUnreadMessages - let isDotShown = hasUnreadMessages || summary.hasUnreadMentions || summary.hasUnreadNotifications || summary.isMarkedUnread || summary.joinRequestType?.isKnock == true + let isDotShown = hasUnreadMessages || summary.hasUnreadMentions || summary.hasUnreadNotifications || summary.isMarkedUnread || summary.knockRequestType?.isKnock == true let isMentionShown = summary.hasUnreadMentions && !summary.isMuted let isMuteShown = summary.isMuted let isCallShown = summary.hasOngoingCall - let isHighlighted = summary.isMarkedUnread || (!summary.isMuted && (summary.hasUnreadNotifications || summary.hasUnreadMentions)) || summary.joinRequestType?.isKnock == true + let isHighlighted = summary.isMarkedUnread || (!summary.isMuted && (summary.hasUnreadNotifications || summary.hasUnreadMentions)) || summary.knockRequestType?.isKnock == true - let type: HomeScreenRoom.RoomType = switch summary.joinRequestType { + let type: HomeScreenRoom.RoomType = switch summary.knockRequestType { case .invite(let inviter): .invite(inviterDetails: inviter.map(RoomInviterDetails.init)) case .knock: .knock case .none: .room diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index 12313779a4..a7084c22ac 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -326,11 +326,10 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.state.bindings.alertInfo = AlertInfo(id: UUID(), title: L10n.bannerMigrateToNativeSlidingSyncForceLogoutTitle, - primaryButton: .init(title: L10n.bannerMigrateToNativeSlidingSyncAction, - action: { [weak self] in - self?.appSettings.slidingSyncDiscovery = .native - self?.actionsSubject.send(.logoutWithoutConfirmation) - })) + primaryButton: .init(title: L10n.bannerMigrateToNativeSlidingSyncAction) { [weak self] in + self?.appSettings.slidingSyncDiscovery = .native + self?.actionsSubject.send(.logoutWithoutConfirmation) + }) } } } @@ -364,12 +363,12 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol } if roomProxy.infoPublisher.value.isPublic { - state.bindings.leaveRoomAlertItem = LeaveRoomAlertItem(roomID: roomID, isDM: roomProxy.isEncryptedOneToOneRoom, state: .public) + state.bindings.leaveRoomAlertItem = LeaveRoomAlertItem(roomID: roomID, isDM: roomProxy.isDirectOneToOneRoom, state: .public) } else { state.bindings.leaveRoomAlertItem = if roomProxy.infoPublisher.value.joinedMembersCount > 1 { - LeaveRoomAlertItem(roomID: roomID, isDM: roomProxy.isEncryptedOneToOneRoom, state: .private) + LeaveRoomAlertItem(roomID: roomID, isDM: roomProxy.isDirectOneToOneRoom, state: .private) } else { - LeaveRoomAlertItem(roomID: roomID, isDM: roomProxy.isEncryptedOneToOneRoom, state: .empty) + LeaveRoomAlertItem(roomID: roomID, isDM: roomProxy.isDirectOneToOneRoom, state: .empty) } } } @@ -433,7 +432,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol title: title, message: message, primaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil), - secondaryButton: .init(title: L10n.actionDecline, role: .destructive, action: { Task { await self.declineInvite(roomID: room.id) } })) + secondaryButton: .init(title: L10n.actionDecline, role: .destructive) { Task { await self.declineInvite(roomID: room.id) } }) } private func declineInvite(roomID: String) async { diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenEmptyStateView.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenEmptyStateView.swift index 076f85ebd0..1b6ea1e86f 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenEmptyStateView.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenEmptyStateView.swift @@ -63,7 +63,7 @@ struct HomeScreenEmptyStateLayout: Layout { } func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) { - let mainView = subviews.first(where: { $0.priority > 0 }) + let mainView = subviews.first { $0.priority > 0 } let topViews = subviews.filter { $0 != mainView } var y: CGFloat = bounds.minY diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift index db5c73a3ed..c8809e7b88 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift @@ -181,7 +181,7 @@ private extension HomeScreenRoom { let summary = RoomSummary(roomListItem: RoomListItemSDKMock(), id: "@someone:somewhere.com", - joinRequestType: .invite(inviter: inviter), + knockRequestType: .invite(inviter: inviter), name: "Some Guy", isDirect: true, avatarURL: nil, @@ -204,11 +204,11 @@ private extension HomeScreenRoom { let inviter = RoomMemberProxyMock() inviter.displayName = "Luca" inviter.userID = "@jack:somewhi.nl" - inviter.avatarURL = avatarURL + inviter.avatarURL = avatarURL.map { _ in .mockMXCUserAvatar } let summary = RoomSummary(roomListItem: RoomListItemSDKMock(), id: "@someone:somewhere.com", - joinRequestType: .invite(inviter: inviter), + knockRequestType: .invite(inviter: inviter), name: "Awesome Room", isDirect: false, avatarURL: avatarURL, diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift index 2a79f62e18..83c1aa64e3 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift @@ -152,7 +152,7 @@ private extension HomeScreenRoom { let summary = RoomSummary(roomListItem: RoomListItemSDKMock(), id: "@someone:somewhere.com", - joinRequestType: .invite(inviter: inviter), + knockRequestType: .invite(inviter: inviter), name: "Some Guy", isDirect: true, avatarURL: nil, @@ -179,7 +179,7 @@ private extension HomeScreenRoom { let summary = RoomSummary(roomListItem: RoomListItemSDKMock(), id: "@someone:somewhere.com", - joinRequestType: .invite(inviter: inviter), + knockRequestType: .invite(inviter: inviter), name: "Awesome Room", isDirect: false, avatarURL: avatarURL, diff --git a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift index b5e081497e..e9e18e5b88 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift @@ -52,7 +52,7 @@ struct InviteUsersScreenSelectedItem_Previews: PreviewProvider, TestablePreview ScrollView(.horizontal) { HStack(spacing: 28) { ForEach(people, id: \.userID) { user in - InviteUsersScreenSelectedItem(user: user, mediaProvider: MediaProviderMock(configuration: .init()), dismissAction: { }) + InviteUsersScreenSelectedItem(user: user, mediaProvider: MediaProviderMock(configuration: .init())) { } .frame(width: 72) } } diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift index 6312924698..724b969ced 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift @@ -221,7 +221,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo title: L10n.screenInvitesDeclineChatTitle, message: L10n.screenInvitesDeclineChatMessage(roomName), primaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil), - secondaryButton: .init(title: L10n.actionDecline, role: .destructive, action: { Task { await self.declineInvite() } })) + secondaryButton: .init(title: L10n.actionDecline, role: .destructive) { Task { await self.declineInvite() } }) } private func showCancelKnockConfirmationAlert() { @@ -229,7 +229,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo title: L10n.screenJoinRoomCancelKnockAlertTitle, message: L10n.screenJoinRoomCancelKnockAlertDescription, primaryButton: .init(title: L10n.actionNo, role: .cancel, action: nil), - secondaryButton: .init(title: L10n.screenJoinRoomCancelKnockAlertConfirmation, role: .destructive, action: { Task { await self.cancelKnock() } })) + secondaryButton: .init(title: L10n.screenJoinRoomCancelKnockAlertConfirmation, role: .destructive) { Task { await self.cancelKnock() } }) } private func declineInvite() async { diff --git a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift index 3953ed96c6..266d713068 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift @@ -13,9 +13,14 @@ struct JoinRoomScreen: View { @Environment(\.dynamicTypeSize) private var dynamicTypeSize @ObservedObject var context: JoinRoomScreenViewModel.Context + @FocusState private var focus: Focus? + private enum Focus { + case knockMessage + } + var body: some View { - FullscreenDialog(topPadding: context.viewState.mode == .knocked ? 151 : 35, background: .bloom) { + FullscreenDialog(topPadding: context.viewState.mode == .knocked ? 151 : 35) { if context.viewState.mode == .loading { EmptyView() } else { @@ -29,6 +34,7 @@ struct JoinRoomScreen: View { .backgroundStyle(.compound.bgCanvasDefault) .navigationBarTitleDisplayMode(.inline) .toolbar { toolbar } + .shouldScrollOnKeyboardDidShow(focus == .knockMessage, to: Focus.knockMessage) } @ViewBuilder @@ -117,6 +123,7 @@ struct JoinRoomScreen: View { VStack(alignment: .leading, spacing: 12) { HStack(spacing: 0) { TextField("", text: $context.knockMessage, axis: .vertical) + .focused($focus, equals: .knockMessage) .onChange(of: context.knockMessage) { _, newValue in context.knockMessage = String(newValue.prefix(maxKnockMessageLength)) } @@ -124,6 +131,7 @@ struct JoinRoomScreen: View { .font(.compound.bodyMD) .padding(.horizontal, 16) .padding(.vertical, 12) + .id(Focus.knockMessage) } .background(.compound.bgCanvasDefault) .cornerRadius(8) @@ -261,7 +269,7 @@ struct JoinRoomScreen_Previews: PreviewProvider, TestablePreview { topic: "“Science and technology were the only keys to opening the door to the future, and people approached science with the faith and sincerity of elementary school students.”", avatarURL: .mockMXCAvatar, memberCount: UInt(100), - isHistoryWorldReadable: false, + isHistoryWorldReadable: nil, isJoined: membership.isJoined, isInvited: membership.isInvited, isPublic: membership.isPublic, diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift index 5d14686abb..aac3e87c4c 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift @@ -13,6 +13,7 @@ import SwiftUI struct KnockRequestsListScreenCoordinatorParameters { let roomProxy: JoinedRoomProxyProtocol let mediaProvider: MediaProviderProtocol + let userIndicatorController: UserIndicatorControllerProtocol } enum KnockRequestsListScreenCoordinatorAction { } @@ -29,7 +30,8 @@ final class KnockRequestsListScreenCoordinator: CoordinatorProtocol { init(parameters: KnockRequestsListScreenCoordinatorParameters) { viewModel = KnockRequestsListScreenViewModel(roomProxy: parameters.roomProxy, - mediaProvider: parameters.mediaProvider) + mediaProvider: parameters.mediaProvider, + userIndicatorController: parameters.userIndicatorController) } func start() { } diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift index 5747aff5f9..bdcf15f9cd 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift @@ -10,18 +10,43 @@ import Foundation enum KnockRequestsListScreenViewModelAction { } struct KnockRequestsListScreenViewState: BindableState { - // TODO: Not sure yet how we will fetch this, this is just for testing purposes - var requests: [KnockRequestCellInfo] = [.init(id: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "Now", reason: "Hello")] + var requestsState: KnockRequestsListState = .loading + + var displayedRequests: [KnockRequestCellInfo] { + guard case let .loaded(requests) = requestsState else { + return [] + } + return requests.filter { !handledEventIDs.contains($0.id) } + } + + var isLoading: Bool { + switch requestsState { + case .loading: + true + default: + false + } + } + // If you are in this view one of these must have been true so by default we assume all of them to be true var canAccept = true var canDecline = true var canBan = true var isKnockableRoom = true + var handledEventIDs: Set = [] // If all the permissions are denied or the join rule changes while we are in the view // we want to stop displaying any request var shouldDisplayRequests: Bool { - !requests.isEmpty && isKnockableRoom && (canAccept || canDecline || canBan) + !displayedRequests.isEmpty && isKnockableRoom && (canAccept || canDecline || canBan) + } + + var shouldDisplayAcceptAllButton: Bool { + !isLoading && shouldDisplayRequests && displayedRequests.count > 1 + } + + var shouldDisplayEmptyView: Bool { + !isLoading && !shouldDisplayRequests } var bindings = KnockRequestsListStateBindings() @@ -35,11 +60,39 @@ enum KnockRequestsListAlertType { case acceptAllRequests case declineRequest case declineAndBan + case acceptAllFailed + case acceptFailed + case declineFailed } enum KnockRequestsListScreenViewAction { case acceptAllRequests - case acceptRequest(userID: String) - case declineRequest(userID: String) - case ban(userID: String) + case acceptRequest(eventID: String) + case declineRequest(eventID: String) + case ban(eventID: String) +} + +enum KnockRequestsListState: Equatable { + case loading + case loaded([KnockRequestCellInfo]) + + init(from state: KnockRequestsState) { + switch state { + case .loading: + self = .loading + case .loaded(let requests): + self = .loaded(requests.map(KnockRequestCellInfo.init)) + } + } +} + +private extension KnockRequestCellInfo { + init(from proxy: KnockRequestProxyProtocol) { + self.init(eventID: proxy.eventID, + userID: proxy.userID, + displayName: proxy.displayName, + avatarURL: proxy.avatarURL, + timestamp: proxy.formattedTimestamp, + reason: proxy.reason) + } } diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift index 391cc60a95..fe023951d4 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift @@ -12,14 +12,18 @@ typealias KnockRequestsListScreenViewModelType = StateStoreViewModel = .init() var actionsPublisher: AnyPublisher { actionsSubject.eraseToAnyPublisher() } - init(roomProxy: JoinedRoomProxyProtocol, mediaProvider: MediaProviderProtocol) { + init(roomProxy: JoinedRoomProxyProtocol, + mediaProvider: MediaProviderProtocol, + userIndicatorController: UserIndicatorControllerProtocol) { self.roomProxy = roomProxy + self.userIndicatorController = userIndicatorController super.init(initialViewState: KnockRequestsListScreenViewState(), mediaProvider: mediaProvider) updateRoomInfo(roomInfo: roomProxy.infoPublisher.value) @@ -39,35 +43,147 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn title: L10n.screenKnockRequestsListAcceptAllAlertTitle, message: L10n.screenKnockRequestsListAcceptAllAlertDescription, primaryButton: .init(title: L10n.screenKnockRequestsListAcceptAllAlertConfirmButtonTitle, - // TODO: Implement action - action: nil), + action: acceptAll), secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) - case .acceptRequest(let userID): - // TODO: Implement - break - case .declineRequest(let userID): + case .acceptRequest(let eventID): + guard let request = getRequest(eventID: eventID) else { + return + } + accept(request: request) + case .declineRequest(let eventID): + guard let request = getRequest(eventID: eventID) else { + return + } + state.bindings.alertInfo = .init(id: .declineRequest, title: L10n.screenKnockRequestsListDeclineAlertTitle, - message: L10n.screenKnockRequestsListDeclineAlertDescription(userID), + message: L10n.screenKnockRequestsListDeclineAlertDescription(request.userID), primaryButton: .init(title: L10n.screenKnockRequestsListDeclineAlertConfirmButtonTitle, - role: .destructive, - // TODO: Implement action - action: nil), + role: .destructive) { [weak self] in self?.decline(request: request) }, secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) - case .ban(let userID): + case .ban(let eventID): + guard let request = getRequest(eventID: eventID) else { + return + } + state.bindings.alertInfo = .init(id: .declineAndBan, title: L10n.screenKnockRequestsListBanAlertTitle, - message: L10n.screenKnockRequestsListBanAlertDescription(userID), - // TODO: Implement action primaryButton: .init(title: L10n.screenKnockRequestsListBanAlertConfirmButtonTitle, - role: .destructive, - action: nil), + role: .destructive) { [weak self] in self?.declineAndBan(request: request) }, secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) } } // MARK: - Private + private func getRequest(eventID: String) -> KnockRequestProxyProtocol? { + guard case let .loaded(requests) = roomProxy.knockRequestsStatePublisher.value, + let request = requests.first(where: { $0.eventID == eventID }) else { + return nil + } + return request + } + + private func accept(request: KnockRequestProxyProtocol) { + showLoadingIndicator(title: L10n.screenKnockRequestsListAcceptLoadingTitle) + + let eventID = request.eventID + state.handledEventIDs.insert(eventID) + + Task { + switch await request.accept() { + case .success: + hideLoadingIndicator() + case .failure: + hideLoadingIndicator() + state.handledEventIDs.remove(eventID) + state.bindings.alertInfo = .init(id: .acceptFailed, + title: L10n.screenKnockRequestsListAcceptFailedAlertTitle, + message: L10n.screenKnockRequestsListAcceptFailedAlertDescription, + primaryButton: .init(title: L10n.actionYesTryAgain) { [weak self] in self?.accept(request: request) }, + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) + } + } + } + + private func decline(request: KnockRequestProxyProtocol) { + showLoadingIndicator(title: L10n.screenKnockRequestsListDeclineLoadingTitle) + + let eventID = request.eventID + state.handledEventIDs.insert(eventID) + + Task { + switch await request.decline() { + case .success: + hideLoadingIndicator() + case .failure: + hideLoadingIndicator() + state.handledEventIDs.remove(eventID) + state.bindings.alertInfo = .init(id: .declineFailed, + title: L10n.screenKnockRequestsListDeclineFailedAlertTitle, + message: L10n.screenKnockRequestsListDeclineFailedAlertDescription, + primaryButton: .init(title: L10n.actionYesTryAgain) { [weak self] in self?.decline(request: request) }, + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) + } + } + } + + private func declineAndBan(request: KnockRequestProxyProtocol) { + showLoadingIndicator(title: L10n.screenKnockRequestsListBanLoadingTitle) + + let eventID = request.eventID + state.handledEventIDs.insert(eventID) + + Task { + switch await request.ban() { + case .success: + hideLoadingIndicator() + case .failure: + hideLoadingIndicator() + state.handledEventIDs.remove(eventID) + state.bindings.alertInfo = .init(id: .declineFailed, + title: L10n.screenKnockRequestsListDeclineFailedAlertTitle, + message: L10n.screenKnockRequestsListDeclineFailedAlertDescription, + primaryButton: .init(title: L10n.actionYesTryAgain) { [weak self] in self?.declineAndBan(request: request) }, + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) + } + } + } + + private func acceptAll() { + guard case let .loaded(requests) = roomProxy.knockRequestsStatePublisher.value else { + return + } + showLoadingIndicator(title: L10n.screenKnockRequestsListAcceptAllLoadingTitle) + state.handledEventIDs.formUnion(Set(requests.map(\.eventID))) + + Task { + let failedIDs = await withTaskGroup(of: (String, Result).self) { group in + for request in requests { + group.addTask { + await (request.eventID, request.accept()) + } + } + + var failedIDs = [String]() + for await result in group where result.1.isFailure { + failedIDs.append(result.0) + } + return failedIDs + } + hideLoadingIndicator() + + if !failedIDs.isEmpty { + state.handledEventIDs.subtract(failedIDs) + state.bindings.alertInfo = .init(id: .acceptAllFailed, + title: L10n.screenKnockRequestsListAcceptAllFailedAlertTitle, + message: L10n.screenKnockRequestsListAcceptAllFailedAlertDescription, + primaryButton: .init(title: L10n.actionYesTryAgain) { [weak self] in self?.acceptAll() }, + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) + } + } + } + private func setupSubscriptions() { roomProxy.infoPublisher .receive(on: DispatchQueue.main) @@ -76,6 +192,26 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn Task { await self?.updatePermissions() } } .store(in: &cancellables) + + roomProxy.knockRequestsStatePublisher + .map(KnockRequestsListState.init) + .removeDuplicates() + .throttle(for: .milliseconds(100), scheduler: DispatchQueue.main, latest: true) + .weakAssign(to: \.state.requestsState, on: self) + .store(in: &cancellables) + + context.$viewState + .map(\.isLoading) + .removeDuplicates() + .sink { [weak self] isLoading in + guard let self else { return } + if isLoading { + showInitialLoadingIndicator() + } else { + hideLoadingIndicator() + } + } + .store(in: &cancellables) } private func updateRoomInfo(roomInfo: RoomInfoProxy) { @@ -93,15 +229,29 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn state.canBan = await (try? roomProxy.canUserBan(userID: roomProxy.ownUserID).get()) == true } - // For testing purposes - private init(initialViewState: KnockRequestsListScreenViewState) { - roomProxy = JoinedRoomProxyMock(.init()) - super.init(initialViewState: initialViewState) + private static let loadingIndicatorIdentifier = "\(KnockRequestsListScreenViewModel.self)-Loading" + + private func showInitialLoadingIndicator() { + userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier, + type: .modal(progress: .indeterminate, + interactiveDismissDisabled: false, + allowsInteraction: true), + title: L10n.screenKnockRequestsListInitialLoadingTitle, + persistent: true), + delay: .milliseconds(100)) } -} - -extension KnockRequestsListScreenViewModel { - static func mockWithInitialState(_ initialViewState: KnockRequestsListScreenViewState) -> KnockRequestsListScreenViewModel { - .init(initialViewState: initialViewState) + + private func showLoadingIndicator(title: String) { + userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier, + type: .modal(progress: .indeterminate, + interactiveDismissDisabled: false, + allowsInteraction: false), + title: title, + persistent: true), + delay: .milliseconds(200)) + } + + private func hideLoadingIndicator() { + userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier) } } diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift index db6962d1f1..f68b24b4a8 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift @@ -15,9 +15,9 @@ import Compound import SwiftUI -struct KnockRequestCellInfo: Identifiable { - /// user identifier of the usee that sent the request - let id: String +struct KnockRequestCellInfo: Equatable { + let eventID: String + let userID: String let displayName: String? let avatarURL: URL? let timestamp: String? @@ -35,7 +35,7 @@ struct KnockRequestCell: View { HStack(alignment: .top, spacing: 16) { LoadableAvatarImage(url: cellInfo.avatarURL, name: cellInfo.displayName, - contentID: cellInfo.id, + contentID: cellInfo.userID, avatarSize: .user(on: .knockingUserList), mediaProvider: mediaProvider) VStack(alignment: .leading, spacing: 12) { @@ -60,7 +60,7 @@ struct KnockRequestCell: View { private var header: some View { VStack(alignment: .leading, spacing: 0) { HStack(alignment: .top, spacing: 0) { - Text(cellInfo.displayName ?? cellInfo.id) + Text(cellInfo.displayName ?? cellInfo.userID) .font(.compound.bodyLGSemibold) .foregroundStyle(.compound.textPrimary) .frame(maxWidth: .infinity, alignment: .leading) @@ -71,7 +71,7 @@ struct KnockRequestCell: View { } } if cellInfo.displayName != nil { - Text(cellInfo.id) + Text(cellInfo.userID) .font(.compound.bodyMD) .foregroundStyle(.compound.textSecondary) } @@ -85,14 +85,14 @@ struct KnockRequestCell: View { HStack(spacing: 16) { if let onDecline { Button(L10n.actionDecline) { - onDecline(cellInfo.id) + onDecline(cellInfo.eventID) } .buttonStyle(.compound(.secondary, size: .medium)) } if let onAccept { Button(L10n.actionAccept) { - onAccept(cellInfo.id) + onAccept(cellInfo.eventID) } .buttonStyle(.compound(.primary, size: .medium)) } @@ -101,7 +101,7 @@ struct KnockRequestCell: View { if let onDeclineAndBan { Button(role: .destructive) { - onDeclineAndBan(cellInfo.id) + onDeclineAndBan(cellInfo.eventID) } label: { Text(L10n.screenKnockRequestsListDeclineAndBanActionTitle) .padding(.top, 8) @@ -166,30 +166,34 @@ private struct DisclosableText: View { } } +extension KnockRequestCellInfo: Identifiable { + var id: String { eventID } +} + struct KnockRequestCell_Previews: PreviewProvider, TestablePreview { // swiftlint:disable:next line_length - static let aliceWithLongReason = KnockRequestCellInfo(id: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "20 Nov 2024", reason: "Hello would like to join this room, also this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long reason") + static let aliceWithLongReason = KnockRequestCellInfo(eventID: "1", userID: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "20 Nov 2024", reason: "Hello would like to join this room, also this is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long reason") - static let aliceWithShortReason = KnockRequestCellInfo(id: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "20 Nov 2024", reason: "Hello, I am Alice and would like to join this room, please") + static let aliceWithShortReason = KnockRequestCellInfo(eventID: "1", userID: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "20 Nov 2024", reason: "Hello, I am Alice and would like to join this room, please") - static let aliceWithNoReason = KnockRequestCellInfo(id: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "20 Nov 2024", reason: nil) + static let aliceWithNoReason = KnockRequestCellInfo(eventID: "1", userID: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "20 Nov 2024", reason: nil) - static let aliceWithNoName = KnockRequestCellInfo(id: "@alice:matrix.org", displayName: nil, avatarURL: nil, timestamp: "20 Nov 2024", reason: nil) + static let aliceWithNoName = KnockRequestCellInfo(eventID: "1", userID: "@alice:matrix.org", displayName: nil, avatarURL: nil, timestamp: "20 Nov 2024", reason: nil) static var previews: some View { - KnockRequestCell(cellInfo: aliceWithLongReason, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in }) + KnockRequestCell(cellInfo: aliceWithLongReason) { _ in } onDecline: { _ in } onDeclineAndBan: { _ in } .previewDisplayName("Long reason") - KnockRequestCell(cellInfo: aliceWithShortReason, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in }) + KnockRequestCell(cellInfo: aliceWithShortReason) { _ in } onDecline: { _ in } onDeclineAndBan: { _ in } .previewDisplayName("Short reason") - KnockRequestCell(cellInfo: aliceWithNoReason, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in }) + KnockRequestCell(cellInfo: aliceWithNoReason) { _ in } onDecline: { _ in } onDeclineAndBan: { _ in } .previewDisplayName("No reason") - KnockRequestCell(cellInfo: aliceWithNoName, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in }) + KnockRequestCell(cellInfo: aliceWithNoName) { _ in } onDecline: { _ in } onDeclineAndBan: { _ in } .previewDisplayName("No name") - KnockRequestCell(cellInfo: aliceWithShortReason, onAccept: nil, onDecline: { _ in }, onDeclineAndBan: { _ in }) - .previewDisplayName("No Accept") - KnockRequestCell(cellInfo: aliceWithShortReason, onAccept: nil, onDecline: nil, onDeclineAndBan: { _ in }) - .previewDisplayName("No Accept and Decline") - KnockRequestCell(cellInfo: aliceWithShortReason, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: nil) - .previewDisplayName("No Ban") +// KnockRequestCell(cellInfo: aliceWithShortReason, onAccept: nil) onDecline: { _ in } onDeclineAndBan: { _ in } +// .previewDisplayName("No Accept") +// KnockRequestCell(cellInfo: aliceWithShortReason) onDeclineAndBan: { _ in } +// .previewDisplayName("No Accept and Decline") +// KnockRequestCell(cellInfo: aliceWithShortReason) { _ in } onDecline: { _ in }) +// .previewDisplayName("No Ban") } } diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift index d3bc5915a4..7adebe7033 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift @@ -17,12 +17,12 @@ struct KnockRequestsListScreen: View { .navigationTitle(L10n.screenKnockRequestsListTitle) .background(.compound.bgCanvasDefault) .overlay { - if !context.viewState.shouldDisplayRequests { + if context.viewState.shouldDisplayEmptyView { KnockRequestsListEmptyStateView() } } .safeAreaInset(edge: .bottom) { - if context.viewState.shouldDisplayRequests { + if context.viewState.shouldDisplayAcceptAllButton { acceptAllButton } } @@ -31,10 +31,18 @@ struct KnockRequestsListScreen: View { @ViewBuilder private var mainContent: some View { + if context.viewState.isLoading { + EmptyView() + } else { + list + } + } + + private var list: some View { ScrollView { LazyVStack(spacing: 0) { if context.viewState.shouldDisplayRequests { - ForEach(context.viewState.requests) { requestInfo in + ForEach(context.viewState.displayedRequests) { requestInfo in ListRow(kind: .custom { KnockRequestCell(cellInfo: requestInfo, mediaProvider: context.mediaProvider, @@ -60,37 +68,93 @@ struct KnockRequestsListScreen: View { .background(.compound.bgCanvasDefault) } - private func onAccept(userID: String) { - context.send(viewAction: .acceptRequest(userID: userID)) + private func onAccept(eventID: String) { + context.send(viewAction: .acceptRequest(eventID: eventID)) } - private func onDecline(userID: String) { - context.send(viewAction: .declineRequest(userID: userID)) + private func onDecline(eventID: String) { + context.send(viewAction: .declineRequest(eventID: eventID)) } - private func onDeclineAndBan(userID: String) { - context.send(viewAction: .ban(userID: userID)) + private func onDeclineAndBan(eventID: String) { + context.send(viewAction: .ban(eventID: eventID)) } } // MARK: - Previews struct KnockRequestsListScreen_Previews: PreviewProvider, TestablePreview { - static let emptyViewModel = KnockRequestsListScreenViewModel.mockWithInitialState(.init(requests: [])) + static let loadingViewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loading) + + static let emptyViewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([])) + + static let singleRequestViewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([KnockRequestProxyMock(.init(eventID: "1", + userID: "@alice:matrix.org", + displayName: "Alice", + avatarURL: nil, + timestamp: "Now", + reason: "Hello"))])) + + static let viewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([ + KnockRequestProxyMock(.init(eventID: "1", + userID: "@alice:matrix.org", + displayName: "Alice", + avatarURL: nil, + timestamp: "Now", + reason: "Hello")), + KnockRequestProxyMock(.init(eventID: "2", + userID: "@bob:matrix.org", + displayName: "Bob", + avatarURL: nil, + timestamp: "Now", + // swiftlint:disable:next line_length + reason: "Hello this one is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long reason")), + KnockRequestProxyMock(.init(eventID: "3", + userID: "@charlie:matrix.org", + displayName: "Charlie", + avatarURL: nil, + timestamp: "Now", + reason: nil)), + KnockRequestProxyMock(.init(eventID: "4", + userID: "@dan:matrix.org", + displayName: "Dan", + avatarURL: nil, + timestamp: "Now", + reason: "Hello! It's a me! Dan!")) + ])) - static let viewModel = KnockRequestsListScreenViewModel.mockWithInitialState(.init(requests: [.init(id: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "Now", reason: "Hello"), - // swiftlint:disable:next line_length - .init(id: "@bob:matrix.org", displayName: "Bob", avatarURL: nil, timestamp: "Now", reason: "Hello this one is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long reason"), - .init(id: "@charlie:matrix.org", displayName: "Charlie", avatarURL: nil, timestamp: "Now", reason: nil), - .init(id: "@dan:matrix.org", displayName: "Dan", avatarURL: nil, timestamp: "Now", reason: "Hello! It's a me! Dan!")])) - static var previews: some View { NavigationStack { KnockRequestsListScreen(context: viewModel.context) } + .snapshotPreferences(delay: 0.2) + + NavigationStack { + KnockRequestsListScreen(context: singleRequestViewModel.context) + } + .previewDisplayName("Single Request") + .snapshotPreferences(delay: 0.2) + NavigationStack { KnockRequestsListScreen(context: emptyViewModel.context) } .previewDisplayName("Empty state") + .snapshotPreferences(delay: 0.2) + + NavigationStack { + KnockRequestsListScreen(context: loadingViewModel.context) + } + .previewDisplayName("Loading state") + } +} + +extension KnockRequestsListScreenViewModel { + static func mockWithRequestsState(_ requestsState: KnockRequestsState) -> KnockRequestsListScreenViewModel { + .init(roomProxy: JoinedRoomProxyMock(.init(members: [.mockAdmin], + knockRequestsState: requestsState, + ownUserID: RoomMemberProxyMock.mockAdmin.userID, + joinRule: .knock)), + mediaProvider: MediaProviderMock(), + userIndicatorController: UserIndicatorControllerMock()) } } diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenCoordinator.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenCoordinator.swift new file mode 100644 index 0000000000..b04688eefa --- /dev/null +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenCoordinator.swift @@ -0,0 +1,81 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import SwiftUI + +struct MediaEventsTimelineScreenCoordinatorParameters { + let roomProxy: JoinedRoomProxyProtocol + let mediaTimelineController: RoomTimelineControllerProtocol + let filesTimelineController: RoomTimelineControllerProtocol + let mediaProvider: MediaProviderProtocol + let mediaPlayerProvider: MediaPlayerProviderProtocol + let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol + let appMediator: AppMediatorProtocol + let emojiProvider: EmojiProviderProtocol + let userIndicatorController: UserIndicatorControllerProtocol +} + +enum MediaEventsTimelineScreenCoordinatorAction { + case viewItem(TimelineMediaPreviewContext) +} + +final class MediaEventsTimelineScreenCoordinator: CoordinatorProtocol { + private let parameters: MediaEventsTimelineScreenCoordinatorParameters + private let viewModel: MediaEventsTimelineScreenViewModelProtocol + + private var cancellables = Set() + + private let actionsSubject: PassthroughSubject = .init() + var actions: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(parameters: MediaEventsTimelineScreenCoordinatorParameters) { + self.parameters = parameters + + let mediaTimelineViewModel = TimelineViewModel(roomProxy: parameters.roomProxy, + timelineController: parameters.mediaTimelineController, + mediaProvider: parameters.mediaProvider, + mediaPlayerProvider: parameters.mediaPlayerProvider, + voiceMessageMediaManager: parameters.voiceMessageMediaManager, + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: parameters.appMediator, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics, + emojiProvider: parameters.emojiProvider) + + let filesTimelineViewModel = TimelineViewModel(roomProxy: parameters.roomProxy, + timelineController: parameters.filesTimelineController, + mediaProvider: parameters.mediaProvider, + mediaPlayerProvider: parameters.mediaPlayerProvider, + voiceMessageMediaManager: parameters.voiceMessageMediaManager, + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: parameters.appMediator, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics, + emojiProvider: parameters.emojiProvider) + + viewModel = MediaEventsTimelineScreenViewModel(mediaTimelineViewModel: mediaTimelineViewModel, + filesTimelineViewModel: filesTimelineViewModel, + mediaProvider: parameters.mediaProvider, + userIndicatorController: parameters.userIndicatorController) + + viewModel.actionsPublisher + .sink { [weak self] action in + switch action { + case .viewItem(let previewContext): + self?.actionsSubject.send(.viewItem(previewContext)) + } + } + .store(in: &cancellables) + } + + func toPresentable() -> AnyView { + AnyView(MediaEventsTimelineScreen(context: viewModel.context)) + } +} diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenModels.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenModels.swift new file mode 100644 index 0000000000..72fa7e2313 --- /dev/null +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenModels.swift @@ -0,0 +1,47 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import SwiftUI + +enum MediaEventsTimelineScreenViewModelAction { + case viewItem(TimelineMediaPreviewContext) +} + +enum MediaEventsTimelineScreenMode { + case media + case files +} + +struct MediaEventsTimelineGroup: Identifiable { + var id: String + var title: String + var items: [RoomTimelineItemViewState] +} + +struct MediaEventsTimelineScreenViewState: BindableState { + var isBackPaginating = false + var shouldShowEmptyState = false + + var groups = [MediaEventsTimelineGroup]() + + var activeTimelineContextProvider: (() -> TimelineViewModel.Context)! + + var bindings: MediaEventsTimelineScreenViewStateBindings + + var currentPreviewItemID: TimelineItemIdentifier? +} + +struct MediaEventsTimelineScreenViewStateBindings { + var screenMode: MediaEventsTimelineScreenMode +} + +enum MediaEventsTimelineScreenViewAction { + case changedScreenMode + case oldestItemDidAppear + case oldestItemDidDisappear + case tappedItem(item: RoomTimelineItemViewState, namespace: Namespace.ID) +} diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenViewModel.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenViewModel.swift new file mode 100644 index 0000000000..a4085f620c --- /dev/null +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenViewModel.swift @@ -0,0 +1,175 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import SwiftUI + +typealias MediaEventsTimelineScreenViewModelType = StateStoreViewModel + +class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType, MediaEventsTimelineScreenViewModelProtocol { + private let mediaTimelineViewModel: TimelineViewModelProtocol + private let filesTimelineViewModel: TimelineViewModelProtocol + private let userIndicatorController: UserIndicatorControllerProtocol + + private var isOldestItemVisible = false + + private var activeTimelineViewModel: TimelineViewModelProtocol { + switch state.bindings.screenMode { + case .media: + mediaTimelineViewModel + case .files: + filesTimelineViewModel + } + } + + private var mediaPreviewCancellable: AnyCancellable? + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(mediaTimelineViewModel: TimelineViewModelProtocol, + filesTimelineViewModel: TimelineViewModelProtocol, + initialViewState: MediaEventsTimelineScreenViewState = .init(bindings: .init(screenMode: .media)), + mediaProvider: MediaProviderProtocol, + userIndicatorController: UserIndicatorControllerProtocol) { + self.mediaTimelineViewModel = mediaTimelineViewModel + self.filesTimelineViewModel = filesTimelineViewModel + self.userIndicatorController = userIndicatorController + + super.init(initialViewState: initialViewState, mediaProvider: mediaProvider) + + state.activeTimelineContextProvider = { [weak self] in + guard let self else { fatalError() } + + return activeTimelineViewModel.context + } + + mediaTimelineViewModel.context.$viewState.sink { [weak self] timelineViewState in + guard let self, state.bindings.screenMode == .media else { + return + } + + updateWithTimelineViewState(timelineViewState) + } + .store(in: &cancellables) + + filesTimelineViewModel.context.$viewState.sink { [weak self] timelineViewState in + guard let self, state.bindings.screenMode == .files else { + return + } + + updateWithTimelineViewState(timelineViewState) + } + .store(in: &cancellables) + + updateWithTimelineViewState(activeTimelineViewModel.context.viewState) + } + + // MARK: - Public + + override func process(viewAction: MediaEventsTimelineScreenViewAction) { + MXLog.info("View model: received view action: \(viewAction)") + + switch viewAction { + case .changedScreenMode: + updateWithTimelineViewState(activeTimelineViewModel.context.viewState) + case .oldestItemDidAppear: + isOldestItemVisible = true + backPaginateIfNecessary(paginationStatus: activeTimelineViewModel.context.viewState.timelineState.paginationState.backward) + case .oldestItemDidDisappear: + isOldestItemVisible = false + case .tappedItem(let item, let namespace): + handleItemTapped(item, namespace: namespace) + } + } + + // MARK: - Private + + private func updateWithTimelineViewState(_ timelineViewState: TimelineViewState) { + var newGroups = [MediaEventsTimelineGroup]() + var currentItems = [RoomTimelineItemViewState]() + + timelineViewState.timelineState.itemViewStates.filter { itemViewState in + switch itemViewState.type { + case .image, .video: + state.bindings.screenMode == .media + case .audio, .file, .voice: + state.bindings.screenMode == .files + case .separator: + true + default: + false + } + }.reversed().forEach { item in + if case .separator(let item) = item.type { + let group = MediaEventsTimelineGroup(id: item.id.uniqueID.id, + title: titleForDate(item.timestamp), + items: currentItems) + if !currentItems.isEmpty { + newGroups.append(group) + currentItems = [] + } + } else { + currentItems.append(item) + } + } + + if !currentItems.isEmpty { + MXLog.warning("Found ungrouped timeline items, appending them at end.") + let group = MediaEventsTimelineGroup(id: UUID().uuidString, + title: titleForDate(.now), + items: currentItems) + newGroups.append(group) + } + + state.groups = newGroups + + state.isBackPaginating = timelineViewState.timelineState.paginationState.backward == .paginating + state.shouldShowEmptyState = newGroups.isEmpty && timelineViewState.timelineState.paginationState.backward == .timelineEndReached + backPaginateIfNecessary(paginationStatus: timelineViewState.timelineState.paginationState.backward) + } + + private func backPaginateIfNecessary(paginationStatus: PaginationStatus) { + if paginationStatus == .idle, isOldestItemVisible { + activeTimelineViewModel.context.send(viewAction: .paginateBackwards) + } + } + + private func handleItemTapped(_ item: RoomTimelineItemViewState, namespace: Namespace.ID) { + let item: EventBasedMessageTimelineItemProtocol? = switch item.type { + case .audio(let audioItem): audioItem + case .file(let fileItem): fileItem + case .image(let imageItem): imageItem + case .video(let videoItem): videoItem + default: nil + } + + guard let item else { + MXLog.error("Unexpected item type tapped.") + return + } + + actionsSubject.send(.viewItem(.init(item: item, + viewModel: activeTimelineViewModel, + namespace: namespace) { [weak self] itemID in + self?.state.currentPreviewItemID = itemID + })) + + // Set the current item in the next run loop so that (hopefully) the presentation will be ready before we flip the thumbnail. + Task { state.currentPreviewItemID = item.id } + } + + private func titleForDate(_ date: Date) -> String { + if Calendar.current.isDate(date, equalTo: .now, toGranularity: .month) { + L10n.commonDateThisMonth + } else { + date.formatted(.dateTime.month(.wide).year()) + } + } +} diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenViewModelProtocol.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenViewModelProtocol.swift new file mode 100644 index 0000000000..d6fd4f6c7a --- /dev/null +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenViewModelProtocol.swift @@ -0,0 +1,14 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine + +@MainActor +protocol MediaEventsTimelineScreenViewModelProtocol { + var actionsPublisher: AnyPublisher { get } + var context: MediaEventsTimelineScreenViewModelType.Context { get } +} diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/MediaEventsTimelineScreen.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/MediaEventsTimelineScreen.swift new file mode 100644 index 0000000000..2c9c7ce0f6 --- /dev/null +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/MediaEventsTimelineScreen.swift @@ -0,0 +1,280 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct MediaEventsTimelineScreen: View { + @ObservedObject var context: MediaEventsTimelineScreenViewModel.Context + + @Namespace private var zoomTransition + + var body: some View { + mainContent + .navigationBarTitleDisplayMode(.inline) + .background(.compound.bgCanvasDefault) + // Doesn't play well with the transformed scrollView + .toolbarBackground(.visible, for: .navigationBar) + .toolbar { + ToolbarItem(placement: .principal) { + Picker("", selection: $context.screenMode) { + Text(L10n.screenMediaBrowserListModeMedia) + .padding() + .tag(MediaEventsTimelineScreenMode.media) + Text(L10n.screenMediaBrowserListModeFiles) + .padding() + .tag(MediaEventsTimelineScreenMode.files) + } + .pickerStyle(.segmented) + } + } + .environmentObject(context.viewState.activeTimelineContextProvider()) + .environment(\.timelineContext, context.viewState.activeTimelineContextProvider()) + .onChange(of: context.screenMode) { _, _ in + context.send(viewAction: .changedScreenMode) + } + } + + // The scale effects do the following: + // * flip the scrollView vertically to keep the items + // at the bottom and have pagination working properly + // * flip the grid vertically to counteract the scroll view + // but also horizontally to preserve the correct item order + // * flip the items on both axes have them render correctly + @ViewBuilder + private var mainContent: some View { + if context.viewState.shouldShowEmptyState { + emptyState + } else { + ScrollView { + Group { + switch context.viewState.bindings.screenMode { + case .media: + mediaContent + case .files: + filesContent + } + + header + } + } + .scaleEffect(.init(width: 1, height: -1)) + } + } + + @ViewBuilder + private var mediaContent: some View { + let columns = [GridItem(.adaptive(minimum: 80, maximum: 150), spacing: 1)] + LazyVGrid(columns: columns, alignment: .center, spacing: 1) { + ForEach(context.viewState.groups) { group in + Section { + ForEach(group.items) { item in + Button { + tappedItem(item) + } label: { + viewForTimelineItem(item) + .scaleEffect(scale(for: item, isGridLayout: true)) + } + .zoomTransitionSource(id: item.identifier, in: zoomTransition) + } + } footer: { + // Use a footer as the header because the scrollView is flipped + SeparatorMediaEventsTimelineView(group: group) + .scaleEffect(.init(width: -1, height: -1)) + } + } + } + .scaleEffect(.init(width: -1, height: 1)) + } + + @ViewBuilder + private var filesContent: some View { + LazyVStack(alignment: .center, spacing: 16) { + ForEach(context.viewState.groups) { group in + Section { + ForEach(group.items) { item in + VStack(spacing: 20) { + Divider() + + Button { + tappedItem(item) + } label: { + viewForTimelineItem(item) + .scaleEffect(scale(for: item, isGridLayout: false)) + } + .zoomTransitionSource(id: item.identifier, in: zoomTransition) + } + .padding(.horizontal, 16) + } + } footer: { + // Use a footer as the header because the scrollView is flipped + SeparatorMediaEventsTimelineView(group: group) + .scaleEffect(.init(width: 1, height: -1)) + } + } + } + } + + private var header: some View { + // Needs to be wrapped in a LazyStack otherwise appearance calls don't trigger + LazyVStack(spacing: 0) { + ProgressView() + .padding() + .opacity(context.viewState.isBackPaginating ? 1 : 0) + .scaleEffect(.init(width: 1, height: -1)) // Make sure it spins the right way around 🙃 + + Rectangle() + .frame(height: 1) + .foregroundStyle(.compound.bgCanvasDefault) + .onAppear { + context.send(viewAction: .oldestItemDidAppear) + } + .onDisappear { + context.send(viewAction: .oldestItemDidDisappear) + } + } + } + + @ViewBuilder + private func viewForTimelineItem(_ item: RoomTimelineItemViewState) -> some View { + switch item.type { + case .image(let timelineItem): + ImageMediaEventsTimelineView(timelineItem: timelineItem) + case .video(let timelineItem): + VideoMediaEventsTimelineView(timelineItem: timelineItem) + case .file(let timelineItem): + FileMediaEventsTimelineView(timelineItem: timelineItem) + case .audio(let timelineItem): + AudioMediaEventsTimelineView(timelineItem: timelineItem) + case .voice(let timelineItem): + let defaultPlayerState = AudioPlayerState(id: .timelineItemIdentifier(timelineItem.id), title: L10n.commonVoiceMessage, duration: 0) + let playerState = context.viewState.activeTimelineContextProvider().viewState.audioPlayerStateProvider?(timelineItem.id) ?? defaultPlayerState + VoiceMessageMediaEventsTimelineView(timelineItem: timelineItem, playerState: playerState) + default: + EmptyView() + } + } + + @ViewBuilder + private var emptyState: some View { + FullscreenDialog(topPadding: UIConstants.iconTopPaddingToNavigationBar, background: .gradient) { + VStack(spacing: 16) { + switch context.screenMode { + case .media: + emptyMedia + case .files: + emptyFiles + } + } + .padding(16) + } bottomContent: { EmptyView() } + } + + private var emptyMedia: some View { + Group { + BigIcon(icon: \.image) + + Text(L10n.screenMediaBrowserMediaEmptyStateTitle) + .foregroundColor(.compound.textPrimary) + .font(.compound.headingMDBold) + .multilineTextAlignment(.center) + + Text(L10n.screenMediaBrowserMediaEmptyStateSubtitle) + .foregroundColor(.compound.textSecondary) + .font(.compound.bodyMD) + .multilineTextAlignment(.center) + } + } + + private var emptyFiles: some View { + Group { + BigIcon(icon: \.document) + + Text(L10n.screenMediaBrowserFilesEmptyStateTitle) + .foregroundColor(.compound.textPrimary) + .font(.compound.headingMDBold) + .multilineTextAlignment(.center) + + Text(L10n.screenMediaBrowserFilesEmptyStateSubtitle) + .foregroundColor(.compound.textSecondary) + .font(.compound.bodyMD) + .multilineTextAlignment(.center) + } + } + + func tappedItem(_ item: RoomTimelineItemViewState) { + context.send(viewAction: .tappedItem(item: item, namespace: zoomTransition)) + } + + func scale(for item: RoomTimelineItemViewState, isGridLayout: Bool) -> CGSize { + if item.identifier == context.viewState.currentPreviewItemID, #available(iOS 18.0, *) { + // Remove the flip when presenting a preview so that the zoom transition is the right way up 🙃 + CGSize(width: 1, height: 1) + } else { + CGSize(width: isGridLayout ? -1 : 1, height: -1) + } + } +} + +// MARK: - Previews + +struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview { + static let mediaViewModel = makeViewModel(screenMode: .media) + static let filesViewModel = makeViewModel(screenMode: .files) + static let emptyMediaViewModel = makeViewModel(empty: true, screenMode: .media) + static let emptyFilesViewModel = makeViewModel(empty: true, screenMode: .files) + + static var previews: some View { + NavigationStack { + MediaEventsTimelineScreen(context: mediaViewModel.context) + } + .previewDisplayName("Media") + + NavigationStack { + MediaEventsTimelineScreen(context: filesViewModel.context) + } + .previewDisplayName("Files") + + NavigationStack { + MediaEventsTimelineScreen(context: emptyMediaViewModel.context) + } + .previewDisplayName("Empty Media") + + NavigationStack { + MediaEventsTimelineScreen(context: emptyFilesViewModel.context) + } + .previewDisplayName("Empty Files") + } + + private static func makeViewModel(empty: Bool = false, + screenMode: MediaEventsTimelineScreenMode) -> MediaEventsTimelineScreenViewModel { + MediaEventsTimelineScreenViewModel(mediaTimelineViewModel: makeTimelineViewModel(empty: empty), + filesTimelineViewModel: makeTimelineViewModel(empty: empty), + initialViewState: .init(bindings: .init(screenMode: screenMode)), + mediaProvider: MediaProviderMock(configuration: .init()), + userIndicatorController: UserIndicatorControllerMock()) + } + + private static func makeTimelineViewModel(empty: Bool) -> TimelineViewModel { + let timelineController = if empty { + MockRoomTimelineController.emptyMediaGallery + } else { + MockRoomTimelineController.mediaGallery + } + + return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), + timelineController: timelineController, + mediaProvider: MediaProviderMock(configuration: .init()), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: UserIndicatorControllerMock(), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics, + emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) + } +} diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/AudioFileEventsTimelineView.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/AudioFileEventsTimelineView.swift new file mode 100644 index 0000000000..b1175e1838 --- /dev/null +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/AudioFileEventsTimelineView.swift @@ -0,0 +1,58 @@ +// +// Copyright 2023, 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct AudioMediaEventsTimelineView: View { + let timelineItem: AudioRoomTimelineItem + + var body: some View { + MediaFileRoomTimelineContent(filename: timelineItem.content.filename, + fileSize: timelineItem.content.fileSize, + caption: timelineItem.content.caption, + formattedCaption: timelineItem.content.formattedCaption, + additionalWhitespaces: timelineItem.additionalWhitespaces(), + isAudioFile: true) + .accessibilityLabel(L10n.commonAudio) + .frame(maxWidth: .infinity, alignment: .leading) + .bubbleBackground(isOutgoing: timelineItem.isOutgoing) + } +} + +struct AudioMediaEventsTimelineView_Previews: PreviewProvider, TestablePreview { + static let viewModel = TimelineViewModel.mock + + static var previews: some View { + VStack(spacing: 20) { + AudioMediaEventsTimelineView(timelineItem: makeItem(filename: "audio.ogg", + fileSize: 2 * 1024 * 1024)) + + AudioMediaEventsTimelineView(timelineItem: makeItem(filename: "Best Song Ever.mp3", + fileSize: 7 * 1024 * 1024, + caption: "This song rocks!")) + } + .environmentObject(viewModel.context) + } + + static func makeItem(filename: String, fileSize: UInt, caption: String? = nil) -> AudioRoomTimelineItem { + .init(id: .randomEvent, + timestamp: .mock, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(filename: filename, + caption: caption, + duration: 300, + waveform: nil, + source: nil, + fileSize: fileSize, + contentType: nil)) + } +} diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/FileMediaEventsTimelineView.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/FileMediaEventsTimelineView.swift new file mode 100644 index 0000000000..4c07806830 --- /dev/null +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/FileMediaEventsTimelineView.swift @@ -0,0 +1,67 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct FileMediaEventsTimelineView: View { + let timelineItem: FileRoomTimelineItem + + var body: some View { + MediaFileRoomTimelineContent(filename: timelineItem.content.filename, + fileSize: timelineItem.content.fileSize, + caption: timelineItem.content.caption, + formattedCaption: timelineItem.content.formattedCaption, + additionalWhitespaces: timelineItem.additionalWhitespaces()) + .accessibilityLabel(L10n.commonFile) + .frame(maxWidth: .infinity, alignment: .leading) + .bubbleBackground(isOutgoing: timelineItem.isOutgoing) + } +} + +struct FileMediaEventsTimelineView_Previews: PreviewProvider, TestablePreview { + static let viewModel = TimelineViewModel.mock + + static var previews: some View { + VStack(spacing: 20.0) { + FileMediaEventsTimelineView(timelineItem: makeItem(filename: "document.pdf")) + + FileMediaEventsTimelineView(timelineItem: makeItem(filename: "document.pdf", + fileSize: 3 * 1024 * 1024)) + + FileMediaEventsTimelineView(timelineItem: makeItem(filename: "spreadsheet.xlsx", + fileSize: 17 * 1024, + caption: "The important figures you asked me to send over.")) + + FileMediaEventsTimelineView(timelineItem: makeItem(filename: "document.txt", + fileSize: 456, + caption: "Plain caption", + formattedCaption: "Formatted caption")) + } + .environmentObject(viewModel.context) + } + + static func makeItem(filename: String, + fileSize: UInt? = nil, + caption: String? = nil, + formattedCaption: AttributedString? = nil) -> FileRoomTimelineItem { + .init(id: .randomEvent, + timestamp: .mock, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(filename: filename, + caption: caption, + formattedCaption: formattedCaption, + source: nil, + fileSize: fileSize, + thumbnailSource: nil, + contentType: nil)) + } +} diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/ImageMediaEventsTimelineView.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/ImageMediaEventsTimelineView.swift new file mode 100644 index 0000000000..97a36827f1 --- /dev/null +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/ImageMediaEventsTimelineView.swift @@ -0,0 +1,81 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct ImageMediaEventsTimelineView: View { + @Environment(\.timelineContext) private var context + let timelineItem: ImageRoomTimelineItem + + var body: some View { + Color.clear // Let the image aspect fill in place + .aspectRatio(1, contentMode: .fill) + .overlay { + loadableImage + } + .clipped() + .accessibilityElement(children: .ignore) + .accessibilityLabel(L10n.commonImage) + } + + @ViewBuilder + private var loadableImage: some View { + if timelineItem.content.contentType == .gif { + LoadableImage(mediaSource: timelineItem.content.imageInfo.source, + mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), + blurhash: timelineItem.content.blurhash, + size: timelineItem.content.imageInfo.size, + mediaProvider: context?.mediaProvider) { + placeholder + } + .mediaGalleryTimelineAspectRatio(imageInfo: timelineItem.content.imageInfo) + } else { + LoadableImage(mediaSource: timelineItem.content.thumbnailInfo?.source ?? timelineItem.content.imageInfo.source, + mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), + blurhash: timelineItem.content.blurhash, + size: timelineItem.content.thumbnailInfo?.size ?? timelineItem.content.imageInfo.size, + mediaProvider: context?.mediaProvider) { + placeholder + } + .mediaGalleryTimelineAspectRatio(imageInfo: timelineItem.content.thumbnailInfo ?? timelineItem.content.imageInfo) + } + } + + private var placeholder: some View { + Rectangle() + .foregroundColor(.compound.bgSubtleSecondary) + .opacity(0.3) + } +} + +struct ImageMediaEventsTimelineView_Previews: PreviewProvider, TestablePreview { + static let viewModel = TimelineViewModel.mock + + static var previews: some View { + ImageMediaEventsTimelineView(timelineItem: makeTimelineItem()) + .frame(width: 100, height: 100) + .environmentObject(viewModel.context) + .environment(\.timelineContext, viewModel.context) + .previewLayout(.sizeThatFits) + .background(.black) + } + + private static func makeTimelineItem() -> ImageRoomTimelineItem { + ImageRoomTimelineItem(id: .randomEvent, + timestamp: .mock, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(filename: "image.jpg", + imageInfo: .mockImage, + thumbnailInfo: .mockThumbnail, + contentType: .jpeg)) + } +} diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/SeparatorMediaEventsTimelineView.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/SeparatorMediaEventsTimelineView.swift new file mode 100644 index 0000000000..bbe66129c3 --- /dev/null +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/SeparatorMediaEventsTimelineView.swift @@ -0,0 +1,32 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct SeparatorMediaEventsTimelineView: View { + let group: MediaEventsTimelineGroup + + var body: some View { + Text(group.title) + .font(.compound.bodySMSemibold) + .foregroundColor(.compound.textPrimary) + .frame(alignment: .center) + .padding(.vertical, 16) + } +} + +struct SeparatorMediaEventsTimelineView_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + let item = SeparatorRoomTimelineItem(id: .virtual(uniqueID: .init(id: "Separator")), + timestamp: .mock) + + SeparatorMediaEventsTimelineView(group: .init(id: item.id.uniqueID.id, + title: "Group", + items: [])) + } +} diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/VideoMediaEventsTimelineView.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/VideoMediaEventsTimelineView.swift new file mode 100644 index 0000000000..08ea45da79 --- /dev/null +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/VideoMediaEventsTimelineView.swift @@ -0,0 +1,91 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct VideoMediaEventsTimelineView: View { + @Environment(\.timelineContext) private var context + let timelineItem: VideoRoomTimelineItem + + var body: some View { + Color.clear // Let the image aspect fill in place + .aspectRatio(1, contentMode: .fill) + .overlay { + thumbnail + } + .clipped() + .overlay(alignment: .bottom) { overlay } + .accessibilityElement(children: .ignore) + .accessibilityLabel(L10n.commonVideo) + } + + @ViewBuilder + var thumbnail: some View { + if let thumbnailSource = timelineItem.content.thumbnailInfo?.source { + LoadableImage(mediaSource: thumbnailSource, + mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), + blurhash: timelineItem.content.blurhash, + size: timelineItem.content.thumbnailInfo?.size, + mediaProvider: context?.mediaProvider) { + placeholder + } + .mediaGalleryTimelineAspectRatio(imageInfo: timelineItem.content.thumbnailInfo) + } else { + overlay + } + } + + var overlay: some View { + HStack(spacing: 0) { + CompoundIcon(\.videoCallSolid) + Spacer() + Text(Duration.seconds(timelineItem.content.videoInfo.duration).formatted(.time(pattern: .minuteSecond))) + } + .padding(8) + .background { + LinearGradient(stops: [.init(color: .clear, location: 0.0), + .init(color: .compound.bgCanvasDefault, location: 1.0)], + startPoint: .top, + endPoint: .bottom) + } + .font(.compound.bodyXSSemibold) + .foregroundStyle(.compound.textPrimary) + } + + var placeholder: some View { + Rectangle() + .foregroundColor(.compound.bgSubtleSecondary) + .opacity(0.3) + } +} + +struct VideoMediaEventsTimelineView_Previews: PreviewProvider, TestablePreview { + static let viewModel = TimelineViewModel.mock + + static var previews: some View { + VideoMediaEventsTimelineView(timelineItem: makeTimelineItem()) + .frame(width: 100, height: 100) + .environmentObject(viewModel.context) + .environment(\.timelineContext, viewModel.context) + .previewLayout(.sizeThatFits) + .background(.black) + } + + private static func makeTimelineItem(caption: String? = nil, isEdited: Bool = false) -> VideoRoomTimelineItem { + VideoRoomTimelineItem(id: .randomEvent, + timestamp: .mock, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(filename: "video.mp4", + videoInfo: .mockVideo, + thumbnailInfo: .mockVideoThumbnail)) + } +} diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/VoiceMessageMediaEventsTimelineView.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/VoiceMessageMediaEventsTimelineView.swift new file mode 100644 index 0000000000..3443f9783c --- /dev/null +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/TimelineViews/VoiceMessageMediaEventsTimelineView.swift @@ -0,0 +1,58 @@ +// +// Copyright 2023, 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct VoiceMessageMediaEventsTimelineView: View { + let timelineItem: VoiceMessageRoomTimelineItem + let playerState: AudioPlayerState + + var body: some View { + VoiceMessageRoomTimelineContent(timelineItem: timelineItem, + playerState: playerState) + .accessibilityLabel(L10n.commonVoiceMessage) + .frame(maxWidth: .infinity, alignment: .leading) + .bubbleBackground(isOutgoing: timelineItem.isOutgoing) + } +} + +// MARK: - Content + +struct VoiceMessageMediaEventsTimelineView_Previews: PreviewProvider, TestablePreview { + static let viewModel = TimelineViewModel.mock + static let timelineItemIdentifier = TimelineItemIdentifier.randomEvent + static let voiceRoomTimelineItem = VoiceMessageRoomTimelineItem(id: timelineItemIdentifier, + timestamp: .mock, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(filename: "audio.ogg", + duration: 300, + waveform: EstimatedWaveform.mockWaveform, + source: nil, + fileSize: nil, + contentType: nil)) + + static let playerState = AudioPlayerState(id: .timelineItemIdentifier(timelineItemIdentifier), + title: L10n.commonVoiceMessage, + duration: 10.0, + waveform: EstimatedWaveform.mockWaveform, + progress: 0.4) + + static var previews: some View { + body + .environmentObject(viewModel.context) + } + + static var body: some View { + VoiceMessageMediaEventsTimelineView(timelineItem: voiceRoomTimelineItem, playerState: playerState) + .fixedSize(horizontal: false, vertical: true) + } +} diff --git a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift index 80dcd267cd..07d089c84b 100644 --- a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift +++ b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift @@ -37,8 +37,7 @@ struct PinnedEventsTimelineScreen: View { pinnedEventIDs: timelineContext.viewState.pinnedEventIDs, isDM: timelineContext.viewState.isEncryptedOneToOneRoom, isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled, - isCreateMediaCaptionsEnabled: timelineContext.viewState.isCreateMediaCaptionsEnabled, - isPinnedEventsTimeline: timelineContext.viewState.isPinnedEventsTimeline, + timelineKind: timelineContext.viewState.timelineKind, emojiProvider: timelineContext.viewState.emojiProvider) .makeActions() if let actions { @@ -69,7 +68,7 @@ struct PinnedEventsTimelineScreen: View { TimelineView() .id(timelineContext.viewState.roomID) .environmentObject(timelineContext) - .environment(\.focussedEventID, timelineContext.viewState.timelineViewState.focussedEvent?.eventID) + .environment(\.focussedEventID, timelineContext.viewState.timelineState.focussedEvent?.eventID) } } diff --git a/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSelectedItem.swift b/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSelectedItem.swift index 435fd33a97..b688c2612f 100644 --- a/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSelectedItem.swift +++ b/ElementX/Sources/Screens/RoomChangeRolesScreen/View/RoomChangeRolesScreenSelectedItem.swift @@ -60,8 +60,7 @@ struct RoomChangeRolesScreenSelectedItem_Previews: PreviewProvider, TestablePrev HStack(spacing: 12) { ForEach(members, id: \.id) { member in RoomChangeRolesScreenSelectedItem(member: member, - mediaProvider: MediaProviderMock(configuration: .init()), - dismissAction: { }) + mediaProvider: MediaProviderMock(configuration: .init())) { } .frame(width: 72) } } diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift index 43e2f1b2aa..012bed15bc 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift @@ -29,7 +29,9 @@ enum RoomDetailsScreenCoordinatorAction { case presentRolesAndPermissionsScreen case presentCall case presentPinnedEventsTimeline + case presentMediaEventsTimeline case presentKnockingRequestsListScreen + case presentSecurityAndPrivacyScreen } final class RoomDetailsScreenCoordinator: CoordinatorProtocol { @@ -80,8 +82,12 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol { actionsSubject.send(.presentCall) case .displayPinnedEventsTimeline: actionsSubject.send(.presentPinnedEventsTimeline) + case .displayMediaEventsTimeline: + actionsSubject.send(.presentMediaEventsTimeline) case .displayKnockingRequests: actionsSubject.send(.presentKnockingRequestsListScreen) + case .displaySecurityAndPrivacy: + actionsSubject.send(.presentSecurityAndPrivacyScreen) } } .store(in: &cancellables) diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift index cfd247cdc3..e8875dc426 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift @@ -22,7 +22,9 @@ enum RoomDetailsScreenViewModelAction { case requestRolesAndPermissionsPresentation case startCall case displayPinnedEventsTimeline + case displayMediaEventsTimeline case displayKnockingRequests + case displaySecurityAndPrivacy } // MARK: View @@ -48,13 +50,19 @@ struct RoomDetailsScreenViewState: BindableState { var notificationSettingsState: RoomDetailsNotificationSettingsState = .loading var canJoinCall = false var pinnedEventsActionState = RoomDetailsScreenPinnedEventsActionState.loading + var knockingEnabled = false var isKnockableRoom = false + var knockRequestsCount = 0 var canSeeKnockingRequests: Bool { knockingEnabled && dmRecipient == nil && isKnockableRoom && (canInviteUsers || canKickUsers || canBanUsers) } + var canSeeSecurityAndPrivacy: Bool { + knockingEnabled && dmRecipient == nil && canEditRolesOrPermissions + } + var canEdit: Bool { !isDirect && (canEditRoomName || canEditRoomTopic || canEditRoomAvatar) } @@ -195,8 +203,10 @@ enum RoomDetailsScreenViewAction { case processTapPolls case toggleFavourite(isFavourite: Bool) case processTapRolesAndPermissions + case processTapSecurityAndPrivacy case processTapCall case processTapPinnedEvents + case processTapMediaEvents case processTapRequestsToJoin } diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift index a7a8cbd856..2266a2fcec 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift @@ -125,11 +125,11 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr actionsSubject.send(.requestInvitePeoplePresentation) case .processTapLeave: guard state.joinedMembersCount > 1 else { - state.bindings.leaveRoomAlertItem = LeaveRoomAlertItem(roomID: roomProxy.id, isDM: roomProxy.isEncryptedOneToOneRoom, state: .empty) + state.bindings.leaveRoomAlertItem = LeaveRoomAlertItem(roomID: roomProxy.id, isDM: roomProxy.isDirectOneToOneRoom, state: .empty) return } state.bindings.leaveRoomAlertItem = LeaveRoomAlertItem(roomID: roomProxy.id, - isDM: roomProxy.isEncryptedOneToOneRoom, + isDM: roomProxy.isDirectOneToOneRoom, state: roomProxy.infoPublisher.value.isPublic ? .public : .private) case .confirmLeave: Task { await leaveRoom() } @@ -164,8 +164,12 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr case .processTapPinnedEvents: analyticsService.trackInteraction(name: .PinnedMessageRoomInfoButton) actionsSubject.send(.displayPinnedEventsTimeline) + case .processTapMediaEvents: + actionsSubject.send(.displayMediaEventsTimeline) case .processTapRequestsToJoin: actionsSubject.send(.displayKnockingRequests) + case .processTapSecurityAndPrivacy: + actionsSubject.send(.displaySecurityAndPrivacy) } } @@ -179,6 +183,18 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr Task { await self?.updatePowerLevelPermissions() } } .store(in: &cancellables) + + roomProxy.knockRequestsStatePublisher + .map { requestsState in + guard case let .loaded(requests) = requestsState else { + return 0 + } + return requests.count + } + .removeDuplicates() + .throttle(for: .milliseconds(100), scheduler: DispatchQueue.main, latest: true) + .weakAssign(to: \.state.knockRequestsCount, on: self) + .store(in: &cancellables) } private func updateRoomInfo(_ roomInfo: RoomInfoProxy) { @@ -199,7 +215,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr private func fetchMembersIfNeeded() async { // We need to fetch members just in 1-to-1 chat to get the member object for the other person - guard roomProxy.isEncryptedOneToOneRoom else { + guard roomProxy.isDirectOneToOneRoom else { return } @@ -207,8 +223,8 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr .receive(on: DispatchQueue.main) .sink { [weak self, ownUserID = roomProxy.ownUserID] members in guard let self else { return } - let accountOwner = members.first(where: { $0.userID == ownUserID }) - let dmRecipient = members.first(where: { $0.userID != ownUserID }) + let accountOwner = members.first { $0.userID == ownUserID } + let dmRecipient = members.first { $0.userID != ownUserID } self.dmRecipient = dmRecipient self.state.dmRecipient = dmRecipient.map(RoomMemberDetails.init(withProxy:)) self.state.accountOwner = accountOwner.map(RoomMemberDetails.init(withProxy:)) diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift index 6a8613d167..d68b6910aa 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -26,6 +26,10 @@ struct RoomDetailsScreen: View { topicSection configurationSection + + if context.viewState.dmRecipient == nil { + peopleSection + } aboutSection @@ -151,39 +155,25 @@ struct RoomDetailsScreen: View { private var aboutSection: some View { Section { - if context.viewState.dmRecipient == nil { - ListRow(label: .default(title: L10n.commonPeople, - icon: \.user), - details: .title(String(context.viewState.joinedMembersCount)), - kind: .navigationLink { - context.send(viewAction: .processTapPeople) - }) - .accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.people) - } - ListRow(label: .default(title: L10n.screenRoomDetailsPinnedEventsRowTitle, icon: \.pin), details: context.viewState.pinnedEventsActionState.isLoading ? .isWaiting(true) : .title(context.viewState.pinnedEventsActionState.count), - kind: context.viewState.pinnedEventsActionState.isLoading ? .label : .navigationLink(action: { + kind: context.viewState.pinnedEventsActionState.isLoading ? .label : .navigationLink { context.send(viewAction: .processTapPinnedEvents) - })) + }) .disabled(context.viewState.pinnedEventsActionState.isLoading) - if context.viewState.canSeeKnockingRequests { - ListRow(label: .default(title: L10n.screenRoomDetailsRequestsToJoinTitle, - icon: \.askToJoin), - // TODO: Display count if requests > 0 when an API for them is available - details: .counter(1), - kind: .navigationLink { - context.send(viewAction: .processTapRequestsToJoin) - }) - } ListRow(label: .default(title: L10n.screenPollsHistoryTitle, icon: \.polls), kind: .navigationLink { context.send(viewAction: .processTapPolls) }) .accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.pollsHistory) + + ListRow(label: .default(title: L10n.screenMediaBrowserTitle, icon: \.image), + kind: .navigationLink { + context.send(viewAction: .processTapMediaEvents) + }) } } @@ -207,6 +197,35 @@ struct RoomDetailsScreen: View { context.send(viewAction: .toggleFavourite(isFavourite: newValue)) } + if context.viewState.canSeeSecurityAndPrivacy { + ListRow(label: .default(title: L10n.screenRoomDetailsSecurityAndPrivacyTitle, + icon: \.lock), + kind: .navigationLink { + context.send(viewAction: .processTapSecurityAndPrivacy) + }) + } + } + } + + private var peopleSection: some View { + Section { + ListRow(label: .default(title: L10n.commonPeople, + icon: \.user), + details: .title(String(context.viewState.joinedMembersCount)), + kind: .navigationLink { + context.send(viewAction: .processTapPeople) + }) + .accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.people) + + if context.viewState.canSeeKnockingRequests { + ListRow(label: .default(title: L10n.screenRoomDetailsRequestsToJoinTitle, + icon: \.askToJoin), + details: context.viewState.knockRequestsCount > 0 ? .counter(context.viewState.knockRequestsCount) : nil, + kind: .navigationLink { + context.send(viewAction: .processTapRequestsToJoin) + }) + } + if context.viewState.canEditRolesOrPermissions, context.viewState.dmRecipient == nil { ListRow(label: .default(title: L10n.screenRoomDetailsRolesAndPermissions, icon: \.admin), @@ -215,7 +234,6 @@ struct RoomDetailsScreen: View { }) } } - .disabled(context.viewState.notificationSettingsState.isLoading) } private var toggleMuteButton: some View { @@ -305,6 +323,7 @@ struct RoomDetailsScreen: View { struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { static let genericRoomViewModel = { ServiceLocator.shared.settings.knockingEnabled = true + let knockRequests: [KnockRequestProxyMock] = [.init()] let members: [RoomMemberProxyMock] = [ .mockMeAdmin, .mockAlice, @@ -325,6 +344,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { isEncrypted: true, canonicalAlias: "#alias:domain.com", members: members, + knockRequestsState: .loaded(knockRequests), joinRule: .knock)) var notificationSettingsProxyMockConfiguration = NotificationSettingsProxyMockConfiguration() @@ -369,6 +389,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { }() static let simpleRoomViewModel = { + let knockRequests: [KnockRequestProxyMock] = [.init()] ServiceLocator.shared.settings.knockingEnabled = true let members: [RoomMemberProxyMock] = [ .mockMeAdmin, @@ -381,6 +402,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { isDirect: false, isEncrypted: false, members: members, + knockRequestsState: .loaded(knockRequests), joinRule: .knock)) let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init()) diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift index c075c5618f..490d3a7ae6 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift @@ -46,8 +46,7 @@ struct RoomMemberDetailsScreen: View { AvatarHeaderView(user: UserProfileProxy(userID: context.viewState.userID), isVerified: context.viewState.showVerifiedBadge, avatarSize: .user(on: .memberDetails), - mediaProvider: context.mediaProvider, - footer: { }) + mediaProvider: context.mediaProvider) { } } } diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift index 2322ad4047..d129a6abd3 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift @@ -91,13 +91,13 @@ struct RoomMembersListMemberCell_Previews: PreviewProvider, TestablePreview { .mockAdmin, .mockModerator, .init(with: .init(userID: "@nodisplayname:matrix.org", membership: .join)), - .init(with: .init(userID: "@avatar:matrix.org", displayName: "Avatar", avatarURL: .mockMXCAvatar, membership: .join)) + .init(with: .init(userID: "@avatar:matrix.org", displayName: "Avatar", avatarURL: .mockMXCUserAvatar, membership: .join)) ] static let bannedMembers: [RoomMemberProxyMock] = [ .init(with: .init(userID: "@nodisplayname:matrix.org", membership: .ban)), .init(with: .init(userID: "@fake:matrix.org", displayName: "President", membership: .ban)), - .init(with: .init(userID: "@badavatar:matrix.org", avatarURL: .mockMXCAvatar, membership: .ban)) + .init(with: .init(userID: "@badavatar:matrix.org", avatarURL: .mockMXCUserAvatar, membership: .ban)) ] static let viewModel = RoomMembersListScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Some room", diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionService.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionService.swift index a084736de8..72a835b6cb 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionService.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/CompletionSuggestionService.swift @@ -46,7 +46,7 @@ final class CompletionSuggestionService: CompletionSuggestionServiceProtocol { } if self.canMentionAllUsers, - !self.roomProxy.isEncryptedOneToOneRoom, + !self.roomProxy.isDirectOneToOneRoom, Self.shouldIncludeMember(userID: PillConstants.atRoom, displayName: PillConstants.everyone, searchText: suggestionTrigger.text) { membersSuggestion .insert(SuggestionItem.allUsers(item: .init(id: PillConstants.atRoom, diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift index c8e77830c2..0dda2a5271 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift @@ -586,14 +586,14 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool private func makeCreateWithTextAlertInfo(urlBinding: Binding, textBinding: Binding) -> AlertInfo { AlertInfo(id: UUID(), title: L10n.richTextEditorCreateLink, - primaryButton: AlertInfo.AlertButton(title: L10n.actionCancel, action: { + primaryButton: AlertInfo.AlertButton(title: L10n.actionCancel) { self.restoreComposerSelectedRange() - }), - secondaryButton: AlertInfo.AlertButton(title: L10n.actionSave, action: { + }, + secondaryButton: AlertInfo.AlertButton(title: L10n.actionSave) { self.restoreComposerSelectedRange() self.createLinkWithText() - }), + }, textFields: [AlertInfo.AlertTextField(placeholder: L10n.commonText, text: textBinding, autoCapitalization: .never, @@ -607,14 +607,14 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool private func makeSetUrlAlertInfo(urlBinding: Binding, isEdit: Bool) -> AlertInfo { AlertInfo(id: UUID(), title: isEdit ? L10n.richTextEditorEditLink : L10n.richTextEditorCreateLink, - primaryButton: AlertInfo.AlertButton(title: L10n.actionCancel, action: { + primaryButton: AlertInfo.AlertButton(title: L10n.actionCancel) { self.restoreComposerSelectedRange() - }), - secondaryButton: AlertInfo.AlertButton(title: L10n.actionSave, action: { + }, + secondaryButton: AlertInfo.AlertButton(title: L10n.actionSave) { self.restoreComposerSelectedRange() self.setLink() - }), + }, textFields: [AlertInfo.AlertTextField(placeholder: L10n.richTextEditorUrlPlaceholder, text: urlBinding, autoCapitalization: .never, @@ -624,16 +624,16 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool private func makeEditChoiceAlertInfo(urlBinding: Binding) -> AlertInfo { AlertInfo(id: UUID(), title: L10n.richTextEditorEditLink, - primaryButton: AlertInfo.AlertButton(title: L10n.actionRemove, role: .destructive, action: { + primaryButton: AlertInfo.AlertButton(title: L10n.actionRemove, role: .destructive) { self.restoreComposerSelectedRange() self.removeLinks() - }), - verticalButtons: [AlertInfo.AlertButton(title: L10n.actionEdit, action: { + }, + verticalButtons: [AlertInfo.AlertButton(title: L10n.actionEdit) { self.state.bindings.alertInfo = nil DispatchQueue.main.async { self.state.bindings.alertInfo = self.makeSetUrlAlertInfo(urlBinding: urlBinding, isEdit: true) } - })]) + }]) } private func restoreComposerSelectedRange() { diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/CompletionSuggestionView.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/CompletionSuggestionView.swift index 2599f522d1..98e85f98db 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/CompletionSuggestionView.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/CompletionSuggestionView.swift @@ -118,7 +118,7 @@ struct CompletionSuggestion_Previews: PreviewProvider, TestablePreview { VStack(spacing: 8) { CompletionSuggestionView(mediaProvider: MediaProviderMock(configuration: .init()), items: [.user(item: MentionSuggestionItem(id: "@user_mention_1:matrix.org", displayName: "User 1", avatarURL: nil, range: .init())), - .user(item: MentionSuggestionItem(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: .mockMXCAvatar, range: .init()))]) { _ in } + .user(item: MentionSuggestionItem(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: .mockMXCUserAvatar, range: .init()))]) { _ in } } VStack(spacing: 8) { CompletionSuggestionView(mediaProvider: MediaProviderMock(configuration: .init()), diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift index dc87b4c31d..92e9d02178 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift @@ -304,7 +304,7 @@ struct ComposerToolbar_Previews: PreviewProvider, TestablePreview { analyticsService: ServiceLocator.shared.analytics, composerDraftService: ComposerDraftServiceMock()) static let suggestions: [SuggestionItem] = [.user(item: MentionSuggestionItem(id: "@user_mention_1:matrix.org", displayName: "User 1", avatarURL: nil, range: .init())), - .user(item: MentionSuggestionItem(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: .mockMXCAvatar, range: .init()))] + .user(item: MentionSuggestionItem(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: .mockMXCUserAvatar, range: .init()))] static var previews: some View { ComposerToolbar.mock(focused: true) diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MentionSuggestionItemView.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MentionSuggestionItemView.swift index cc4bef92be..03fddcd94e 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MentionSuggestionItemView.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MentionSuggestionItemView.swift @@ -41,7 +41,7 @@ struct MentionSuggestionItemView_Previews: PreviewProvider, TestablePreview { static let mockMediaProvider = MediaProviderMock(configuration: .init()) static var previews: some View { - MentionSuggestionItemView(mediaProvider: mockMediaProvider, item: .init(id: "test", displayName: "Test", avatarURL: .mockMXCAvatar, range: .init())) + MentionSuggestionItemView(mediaProvider: mockMediaProvider, item: .init(id: "test", displayName: "Test", avatarURL: .mockMXCUserAvatar, range: .init())) MentionSuggestionItemView(mediaProvider: mockMediaProvider, item: .init(id: "test2", displayName: nil, avatarURL: nil, range: .init())) } } diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift index 649321db83..6570e127ca 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift @@ -267,7 +267,7 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview { eventContent: .message(.video(.init(filename: "never.mov", caption: "Video: Through the never", videoInfo: .mockVideo, - thumbnailInfo: .mockThumbnail)))), + thumbnailInfo: .mockVideoThumbnail)))), .loading(eventID: "") ] diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift index e9b16fa378..366d51777b 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift @@ -8,7 +8,7 @@ import Foundation import OrderedCollections -enum RoomScreenViewModelAction { +enum RoomScreenViewModelAction: Equatable { case focusEvent(eventID: String) case displayPinnedEventsTimeline case displayRoomDetails @@ -23,7 +23,7 @@ enum RoomScreenViewAction { case displayRoomDetails case displayCall case footerViewAction(RoomScreenFooterViewAction) - case acceptKnock(userID: String) + case acceptKnock(eventID: String) case dismissKnockRequests case viewKnockRequests } @@ -48,11 +48,18 @@ struct RoomScreenViewState: BindableState { var canAcceptKnocks = false var canDeclineKnocks = false var canBan = false - // TODO: We still don't know how to get these, but these will be the non already seen knock requests of the room, for now we are using this as a mock for testing purposes - var unseenKnockRequests: [KnockRequestInfo] = [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: "Helloooo")] + var unseenKnockRequests: [KnockRequestInfo] = [] + var handledEventIDs: Set = [] + + var displayedKnockRequests: [KnockRequestInfo] { + unseenKnockRequests.filter { !handledEventIDs.contains($0.eventID) } + } var shouldSeeKnockRequests: Bool { - isKnockingEnabled && isKnockableRoom && !unseenKnockRequests.isEmpty && (canAcceptKnocks || canDeclineKnocks || canBan) + isKnockingEnabled && + isKnockableRoom && + !displayedKnockRequests.isEmpty && + (canAcceptKnocks || canDeclineKnocks || canBan) } var footerDetails: RoomScreenFooterViewDetails? diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift index c518a39e4a..93f9422f8d 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift @@ -103,12 +103,10 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol case .resolvePinViolation(let userID): Task { await resolveIdentityPinningViolation(userID) } } - case .acceptKnock(userID: let userID): - // TODO: API to accept a knock required - break + case .acceptKnock(let eventID): + Task { await acceptKnock(eventID: eventID) } case .dismissKnockRequests: - // TODO: API to mark knocks as seen required - break + Task { await markAllKnocksAsSeen() } case .viewKnockRequests: actionsSubject.send(.displayKnockRequests) } @@ -181,6 +179,31 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol state.shouldShowCallButton = ongoingCallRoomID != roomProxy.id } .store(in: &cancellables) + + roomProxy.knockRequestsStatePublisher + // We only care about unseen requests + .map { knockRequestsState in + guard case let .loaded(requests) = knockRequestsState else { + return [] + } + + return requests + .filter { !$0.isSeen } + .map(KnockRequestInfo.init) + } + // If the requests have the same event ids we can discard the output + .removeDuplicates { Set($0.map(\.eventID)) == Set($1.map(\.eventID)) } + .throttle(for: .milliseconds(100), scheduler: DispatchQueue.main, latest: true) + .weakAssign(to: \.state.unseenKnockRequests, on: self) + .store(in: &cancellables) + + NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification) + .sink { [weak self] _ in + Task { + await self?.roomProxy.timeline.retryDecryption() + } + } + .store(in: &cancellables) } private func processIdentityStatusChanges(_ changes: [IdentityStatusChange]) async { @@ -248,7 +271,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol state.pinnedEventsBannerState = .loading(numbersOfEvents: pinnedEventIDs.count) } - switch (roomProxy.isEncryptedOneToOneRoom, roomInfo.joinRule) { + switch (roomProxy.isDirectOneToOneRoom, roomInfo.joinRule) { case (false, .knock), (false, .knockRestricted): state.isKnockableRoom = true default: @@ -277,10 +300,49 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol } } } + + private func acceptKnock(eventID: String) async { + guard case let .loaded(requests) = roomProxy.knockRequestsStatePublisher.value, + let request = requests.first(where: { $0.eventID == eventID }) else { + return + } + + state.handledEventIDs.insert(eventID) + switch await request.accept() { + case .success: + break + case .failure: + userIndicatorController.submitIndicator(.init(id: Self.errorIndicatorIdentifier, type: .toast, title: L10n.errorUnknown)) + state.handledEventIDs.remove(eventID) + } + } + + private func markAllKnocksAsSeen() async { + guard case let .loaded(requests) = roomProxy.knockRequestsStatePublisher.value else { + return + } + state.handledEventIDs.formUnion(Set(requests.map(\.eventID))) + + let failedIDs = await withTaskGroup(of: (String, Result).self) { group in + for request in requests { + group.addTask { + await (request.eventID, request.markAsSeen()) + } + } + + var failedIDs = [String]() + for await result in group where result.1.isFailure { + failedIDs.append(result.0) + } + return failedIDs + } + state.handledEventIDs.subtract(failedIDs) + } // MARK: Loading indicators private static let loadingIndicatorIdentifier = "\(RoomScreenViewModel.self)-Loading" + private static let errorIndicatorIdentifier = "\(RoomScreenViewModel.self)-Error" private func showLoadingIndicator() { userIndicatorController.submitIndicator(.init(id: Self.loadingIndicatorIdentifier, type: .toast, title: L10n.commonLoading)) @@ -304,3 +366,13 @@ extension RoomScreenViewModel { userIndicatorController: ServiceLocator.shared.userIndicatorController) } } + +private extension KnockRequestInfo { + init(from proxy: KnockRequestProxyProtocol) { + self.init(displayName: proxy.displayName, + avatarURL: proxy.avatarURL, + userID: proxy.userID, + reason: proxy.reason, + eventID: proxy.eventID) + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift b/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift index ae33410794..b50f5a7129 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift @@ -8,11 +8,12 @@ import Compound import SwiftUI -struct KnockRequestInfo { +struct KnockRequestInfo: Equatable { let displayName: String? let avatarURL: URL? let userID: String let reason: String? + let eventID: String } struct KnockRequestsBannerView: View { @@ -25,7 +26,7 @@ struct KnockRequestsBannerView: View { var body: some View { mainContent .padding(16) - .background(.compound.bgCanvasDefault, in: RoundedRectangle(cornerRadius: 12)) + .background(.compound.bgCanvasDefaultLevel1, in: RoundedRectangle(cornerRadius: 12)) .compositingGroup() .shadow(color: Color(red: 0.11, green: 0.11, blue: 0.13).opacity(0.1), radius: 12, x: 0, y: 4) .padding(.horizontal, 16) @@ -102,10 +103,8 @@ private struct SingleKnockRequestBannerContent: View { Button(L10n.screenRoomSingleKnockRequestViewButtonTitle, action: onViewAll) .buttonStyle(.compound(.secondary, size: .medium)) if let onAccept { - Button(L10n.screenRoomSingleKnockRequestAcceptButtonTitle, action: { - onAccept(request.userID) - }) - .buttonStyle(.compound(.primary, size: .medium)) + Button(L10n.screenRoomSingleKnockRequestAcceptButtonTitle) { onAccept(request.eventID) } + .buttonStyle(.compound(.primary, size: .medium)) } } .padding(.top, request.reason == nil ? 0 : 2) @@ -123,7 +122,6 @@ private struct MultipleKnockRequestsBannerContent: View { requests .prefix(3) .map { .init(url: $0.avatarURL, name: $0.displayName, contentID: $0.userID) } - .reversed() } private var multipleKnockRequestsTitle: String { @@ -138,7 +136,7 @@ private struct MultipleKnockRequestsBannerContent: View { var body: some View { VStack(spacing: 14) { HStack(spacing: 10) { - StackedAvatarsView(overlap: 16, lineWidth: 2, shouldStackFromLast: true, avatars: avatars, avatarSize: .user(on: .knockingUsersBannerStack), mediaProvider: mediaProvider) + StackedAvatarsView(overlap: 16, lineWidth: 2, avatars: avatars, avatarSize: .user(on: .knockingUsersBannerStack), mediaProvider: mediaProvider) HStack(alignment: .top, spacing: 0) { Text(multipleKnockRequestsTitle) .lineLimit(2) @@ -166,37 +164,42 @@ private struct KnockRequestsBannerDismissButton: View { CompoundIcon(\.close, size: .medium, relativeTo: .compound.bodySMSemibold) .foregroundColor(.compound.iconTertiary) } - .alignmentGuide(.top, computeValue: { _ in + .alignmentGuide(.top) { _ in 3 - }) + } } } struct KnockRequestsBannerView_Previews: PreviewProvider, TestablePreview { - static let singleRequest: [KnockRequestInfo] = [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: nil)] + static let singleRequest: [KnockRequestInfo] = [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: nil, eventID: "1")] - static let singleRequestWithReason: [KnockRequestInfo] = [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: "Hey, I’d like to join this room because of xyz topic and I’d like to participate in the room.")] + static let singleRequestWithReason: [KnockRequestInfo] = [.init(displayName: "Alice", + avatarURL: nil, + userID: "@alice:matrix.org", + reason: "Hey, I’d like to join this room because of xyz topic and I’d like to participate in the room.", + eventID: "1")] - static let singleRequestNoDisplayName: [KnockRequestInfo] = [.init(displayName: nil, avatarURL: nil, userID: "@alice:matrix.org", reason: nil)] + static let singleRequestNoDisplayName: [KnockRequestInfo] = [.init(displayName: nil, avatarURL: nil, userID: "@alice:matrix.org", reason: nil, eventID: "1")] static let multipleRequests: [KnockRequestInfo] = [ - .init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: nil), - .init(displayName: "Bob", avatarURL: nil, userID: "@bob:matrix.org", reason: nil), - .init(displayName: "Charlie", avatarURL: nil, userID: "@charlie:matrix.org", reason: nil), - .init(displayName: "Dan", avatarURL: nil, userID: "@dan:matrix.org", reason: nil), - .init(displayName: "Test", avatarURL: nil, userID: "@dan:matrix.org", reason: nil) + .init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: nil, eventID: "1"), + .init(displayName: "Bob", avatarURL: nil, userID: "@bob:matrix.org", reason: nil, eventID: "2"), + .init(displayName: "Charlie", avatarURL: nil, userID: "@charlie:matrix.org", reason: nil, eventID: "3"), + .init(displayName: "Dan", avatarURL: nil, userID: "@dan:matrix.org", reason: nil, eventID: "4"), + .init(displayName: "Test", avatarURL: nil, userID: "@dan:matrix.org", reason: nil, eventID: "5") ] static var previews: some View { - KnockRequestsBannerView(requests: singleRequest, onDismiss: { }, onAccept: { _ in }, onViewAll: { }) + KnockRequestsBannerView(requests: singleRequest) { } onAccept: { _ in } onViewAll: { } .previewDisplayName("Single Request") + // swiftlint:disable:next trailing_closure KnockRequestsBannerView(requests: singleRequest, onDismiss: { }, onAccept: nil, onViewAll: { }) .previewDisplayName("Single Request, no accept action") - KnockRequestsBannerView(requests: singleRequestWithReason, onDismiss: { }, onAccept: { _ in }, onViewAll: { }) + KnockRequestsBannerView(requests: singleRequestWithReason) { } onAccept: { _ in } onViewAll: { } .previewDisplayName("Single Request with reason") - KnockRequestsBannerView(requests: singleRequestNoDisplayName, onDismiss: { }, onAccept: { _ in }, onViewAll: { }) + KnockRequestsBannerView(requests: singleRequestNoDisplayName) { } onAccept: { _ in } onViewAll: { } .previewDisplayName("Single Request, No Display Name") - KnockRequestsBannerView(requests: multipleRequests, onDismiss: { }, onAccept: { _ in }, onViewAll: { }) + KnockRequestsBannerView(requests: multipleRequests) { } onAccept: { _ in } onViewAll: { } .previewDisplayName("Multiple Requests") } } diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift index c6f1792259..932bf73818 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift @@ -75,8 +75,7 @@ struct RoomScreen: View { pinnedEventIDs: timelineContext.viewState.pinnedEventIDs, isDM: timelineContext.viewState.isEncryptedOneToOneRoom, isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled, - isCreateMediaCaptionsEnabled: timelineContext.viewState.isCreateMediaCaptionsEnabled, - isPinnedEventsTimeline: timelineContext.viewState.isPinnedEventsTimeline, + timelineKind: timelineContext.viewState.timelineKind, emojiProvider: timelineContext.viewState.emojiProvider) .makeActions() if let actions { @@ -113,7 +112,7 @@ struct RoomScreen: View { TimelineView() .id(timelineContext.viewState.roomID) .environmentObject(timelineContext) - .environment(\.focussedEventID, timelineContext.viewState.timelineViewState.focussedEvent?.eventID) + .environment(\.focussedEventID, timelineContext.viewState.timelineState.focussedEvent?.eventID) .overlay(alignment: .bottomTrailing) { scrollToBottomButton } @@ -136,7 +135,7 @@ struct RoomScreen: View { private var knockRequestsBanner: some View { Group { if roomContext.viewState.shouldSeeKnockRequests { - KnockRequestsBannerView(requests: roomContext.viewState.unseenKnockRequests, + KnockRequestsBannerView(requests: roomContext.viewState.displayedKnockRequests, onDismiss: dismissKnockRequestsBanner, onAccept: roomContext.viewState.canAcceptKnocks ? acceptKnockRequest : nil, onViewAll: onViewAllKnockRequests, @@ -152,8 +151,8 @@ struct RoomScreen: View { roomContext.send(viewAction: .dismissKnockRequests) } - private func acceptKnockRequest(userID: String) { - roomContext.send(viewAction: .acceptKnock(userID: userID)) + private func acceptKnockRequest(eventID: String) { + roomContext.send(viewAction: .acceptKnock(eventID: eventID)) } private func onViewAllKnockRequests() { @@ -183,7 +182,7 @@ struct RoomScreen: View { } private var isAtBottomAndLive: Bool { - timelineContext.isScrolledToBottom && timelineContext.viewState.timelineViewState.isLive + timelineContext.isScrolledToBottom && timelineContext.viewState.timelineState.isLive } @ViewBuilder diff --git a/ElementX/Sources/Screens/RoomScreen/View/SwipeRightAction.swift b/ElementX/Sources/Screens/RoomScreen/View/SwipeRightAction.swift index 78b444b83c..c2327cbd03 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/SwipeRightAction.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/SwipeRightAction.swift @@ -138,7 +138,8 @@ struct SwipeRightAction_Previews: PreviewProvider, TestablePreview { NavigationStack { ScrollView { VStack(alignment: .leading, spacing: 2) { - mockBubble("This is a message from somebody with a couple of lines of text.") + Text("This is a message from somebody with a couple of lines of text.") + .bubbleBackground() .swipeRightAction { Image(systemName: "flame") } shouldStartAction: { @@ -157,12 +158,5 @@ struct SwipeRightAction_Previews: PreviewProvider, TestablePreview { .presentationDetents([.medium]) } } - - func mockBubble(_ body: String) -> some View { - Text(body) - .padding(.horizontal, 12) - .padding(.vertical, 4) - .background(Color.compound._bgBubbleOutgoing, in: RoundedRectangle(cornerRadius: 12)) - } } } diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenCoordinator.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenCoordinator.swift new file mode 100644 index 0000000000..247414a655 --- /dev/null +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenCoordinator.swift @@ -0,0 +1,54 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import SwiftUI + +struct SecurityAndPrivacyScreenCoordinatorParameters { + let roomProxy: JoinedRoomProxyProtocol +} + +enum SecurityAndPrivacyScreenCoordinatorAction { + case done + + // Consider adding CustomStringConvertible conformance if the actions contain PII +} + +final class SecurityAndPrivacyScreenCoordinator: CoordinatorProtocol { + private let parameters: SecurityAndPrivacyScreenCoordinatorParameters + private let viewModel: SecurityAndPrivacyScreenViewModelProtocol + + private var cancellables = Set() + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(parameters: SecurityAndPrivacyScreenCoordinatorParameters) { + self.parameters = parameters + + viewModel = SecurityAndPrivacyScreenViewModel(roomProxy: parameters.roomProxy) + } + + func start() { + viewModel.actionsPublisher.sink { [weak self] action in + MXLog.info("Coordinator: received view model action: \(action)") + + guard let self else { return } + switch action { + case .done: + actionsSubject.send(.done) + } + } + .store(in: &cancellables) + } + + func toPresentable() -> AnyView { + AnyView(SecurityAndPrivacyScreen(context: viewModel.context)) + } +} diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift new file mode 100644 index 0000000000..c017871018 --- /dev/null +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift @@ -0,0 +1,54 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Foundation + +enum SecurityAndPrivacyScreenViewModelAction { + case done +} + +struct SecurityAndPrivacyScreenViewState: BindableState { + var bindings: SecurityAndPrivacyScreenViewStateBindings + + var currentSettings: SecurityAndPrivacySettings + + var hasChanges: Bool { + currentSettings != bindings.desiredSettings + } + + init(accessType: SecurityAndPrivacyRoomAccessType, + isEncryptionEnabled: Bool) { + let settings = SecurityAndPrivacySettings(accessType: accessType, isEncryptionEnabled: isEncryptionEnabled) + currentSettings = settings + bindings = SecurityAndPrivacyScreenViewStateBindings(desiredSettings: settings) + } +} + +struct SecurityAndPrivacyScreenViewStateBindings { + var desiredSettings: SecurityAndPrivacySettings + var alertInfo: AlertInfo? +} + +struct SecurityAndPrivacySettings: Equatable { + var accessType: SecurityAndPrivacyRoomAccessType + var isEncryptionEnabled: Bool +} + +enum SecurityAndPrivacyRoomAccessType { + case inviteOnly + case askToJoin + case anyone +} + +enum SecurityAndPrivacyAlertType { + case enableEncryption +} + +enum SecurityAndPrivacyScreenViewAction { + case save + case tryUpdatingEncryption(Bool) +} diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift new file mode 100644 index 0000000000..effae2043a --- /dev/null +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift @@ -0,0 +1,62 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import SwiftUI + +typealias SecurityAndPrivacyScreenViewModelType = StateStoreViewModel + +class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType, SecurityAndPrivacyScreenViewModelProtocol { + private let roomProxy: JoinedRoomProxyProtocol + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(roomProxy: JoinedRoomProxyProtocol) { + self.roomProxy = roomProxy + super.init(initialViewState: SecurityAndPrivacyScreenViewState(accessType: roomProxy.infoPublisher.value.roomAccessType, + isEncryptionEnabled: roomProxy.isEncrypted)) + } + + // MARK: - Public + + override func process(viewAction: SecurityAndPrivacyScreenViewAction) { + MXLog.info("View model: received view action: \(viewAction)") + + switch viewAction { + case .save: + actionsSubject.send(.done) + case .tryUpdatingEncryption(let updatedValue): + if updatedValue { + state.bindings.alertInfo = .init(id: .enableEncryption, + title: L10n.screenSecurityAndPrivacyEnableEncryptionAlertTitle, + message: L10n.screenSecurityAndPrivacyEnableEncryptionAlertDescription, + primaryButton: .init(title: L10n.screenSecurityAndPrivacyEnableEncryptionAlertConfirmButtonTitle) { [weak self] in + self?.state.bindings.desiredSettings.isEncryptionEnabled = true + }, + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) + } else { + state.bindings.desiredSettings.isEncryptionEnabled = false + } + } + } +} + +private extension RoomInfoProxy { + var roomAccessType: SecurityAndPrivacyRoomAccessType { + switch joinRule { + case .invite, .restricted: + return .inviteOnly + case .knock, .knockRestricted: + return .askToJoin + default: + return .anyone + } + } +} diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModelProtocol.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModelProtocol.swift new file mode 100644 index 0000000000..a7e41e348e --- /dev/null +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModelProtocol.swift @@ -0,0 +1,14 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine + +@MainActor +protocol SecurityAndPrivacyScreenViewModelProtocol { + var actionsPublisher: AnyPublisher { get } + var context: SecurityAndPrivacyScreenViewModelType.Context { get } +} diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift new file mode 100644 index 0000000000..47379e3c60 --- /dev/null +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift @@ -0,0 +1,87 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +struct SecurityAndPrivacyScreen: View { + @ObservedObject var context: SecurityAndPrivacyScreenViewModel.Context + + var body: some View { + Form { + roomAccessSection + encryptionSection + } + .compoundList() + .navigationBarTitleDisplayMode(.inline) + .navigationTitle(L10n.screenSecurityAndPrivacyTitle) + .toolbar { toolbar } + .alert(item: $context.alertInfo) + } + + private var roomAccessSection: some View { + Section { + ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomAccessInviteOnlyOptionTitle, + description: L10n.screenSecurityAndPrivacyRoomAccessInviteOnlyOptionDescription), + kind: .selection(isSelected: context.desiredSettings.accessType == .inviteOnly) { context.desiredSettings.accessType = .inviteOnly }) + ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyAskToJoinOptionTitle, + description: L10n.screenSecurityAndPrivacyAskToJoinOptionDescription), + kind: .selection(isSelected: context.desiredSettings.accessType == .askToJoin) { context.desiredSettings.accessType = .askToJoin }) + ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomAccessAnyoneOptionTitle, + description: L10n.screenSecurityAndPrivacyRoomAccessAnyoneOptionDescription), + kind: .selection(isSelected: context.desiredSettings.accessType == .anyone) { context.desiredSettings.accessType = .anyone }) + } header: { + Text(L10n.screenSecurityAndPrivacyRoomAccessSectionTitle) + .compoundListSectionHeader() + } + } + + @ViewBuilder + private var encryptionSection: some View { + let encryptionBinding = Binding(get: { + context.desiredSettings.isEncryptionEnabled + }, set: { newValue in + context.send(viewAction: .tryUpdatingEncryption(newValue)) + }) + + Section { + ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyEncryptionToggleTitle), + kind: .toggle(encryptionBinding)) + // We don't allow editing the encryption state if the current setting on the server is `enabled` + .disabled(context.viewState.currentSettings.isEncryptionEnabled) + } header: { + Text(L10n.screenSecurityAndPrivacyEncryptionSectionTitle) + .compoundListSectionHeader() + } footer: { + Text(L10n.screenSecurityAndPrivacyEncryptionSectionFooter) + .compoundListSectionFooter() + } + } + + @ToolbarContentBuilder + var toolbar: some ToolbarContent { + ToolbarItem(placement: .confirmationAction) { + Button(L10n.actionSave) { + context.send(viewAction: .save) + } + .disabled(!context.viewState.hasChanges) + } + } +} + +// MARK: - Previews + +// TODO: Add back TestablePreview, this is WIP so running preview tests for it is not necessary +struct SecurityAndPrivacyScreen_Previews: PreviewProvider { + static let inviteOnlyViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(joinRule: .invite))) + + static var previews: some View { + NavigationStack { + SecurityAndPrivacyScreen(context: inviteOnlyViewModel.context) + } + } +} diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift index d8a496c8f0..ab0d01705d 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift @@ -50,7 +50,7 @@ protocol DeveloperOptionsProtocol: AnyObject { var enableOnlySignedDeviceIsolationMode: Bool { get set } var elementCallBaseURLOverride: URL? { get set } var knockingEnabled: Bool { get set } - var createMediaCaptionsEnabled: Bool { get set } + var eventCacheEnabled: Bool { get set } } extension AppSettings: DeveloperOptionsProtocol { } diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift index de6909cc5f..67cca634c0 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift @@ -23,6 +23,15 @@ struct DeveloperOptionsScreen: View { LogLevelConfigurationView(logLevel: $context.logLevel) } + Section("General") { + Toggle(isOn: $context.eventCacheEnabled) { + Text("Event cache") + } + .onChange(of: context.eventCacheEnabled) { + context.send(viewAction: .clearCache) + } + } + Section { Picker("Discovery", selection: $context.slidingSyncDiscovery) { Text("Proxy only").tag(AppSettings.SlidingSyncDiscovery.proxy) @@ -49,14 +58,10 @@ struct DeveloperOptionsScreen: View { } } - Section("Timeline") { + Section("Room") { Toggle(isOn: $context.hideTimelineMedia) { Text("Hide image & video previews") } - - Toggle(isOn: $context.createMediaCaptionsEnabled) { - Text("Allow creation of media captions") - } } Section("Join rules") { diff --git a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModel.swift b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModel.swift index 934b383798..ee46ec9088 100644 --- a/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModel.swift +++ b/ElementX/Sources/Screens/Settings/NotificationSettingsEditScreen/NotificationSettingsEditScreenViewModel.swift @@ -123,7 +123,7 @@ class NotificationSettingsEditScreenViewModel: NotificationSettingsEditScreenVie guard !Task.isCancelled else { return } let filteredRoomsSummary = roomSummaryProvider.roomListPublisher.value.filter { summary in - roomsWithUserDefinedRules.contains(where: { summary.id == $0 }) + roomsWithUserDefinedRules.contains { summary.id == $0 } } var roomsWithUserDefinedMode: [NotificationSettingsEditScreenRoom] = [] @@ -142,7 +142,7 @@ class NotificationSettingsEditScreenViewModel: NotificationSettingsEditScreenVie } // Sort the room list - roomsWithUserDefinedMode.sort(by: { $0.name.localizedCompare($1.name) == .orderedAscending }) + roomsWithUserDefinedMode.sort { $0.name.localizedCompare($1.name) == .orderedAscending } state.roomsWithUserDefinedMode = roomsWithUserDefinedMode } diff --git a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift index 2e610569ca..3231c0769d 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift @@ -157,8 +157,6 @@ class TimelineInteractionHandler { let debugInfo = timelineController.debugInfo(for: eventTimelineItem.id) MXLog.info("Showing debug info for \(eventTimelineItem.id)") actionsSubject.send(.showDebugInfo(debugInfo)) - case .retryDecryption(let sessionID): - Task { await timelineController.retryDecryption(for: sessionID) } case .report: actionsSubject.send(.displayReportContent(itemID: itemID, senderID: eventTimelineItem.sender.id)) case .react: @@ -391,7 +389,6 @@ class TimelineInteractionHandler { // MARK: Audio Playback - // swiftlint:disable:next cyclomatic_complexity func playPauseAudio(for itemID: TimelineItemIdentifier) async { MXLog.info("Toggle play/pause audio for itemID \(itemID)") guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID) else { diff --git a/ElementX/Sources/Screens/Timeline/TimelineModels.swift b/ElementX/Sources/Screens/Timeline/TimelineModels.swift index 2108e635a0..b27f432aad 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineModels.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineModels.swift @@ -85,21 +85,20 @@ enum TimelineComposerAction { } struct TimelineViewState: BindableState { - let isPinnedEventsTimeline: Bool + let timelineKind: TimelineKind var roomID: String var members: [String: RoomMemberState] = [:] var typingMembers: [String] = [] var showLoading = false var showReadReceipts = false var isEncryptedOneToOneRoom = false - var timelineViewState: TimelineState // check the doc before changing this + var timelineState: TimelineState // check the doc before changing this var ownUserID: String var canCurrentUserRedactOthers = false var canCurrentUserRedactSelf = false var canCurrentUserPin = false var isViewSourceEnabled: Bool - var isCreateMediaCaptionsEnabled: Bool var hideTimelineMedia: Bool // The `pinnedEventIDs` are used only to determine if an item is already pinned or not. diff --git a/ElementX/Sources/Screens/Timeline/TimelineTableViewController.swift b/ElementX/Sources/Screens/Timeline/TimelineTableViewController.swift index 84fde96d3b..eeac0ba9c4 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineTableViewController.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineTableViewController.swift @@ -316,7 +316,7 @@ class TimelineTableViewController: UIViewController { var snapshot = NSDiffableDataSourceSnapshot() // We don't want to display the typing notification in this timeline - if !coordinator.context.viewState.isPinnedEventsTimeline { + if coordinator.context.viewState.timelineKind != .pinned { snapshot.appendSections([.typingIndicator]) snapshot.appendItems([TimelineUniqueId(id: TimelineTypingIndicatorCell.reuseIdentifier)]) } diff --git a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift index 3777feed1d..8c281b5187 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift @@ -75,13 +75,12 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { appSettings: appSettings, analyticsService: analyticsService) - super.init(initialViewState: TimelineViewState(isPinnedEventsTimeline: timelineController.timelineKind == .pinned, + super.init(initialViewState: TimelineViewState(timelineKind: timelineController.timelineKind, roomID: roomProxy.id, - isEncryptedOneToOneRoom: roomProxy.isEncryptedOneToOneRoom, - timelineViewState: TimelineState(focussedEvent: focussedEventID.map { .init(eventID: $0, appearance: .immediate) }), + isEncryptedOneToOneRoom: roomProxy.isDirectOneToOneRoom, + timelineState: TimelineState(focussedEvent: focussedEventID.map { .init(eventID: $0, appearance: .immediate) }), ownUserID: roomProxy.ownUserID, isViewSourceEnabled: appSettings.viewSourceEnabled, - isCreateMediaCaptionsEnabled: appSettings.createMediaCaptionsEnabled, hideTimelineMedia: appSettings.hideTimelineMedia, pinnedEventIDs: roomProxy.infoPublisher.value.pinnedEventIDs, bindings: .init(reactionsCollapsed: [:]), @@ -107,6 +106,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { return self.timelineInteractionHandler.audioPlayerState(for: itemID) } + state.timelineState.paginationState = timelineController.paginationState buildTimelineViews(timelineItems: timelineController.timelineItems) updateMembers(roomProxy.membersPublisher.value) @@ -174,7 +174,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { case .scrolledToFocussedItem: didScrollToFocussedItem() case .hasSwitchedTimeline: - Task { state.timelineViewState.isSwitchingTimelines = false } + Task { state.timelineState.isSwitchingTimelines = false } case let .hasScrolled(direction): actionsSubject.send(.hasScrolled(direction: direction)) case .setOpenURLAction(let action): @@ -215,8 +215,8 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { } func focusOnEvent(eventID: String) async { - if state.timelineViewState.hasLoadedItem(with: eventID) { - state.timelineViewState.focussedEvent = .init(eventID: eventID, appearance: .animated) + if state.timelineState.hasLoadedItem(with: eventID) { + state.timelineState.focussedEvent = .init(eventID: eventID, appearance: .animated) return } @@ -225,7 +225,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { switch await timelineController.focusOnEvent(eventID, timelineSize: Constants.detachedTimelineSize) { case .success: - state.timelineViewState.focussedEvent = .init(eventID: eventID, appearance: .immediate) + state.timelineState.focussedEvent = .init(eventID: eventID, appearance: .immediate) case .failure(let error): MXLog.error("Failed to focus on event \(eventID)") @@ -244,9 +244,9 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { } private func didScrollToFocussedItem() { - if var focussedEvent = state.timelineViewState.focussedEvent { + if var focussedEvent = state.timelineState.focussedEvent { focussedEvent.appearance = .hasAppeared - state.timelineViewState.focussedEvent = focussedEvent + state.timelineState.focussedEvent = focussedEvent hideFocusLoadingIndicator() } } @@ -362,16 +362,16 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { case .updatedTimelineItems(let updatedItems, let isSwitchingTimelines): buildTimelineViews(timelineItems: updatedItems, isSwitchingTimelines: isSwitchingTimelines) case .paginationState(let paginationState): - if state.timelineViewState.paginationState != paginationState { - state.timelineViewState.paginationState = paginationState + if state.timelineState.paginationState != paginationState { + state.timelineState.paginationState = paginationState } case .isLive(let isLive): - if state.timelineViewState.isLive != isLive { - state.timelineViewState.isLive = isLive + if state.timelineState.isLive != isLive { + state.timelineState.isLive = isLive // Remove the event highlight *only* when transitioning from non-live to live. - if isLive, state.timelineViewState.focussedEvent != nil { - state.timelineViewState.focussedEvent = nil + if isLive, state.timelineState.focussedEvent != nil { + state.timelineState.focussedEvent = nil } } } @@ -448,10 +448,6 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { .weakAssign(to: \.state.isViewSourceEnabled, on: self) .store(in: &cancellables) - appSettings.$createMediaCaptionsEnabled - .weakAssign(to: \.state.isCreateMediaCaptionsEnabled, on: self) - .store(in: &cancellables) - appSettings.$hideTimelineMedia .weakAssign(to: \.state.hideTimelineMedia, on: self) .store(in: &cancellables) @@ -516,7 +512,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { break } - if state.timelineViewState.paginationState.forward == .timelineEndReached { + if state.timelineState.paginationState.forward == .timelineEndReached { focusLive() } @@ -525,8 +521,8 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { } private func scrollToBottom() { - if state.timelineViewState.isLive { - state.timelineViewState.scrollToBottomPublisher.send(()) + if state.timelineState.isLive { + state.timelineState.scrollToBottomPublisher.send(()) } else { focusLive() } @@ -689,13 +685,13 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { } else { for (index, item) in itemGroup.enumerated() { if index == 0 { - timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.isPinnedEventsTimeline ? .single : .first), + timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.timelineKind == .pinned ? .single : .first), forKey: item.id.uniqueID) } else if index == itemGroup.count - 1 { - timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.isPinnedEventsTimeline ? .single : .last), + timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.timelineKind == .pinned ? .single : .last), forKey: item.id.uniqueID) } else { - timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.isPinnedEventsTimeline ? .single : .middle), + timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.timelineKind == .pinned ? .single : .middle), forKey: item.id.uniqueID) } } @@ -703,14 +699,14 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { } if isSwitchingTimelines { - state.timelineViewState.isSwitchingTimelines = true + state.timelineState.isSwitchingTimelines = true } - state.timelineViewState.itemsDictionary = timelineItemsDictionary + state.timelineState.itemsDictionary = timelineItemsDictionary } private func updateViewState(item: RoomTimelineItemProtocol, groupStyle: TimelineGroupStyle) -> RoomTimelineItemViewState { - if let timelineItemViewState = state.timelineViewState.itemsDictionary[item.id.uniqueID] { + if let timelineItemViewState = state.timelineState.itemsDictionary[item.id.uniqueID] { timelineItemViewState.groupStyle = groupStyle timelineItemViewState.type = .init(item: item) return timelineItemViewState @@ -744,7 +740,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { userIndicatorController.alertInfo = .init(id: .init(), title: L10n.screenRoomInviteAgainAlertTitle, message: L10n.screenRoomInviteAgainAlertMessage, - primaryButton: .init(title: L10n.actionInvite, action: { [weak self] in self?.inviteOtherDMUserBack() }), + primaryButton: .init(title: L10n.actionInvite) { [weak self] in self?.inviteOtherDMUserBack() }, secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) } @@ -830,14 +826,14 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { state.bindings.alertInfo = .init(id: type, title: L10n.dialogPermissionMicrophoneTitleIos(InfoPlistReader.main.bundleDisplayName), message: L10n.dialogPermissionMicrophoneDescriptionIos, - primaryButton: .init(title: L10n.commonSettings, action: { [weak self] in self?.appMediator.openAppSettings() }), + primaryButton: .init(title: L10n.commonSettings) { [weak self] in self?.appMediator.openAppSettings() }, secondaryButton: .init(title: L10n.actionNotNow, role: .cancel, action: nil)) case .pollEndConfirmation(let pollStartID): state.bindings.alertInfo = .init(id: type, title: L10n.actionEndPoll, message: L10n.commonPollEndConfirmation, primaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil), - secondaryButton: .init(title: L10n.actionOk, action: { self.timelineInteractionHandler.endPoll(pollStartID: pollStartID) })) + secondaryButton: .init(title: L10n.actionOk) { self.timelineInteractionHandler.endPoll(pollStartID: pollStartID) }) case .sendingFailed: state.bindings.alertInfo = .init(id: type, title: L10n.commonSendingFailed, @@ -867,29 +863,21 @@ private extension RoomInfoProxy { // MARK: - Mocks extension TimelineViewModel { - static let mock = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), - focussedEventID: nil, - timelineController: MockRoomTimelineController(), - mediaProvider: MediaProviderMock(configuration: .init()), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: ServiceLocator.shared.userIndicatorController, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics, - emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) - - static let pinnedEventsTimelineMock = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), - focussedEventID: nil, - timelineController: MockRoomTimelineController(timelineKind: .pinned), - mediaProvider: MediaProviderMock(configuration: .init()), - mediaPlayerProvider: MediaPlayerProviderMock(), - voiceMessageMediaManager: VoiceMessageMediaManagerMock(), - userIndicatorController: ServiceLocator.shared.userIndicatorController, - appMediator: AppMediatorMock.default, - appSettings: ServiceLocator.shared.settings, - analyticsService: ServiceLocator.shared.analytics, - emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) + static let mock = mock(timelineKind: .live) + + static func mock(timelineKind: TimelineKind = .live, timelineController: MockRoomTimelineController? = nil) -> TimelineViewModel { + TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), + focussedEventID: nil, + timelineController: timelineController ?? MockRoomTimelineController(timelineKind: timelineKind), + mediaProvider: MediaProviderMock(configuration: .init()), + mediaPlayerProvider: MediaPlayerProviderMock(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock(), + userIndicatorController: ServiceLocator.shared.userIndicatorController, + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics, + emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) + } } extension EnvironmentValues { diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift index 0dbfb0670e..4d595fb303 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift @@ -85,7 +85,7 @@ struct TimelineItemMenu: View { Spacer(minLength: 16.0) - Text(item.timestamp) + Text(item.timestamp.formattedTime()) .font(.compound.bodyXS) .foregroundColor(.compound.textSecondary) } @@ -345,8 +345,7 @@ struct TimelineItemMenu_Previews: PreviewProvider, TestablePreview { pinnedEventIDs: [], isDM: true, isViewSourceEnabled: true, - isCreateMediaCaptionsEnabled: true, - isPinnedEventsTimeline: false, + timelineKind: .live, emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) guard let actions = provider.makeActions() else { return nil } diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift index 3a0e88b792..6e6728d540 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift @@ -67,7 +67,6 @@ enum TimelineItemMenuAction: Identifiable, Hashable { case reply(isThread: Bool) case forward(itemID: TimelineItemIdentifier) case viewSource - case retryDecryption(sessionID: String) case report case react case toggleReaction(key: String) @@ -82,9 +81,9 @@ enum TimelineItemMenuAction: Identifiable, Hashable { var switchToDefaultComposer: Bool { switch self { case .reply, .edit, .addCaption, .editCaption, .editPoll: - return false + false default: - return true + true } } @@ -92,9 +91,9 @@ enum TimelineItemMenuAction: Identifiable, Hashable { var canAppearInFailedEcho: Bool { switch self { case .copy, .edit, .redact, .viewSource, .editPoll: - return true + true default: - return false + false } } @@ -102,9 +101,9 @@ enum TimelineItemMenuAction: Identifiable, Hashable { var canAppearInRedacted: Bool { switch self { case .viewSource, .unpin, .viewInRoomTimeline: - return true + true default: - return false + false } } @@ -112,18 +111,27 @@ enum TimelineItemMenuAction: Identifiable, Hashable { var isDestructive: Bool { switch self { case .redact, .report, .removeCaption: - return true + true default: - return false + false } } var canAppearInPinnedEventsTimeline: Bool { switch self { case .viewInRoomTimeline, .pin, .unpin, .forward: - return true + true default: - return false + false + } + } + + var canAppearInMediaDetails: Bool { + switch self { + case .viewInRoomTimeline, .redact: + true + default: + false } } @@ -155,8 +163,6 @@ enum TimelineItemMenuAction: Identifiable, Hashable { Label(L10n.actionRemoveMessage, icon: \.delete) case .viewSource: Label(L10n.actionViewSource, icon: \.code) - case .retryDecryption: - Label(L10n.actionRetryDecryption, systemImage: "arrow.down.message") case .report: Label(L10n.actionReportContent, icon: \.chatProblem) case .react: diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift index 4d624fb3f7..505d1ae45a 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift @@ -16,8 +16,7 @@ struct TimelineItemMenuActionProvider { let pinnedEventIDs: Set let isDM: Bool let isViewSourceEnabled: Bool - let isCreateMediaCaptionsEnabled: Bool - let isPinnedEventsTimeline: Bool + let timelineKind: TimelineKind let emojiProvider: EmojiProviderProtocol // swiftlint:disable:next cyclomatic_complexity @@ -38,6 +37,14 @@ struct TimelineItemMenuActionProvider { var actions: [TimelineItemMenuAction] = [] var secondaryActions: [TimelineItemMenuAction] = [] + + if timelineKind == .pinned || timelineKind == .media(.mediaFilesScreen) { + actions.append(.viewInRoomTimeline) + } + + if canRedactItem(item), let poll = item.pollIfAvailable, !poll.hasEnded, let eventID = item.id.eventID { + actions.append(.endPoll(pollStartID: eventID)) + } if item.canBeRepliedTo { if let messageItem = item as? EventBasedMessageTimelineItemProtocol { @@ -51,19 +58,11 @@ struct TimelineItemMenuActionProvider { actions.append(.forward(itemID: item.id)) } - if canCurrentUserPin, let eventID = item.id.eventID { - actions.append(pinnedEventIDs.contains(eventID) ? .unpin : .pin) - } - - if item.isRemoteMessage { - actions.append(.copyPermalink) - } - if item.isEditable { if item.supportsMediaCaption { if item.hasMediaCaption { actions.append(.editCaption) - } else if isCreateMediaCaptionsEnabled { + } else { actions.append(.addCaption) } } else if item is PollRoomTimelineItem { @@ -72,6 +71,14 @@ struct TimelineItemMenuActionProvider { actions.append(.edit) } } + + if item.isRemoteMessage { + actions.append(.copyPermalink) + } + + if canCurrentUserPin, let eventID = item.id.eventID { + actions.append(pinnedEventIDs.contains(eventID) ? .unpin : .pin) + } if item.isCopyable { actions.append(.copy) @@ -79,14 +86,10 @@ struct TimelineItemMenuActionProvider { actions.append(.copyCaption) } - if item.hasMediaCaption { + if item.isEditable, item.hasMediaCaption { actions.append(.removeCaption) } - if canRedactItem(item), let poll = item.pollIfAvailable, !poll.hasEnded, let eventID = item.id.eventID { - actions.append(.endPoll(pollStartID: eventID)) - } - if isViewSourceEnabled { actions.append(.viewSource) } @@ -99,10 +102,15 @@ struct TimelineItemMenuActionProvider { secondaryActions.append(.redact) } - if isPinnedEventsTimeline { - actions.insert(.viewInRoomTimeline, at: 0) + switch timelineKind { + case .pinned: actions = actions.filter(\.canAppearInPinnedEventsTimeline) secondaryActions = secondaryActions.filter(\.canAppearInPinnedEventsTimeline) + case .media: + actions = actions.filter(\.canAppearInMediaDetails) + secondaryActions = secondaryActions.filter(\.canAppearInMediaDetails) + case .live, .detached: + break // viewInRoomTimeline is the only non-room item and was added conditionally. } if item.hasFailedToSend { @@ -114,31 +122,22 @@ struct TimelineItemMenuActionProvider { actions = actions.filter(\.canAppearInRedacted) secondaryActions = secondaryActions.filter(\.canAppearInRedacted) } + + let isReactable = timelineKind == .live || timelineKind == .detached ? item.isReactable : false - return .init(isReactable: isPinnedEventsTimeline ? false : item.isReactable, - actions: actions, - secondaryActions: secondaryActions, - emojiProvider: emojiProvider) + return .init(isReactable: isReactable, actions: actions, secondaryActions: secondaryActions, emojiProvider: emojiProvider) } private func makeEncryptedItemActions(_ encryptedItem: EncryptedRoomTimelineItem) -> TimelineItemMenuActions? { var actions: [TimelineItemMenuAction] = [.copyPermalink] - var secondaryActions: [TimelineItemMenuAction] = [] - + if isViewSourceEnabled { actions.append(.viewSource) } - - switch encryptedItem.encryptionType { - case .megolmV1AesSha2(let sessionID, _): - secondaryActions.append(.retryDecryption(sessionID: sessionID)) - default: - break - } - + return .init(isReactable: false, actions: actions, - secondaryActions: secondaryActions, + secondaryActions: [], emojiProvider: emojiProvider) } diff --git a/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptCell.swift b/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptCell.swift index 4e6996e9c2..158739925c 100644 --- a/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptCell.swift +++ b/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptCell.swift @@ -69,7 +69,7 @@ struct ReadReceiptCell_Previews: PreviewProvider, TestablePreview { ReadReceiptCell(readReceipt: .init(userID: "@test:matrix.org", formattedTimestamp: "10:00"), memberState: .init(displayName: "Test", - avatarURL: .mockMXCAvatar), + avatarURL: .mockMXCUserAvatar), mediaProvider: MediaProviderMock(configuration: .init())) .previewDisplayName("With Image") ReadReceiptCell(readReceipt: .init(userID: "@test:matrix.org", diff --git a/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift b/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift index 48810a9023..e7a3812ebc 100644 --- a/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift @@ -277,7 +277,7 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview { eventContent: .message(.video(.init(filename: "video.mp4", caption: "Some video", videoInfo: .mockVideo, - thumbnailInfo: .mockThumbnail))))), + thumbnailInfo: .mockVideoThumbnail))))), TimelineReplyView(placement: .timeline, timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), eventID: "123", diff --git a/ElementX/Sources/Screens/Timeline/View/Style/LongPressWithFeedback.swift b/ElementX/Sources/Screens/Timeline/View/Style/LongPressWithFeedback.swift index 357960c313..1b2c207771 100644 --- a/ElementX/Sources/Screens/Timeline/View/Style/LongPressWithFeedback.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/LongPressWithFeedback.swift @@ -95,9 +95,7 @@ struct LongPressWithFeedback_Previews: PreviewProvider, TestablePreview { func mockBubble(_ body: String) -> some View { Text(body) - .padding(.horizontal, 12) - .padding(.vertical, 4) - .background(Color.compound._bgBubbleOutgoing, in: RoundedRectangle(cornerRadius: 12)) + .bubbleBackground() .contentShape(.contextMenuPreview, RoundedRectangle(cornerRadius: 12)) .onTapGesture { /* Fix long press gesture blocking the scroll view */ } } diff --git a/ElementX/Sources/Screens/Timeline/View/Style/SwipeToReplyView.swift b/ElementX/Sources/Screens/Timeline/View/Style/SwipeToReplyView.swift index 476ee8465f..12da71ea4a 100644 --- a/ElementX/Sources/Screens/Timeline/View/Style/SwipeToReplyView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/SwipeToReplyView.swift @@ -20,7 +20,7 @@ struct SwipeToReplyView: View { struct SwipeToReplyView_Previews: PreviewProvider, TestablePreview { static let timelineItem = TextRoomTimelineItem(id: .randomEvent, - timestamp: "", + timestamp: .mock, isOutgoing: true, isEditable: true, canBeRepliedTo: true, diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbleBackground.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbleBackground.swift new file mode 100644 index 0000000000..156f5864a3 --- /dev/null +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbleBackground.swift @@ -0,0 +1,59 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Compound +import SwiftUI + +extension View { + /// - Parameters: + /// - isOutgoing: rounds the corners according to the side it shows on, defaults to true + /// - insets: defaults to what we use for file timeline items, text uses custom values + /// - color: self explanatory, defaults to subtle secondary + func bubbleBackground(isOutgoing: Bool = true, + insets: EdgeInsets = .init(top: 8, leading: 12, bottom: 8, trailing: 12), + color: Color? = .compound.bgSubtleSecondary) -> some View { + modifier(TimelineItemBubbleBackgroundModifier(isOutgoing: isOutgoing, + insets: insets, + color: color)) + } +} + +private struct TimelineItemBubbleBackgroundModifier: ViewModifier { + @Environment(\.timelineGroupStyle) private var timelineGroupStyle + + let isOutgoing: Bool + let insets: EdgeInsets + var color: Color? + + func body(content: Content) -> some View { + content + .padding(insets) + .background(color) + .cornerRadius(12, corners: roundedCorners) + } + + private var roundedCorners: UIRectCorner { + switch timelineGroupStyle { + case .single: + return .allCorners + case .first: + if isOutgoing { + return [.topLeft, .topRight, .bottomLeft] + } else { + return [.topLeft, .topRight, .bottomRight] + } + case .middle: + return isOutgoing ? [.topLeft, .bottomLeft] : [.topRight, .bottomRight] + case .last: + if isOutgoing { + return [.topLeft, .bottomLeft, .bottomRight] + } else { + return [.topRight, .bottomLeft, .bottomRight] + } + } + } +} diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift index fcfd2160d8..cfe3626912 100644 --- a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift @@ -20,7 +20,7 @@ struct TimelineItemBubbledStylerView: View { private var isEncryptedOneToOneRoom: Bool { context.viewState.isEncryptedOneToOneRoom } private var isFocussed: Bool { focussedEventID != nil && timelineItem.id.eventID == focussedEventID } private var isPinned: Bool { - guard !context.viewState.isPinnedEventsTimeline, + guard context.viewState.timelineKind != .pinned, let eventID = timelineItem.id.eventID else { return false } @@ -110,7 +110,7 @@ struct TimelineItemBubbledStylerView: View { } // Do not display reactions in the pinned events timeline - if !context.viewState.isPinnedEventsTimeline, + if context.viewState.timelineKind != .pinned, !timelineItem.properties.reactions.isEmpty { TimelineReactionsView(context: context, itemID: timelineItem.id, @@ -149,8 +149,7 @@ struct TimelineItemBubbledStylerView: View { pinnedEventIDs: context.viewState.pinnedEventIDs, isDM: context.viewState.isEncryptedOneToOneRoom, isViewSourceEnabled: context.viewState.isViewSourceEnabled, - isCreateMediaCaptionsEnabled: context.viewState.isCreateMediaCaptionsEnabled, - isPinnedEventsTimeline: context.viewState.isPinnedEventsTimeline, + timelineKind: context.viewState.timelineKind, emojiProvider: context.viewState.emojiProvider) TimelineItemMacContextMenu(item: timelineItem, actionProvider: provider) { action in context.send(viewAction: .handleTimelineItemMenuAction(itemID: timelineItem.id, action: action)) @@ -163,9 +162,9 @@ struct TimelineItemBubbledStylerView: View { var messageBubble: some View { contentWithReply .timelineItemSendInfo(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus, context: context) - .bubbleStyle(insets: timelineItem.bubbleInsets, - color: timelineItem.bubbleBackgroundColor, - corners: roundedCorners) + .bubbleBackground(isOutgoing: timelineItem.isOutgoing, + insets: timelineItem.bubbleInsets, + color: timelineItem.bubbleBackgroundColor) } @ViewBuilder @@ -217,40 +216,11 @@ struct TimelineItemBubbledStylerView: View { timelineItem.isOutgoing ? .trailing : .leading } - private var roundedCorners: UIRectCorner { - switch timelineGroupStyle { - case .single: - return .allCorners - case .first: - if timelineItem.isOutgoing { - return [.topLeft, .topRight, .bottomLeft] - } else { - return [.topLeft, .topRight, .bottomRight] - } - case .middle: - return timelineItem.isOutgoing ? [.topLeft, .bottomLeft] : [.topRight, .bottomRight] - case .last: - if timelineItem.isOutgoing { - return [.topLeft, .bottomLeft, .bottomRight] - } else { - return [.topRight, .bottomLeft, .bottomRight] - } - } - } - private var shouldShowSenderDetails: Bool { timelineGroupStyle.shouldShowSenderDetails } } -private extension View { - func bubbleStyle(insets: EdgeInsets, color: Color? = nil, cornerRadius: CGFloat = 12, corners: UIRectCorner) -> some View { - padding(insets) - .background(color) - .cornerRadius(cornerRadius, corners: corners) - } -} - private extension EventBasedTimelineItemProtocol { var bubbleBackgroundColor: Color? { let defaultColor: Color = isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming @@ -374,25 +344,33 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview static var previews: some View { mockTimeline .previewDisplayName("Mock Timeline") + .previewLayout(.fixed(width: 390, height: 900)) + .padding(.bottom, 20) mockTimeline .environment(\.layoutDirection, .rightToLeft) .previewDisplayName("Mock Timeline RTL") + .previewLayout(.fixed(width: 390, height: 900)) + .padding(.bottom, 20) replies .previewDisplayName("Replies") threads .previewDisplayName("Thread decorator") .snapshotPreferences(delay: 1) + .previewLayout(.fixed(width: 390, height: 1700)) + .padding(.bottom, 20) encryptionAuthenticity .previewDisplayName("Encryption Indicators") pinned .previewDisplayName("Pinned messages") .snapshotPreferences(delay: 1) + .previewLayout(.fixed(width: 390, height: 1150)) + .padding(.bottom, 20) } static var mockTimeline: some View { ScrollView { VStack(alignment: .leading, spacing: 0) { - ForEach(viewModel.state.timelineViewState.itemViewStates) { viewState in + ForEach(viewModel.state.timelineState.itemViewStates) { viewState in RoomTimelineItemView(viewState: viewState) } } @@ -404,7 +382,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview static var replies: some View { VStack(spacing: 0) { RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .randomEvent, - timestamp: "10:42", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -417,7 +395,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview groupStyle: .single)) RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .randomEvent, - timestamp: "10:42", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -452,7 +430,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview static var encryptionAuthenticity: some View { VStack(spacing: 0) { RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .randomEvent, - timestamp: "10:42", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -463,7 +441,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview groupStyle: .single)) RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .randomEvent, - timestamp: "10:42", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -475,7 +453,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview groupStyle: .single)) RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .randomEvent, - timestamp: "10:42", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -486,7 +464,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview groupStyle: .first)) RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .randomEvent, - timestamp: "10:42", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -497,7 +475,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview groupStyle: .last)) ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -510,7 +488,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray)))) VoiceMessageRoomTimelineView(timelineItem: .init(id: .randomEvent, - timestamp: "10:42", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -539,7 +517,7 @@ private struct MockTimelineContent: View { var body: some View { RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: makeItemIdentifier(), - timestamp: "10:42", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -550,7 +528,7 @@ private struct MockTimelineContent: View { groupStyle: .single)) AudioRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(), - timestamp: "10:42", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -565,7 +543,7 @@ private struct MockTimelineContent: View { replyDetails: replyDetails)) FileRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(), - timestamp: "10:42", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -580,7 +558,7 @@ private struct MockTimelineContent: View { replyDetails: replyDetails)) ImageRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(), - timestamp: "10:42", + timestamp: .mock, isOutgoing: true, isEditable: true, canBeRepliedTo: true, @@ -592,7 +570,7 @@ private struct MockTimelineContent: View { replyDetails: replyDetails)) LocationRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(), - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -605,7 +583,7 @@ private struct MockTimelineContent: View { replyDetails: replyDetails)) LocationRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(), - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -616,7 +594,7 @@ private struct MockTimelineContent: View { replyDetails: replyDetails)) VoiceMessageRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(), - timestamp: "10:42", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineStyler.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineStyler.swift index f69da64db7..b4cad8f695 100644 --- a/ElementX/Sources/Screens/Timeline/View/Style/TimelineStyler.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineStyler.swift @@ -58,7 +58,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview { static let viewModel = TimelineViewModel.mock static let base = TextRoomTimelineItem(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -79,9 +79,9 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview { }() static let sendingLast: TextRoomTimelineItem = { - let id = viewModel.state.timelineViewState.uniqueIDs.last ?? .init(id: UUID().uuidString) + let id = viewModel.state.timelineState.uniqueIDs.last ?? .init(id: UUID().uuidString) var result = TextRoomTimelineItem(id: .event(uniqueID: id, eventOrTransactionID: .eventId(eventId: UUID().uuidString)), - timestamp: "Now", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -99,9 +99,9 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview { }() static let sentLast: TextRoomTimelineItem = { - let id = viewModel.state.timelineViewState.uniqueIDs.last ?? .init(id: UUID().uuidString) + let id = viewModel.state.timelineState.uniqueIDs.last ?? .init(id: UUID().uuidString) let result = TextRoomTimelineItem(id: .event(uniqueID: id, eventOrTransactionID: .eventId(eventId: UUID().uuidString)), - timestamp: "Now", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -112,7 +112,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview { }() static let ltrString = TextRoomTimelineItem(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -120,7 +120,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview { sender: .test, content: .init(body: "house!")) static let rtlString = TextRoomTimelineItem(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -128,7 +128,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview { sender: .test, content: .init(body: "באמת!")) static let ltrStringThatContainsRtl = TextRoomTimelineItem(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -137,7 +137,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview { content: .init(body: "house! -- באמת‏! -- house!")) static let rtlStringThatContainsLtr = TextRoomTimelineItem(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -146,7 +146,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview { content: .init(body: "באמת‏! -- house! -- באמת!")) static let ltrStringThatFinishesInRtl = TextRoomTimelineItem(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -155,7 +155,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview { content: .init(body: "house! -- באמת!")) static let rtlStringThatFinishesInLtr = TextRoomTimelineItem(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, diff --git a/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineItemStatusView.swift b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineItemStatusView.swift index 1729d149d6..1a5ed45a2a 100644 --- a/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineItemStatusView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineItemStatusView.swift @@ -14,7 +14,7 @@ struct TimelineItemStatusView: View { @EnvironmentObject private var context: TimelineViewModel.Context private var isLastOutgoingMessage: Bool { - timelineItem.isOutgoing && context.viewState.timelineViewState.uniqueIDs.last == timelineItem.id.uniqueID + timelineItem.isOutgoing && context.viewState.timelineState.uniqueIDs.last == timelineItem.id.uniqueID } var body: some View { @@ -23,7 +23,7 @@ struct TimelineItemStatusView: View { @ViewBuilder private var mainContent: some View { - if context.viewState.isPinnedEventsTimeline { + if context.viewState.timelineKind == .pinned { // Do not display any status when is a pinned events timeline EmptyView() } else if context.viewState.showReadReceipts, !timelineItem.properties.orderedReadReceipts.isEmpty { diff --git a/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineReadReceiptsView.swift b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineReadReceiptsView.swift index cb82e40ae5..261d584368 100644 --- a/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineReadReceiptsView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineReadReceiptsView.swift @@ -102,7 +102,7 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview { static func mockTimelineItem(with receipts: [ReadReceipt]) -> TextRoomTimelineItem { TextRoomTimelineItem(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift index dd0ef08829..2759361f35 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift @@ -9,18 +9,20 @@ import Foundation import SwiftUI struct AudioRoomTimelineView: View { + @Environment(\.timelineContext) private var context let timelineItem: AudioRoomTimelineItem var body: some View { TimelineStyler(timelineItem: timelineItem) { - MediaFileRoomTimelineContent(timelineItemID: timelineItem.id, - filename: timelineItem.content.filename, + MediaFileRoomTimelineContent(filename: timelineItem.content.filename, fileSize: timelineItem.content.fileSize, caption: timelineItem.content.caption, formattedCaption: timelineItem.content.formattedCaption, additionalWhitespaces: timelineItem.additionalWhitespaces(), - isAudioFile: true) - .accessibilityLabel(L10n.commonAudio) + isAudioFile: true) { + context?.send(viewAction: .mediaTapped(itemID: timelineItem.id)) + } + .accessibilityLabel(L10n.commonAudio) } } } @@ -42,7 +44,7 @@ struct AudioRoomTimelineView_Previews: PreviewProvider, TestablePreview { static func makeItem(filename: String, fileSize: UInt, caption: String? = nil) -> AudioRoomTimelineItem { .init(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallInviteRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallInviteRoomTimelineView.swift index 05d57448c8..633d605b8d 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallInviteRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallInviteRoomTimelineView.swift @@ -16,7 +16,7 @@ struct CallInviteRoomTimelineView: View { Label { Text(L10n.screenRoomTimelineLegacyCall) } icon: { - CompoundIcon(\.voiceCall, size: .medium, relativeTo: .compound.bodyMD) + CompoundIcon(\.voiceCallSolid, size: .medium, relativeTo: .compound.bodyMD) } .font(.compound.bodyMD) .foregroundColor(.compound.textSecondary) @@ -34,7 +34,7 @@ struct CallInviteRoomTimelineView_Previews: PreviewProvider, TestablePreview { static var body: some View { CallInviteRoomTimelineView(timelineItem: .init(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isEditable: false, canBeRepliedTo: false, sender: .init(id: "Bob"))) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallNotificationRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallNotificationRoomTimelineView.swift index e4a8c93b0a..4900cc5d65 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallNotificationRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallNotificationRoomTimelineView.swift @@ -39,7 +39,7 @@ struct CallNotificationRoomTimelineView: View { Spacer() - Text(timelineItem.timestamp) + Text(timelineItem.timestamp.formattedTime()) .font(.compound.bodyXS) .foregroundColor(.compound.textSecondary) } @@ -61,7 +61,7 @@ struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePrevi static var body: some View { CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isEditable: false, canBeRepliedTo: false, sender: .init(id: "Bob"))) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CollapsibleRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CollapsibleRoomTimelineView.swift index d7b85ce801..31dd6543f0 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CollapsibleRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CollapsibleRoomTimelineView.swift @@ -52,8 +52,8 @@ struct CollapsibleRoomTimelineView: View { struct CollapsibleRoomTimelineView_Previews: PreviewProvider, TestablePreview { static let item = CollapsibleTimelineItem(items: [ - SeparatorRoomTimelineItem(id: .virtual(uniqueID: .init(id: "First separator")), text: "This is a separator"), - SeparatorRoomTimelineItem(id: .virtual(uniqueID: .init(id: "Second separator")), text: "This is another separator") + SeparatorRoomTimelineItem(id: .virtual(uniqueID: .init(id: "First separator")), timestamp: .mock), + SeparatorRoomTimelineItem(id: .virtual(uniqueID: .init(id: "Second separator")), timestamp: .mock) ]) static var previews: some View { diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EmoteRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EmoteRoomTimelineView.swift index 3fd741ccd4..794285caf4 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EmoteRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EmoteRoomTimelineView.swift @@ -32,16 +32,16 @@ struct EmoteRoomTimelineView_Previews: PreviewProvider, TestablePreview { static var body: some View { VStack(alignment: .leading, spacing: 20.0) { EmoteRoomTimelineView(timelineItem: itemWith(text: "Short loin ground round tongue hamburger, fatback salami shoulder. Beef turkey sausage kielbasa strip steak. Alcatra capicola pig tail pancetta chislic.", - timestamp: "Now", + timestamp: .mock, senderId: "Bob")) EmoteRoomTimelineView(timelineItem: itemWith(text: "Some other text", - timestamp: "Later", + timestamp: .mock, senderId: "Anne")) } } - private static func itemWith(text: String, timestamp: String, senderId: String) -> EmoteRoomTimelineItem { + private static func itemWith(text: String, timestamp: Date, senderId: String) -> EmoteRoomTimelineItem { EmoteRoomTimelineItem(id: .randomEvent, timestamp: timestamp, isOutgoing: false, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EncryptedRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EncryptedRoomTimelineView.swift index ff43aedda4..6605726522 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EncryptedRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EncryptedRoomTimelineView.swift @@ -18,9 +18,12 @@ struct EncryptedRoomTimelineView: View { case .unknown: return \.time case .sentBeforeWeJoined, - .historicalMessage, + .historicalMessageAndBackupDisabled, + .historicalMessageAndDeviceIsUnverified, .verificationViolation, - .insecureDevice: + .insecureDevice, + .witheldBySender, + .withheldForUnverifiedOrInsecureDevice: return \.block } default: @@ -59,27 +62,27 @@ struct EncryptedRoomTimelineView_Previews: PreviewProvider, TestablePreview { static var body: some View { VStack(alignment: .leading, spacing: 20.0) { EncryptedRoomTimelineView(timelineItem: itemWith(text: L10n.commonWaitingForDecryptionKey, - timestamp: "Now", + timestamp: .mock, isOutgoing: false, senderId: "Bob")) EncryptedRoomTimelineView(timelineItem: itemWith(text: L10n.commonWaitingForDecryptionKey, - timestamp: "Later", + timestamp: .mock, isOutgoing: true, senderId: "Anne")) EncryptedRoomTimelineView(timelineItem: itemWith(text: "Some other text that is very long and will wrap onto multiple lines.", - timestamp: "Later", + timestamp: .mock, isOutgoing: true, senderId: "Anne")) - EncryptedRoomTimelineView(timelineItem: expectedItemWith(timestamp: "Now", + EncryptedRoomTimelineView(timelineItem: expectedItemWith(timestamp: .mock, isOutgoing: false, senderId: "Bob")) } } - private static func itemWith(text: String, timestamp: String, isOutgoing: Bool, senderId: String) -> EncryptedRoomTimelineItem { + private static func itemWith(text: String, timestamp: Date, isOutgoing: Bool, senderId: String) -> EncryptedRoomTimelineItem { EncryptedRoomTimelineItem(id: .randomEvent, body: text, encryptionType: .unknown, @@ -90,7 +93,7 @@ struct EncryptedRoomTimelineView_Previews: PreviewProvider, TestablePreview { sender: .init(id: senderId)) } - private static func expectedItemWith(timestamp: String, isOutgoing: Bool, senderId: String) -> EncryptedRoomTimelineItem { + private static func expectedItemWith(timestamp: Date, isOutgoing: Bool, senderId: String) -> EncryptedRoomTimelineItem { EncryptedRoomTimelineItem(id: .randomEvent, body: L10n.commonUnableToDecryptNoAccess, encryptionType: .megolmV1AesSha2(sessionID: "foo", cause: .sentBeforeWeJoined), diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift index 3bb13c6585..920c19b3b1 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift @@ -9,17 +9,19 @@ import Compound import SwiftUI struct FileRoomTimelineView: View { + @Environment(\.timelineContext) private var context let timelineItem: FileRoomTimelineItem var body: some View { TimelineStyler(timelineItem: timelineItem) { - MediaFileRoomTimelineContent(timelineItemID: timelineItem.id, - filename: timelineItem.content.filename, + MediaFileRoomTimelineContent(filename: timelineItem.content.filename, fileSize: timelineItem.content.fileSize, caption: timelineItem.content.caption, formattedCaption: timelineItem.content.formattedCaption, - additionalWhitespaces: timelineItem.additionalWhitespaces()) - .accessibilityLabel(L10n.commonFile) + additionalWhitespaces: timelineItem.additionalWhitespaces()) { + context?.send(viewAction: .mediaTapped(itemID: timelineItem.id)) + } + .accessibilityLabel(L10n.commonFile) } } } @@ -27,9 +29,6 @@ struct FileRoomTimelineView: View { // MARK: Content struct MediaFileRoomTimelineContent: View { - @Environment(\.timelineContext) private var context - - let timelineItemID: TimelineItemIdentifier let filename: String let fileSize: UInt? let caption: String? @@ -37,16 +36,22 @@ struct MediaFileRoomTimelineContent: View { let additionalWhitespaces: Int var isAudioFile = false - var icon: KeyPath { + var onMediaTap: (() -> Void)? + + private var icon: KeyPath { isAudioFile ? \.audio : \.attachment } var body: some View { VStack(alignment: .leading, spacing: 8) { - filePreview - .onTapGesture { - context?.send(viewAction: .mediaTapped(itemID: timelineItemID)) - } + if let onMediaTap { + filePreview + .onTapGesture { + onMediaTap() + } + } else { + filePreview + } if let formattedCaption { FormattedBodyText(attributedString: formattedCaption, @@ -112,7 +117,7 @@ struct FileRoomTimelineView_Previews: PreviewProvider, TestablePreview { caption: String? = nil, formattedCaption: AttributedString? = nil) -> FileRoomTimelineItem { .init(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FormattedBodyText.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FormattedBodyText.swift index 4790ee5ef6..565d74f690 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FormattedBodyText.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FormattedBodyText.swift @@ -189,18 +189,18 @@ struct FormattedBodyText_Previews: PreviewProvider, TestablePreview { ForEach(htmlStrings, id: \.self) { htmlString in if let attributedString = attributedStringBuilder.fromHTML(htmlString) { FormattedBodyText(attributedString: attributedString) - .previewBubble() + .bubbleBackground() } } FormattedBodyText(attributedString: AttributedString("Some plain text wrapped in an AttributedString.")) - .previewBubble() + .bubbleBackground() FormattedBodyText(text: "Some plain text that's not an attributed component.") - .previewBubble() + .bubbleBackground() FormattedBodyText(text: "Some plain text that's not an attributed component. This one is really long.") - .previewBubble() + .bubbleBackground() FormattedBodyText(text: "❤️", boostEmojiSize: true) - .previewBubble() + .bubbleBackground() } .padding() } @@ -208,19 +208,3 @@ struct FormattedBodyText_Previews: PreviewProvider, TestablePreview { .snapshotPreferences(delay: 0.25) } } - -private struct PreviewBubbleModifier: ViewModifier { - func body(content: Content) -> some View { - content - .padding(8) - .background(Color.compound._bgBubbleOutgoing) - .cornerRadius(12) - .environmentObject(TimelineViewModel.mock.context) - } -} - -private extension View { - func previewBubble() -> some View { - modifier(PreviewBubbleModifier()) - } -} diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift index 86ad073d08..0b82f0760e 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift @@ -74,61 +74,38 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview { static let viewModel = TimelineViewModel.mock static var previews: some View { - body - .environmentObject(viewModel.context) - .environment(\.timelineContext, viewModel.context) + ScrollView { + VStack(spacing: 20.0) { + ImageRoomTimelineView(timelineItem: makeTimelineItem()) + ImageRoomTimelineView(timelineItem: makeTimelineItem(isEdited: true)) + + // Blur hashed item? + + ImageRoomTimelineView(timelineItem: makeTimelineItem(caption: "This is a great image 😎")) + ImageRoomTimelineView(timelineItem: makeTimelineItem(caption: "This is a great image with a really long multiline caption.", + isEdited: true)) + } + } + .environmentObject(viewModel.context) + .environment(\.timelineContext, viewModel.context) + .previewLayout(.fixed(width: 390, height: 1200)) + .padding(.bottom, 20) } - static var body: some View { - VStack(spacing: 20.0) { - ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "image.jpg", - imageInfo: .mockImage, - thumbnailInfo: nil))) - - ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "other.png", - imageInfo: .mockImage, - thumbnailInfo: nil))) - - ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "Blurhashed.jpg", - imageInfo: .mockImage, - thumbnailInfo: nil, - blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW", - contentType: .gif))) - - ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "Blurhashed.jpg", - caption: "This is a great image 😎", - imageInfo: .mockImage, - thumbnailInfo: .mockThumbnail, - blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW", - contentType: .gif))) - } + private static func makeTimelineItem(caption: String? = nil, isEdited: Bool = false) -> ImageRoomTimelineItem { + ImageRoomTimelineItem(id: .randomEvent, + timestamp: .mock, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(filename: "image.jpg", + caption: caption, + imageInfo: .mockImage, + thumbnailInfo: .mockThumbnail, + blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW", + contentType: .jpeg), + properties: .init(isEdited: isEdited)) } } diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift index 6c6b70189f..fafe8006d0 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift @@ -91,7 +91,7 @@ struct LocationRoomTimelineView_Previews: PreviewProvider, TestablePreview { @ViewBuilder static var states: some View { LocationRoomTimelineView(timelineItem: .init(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -100,7 +100,7 @@ struct LocationRoomTimelineView_Previews: PreviewProvider, TestablePreview { content: .init(body: "Fallback geo uri description"))) LocationRoomTimelineView(timelineItem: .init(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -109,7 +109,7 @@ struct LocationRoomTimelineView_Previews: PreviewProvider, TestablePreview { content: .init(body: "Fallback geo uri description", geoURI: .init(latitude: 41.902782, longitude: 12.496366), description: "Location description description description description description description description description"))) LocationRoomTimelineView(timelineItem: .init(id: .randomEvent, - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/NoticeRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/NoticeRoomTimelineView.swift index 098d8b93cd..a1705c97e5 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/NoticeRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/NoticeRoomTimelineView.swift @@ -44,16 +44,16 @@ struct NoticeRoomTimelineView_Previews: PreviewProvider, TestablePreview { static var body: some View { VStack(alignment: .leading, spacing: 20.0) { NoticeRoomTimelineView(timelineItem: itemWith(text: "Short loin ground round tongue hamburger, fatback salami shoulder. Beef turkey sausage kielbasa strip steak. Alcatra capicola pig tail pancetta chislic.", - timestamp: "Now", + timestamp: .mock, senderId: "Bob")) NoticeRoomTimelineView(timelineItem: itemWith(text: "Some other text", - timestamp: "Later", + timestamp: .mock, senderId: "Anne")) } } - private static func itemWith(text: String, timestamp: String, senderId: String) -> NoticeRoomTimelineItem { + private static func itemWith(text: String, timestamp: Date, senderId: String) -> NoticeRoomTimelineItem { NoticeRoomTimelineItem(id: .randomEvent, timestamp: timestamp, isOutgoing: false, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/PollRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/PollRoomTimelineView.swift index 1f5a7d95d5..12aca1688b 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/PollRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/PollRoomTimelineView.swift @@ -12,7 +12,7 @@ struct PollRoomTimelineView: View { @EnvironmentObject private var context: TimelineViewModel.Context private var state: PollViewState { - if context.viewState.isPinnedEventsTimeline { + if context.viewState.timelineKind == .pinned { return .preview } else { return .full(isEditable: timelineItem.isEditable) @@ -51,7 +51,7 @@ struct PollRoomTimelineView: View { struct PollRoomTimelineView_Previews: PreviewProvider, TestablePreview { static let viewModel = TimelineViewModel.mock - static let pinnedEventsTimelineViewModel = TimelineViewModel.pinnedEventsTimelineMock + static let pinnedEventsTimelineViewModel = TimelineViewModel.mock(timelineKind: .pinned) static var previews: some View { PollRoomTimelineView(timelineItem: .mock(poll: .disclosed(), isOutgoing: false)) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ReadMarkerRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ReadMarkerRoomTimelineView.swift index 4314885116..8b6ceab4e9 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ReadMarkerRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ReadMarkerRoomTimelineView.swift @@ -33,9 +33,9 @@ struct ReadMarkerRoomTimelineView_Previews: PreviewProvider, TestablePreview { static var previews: some View { VStack(alignment: .leading, spacing: 0) { - RoomTimelineItemView(viewState: .init(type: .separator(.init(id: .virtual(uniqueID: .init(id: "Separator")), text: "Today")), groupStyle: .single)) + RoomTimelineItemView(viewState: .init(type: .separator(.init(id: .virtual(uniqueID: .init(id: "Separator")), timestamp: .mock)), groupStyle: .single)) RoomTimelineItemView(viewState: .init(type: .text(.init(id: .randomEvent, - timestamp: "", + timestamp: .mock, isOutgoing: true, isEditable: false, canBeRepliedTo: true, @@ -45,9 +45,9 @@ struct ReadMarkerRoomTimelineView_Previews: PreviewProvider, TestablePreview { ReadMarkerRoomTimelineView(timelineItem: item) - RoomTimelineItemView(viewState: .init(type: .separator(.init(id: .virtual(uniqueID: .init(id: "Separator")), text: "Today")), groupStyle: .single)) + RoomTimelineItemView(viewState: .init(type: .separator(.init(id: .virtual(uniqueID: .init(id: "Separator")), timestamp: .mock)), groupStyle: .single)) RoomTimelineItemView(viewState: .init(type: .text(.init(id: .randomEvent, - timestamp: "", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/RedactedRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/RedactedRoomTimelineView.swift index 81274a73f1..0b48d95256 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/RedactedRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/RedactedRoomTimelineView.swift @@ -26,13 +26,13 @@ struct RedactedRoomTimelineView_Previews: PreviewProvider, TestablePreview { static var previews: some View { VStack(alignment: .leading, spacing: 20.0) { RedactedRoomTimelineView(timelineItem: itemWith(text: L10n.commonMessageRemoved, - timestamp: "Later", + timestamp: .mock, senderId: "Anne")) } .environmentObject(viewModel.context) } - private static func itemWith(text: String, timestamp: String, senderId: String) -> RedactedRoomTimelineItem { + private static func itemWith(text: String, timestamp: Date, senderId: String) -> RedactedRoomTimelineItem { RedactedRoomTimelineItem(id: .randomEvent, body: text, timestamp: timestamp, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/SeparatorRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/SeparatorRoomTimelineView.swift index 88633b6904..5f41ed0c16 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/SeparatorRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/SeparatorRoomTimelineView.swift @@ -11,7 +11,7 @@ struct SeparatorRoomTimelineView: View { let timelineItem: SeparatorRoomTimelineItem var body: some View { - Text(timelineItem.text) + Text(timelineItem.timestamp.formatted(date: .complete, time: .omitted)) .font(.compound.bodySMSemibold) .foregroundColor(.compound.textPrimary) .frame(maxWidth: .infinity) @@ -24,7 +24,7 @@ struct SeparatorRoomTimelineView: View { struct SeparatorRoomTimelineView_Previews: PreviewProvider, TestablePreview { static var previews: some View { let item = SeparatorRoomTimelineItem(id: .virtual(uniqueID: .init(id: "Separator")), - text: "This is a separator") + timestamp: .mock) SeparatorRoomTimelineView(timelineItem: item) } } diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StateRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StateRoomTimelineView.swift index 636e89a513..38aeaca118 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StateRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StateRoomTimelineView.swift @@ -32,7 +32,7 @@ struct StateRoomTimelineView_Previews: PreviewProvider, TestablePreview { static let item = StateRoomTimelineItem(id: .randomVirtual, body: "Alice joined", - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift index 043d68834b..23565de405 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift @@ -41,25 +41,10 @@ struct StickerRoomTimelineView_Previews: PreviewProvider, TestablePreview { static let viewModel = TimelineViewModel.mock static var previews: some View { - body - .environmentObject(viewModel.context) - .environment(\.timelineContext, viewModel.context) - } - - static var body: some View { VStack(spacing: 20.0) { StickerRoomTimelineView(timelineItem: StickerRoomTimelineItem(id: .randomEvent, body: "Some image", - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - sender: .init(id: "Bob"), - imageInfo: .mockImage)) - - StickerRoomTimelineView(timelineItem: StickerRoomTimelineItem(id: .randomEvent, - body: "Some other image", - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -68,7 +53,7 @@ struct StickerRoomTimelineView_Previews: PreviewProvider, TestablePreview { StickerRoomTimelineView(timelineItem: StickerRoomTimelineItem(id: .randomEvent, body: "Blurhashed image", - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -76,5 +61,7 @@ struct StickerRoomTimelineView_Previews: PreviewProvider, TestablePreview { imageInfo: .mockImage, blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW")) } + .environmentObject(viewModel.context) + .environment(\.timelineContext, viewModel.context) } } diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TextRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TextRoomTimelineView.swift index ec853d579b..5d0dc45d1b 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TextRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/TextRoomTimelineView.swift @@ -42,44 +42,44 @@ struct TextRoomTimelineView_Previews: PreviewProvider, TestablePreview { ScrollView { VStack(alignment: .leading, spacing: 20.0) { TextRoomTimelineView(timelineItem: itemWith(text: "Short loin ground round tongue hamburger, fatback salami shoulder. Beef turkey sausage kielbasa strip steak. Alcatra capicola pig tail pancetta chislic.", - timestamp: "Now", + timestamp: .mock, isOutgoing: false, senderId: "Bob")) TextRoomTimelineView(timelineItem: itemWith(text: "Some other text", - timestamp: "Later", + timestamp: .mock, isOutgoing: true, senderId: "Anne")) TextRoomTimelineView(timelineItem: itemWith(text: "Short loin ground round tongue hamburger, fatback salami shoulder. Beef turkey sausage kielbasa strip steak. Alcatra capicola pig tail pancetta chislic.", - timestamp: "Now", + timestamp: .mock, isOutgoing: false, senderId: "Bob")) TextRoomTimelineView(timelineItem: itemWith(text: "Some other text", - timestamp: "Later", + timestamp: .mock, isOutgoing: true, senderId: "Anne")) TextRoomTimelineView(timelineItem: itemWith(text: "טקסט אחר", - timestamp: "Later", + timestamp: .mock, isOutgoing: true, senderId: "Anne")) TextRoomTimelineView(timelineItem: itemWith(html: "
  1. First item
  2. Second item
  3. Third item
", - timestamp: "Later", + timestamp: .mock, isOutgoing: true, senderId: "Anne")) TextRoomTimelineView(timelineItem: itemWith(html: "
  1. פריט ראשון
  2. הפריט השני
  3. פריט שלישי
", - timestamp: "Later", + timestamp: .mock, isOutgoing: true, senderId: "Anne")) } } } - private static func itemWith(text: String, timestamp: String, isOutgoing: Bool, senderId: String) -> TextRoomTimelineItem { + private static func itemWith(text: String, timestamp: Date, isOutgoing: Bool, senderId: String) -> TextRoomTimelineItem { TextRoomTimelineItem(id: .randomEvent, timestamp: timestamp, isOutgoing: isOutgoing, @@ -90,7 +90,7 @@ struct TextRoomTimelineView_Previews: PreviewProvider, TestablePreview { content: .init(body: text)) } - private static func itemWith(html: String, timestamp: String, isOutgoing: Bool, senderId: String) -> TextRoomTimelineItem { + private static func itemWith(html: String, timestamp: Date, isOutgoing: Bool, senderId: String) -> TextRoomTimelineItem { let builder = AttributedStringBuilder(cacheKey: "preview", mentionBuilder: MentionBuilder()) let attributedString = builder.fromHTML(html) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/UnsupportedRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/UnsupportedRoomTimelineView.swift index 2d26302ba5..0f50c0b6ab 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/UnsupportedRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/UnsupportedRoomTimelineView.swift @@ -40,18 +40,18 @@ struct UnsupportedRoomTimelineView_Previews: PreviewProvider, TestablePreview { static var body: some View { VStack(alignment: .leading, spacing: 20.0) { UnsupportedRoomTimelineView(timelineItem: itemWith(text: "Text", - timestamp: "Now", + timestamp: .mock, isOutgoing: false, senderId: "Bob")) UnsupportedRoomTimelineView(timelineItem: itemWith(text: "Some other text", - timestamp: "Later", + timestamp: .mock, isOutgoing: true, senderId: "Anne")) } } - private static func itemWith(text: String, timestamp: String, isOutgoing: Bool, senderId: String) -> UnsupportedRoomTimelineItem { + private static func itemWith(text: String, timestamp: Date, isOutgoing: Bool, senderId: String) -> UnsupportedRoomTimelineItem { UnsupportedRoomTimelineItem(id: .randomEvent, body: text, eventType: "Some Event Type", diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift index 88337eb78f..75306d9996 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift @@ -5,7 +5,7 @@ // Please see LICENSE in the repository root for full details. // -import Foundation +import Compound import SwiftUI struct VideoRoomTimelineView: View { @@ -78,56 +78,37 @@ struct VideoRoomTimelineView_Previews: PreviewProvider, TestablePreview { static let viewModel = TimelineViewModel.mock static var previews: some View { - body.environmentObject(viewModel.context) + ScrollView { + VStack(spacing: 20.0) { + VideoRoomTimelineView(timelineItem: makeTimelineItem()) + VideoRoomTimelineView(timelineItem: makeTimelineItem(isEdited: true)) + + // Blurhash item? + + VideoRoomTimelineView(timelineItem: makeTimelineItem(caption: "This is a great image 😎")) + VideoRoomTimelineView(timelineItem: makeTimelineItem(caption: "This is a great image with a really long multiline caption", + isEdited: true)) + } + } + .environmentObject(viewModel.context) + .environment(\.timelineContext, viewModel.context) + .previewLayout(.fixed(width: 390, height: 975)) + .padding(.bottom, 20) } - static var body: some View { - VStack(spacing: 20.0) { - VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "video.mp4", - videoInfo: .mockVideo, - thumbnailInfo: nil))) - - VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "other.mp4", - videoInfo: .mockVideo, - thumbnailInfo: nil))) - - VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "Blurhashed.mp4", - videoInfo: .mockVideo, - thumbnailInfo: nil, - blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW"))) - - VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "video.mp4", - caption: "This is a caption", - videoInfo: .mockVideo, - thumbnailInfo: nil))) - } + private static func makeTimelineItem(caption: String? = nil, isEdited: Bool = false) -> VideoRoomTimelineItem { + VideoRoomTimelineItem(id: .randomEvent, + timestamp: .mock, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "Bob"), + content: .init(filename: "video.mp4", + caption: caption, + videoInfo: .mockVideo, + thumbnailInfo: .mockVideoThumbnail, + blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW"), + properties: .init(isEdited: isEdited)) } } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VoiceMessageRoomTimelineView.swift similarity index 81% rename from ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift rename to ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VoiceMessageRoomTimelineView.swift index df55cf05df..6a8eb44a21 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VoiceMessageRoomTimelineView.swift @@ -9,26 +9,33 @@ import Foundation import SwiftUI struct VoiceMessageRoomTimelineView: View { - @Environment(\.timelineContext) private var context - private let timelineItem: VoiceMessageRoomTimelineItem - private let playerState: AudioPlayerState - @State private var resumePlaybackAfterScrubbing = false - - init(timelineItem: VoiceMessageRoomTimelineItem, playerState: AudioPlayerState) { - self.timelineItem = timelineItem - self.playerState = playerState - } + let timelineItem: VoiceMessageRoomTimelineItem + let playerState: AudioPlayerState var body: some View { TimelineStyler(timelineItem: timelineItem) { - VoiceMessageRoomPlaybackView(playerState: playerState, - onPlayPause: onPlaybackPlayPause, - onSeek: { onPlaybackSeek($0) }, - onScrubbing: { onPlaybackScrubbing($0) }) - .fixedSize(horizontal: false, vertical: true) + VoiceMessageRoomTimelineContent(timelineItem: timelineItem, + playerState: playerState) + .accessibilityLabel(L10n.commonVoiceMessage) .frame(maxWidth: 400) } } +} + +struct VoiceMessageRoomTimelineContent: View { + @Environment(\.timelineContext) private var context + @State private var resumePlaybackAfterScrubbing = false + + let timelineItem: VoiceMessageRoomTimelineItem + let playerState: AudioPlayerState + + var body: some View { + VoiceMessageRoomPlaybackView(playerState: playerState, + onPlayPause: onPlaybackPlayPause, + onSeek: { onPlaybackSeek($0) }, + onScrubbing: { onPlaybackScrubbing($0) }) + .fixedSize(horizontal: false, vertical: true) + } private func onPlaybackPlayPause() { context?.send(viewAction: .handleAudioPlayerAction(.playPause(itemID: timelineItem.id))) @@ -57,7 +64,7 @@ struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview { static let viewModel = TimelineViewModel.mock static let timelineItemIdentifier = TimelineItemIdentifier.randomEvent static let voiceRoomTimelineItem = VoiceMessageRoomTimelineItem(id: timelineItemIdentifier, - timestamp: "Now", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -78,7 +85,6 @@ struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview { static var previews: some View { body.environmentObject(viewModel.context) - .previewDisplayName("Bubble") } static var body: some View { diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineView.swift index 5315b57884..210e269d75 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineView.swift @@ -16,7 +16,7 @@ struct TimelineView: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> TimelineTableViewController { let tableViewController = TimelineTableViewController(coordinator: context.coordinator, isScrolledToBottom: $viewModelContext.isScrolledToBottom, - scrollToBottomPublisher: viewModelContext.viewState.timelineViewState.scrollToBottomPublisher) + scrollToBottomPublisher: viewModelContext.viewState.timelineState.scrollToBottomPublisher) // Needs to be dispatched on main asynchronously otherwise we get a runtime warning DispatchQueue.main.async { viewModelContext.send(viewAction: .setOpenURLAction(openURL)) @@ -44,21 +44,21 @@ struct TimelineView: UIViewControllerRepresentable { /// Updates the specified table view's properties from the current view state. func update(tableViewController: TimelineTableViewController) { - if tableViewController.isSwitchingTimelines != context.viewState.timelineViewState.isSwitchingTimelines { + if tableViewController.isSwitchingTimelines != context.viewState.timelineState.isSwitchingTimelines { // Must come before timelineItemsDictionary in order to disable animations. - tableViewController.isSwitchingTimelines = context.viewState.timelineViewState.isSwitchingTimelines + tableViewController.isSwitchingTimelines = context.viewState.timelineState.isSwitchingTimelines } - if tableViewController.timelineItemsDictionary != context.viewState.timelineViewState.itemsDictionary { - tableViewController.timelineItemsDictionary = context.viewState.timelineViewState.itemsDictionary + if tableViewController.timelineItemsDictionary != context.viewState.timelineState.itemsDictionary { + tableViewController.timelineItemsDictionary = context.viewState.timelineState.itemsDictionary } - if tableViewController.paginationState != context.viewState.timelineViewState.paginationState { - tableViewController.paginationState = context.viewState.timelineViewState.paginationState + if tableViewController.paginationState != context.viewState.timelineState.paginationState { + tableViewController.paginationState = context.viewState.timelineState.paginationState } - if tableViewController.isLive != context.viewState.timelineViewState.isLive { - tableViewController.isLive = context.viewState.timelineViewState.isLive + if tableViewController.isLive != context.viewState.timelineState.isLive { + tableViewController.isLive = context.viewState.timelineState.isLive } - if tableViewController.focussedEvent != context.viewState.timelineViewState.focussedEvent { - tableViewController.focussedEvent = context.viewState.timelineViewState.focussedEvent + if tableViewController.focussedEvent != context.viewState.timelineState.focussedEvent { + tableViewController.focussedEvent = context.viewState.timelineState.focussedEvent } if tableViewController.hideTimelineMedia != context.viewState.hideTimelineMedia { tableViewController.hideTimelineMedia = context.viewState.hideTimelineMedia diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomPlaybackView.swift b/ElementX/Sources/Screens/Timeline/View/VoiceMessageRoomPlaybackView.swift similarity index 96% rename from ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomPlaybackView.swift rename to ElementX/Sources/Screens/Timeline/View/VoiceMessageRoomPlaybackView.swift index 1928a55b4a..7756254709 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomPlaybackView.swift +++ b/ElementX/Sources/Screens/Timeline/View/VoiceMessageRoomPlaybackView.swift @@ -61,9 +61,10 @@ struct VoiceMessageRoomPlaybackView: View { if let url = playerState.fileURL { WaveformView(audioURL: url, configuration: .init(style: .striped(.init(color: .black, width: waveformLineWidth, spacing: waveformLinePadding)), - verticalScalingFactor: 1.0), - placeholder: { estimatedWaveformView }) - .progressMask(progress: playerState.progress) + verticalScalingFactor: 1.0)) { + estimatedWaveformView + } + .progressMask(progress: playerState.progress) } else { estimatedWaveformView } diff --git a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift index 7e90f0fdde..228bc3a4ef 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift @@ -43,8 +43,7 @@ struct UserProfileScreen: View { AvatarHeaderView(user: UserProfileProxy(userID: context.viewState.userID), isVerified: context.viewState.showVerifiedBadge, avatarSize: .user(on: .memberDetails), - mediaProvider: context.mediaProvider, - footer: { }) + mediaProvider: context.mediaProvider) { } } } diff --git a/ElementX/Sources/Services/Analytics/AnalyticsService.swift b/ElementX/Sources/Services/Analytics/AnalyticsService.swift index 3ecbed8054..a3dc13d932 100644 --- a/ElementX/Sources/Services/Analytics/AnalyticsService.swift +++ b/ElementX/Sources/Services/Analytics/AnalyticsService.swift @@ -122,19 +122,26 @@ extension AnalyticsService { /// - Parameter name: The name of the error /// - Parameter timeToDecryptMillis: The time it took to decrypt the event in milliseconds, needs to be used only to track UTD errors, otherwise if the error is nort related to UTD it should be nil. /// Can be found in `UnableToDecryptInfo`. In case the `UnableToDecryptInfo` contains the value as nil, pass it as `-1` - func trackError(context: String?, domain: AnalyticsEvent.Error.Domain, name: AnalyticsEvent.Error.Name, timeToDecryptMillis: Int? = nil) { + func trackError(context: String?, domain: AnalyticsEvent.Error.Domain, + name: AnalyticsEvent.Error.Name, + timeToDecryptMillis: Int? = nil, + eventLocalAgeMillis: Int? = nil, + isFederated: Bool? = nil, + isMatrixDotOrg: Bool? = nil, + userTrustsOwnIdentity: Bool? = nil, + wasVisibleToUser: Bool? = nil) { // CryptoModule is deprecated capture(event: AnalyticsEvent.Error(context: context, cryptoModule: .Rust, cryptoSDK: .Rust, domain: domain, - eventLocalAgeMillis: nil, - isFederated: nil, - isMatrixDotOrg: nil, + eventLocalAgeMillis: eventLocalAgeMillis, + isFederated: isFederated, + isMatrixDotOrg: isMatrixDotOrg, name: name, timeToDecryptMillis: timeToDecryptMillis, - userTrustsOwnIdentity: nil, - wasVisibleToUser: nil)) + userTrustsOwnIdentity: userTrustsOwnIdentity, + wasVisibleToUser: wasVisibleToUser)) } /// Track the creation of a room diff --git a/ElementX/Sources/Services/Authentication/AuthenticationClientBuilder.swift b/ElementX/Sources/Services/Authentication/AuthenticationClientBuilder.swift index 1c448eae92..0c87cdfb38 100644 --- a/ElementX/Sources/Services/Authentication/AuthenticationClientBuilder.swift +++ b/ElementX/Sources/Services/Authentication/AuthenticationClientBuilder.swift @@ -78,7 +78,8 @@ struct AuthenticationClientBuilder: AuthenticationClientBuilderProtocol { slidingSync: slidingSync, sessionDelegate: clientSessionDelegate, appHooks: appHooks, - enableOnlySignedDeviceIsolationMode: appSettings.enableOnlySignedDeviceIsolationMode) + enableOnlySignedDeviceIsolationMode: appSettings.enableOnlySignedDeviceIsolationMode, + eventCacheEnabled: appSettings.eventCacheEnabled) .sessionPaths(dataPath: sessionDirectories.dataPath, cachePath: sessionDirectories.cachePath) .passphrase(passphrase: passphrase) diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 41d264eda0..bf2916a23d 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -506,7 +506,7 @@ class ClientProxy: ClientProxyProtocol { } if !roomSummaryProvider.statePublisher.value.isLoaded { - _ = await roomSummaryProvider.statePublisher.values.first(where: { $0.isLoaded }) + _ = await roomSummaryProvider.statePublisher.values.first { $0.isLoaded } } if shouldAwait { @@ -644,7 +644,7 @@ class ClientProxy: ClientProxyProtocol { } func roomDirectorySearchProxy() -> RoomDirectorySearchProxyProtocol { - RoomDirectorySearchProxy(roomDirectorySearch: client.roomDirectorySearch()) + RoomDirectorySearchProxy(roomDirectorySearch: client.roomDirectorySearch(), appSettings: appSettings) } func resolveRoomAlias(_ alias: String) async -> Result { @@ -951,6 +951,9 @@ class ClientProxy: ClientProxyProtocol { return .joined(roomProxy) case .left: return .left + case .banned: + // TODO: Implement a `bannedRoomProxy` and/or `.banned` case + return .left } } catch { MXLog.error("Failed retrieving room: \(roomID), with error: \(error)") @@ -1146,10 +1149,31 @@ private extension RoomPreviewDetails { topic: roomPreviewInfo.topic, avatarURL: roomPreviewInfo.avatarUrl.flatMap(URL.init(string:)), memberCount: UInt(roomPreviewInfo.numJoinedMembers), - isHistoryWorldReadable: roomPreviewInfo.isHistoryWorldReadable, + isHistoryWorldReadable: roomPreviewInfo.isHistoryWorldReadable ?? false, isJoined: roomPreviewInfo.membership == .joined, isInvited: roomPreviewInfo.membership == .invited, - isPublic: roomPreviewInfo.joinRule == .public, - canKnock: roomPreviewInfo.joinRule == .knock) + isPublic: roomPreviewInfo.isPublic, + canKnock: roomPreviewInfo.canKnock) + } +} + +private extension RoomPreviewInfo { + var canKnock: Bool { + switch joinRule { + case .knock, .knockRestricted: + return true + default: + return false + } + } + + var isPublic: Bool { + switch joinRule { + // for restricted rooms we want to show optimistically that the we may be able to join the room + case .public, .restricted: + return true + default: + return false + } } } diff --git a/ElementX/Sources/Services/ElementCall/ElementCallService.swift b/ElementX/Sources/Services/ElementCall/ElementCallService.swift index 9dffddc981..b35838e7af 100644 --- a/ElementX/Sources/Services/ElementCall/ElementCallService.swift +++ b/ElementX/Sources/Services/ElementCall/ElementCallService.swift @@ -173,7 +173,7 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe } endUnansweredCallTask = Task { [weak self] in - try? await Task.sleep(for: .seconds(15)) + try? await Task.sleep(for: .seconds(90)) guard let self, !Task.isCancelled else { return @@ -298,11 +298,11 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe .infoPublisher .compactMap { ($0.hasRoomCall, $0.activeRoomCallParticipants) } .removeDuplicates { $0 == $1 } - .drop(while: { hasRoomCall, _ in + .drop { hasRoomCall, _ in // Filter all updates before hasRoomCall becomes `true`. Then we can correctly // detect its change to `false` to stop ringing when the caller hangs up. !hasRoomCall - }) + } .sink { [weak self] hasOngoingCall, activeRoomCallParticipants in guard let self else { return } diff --git a/ElementX/Sources/Services/Emojis/EmojiProvider.swift b/ElementX/Sources/Services/Emojis/EmojiProvider.swift index 104f65ce23..877e0adda3 100644 --- a/ElementX/Sources/Services/Emojis/EmojiProvider.swift +++ b/ElementX/Sources/Services/Emojis/EmojiProvider.swift @@ -7,7 +7,6 @@ import Emojibase import Foundation -import OrderedCollections class EmojiProvider: EmojiProviderProtocol { private let maxFrequentEmojis = 20 @@ -61,14 +60,7 @@ class EmojiProvider: EmojiProviderProtocol { return [] } - guard let preferences = UserDefaults(suiteName: "com.apple.EmojiPreferences"), - let defaults = preferences.dictionary(forKey: "EMFDefaultsKey"), - let recents = defaults["EMFRecentsKey"] as? [String] - else { - return [] - } - - return recents + return appSettings.frequentlyUsedSystemEmojis.map(\.key) } func markEmojiAsFrequentlyUsed(_ emoji: String) { @@ -76,16 +68,19 @@ class EmojiProvider: EmojiProviderProtocol { return } - guard let preferences = UserDefaults(suiteName: "com.apple.EmojiPreferences"), - let defaults = preferences.dictionary(forKey: "EMFDefaultsKey"), - let recents = defaults["EMFRecentsKey"] as? [String] else { - return + let frequentlyUsed = if !frequentlyUsedSystemEmojis().contains(emoji) { + appSettings.frequentlyUsedSystemEmojis + [.init(count: 0, key: emoji)] + } else { + appSettings.frequentlyUsedSystemEmojis.map { frequentlyUsedEmoji in + if frequentlyUsedEmoji.key == emoji { + return FrequentlyUsedEmoji(count: frequentlyUsedEmoji.count + 1, key: emoji) + } + + return frequentlyUsedEmoji + } } - var uniqueOrderedRecents = OrderedSet(recents) - uniqueOrderedRecents.insert(emoji, at: 0) - - preferences.setValue(["EMFRecentsKey": Array(uniqueOrderedRecents)], forKey: "EMFDefaultsKey") + appSettings.frequentlyUsedSystemEmojis = frequentlyUsed.sorted { $0.count > $1.count } } // MARK: - Private diff --git a/ElementX/Sources/Services/Emojis/EmojiProviderProtocol.swift b/ElementX/Sources/Services/Emojis/EmojiProviderProtocol.swift index b0137716e8..377560b2ef 100644 --- a/ElementX/Sources/Services/Emojis/EmojiProviderProtocol.swift +++ b/ElementX/Sources/Services/Emojis/EmojiProviderProtocol.swift @@ -31,6 +31,15 @@ enum EmojiProviderState { case loaded([EmojiCategory]) } +struct FrequentlyUsedEmoji: Codable, Hashable { + let count: UInt + let key: String + + static func == (lhs: FrequentlyUsedEmoji, rhs: FrequentlyUsedEmoji) -> Bool { + lhs.key == rhs.key + } +} + @MainActor protocol EmojiProviderProtocol { var state: EmojiProviderState { get } diff --git a/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxy.swift b/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxy.swift index 0b8502ce31..8d130ebf5f 100644 --- a/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxy.swift +++ b/ElementX/Sources/Services/NotificationSettings/NotificationSettingsProxy.swift @@ -120,7 +120,7 @@ final class NotificationSettingsProxy: NotificationSettingsProxyProtocol { // as in this case no API call is made by the RustSDK and the push rules are therefore not updated. _ = await callbacks .timeout(.seconds(2.0), scheduler: DispatchQueue.main, options: nil, customError: nil) - .values.first(where: { $0 == .settingsDidChange }) + .values.first { $0 == .settingsDidChange } } @MainActor diff --git a/ElementX/Sources/Services/Room/JoinedRoomProxy.swift b/ElementX/Sources/Services/Room/JoinedRoomProxy.swift index 021d5df53d..a419e993ad 100644 --- a/ElementX/Sources/Services/Room/JoinedRoomProxy.swift +++ b/ElementX/Sources/Services/Room/JoinedRoomProxy.swift @@ -60,6 +60,8 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol { private var typingNotificationObservationToken: TaskHandle? // periphery:ignore - required for instance retention in the rust codebase private var identityStatusChangesObservationToken: TaskHandle? + // periphery:ignore - required for instance retention in the rust codebase + private var knockRequestsChangesObservationToken: TaskHandle? private var subscribedForUpdates = false @@ -83,6 +85,11 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol { identityStatusChangesSubject.asCurrentValuePublisher() } + private let knockRequestsStateSubject = CurrentValueSubject(.loading) + var knockRequestsStatePublisher: CurrentValuePublisher { + knockRequestsStateSubject.asCurrentValuePublisher() + } + // A room identifier is constant and lazy stops it from being fetched // multiple times over FFI lazy var id: String = room.id() @@ -131,6 +138,8 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol { } subscribeToTypingNotifications() + + await subscribeToKnockRequests() } func subscribeToRoomInfoUpdates() { @@ -166,6 +175,21 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol { } } + func messageFilteredTimeline(allowedMessageTypes: [RoomMessageEventMessageType]) async -> Result { + do { + let timeline = try await TimelineProxy(timeline: room.messageFilteredTimeline(internalIdPrefix: nil, + allowedMessageTypes: allowedMessageTypes, + dateDividerMode: .monthly), + kind: .media(.mediaFilesScreen)) + await timeline.subscribeForUpdates() + + return .success(timeline) + } catch { + MXLog.error("Failed retrieving media events timeline with error: \(error)") + return .failure(.sdkError(error)) + } + } + func redact(_ eventID: String) async -> Result { do { try await room.redact(eventId: eventID, reason: nil) @@ -630,6 +654,19 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol { identityStatusChangesSubject.send(changes) }) } + + private func subscribeToKnockRequests() async { + do { + knockRequestsChangesObservationToken = try await room.subscribeToKnockRequests(listener: RoomKnockRequestsListener { [weak self] requests in + guard let self else { return } + + MXLog.info("Received requests to join update, requests id: \(requests.map(\.eventId))") + knockRequestsStateSubject.send(.loaded(requests.map(KnockRequestProxy.init))) + }) + } catch { + MXLog.error("Failed observing requests to join with error: \(error)") + } + } } private final class RoomInfoUpdateListener: RoomInfoListener { @@ -667,3 +704,15 @@ private final class RoomIdentityStatusChangeListener: IdentityStatusChangeListen onUpdateClosure(identityStatusChange) } } + +private final class RoomKnockRequestsListener: KnockRequestsListener { + private let onUpdateClosure: ([KnockRequest]) -> Void + + init(_ onUpdateClosure: @escaping ([KnockRequest]) -> Void) { + self.onUpdateClosure = onUpdateClosure + } + + func call(joinRequests: [KnockRequest]) { + onUpdateClosure(joinRequests) + } +} diff --git a/ElementX/Sources/Services/Room/KnockRequestProxy.swift b/ElementX/Sources/Services/Room/KnockRequestProxy.swift new file mode 100644 index 0000000000..c350693a07 --- /dev/null +++ b/ElementX/Sources/Services/Room/KnockRequestProxy.swift @@ -0,0 +1,90 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Foundation +import MatrixRustSDK + +struct KnockRequestProxy: KnockRequestProxyProtocol { + private let knockRequest: KnockRequest + + init(knockRequest: KnockRequest) { + self.knockRequest = knockRequest + } + + var eventID: String { + knockRequest.eventId + } + + var userID: String { + knockRequest.userId + } + + var displayName: String? { + knockRequest.displayName + } + + var avatarURL: URL? { + knockRequest.avatarUrl.flatMap(URL.init) + } + + var reason: String? { + knockRequest.reason + } + + var formattedTimestamp: String? { + guard let timestamp = knockRequest.timestamp else { + return nil + } + return Date(timeIntervalSince1970: TimeInterval(timestamp / 1000)).formattedMinimal() + } + + var isSeen: Bool { + knockRequest.isSeen + } + + func accept() async -> Result { + do { + try await knockRequest.actions.accept() + return .success(()) + } catch { + MXLog.error("Failed accepting request with eventID: \(eventID) to join error: \(error)") + return .failure(.sdkError(error)) + } + } + + func decline() async -> Result { + do { + // As of right now we don't provide reasons in the app for declining + try await knockRequest.actions.decline(reason: nil) + return .success(()) + } catch { + MXLog.error("Failed declining request with eventID: \(eventID) to join error: \(error)") + return .failure(.sdkError(error)) + } + } + + func ban() async -> Result { + do { + // As of right now we don't provide reasons in the app for declining and banning + try await knockRequest.actions.declineAndBan(reason: nil) + return .success(()) + } catch { + MXLog.error("Failed declining and banning user for request with eventID: \(eventID) with error: \(error)") + return .failure(.sdkError(error)) + } + } + + func markAsSeen() async -> Result { + do { + try await knockRequest.actions.markAsSeen() + return .success(()) + } catch { + MXLog.error("Failed marking request with eventID: \(eventID) to join as seen error: \(error)") + return .failure(.sdkError(error)) + } + } +} diff --git a/ElementX/Sources/Services/Room/KnockRequestProxyProtocol.swift b/ElementX/Sources/Services/Room/KnockRequestProxyProtocol.swift new file mode 100644 index 0000000000..01acc1f124 --- /dev/null +++ b/ElementX/Sources/Services/Room/KnockRequestProxyProtocol.swift @@ -0,0 +1,28 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Foundation + +enum KnockRequestProxyError: Error { + case sdkError(Error) +} + +// sourcery: AutoMockable +protocol KnockRequestProxyProtocol { + var eventID: String { get } + var userID: String { get } + var displayName: String? { get } + var avatarURL: URL? { get } + var reason: String? { get } + var formattedTimestamp: String? { get } + var isSeen: Bool { get } + + func accept() async -> Result + func decline() async -> Result + func ban() async -> Result + func markAsSeen() async -> Result +} diff --git a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift index a19a735e79..fa5948a7ce 100644 --- a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift @@ -48,6 +48,11 @@ enum JoinedRoomProxyAction: Equatable { case roomInfoUpdate } +enum KnockRequestsState { + case loading + case loaded([KnockRequestProxyProtocol]) +} + // sourcery: AutoMockable protocol JoinedRoomProxyProtocol: RoomProxyProtocol { var isEncrypted: Bool { get } @@ -60,6 +65,8 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol { var identityStatusChangesPublisher: CurrentValuePublisher<[IdentityStatusChange], Never> { get } + var knockRequestsStatePublisher: CurrentValuePublisher { get } + var timeline: TimelineProxyProtocol { get } var pinnedEventsTimeline: TimelineProxyProtocol? { get async } @@ -70,6 +77,8 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol { func timelineFocusedOnEvent(eventID: String, numberOfEvents: UInt16) async -> Result + func messageFilteredTimeline(allowedMessageTypes: [RoomMessageEventMessageType]) async -> Result + func redact(_ eventID: String) async -> Result func reportContent(_ eventID: String, reason: String?) async -> Result @@ -158,8 +167,8 @@ extension JoinedRoomProxyProtocol { isPublic: infoPublisher.value.isPublic) } - var isEncryptedOneToOneRoom: Bool { - infoPublisher.value.isDirect && isEncrypted && infoPublisher.value.activeMembersCount <= 2 + var isDirectOneToOneRoom: Bool { + infoPublisher.value.isDirect && infoPublisher.value.activeMembersCount <= 2 } func members() async -> [RoomMemberProxyProtocol]? { diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift index 7b9b3a5ed7..8143996799 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift @@ -9,7 +9,7 @@ import Foundation import MatrixRustSDK struct RoomSummary { - enum JoinRequestType { + enum KnockRequestType { case invite(inviter: RoomMemberProxyProtocol?) case knock @@ -34,7 +34,7 @@ struct RoomSummary { let id: String - let joinRequestType: JoinRequestType? + let knockRequestType: KnockRequestType? let name: String let isDirect: Bool @@ -103,7 +103,7 @@ extension RoomSummary { canonicalAlias = nil hasOngoingCall = false - joinRequestType = nil + knockRequestType = nil isMarkedUnread = false isFavourite = false } diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift index 4622c5661e..742072a9a7 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift @@ -255,7 +255,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { let notificationMode = roomInfo.cachedUserDefinedNotificationMode.flatMap { RoomNotificationModeProxy.from(roomNotificationMode: $0) } - let joinRequestType: RoomSummary.JoinRequestType? = switch roomInfo.membership { + let knockRequestType: RoomSummary.KnockRequestType? = switch roomInfo.membership { case .invited: .invite(inviter: inviterProxy) case .knocked: .knock default: nil @@ -263,7 +263,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { return RoomSummary(roomListItem: roomListItem, id: roomInfo.id, - joinRequestType: joinRequestType, + knockRequestType: knockRequestType, name: roomInfo.displayName ?? roomInfo.id, isDirect: roomInfo.isDirect, avatarURL: roomInfo.avatarUrl.flatMap(URL.init(string:)), diff --git a/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxy.swift b/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxy.swift index 7b1a74b63e..24d094fd32 100644 --- a/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxy.swift +++ b/ElementX/Sources/Services/RoomDirectorySearch/RoomDirectorySearchProxy.swift @@ -12,6 +12,7 @@ import MatrixRustSDK final class RoomDirectorySearchProxy: RoomDirectorySearchProxyProtocol { private let roomDirectorySearch: RoomDirectorySearchProtocol + private let appSettings: AppSettings private let serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomdirectorysearch", qos: .default) private let resultsSubject = CurrentValueSubject<[RoomDirectorySearchResult], Never>([]) @@ -31,8 +32,10 @@ final class RoomDirectorySearchProxy: RoomDirectorySearchProxyProtocol { private var cancellables = Set() - init(roomDirectorySearch: RoomDirectorySearchProtocol) { + init(roomDirectorySearch: RoomDirectorySearchProtocol, + appSettings: AppSettings) { self.roomDirectorySearch = roomDirectorySearch + self.appSettings = appSettings diffsPublisher .receive(on: serialDispatchQueue) .sink { [weak self] in self?.updateResultsWithDiffs($0) } @@ -146,7 +149,7 @@ final class RoomDirectorySearchProxy: RoomDirectorySearchProxyProtocol { name: value.name, topic: value.topic, avatar: .room(id: value.roomId, name: value.name, avatarURL: value.avatarUrl.flatMap(URL.init(string:))), - canBeJoined: value.joinRule == .public) + canBeJoined: value.joinRule == .public || (appSettings.knockingEnabled && value.joinRule == .knock)) } } diff --git a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift index da1aef5116..2606bec658 100644 --- a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift +++ b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift @@ -10,10 +10,10 @@ import Foundation enum RoomTimelineItemFixtures { /// The default timeline items used in Xcode previews etc. static var `default`: [RoomTimelineItemProtocol] = [ - SeparatorRoomTimelineItem(id: .virtual(uniqueID: .init(id: "Yesterday")), text: "Yesterday"), + SeparatorRoomTimelineItem(id: .virtual(uniqueID: .init(id: "Yesterday")), timestamp: .mock), TextRoomTimelineItem(id: .event(uniqueID: .init(id: ".RoomTimelineItemFixtures.default.0"), eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.0")), - timestamp: "10:10 AM", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -23,7 +23,7 @@ enum RoomTimelineItemFixtures { properties: RoomTimelineItemProperties(isEdited: true)), TextRoomTimelineItem(id: .event(uniqueID: .init(id: "RoomTimelineItemFixtures.default.1"), eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.1")), - timestamp: "10:11 AM", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -35,7 +35,7 @@ enum RoomTimelineItemFixtures { ])), TextRoomTimelineItem(id: .event(uniqueID: .init(id: "RoomTimelineItemFixtures.default.2"), eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.2")), - timestamp: "10:11 AM", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -52,10 +52,10 @@ enum RoomTimelineItemFixtures { ReactionSender(id: "jacob", timestamp: Date()) ]) ])), - SeparatorRoomTimelineItem(id: .virtual(uniqueID: .init(id: "Today")), text: "Today"), + SeparatorRoomTimelineItem(id: .virtual(uniqueID: .init(id: "Today")), timestamp: .mock), TextRoomTimelineItem(id: .event(uniqueID: .init(id: "RoomTimelineItemFixtures.default.3"), eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.3")), - timestamp: "5 PM", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -65,7 +65,7 @@ enum RoomTimelineItemFixtures { properties: RoomTimelineItemProperties(orderedReadReceipts: [ReadReceipt(userID: "alice", formattedTimestamp: nil)])), TextRoomTimelineItem(id: .event(uniqueID: .init(id: "RoomTimelineItemFixtures.default.4"), eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.4")), - timestamp: "5 PM", + timestamp: .mock, isOutgoing: true, isEditable: true, canBeRepliedTo: true, @@ -74,7 +74,7 @@ enum RoomTimelineItemFixtures { content: .init(body: "And John's speech was amazing!")), TextRoomTimelineItem(id: .event(uniqueID: .init(id: "RoomTimelineItemFixtures.default.5"), eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.5")), - timestamp: "5 PM", + timestamp: .mock, isOutgoing: true, isEditable: true, canBeRepliedTo: true, @@ -88,7 +88,7 @@ enum RoomTimelineItemFixtures { ReadReceipt(userID: "dan", formattedTimestamp: nil)])), TextRoomTimelineItem(id: .event(uniqueID: .init(id: "RoomTimelineItemFixtures.default.6"), eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.6")), - timestamp: "5 PM", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -262,12 +262,17 @@ enum RoomTimelineItemFixtures { VoiceMessageRoomTimelineItem(isOutgoing: true) ] } + + static var separator: SeparatorRoomTimelineItem { + SeparatorRoomTimelineItem(id: .virtual(uniqueID: .init(id: UUID().uuidString)), + timestamp: .now) + } } private extension TextRoomTimelineItem { init(id: TimelineItemIdentifier? = nil, text: String, senderDisplayName: String) { self.init(id: id ?? .randomEvent, - timestamp: "10:47 am", + timestamp: .mock, isOutgoing: senderDisplayName == "Alice", isEditable: false, canBeRepliedTo: true, @@ -286,7 +291,7 @@ private extension TextRoomTimelineItem { private extension AudioRoomTimelineItem { init(isOutgoing: Bool, caption: String? = nil) { self.init(id: .randomEvent, - timestamp: "10:47 am", + timestamp: .mock, isOutgoing: isOutgoing, isEditable: isOutgoing, canBeRepliedTo: true, @@ -305,7 +310,7 @@ private extension AudioRoomTimelineItem { private extension FileRoomTimelineItem { init(isOutgoing: Bool, caption: String? = nil) { self.init(id: .randomEvent, - timestamp: "10:47 am", + timestamp: .mock, isOutgoing: isOutgoing, isEditable: isOutgoing, canBeRepliedTo: true, @@ -323,7 +328,7 @@ private extension FileRoomTimelineItem { private extension ImageRoomTimelineItem { init(isOutgoing: Bool, caption: String? = nil) { self.init(id: .randomEvent, - timestamp: "10:47 am", + timestamp: .mock, isOutgoing: isOutgoing, isEditable: isOutgoing, canBeRepliedTo: true, @@ -340,7 +345,7 @@ private extension ImageRoomTimelineItem { private extension VideoRoomTimelineItem { init(isOutgoing: Bool, caption: String? = nil) { self.init(id: .randomEvent, - timestamp: "10:47 am", + timestamp: .mock, isOutgoing: isOutgoing, isEditable: isOutgoing, canBeRepliedTo: true, @@ -349,7 +354,7 @@ private extension VideoRoomTimelineItem { content: .init(filename: "video.mp4", caption: caption, videoInfo: .mockVideo, - thumbnailInfo: .mockThumbnail, + thumbnailInfo: .mockVideoThumbnail, blurhash: "KtI~70X5V?yss9oyrYs:t6")) } } @@ -357,7 +362,7 @@ private extension VideoRoomTimelineItem { private extension VoiceMessageRoomTimelineItem { init(isOutgoing: Bool) { self.init(id: .randomEvent, - timestamp: "10:47 am", + timestamp: .mock, isOutgoing: isOutgoing, isEditable: isOutgoing, canBeRepliedTo: true, diff --git a/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift b/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift index e446a40ee5..cbc5b8fe6e 100644 --- a/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift +++ b/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift @@ -203,7 +203,7 @@ private extension TimelineItemProxy { private extension VirtualTimelineItem { var description: String { switch self { - case .dayDivider(let timestamp): + case .dateDivider(let timestamp): return "DayDiviver(\(timestamp))" case .readMarker: return "ReadMarker" diff --git a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift index b8cf4387e2..6674cdaef8 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift @@ -23,14 +23,34 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { let callbacks = PassthroughSubject() + var paginationState: PaginationState = .initial { + didSet { + callbacks.send(.paginationState(paginationState)) + } + } + var timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default var timelineItemsTimestamp: [TimelineItemIdentifier: Date] = [:] private var client: UITestsSignalling.Client? - init(timelineKind: TimelineKind = .live, listenForSignals: Bool = false) { + static var mediaGallery: MockRoomTimelineController { + MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen), timelineItems: (0..<5).reduce([]) { partialResult, _ in + partialResult + [RoomTimelineItemFixtures.separator] + RoomTimelineItemFixtures.mediaChunk + }) + } + + static var emptyMediaGallery: MockRoomTimelineController { + let mock = MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen)) + mock.paginationState = PaginationState(backward: .timelineEndReached, forward: .timelineEndReached) + return mock + } + + init(timelineKind: TimelineKind = .live, listenForSignals: Bool = false, timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default) { self.timelineKind = timelineKind - callbacks.send(.paginationState(PaginationState(backward: .idle, forward: .timelineEndReached))) + self.timelineItems = timelineItems + + callbacks.send(.paginationState(paginationState)) callbacks.send(.isLive(true)) guard listenForSignals else { return } @@ -56,7 +76,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { } func paginateBackwards(requestSize: UInt16) async -> Result { - callbacks.send(.paginationState(PaginationState(backward: .paginating, forward: .timelineEndReached))) + paginationState = PaginationState(backward: .paginating, forward: .timelineEndReached) if client == nil { try? await simulateBackPagination() @@ -98,7 +118,10 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { func removeCaption(_ eventOrTransactionID: EventOrTransactionId) async { } - func redact(_ eventOrTransactionID: EventOrTransactionId) async { } + private(set) var redactCalled = false + func redact(_ eventOrTransactionID: EventOrTransactionId) async { + redactCalled = true + } func pin(eventID: String) async { } @@ -116,8 +139,6 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { nil } - func retryDecryption(for sessionID: String) async { } - func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date? { timelineItemsTimestamp[itemID] ?? .now } @@ -170,8 +191,8 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { /// Prepends the next chunk of items to the `timelineItems` array. private func simulateBackPagination() async throws { defer { - callbacks.send(.paginationState(PaginationState(backward: backPaginationResponses.isEmpty ? .timelineEndReached : .idle, - forward: .timelineEndReached))) + paginationState = PaginationState(backward: backPaginationResponses.isEmpty ? .timelineEndReached : .idle, + forward: .timelineEndReached) } guard !backPaginationResponses.isEmpty else { return } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift index bdf6a5a6e1..8f9292a4d0 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift @@ -30,6 +30,12 @@ class RoomTimelineController: RoomTimelineControllerProtocol { } private(set) var timelineItems = [RoomTimelineItemProtocol]() + + private(set) var paginationState: PaginationState = .initial { + didSet { + callbacks.send(.paginationState(paginationState)) + } + } var roomID: String { roomProxy.id @@ -64,7 +70,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol { } Task { - callbacks.send(.paginationState(PaginationState(backward: .paginating, forward: .paginating))) + paginationState = PaginationState(backward: .paginating, forward: .paginating) + switch await focusOnEvent(initialFocussedEventID, timelineSize: 100) { case .success: break @@ -349,10 +356,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol { return nil } - func retryDecryption(for sessionID: String) async { - await activeTimeline.retryDecryption(for: sessionID) - } - // MARK: - Private /// The cancellable used to update the timeline items. @@ -368,7 +371,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol { isSwitchingTimelines = true // Inform the world that the initial items are loading from the store - callbacks.send(.paginationState(.init(backward: .paginating, forward: .paginating))) + paginationState = PaginationState(backward: .paginating, forward: .paginating) callbacks.send(.isLive(activeTimelineProvider.kind == .live)) updateTimelineItemsCancellable = activeTimelineProvider @@ -424,7 +427,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol { // Check if we need to add anything to the top of the timeline. switch paginationState.backward { case .timelineEndReached: - if timelineKind != .pinned, !roomProxy.isEncryptedOneToOneRoom { + if timelineKind != .pinned, !roomProxy.isDirectOneToOneRoom { let timelineStart = TimelineStartRoomTimelineItem(name: roomProxy.infoPublisher.value.displayName) newTimelineItems.insert(timelineStart, at: 0) } @@ -446,13 +449,13 @@ class RoomTimelineController: RoomTimelineControllerProtocol { } callbacks.send(.updatedTimelineItems(timelineItems: newTimelineItems, isSwitchingTimelines: isNewTimeline)) - callbacks.send(.paginationState(paginationState)) + self.paginationState = paginationState } private func buildTimelineItem(for itemProxy: TimelineItemProxy) -> RoomTimelineItemProtocol? { switch itemProxy { case .event(let eventTimelineItem): - let timelineItem = timelineItemFactory.buildTimelineItem(for: eventTimelineItem, isDM: roomProxy.isEncryptedOneToOneRoom) + let timelineItem = timelineItemFactory.buildTimelineItem(for: eventTimelineItem, isDM: roomProxy.isDirectOneToOneRoom) if let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol { // Avoid fetching this over and over again as it changes states if it keeps failing to load @@ -463,11 +466,9 @@ class RoomTimelineController: RoomTimelineControllerProtocol { return timelineItem case .virtual(let virtualItem, let uniqueID): switch virtualItem { - case .dayDivider(let timestamp): + case .dateDivider(let timestamp): let date = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000)) - let dateString = date.formatted(date: .complete, time: .omitted) - - return SeparatorRoomTimelineItem(id: .virtual(uniqueID: uniqueID), text: dateString) + return SeparatorRoomTimelineItem(id: .virtual(uniqueID: uniqueID), timestamp: date) case .readMarker: return ReadMarkerRoomTimelineItem(id: .virtual(uniqueID: uniqueID)) } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift index 4e86953c25..c726c37130 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift @@ -6,6 +6,7 @@ // import Foundation +import MatrixRustSDK struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol { func buildRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, @@ -20,12 +21,13 @@ struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol { appSettings: ServiceLocator.shared.settings) } - func buildRoomPinnedTimelineController(roomProxy: JoinedRoomProxyProtocol, - timelineItemFactory: RoomTimelineItemFactoryProtocol, - mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol? { + func buildPinnedEventsRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, + timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol? { guard let pinnedEventsTimeline = await roomProxy.pinnedEventsTimeline else { return nil } + return RoomTimelineController(roomProxy: roomProxy, timelineProxy: pinnedEventsTimeline, initialFocussedEventID: nil, @@ -33,4 +35,21 @@ struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol { mediaProvider: mediaProvider, appSettings: ServiceLocator.shared.settings) } + + func buildMessageFilteredRoomTimelineController(allowedMessageTypes: [RoomMessageEventMessageType], + roomProxy: JoinedRoomProxyProtocol, + timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol) async -> Result { + switch await roomProxy.messageFilteredTimeline(allowedMessageTypes: allowedMessageTypes) { + case .success(let timelineProxy): + return .success(RoomTimelineController(roomProxy: roomProxy, + timelineProxy: timelineProxy, + initialFocussedEventID: nil, + timelineItemFactory: timelineItemFactory, + mediaProvider: mediaProvider, + appSettings: ServiceLocator.shared.settings)) + case .failure(let error): + return .failure(.roomProxyError(error)) + } + } } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift index 0f1093c8f5..443ac78ce0 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift @@ -6,6 +6,11 @@ // import Foundation +import MatrixRustSDK + +enum RoomTimelineFactoryControllerError: Error { + case roomProxyError(RoomProxyError) +} @MainActor protocol RoomTimelineControllerFactoryProtocol { @@ -13,9 +18,15 @@ protocol RoomTimelineControllerFactoryProtocol { initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol - func buildRoomPinnedTimelineController(roomProxy: JoinedRoomProxyProtocol, - timelineItemFactory: RoomTimelineItemFactoryProtocol, - mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol? + + func buildPinnedEventsRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, + timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol? + + func buildMessageFilteredRoomTimelineController(allowedMessageTypes: [RoomMessageEventMessageType], + roomProxy: JoinedRoomProxyProtocol, + timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol) async -> Result } // sourcery: AutoMockable diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift index e32356e25a..67a076ce55 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift @@ -31,7 +31,12 @@ protocol RoomTimelineControllerProtocol { var roomID: String { get } var timelineKind: TimelineKind { get } + /// The currently known items, use only for setting up the intial state. var timelineItems: [RoomTimelineItemProtocol] { get } + + /// The current pagination state, use only for setting up the intial state + var paginationState: PaginationState { get } + var callbacks: PassthroughSubject { get } func processItemAppearance(_ itemID: TimelineItemIdentifier) async @@ -77,7 +82,5 @@ protocol RoomTimelineControllerProtocol { func sendHandle(for itemID: TimelineItemIdentifier) -> SendHandleProxy? - func retryDecryption(for sessionID: String) async - func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date? } diff --git a/ElementX/Sources/Services/Timeline/TimelineItemContent/AggregratedReaction.swift b/ElementX/Sources/Services/Timeline/TimelineItemContent/AggregratedReaction.swift index 8baf77db5d..3903b023a5 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemContent/AggregratedReaction.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemContent/AggregratedReaction.swift @@ -42,7 +42,7 @@ extension AggregatedReaction { /// Whether to highlight the reaction, indicating that the current user sent this reaction. var isHighlighted: Bool { - senders.contains(where: { $0.id == accountOwnerID }) + senders.contains { $0.id == accountOwnerID } } /// The key to be displayed on screen. See `maxDisplayChars`. diff --git a/ElementX/Sources/Services/Timeline/TimelineItemIdentifier.swift b/ElementX/Sources/Services/Timeline/TimelineItemIdentifier.swift index a6efccb371..c65ef4ae0f 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemIdentifier.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemIdentifier.swift @@ -13,7 +13,7 @@ import MatrixRustSDK /// Its value is consistent only per timeline instance, it should **not** be used to identify an item across timeline instances. /// - eventOrTransactionID: Contains the 2 possible identifiers of an event, either it has a remote event id or /// a local transaction id, never both or none. -enum TimelineItemIdentifier: Hashable { +enum TimelineItemIdentifier: Hashable, Sendable { case event(uniqueID: TimelineUniqueId, eventOrTransactionID: EventOrTransactionId) case virtual(uniqueID: TimelineUniqueId) diff --git a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift index bd024e4967..4dc27d6112 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift @@ -221,8 +221,9 @@ struct VideoInfoProxy: Hashable { private(set) var size: CGSize? private(set) var aspectRatio: CGFloat? private(set) var mimeType: String? + private(set) var fileSize: UInt? - init(source: MediaSource, duration: TimeInterval, width: UInt64?, height: UInt64?, mimeType: String?) { + init(source: MediaSource, duration: TimeInterval, width: UInt64?, height: UInt64?, mimeType: String?, fileSize: UInt?) { self.source = MediaSourceProxy(source: source, mimeType: mimeType) self.duration = duration @@ -230,16 +231,18 @@ struct VideoInfoProxy: Hashable { size = mediaInfo.size aspectRatio = mediaInfo.aspectRatio self.mimeType = mediaInfo.mimeType + self.fileSize = fileSize } // MARK: - Mocks - private init(source: MediaSourceProxy, duration: TimeInterval, size: CGSize?, aspectRatio: CGFloat?, mimeType: String?) { + private init(source: MediaSourceProxy, duration: TimeInterval, size: CGSize?, aspectRatio: CGFloat?, mimeType: String?, fileSize: UInt?) { self.source = source self.duration = duration self.size = size self.aspectRatio = aspectRatio self.mimeType = mimeType + self.fileSize = fileSize } static var mockVideo: VideoInfoProxy { @@ -251,7 +254,8 @@ struct VideoInfoProxy: Hashable { duration: 100, size: .init(width: 1920, height: 1080), aspectRatio: 1.78, - mimeType: nil) + mimeType: nil, + fileSize: 45_167_000) } } @@ -260,61 +264,66 @@ struct ImageInfoProxy: Hashable { private(set) var size: CGSize? private(set) var aspectRatio: CGFloat? private(set) var mimeType: String? + private(set) var fileSize: UInt? - init?(source: MediaSource?, width: UInt64?, height: UInt64?, mimeType: String?) { + init?(source: MediaSource?, width: UInt64?, height: UInt64?, mimeType: String?, fileSize: UInt?) { guard let source else { return nil } - self.init(source: .init(source: source, mimeType: mimeType), width: width, height: height, mimeType: mimeType) + self.init(source: .init(source: source, mimeType: mimeType), width: width, height: height, mimeType: mimeType, fileSize: fileSize) } - init(source: MediaSource, width: UInt64?, height: UInt64?, mimeType: String?) { - self.init(source: .init(source: source, mimeType: mimeType), width: width, height: height, mimeType: mimeType) + init(source: MediaSource, width: UInt64?, height: UInt64?, mimeType: String?, fileSize: UInt?) { + self.init(source: .init(source: source, mimeType: mimeType), width: width, height: height, mimeType: mimeType, fileSize: fileSize) } - init(source: MediaSourceProxy, width: UInt64?, height: UInt64?, mimeType: String?) { + init(source: MediaSourceProxy, width: UInt64?, height: UInt64?, mimeType: String?, fileSize: UInt?) { self.source = source let mediaInfo = MediaInfoProxy(width: width, height: height, mimeType: mimeType) size = mediaInfo.size aspectRatio = mediaInfo.aspectRatio self.mimeType = mediaInfo.mimeType + self.fileSize = fileSize } // MARK: - Mocks - private init(source: MediaSourceProxy, size: CGSize?, aspectRatio: CGFloat?, mimeType: String?) { + private init(source: MediaSourceProxy, size: CGSize?, aspectRatio: CGFloat?, fileSize: UInt?) { self.source = source self.size = size self.aspectRatio = aspectRatio - self.mimeType = mimeType + mimeType = source.mimeType + self.fileSize = fileSize } static var mockImage: ImageInfoProxy { - guard let mediaSource = try? MediaSourceProxy(url: .mockMXCImage, mimeType: "image/png") else { + guard let mediaSource = try? MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpg") else { fatalError("Invalid mock media source URL") } - return .init(source: mediaSource, - size: .init(width: 100, height: 100), - aspectRatio: 1, - mimeType: "image/png") + return .init(source: mediaSource, size: .init(width: 2730, height: 2048), aspectRatio: 4 / 3, fileSize: 717_000) } static var mockThumbnail: ImageInfoProxy { - guard let mediaSource = try? MediaSourceProxy(url: .mockMXCImage, mimeType: "image/png") else { + guard let mediaSource = try? MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpg") else { fatalError("Invalid mock media source URL") } - return .init(source: mediaSource, - size: nil, - aspectRatio: nil, - mimeType: nil) + return .init(source: mediaSource, size: .init(width: 800, height: 600), aspectRatio: 4 / 3, fileSize: 84000) + } + + static var mockVideoThumbnail: ImageInfoProxy { + guard let mediaSource = try? MediaSourceProxy(url: .mockMXCVideo, mimeType: "image/jpg") else { + fatalError("Invalid mock media source URL") + } + + return .init(source: mediaSource, size: .init(width: 800, height: 450), aspectRatio: 16 / 9, fileSize: 98000) } } -struct MediaInfoProxy: Hashable { +private struct MediaInfoProxy: Hashable { private(set) var size: CGSize? private(set) var mimeType: String? private(set) var aspectRatio: CGFloat? diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift index 0150401ff9..783614140f 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift @@ -9,7 +9,7 @@ import Foundation import UIKit protocol EventBasedTimelineItemProtocol: RoomTimelineItemProtocol, CustomStringConvertible { - var timestamp: String { get } + var timestamp: Date { get } var isOutgoing: Bool { get } var isEditable: Bool { get } var canBeRepliedTo: Bool { get } @@ -84,7 +84,7 @@ extension EventBasedTimelineItemProtocol { if properties.isEdited { start = "\(L10n.commonEditedSuffix) " } - return start + timestamp + return start + timestamp.formattedTime() } var isCopyable: Bool { diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItem.swift index 6b556dcbe0..1f4f2fff60 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItem.swift @@ -9,7 +9,7 @@ import Foundation struct AudioRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItem.swift index 0adfaf5c8f..5c236bf0c5 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/EmoteRoomTimelineItem.swift @@ -9,7 +9,7 @@ import UIKit struct EmoteRoomTimelineItem: TextBasedRoomTimelineItem, Equatable { let id: TimelineItemIdentifier - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItem.swift index bb025ee776..b5d9da6827 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItem.swift @@ -10,7 +10,7 @@ import UniformTypeIdentifiers struct FileRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItem.swift index b556b1e187..2e53acdc21 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItem.swift @@ -10,7 +10,7 @@ import UniformTypeIdentifiers struct ImageRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItem.swift index 815c17b1d6..8a94eca99c 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/LocationRoomTimelineItem.swift @@ -5,10 +5,12 @@ // Please see LICENSE in the repository root for full details. // +import Foundation + struct LocationRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItem.swift index 7cee6c0ecb..6b13a75839 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/NoticeRoomTimelineItem.swift @@ -9,7 +9,7 @@ import UIKit struct NoticeRoomTimelineItem: TextBasedRoomTimelineItem, Equatable { let id: TimelineItemIdentifier - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItem.swift index 249d873b03..32170640fe 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/TextRoomTimelineItem.swift @@ -10,7 +10,7 @@ import UIKit struct TextRoomTimelineItem: TextBasedRoomTimelineItem, Equatable { let id: TimelineItemIdentifier - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItem.swift index 5247fd6cd2..33a3e4bf2d 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItem.swift @@ -10,7 +10,7 @@ import UniformTypeIdentifiers struct VideoRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessageRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessageRoomTimelineItem.swift index d8e0769988..84561601b0 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessageRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessageRoomTimelineItem.swift @@ -9,7 +9,7 @@ import Foundation struct VoiceMessageRoomTimelineItem: EventBasedMessageTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallInviteRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallInviteRoomTimelineItem.swift index e5b766e0ae..7978721c6a 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallInviteRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallInviteRoomTimelineItem.swift @@ -9,7 +9,7 @@ import Foundation struct CallInviteRoomTimelineItem: RoomTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier - let timestamp: String + let timestamp: Date let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallNotificationRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallNotificationRoomTimelineItem.swift index e252a11de3..b81a07d2e3 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallNotificationRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/CallNotificationRoomTimelineItem.swift @@ -9,7 +9,7 @@ import Foundation struct CallNotificationRoomTimelineItem: RoomTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier - let timestamp: String + let timestamp: Date let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift index f6d5e7e0d5..270ecff92f 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift @@ -19,13 +19,16 @@ struct EncryptedRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable { case verificationViolation case insecureDevice case unknown - case historicalMessage + case historicalMessageAndBackupDisabled + case historicalMessageAndDeviceIsUnverified + case witheldBySender + case withheldForUnverifiedOrInsecureDevice } let id: TimelineItemIdentifier let body: String let encryptionType: EncryptionType - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift index dbe238b2b1..f78d393f6c 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/PollRoomTimelineItem.swift @@ -11,7 +11,7 @@ struct PollRoomTimelineItem: Equatable, EventBasedTimelineItemProtocol { let id: TimelineItemIdentifier let poll: Poll let body: String - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/RedactedRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/RedactedRoomTimelineItem.swift index fe2948d728..aab7178517 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/RedactedRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/RedactedRoomTimelineItem.swift @@ -11,7 +11,7 @@ import UIKit struct RedactedRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier let body: String - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StateRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StateRoomTimelineItem.swift index 59a7a01b57..d193452978 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StateRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StateRoomTimelineItem.swift @@ -10,7 +10,7 @@ import UIKit struct StateRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier let body: String - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift index 466ba2a0f4..202f7b55e1 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift @@ -10,7 +10,7 @@ import UIKit struct StickerRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier let body: String - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/UnsupportedRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/UnsupportedRoomTimelineItem.swift index 51b4956088..5114535245 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/UnsupportedRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/UnsupportedRoomTimelineItem.swift @@ -14,7 +14,7 @@ struct UnsupportedRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable { let eventType: String let error: String - let timestamp: String + let timestamp: Date let isOutgoing: Bool let isEditable: Bool let canBeRepliedTo: Bool diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/SeparatorRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/SeparatorRoomTimelineItem.swift index 5a1a28ce2e..bdc6ceafc2 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/SeparatorRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Virtual/SeparatorRoomTimelineItem.swift @@ -9,5 +9,5 @@ import Foundation struct SeparatorRoomTimelineItem: DecorationTimelineItemProtocol, Equatable { let id: TimelineItemIdentifier - let text: String + let timestamp: Date } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomStateEventStringBuilder.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomStateEventStringBuilder.swift index f7cc691fb4..5f5c92fd59 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomStateEventStringBuilder.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomStateEventStringBuilder.swift @@ -59,7 +59,7 @@ struct RoomStateEventStringBuilder { case .knocked: return memberIsYou ? L10n.stateEventRoomKnockByYou : L10n.stateEventRoomKnock(member) case .knockAccepted: - return senderIsYou ? L10n.stateEventRoomKnockAcceptedByYou(senderDisplayName) : L10n.stateEventRoomKnockAccepted(senderDisplayName, member) + return senderIsYou ? L10n.stateEventRoomKnockAcceptedByYou(member) : L10n.stateEventRoomKnockAccepted(senderDisplayName, member) case .knockRetracted: return memberIsYou ? L10n.stateEventRoomKnockRetractedByYou : L10n.stateEventRoomKnockRetracted(member) case .knockDenied: diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index c26fc8d2b8..a8b88d3928 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -103,7 +103,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { body: L10n.commonUnsupportedEvent, eventType: eventType, error: error, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -116,11 +116,11 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ info: MatrixRustSDK.ImageInfo, _ mediaSource: MediaSource, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { - let imageInfo = ImageInfoProxy(source: mediaSource, width: info.width, height: info.height, mimeType: info.mimetype) + let imageInfo = ImageInfoProxy(source: mediaSource, width: info.width, height: info.height, mimeType: info.mimetype, fileSize: info.size.map(UInt.init)) return StickerRoomTimelineItem(id: eventItemProxy.id, body: body, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -153,9 +153,18 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { case .sentBeforeWeJoined: encryptionType = .megolmV1AesSha2(sessionID: sessionID, cause: .sentBeforeWeJoined) errorLabel = L10n.commonUnableToDecryptNoAccess - case .historicalMessage: - encryptionType = .megolmV1AesSha2(sessionID: sessionID, cause: .historicalMessage) - errorLabel = L10n.commonUnableToDecryptNoAccess + case .historicalMessageAndBackupIsDisabled: + encryptionType = .megolmV1AesSha2(sessionID: sessionID, cause: .historicalMessageAndBackupDisabled) + errorLabel = L10n.timelineDecryptionFailureHistoricalEventNoKeyBackup + case .historicalMessageAndDeviceIsUnverified: + encryptionType = .megolmV1AesSha2(sessionID: sessionID, cause: .historicalMessageAndDeviceIsUnverified) + errorLabel = L10n.timelineDecryptionFailureHistoricalEventUnverifiedDevice + case .withheldForUnverifiedOrInsecureDevice: + encryptionType = .megolmV1AesSha2(sessionID: sessionID, cause: .withheldForUnverifiedOrInsecureDevice) + errorLabel = L10n.timelineDecryptionFailureWithheldUnverified + case .withheldBySender: + encryptionType = .megolmV1AesSha2(sessionID: sessionID, cause: .witheldBySender) + errorLabel = L10n.timelineDecryptionFailureUnableToDecrypt } case .olmV1Curve25519AesSha2(let senderKey): encryptionType = .olmV1Curve25519AesSha2(senderKey: senderKey) @@ -166,7 +175,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { return EncryptedRoomTimelineItem(id: eventItemProxy.id, body: errorLabel, encryptionType: encryptionType, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -178,7 +187,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ isOutgoing: Bool) -> RoomTimelineItemProtocol { RedactedRoomTimelineItem(id: eventItemProxy.id, body: L10n.commonMessageRemoved, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -191,7 +200,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ textMessageContent: TextMessageContent, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { TextRoomTimelineItem(id: eventItemProxy.id, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -211,7 +220,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ imageMessageContent: ImageMessageContent, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { ImageRoomTimelineItem(id: eventItemProxy.id, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -231,7 +240,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ videoMessageContent: VideoMessageContent, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { VideoRoomTimelineItem(id: eventItemProxy.id, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -251,7 +260,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ audioMessageContent: AudioMessageContent, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { AudioRoomTimelineItem(id: eventItemProxy.id, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -271,7 +280,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ audioMessageContent: AudioMessageContent, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { VoiceMessageRoomTimelineItem(id: eventItemProxy.id, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -291,7 +300,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ fileMessageContent: FileMessageContent, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { FileRoomTimelineItem(id: eventItemProxy.id, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -311,7 +320,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ noticeMessageContent: NoticeMessageContent, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { NoticeRoomTimelineItem(id: eventItemProxy.id, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -331,7 +340,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ emoteMessageContent: EmoteMessageContent, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { EmoteRoomTimelineItem(id: eventItemProxy.id, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -351,7 +360,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ locationMessageContent: LocationContent, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { LocationRoomTimelineItem(id: eventItemProxy.id, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -404,7 +413,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { return PollRoomTimelineItem(id: eventItemProxy.id, poll: poll, body: poll.question, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, @@ -418,7 +427,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { private func buildCallInviteTimelineItem(for eventItemProxy: EventTimelineItemProxy) -> RoomTimelineItemProtocol { CallInviteRoomTimelineItem(id: eventItemProxy.id, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, sender: eventItemProxy.sender) @@ -426,7 +435,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { private func buildCallNotificationTimelineItem(for eventItemProxy: EventTimelineItemProxy) -> RoomTimelineItemProtocol { CallNotificationRoomTimelineItem(id: eventItemProxy.id, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, sender: eventItemProxy.sender) @@ -512,12 +521,14 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { let thumbnailInfo = ImageInfoProxy(source: messageContent.info?.thumbnailSource, width: messageContent.info?.thumbnailInfo?.width, height: messageContent.info?.thumbnailInfo?.height, - mimeType: messageContent.info?.thumbnailInfo?.mimetype) + mimeType: messageContent.info?.thumbnailInfo?.mimetype, + fileSize: messageContent.info?.size.map(UInt.init)) let imageInfo = ImageInfoProxy(source: messageContent.source, width: messageContent.info?.width, height: messageContent.info?.height, - mimeType: messageContent.info?.mimetype) + mimeType: messageContent.info?.mimetype, + fileSize: messageContent.info?.size.map(UInt.init)) return .init(filename: messageContent.filename, caption: messageContent.caption, @@ -536,13 +547,15 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { let thumbnailInfo = ImageInfoProxy(source: messageContent.info?.thumbnailSource, width: messageContent.info?.thumbnailInfo?.width, height: messageContent.info?.thumbnailInfo?.height, - mimeType: messageContent.info?.thumbnailInfo?.mimetype) + mimeType: messageContent.info?.thumbnailInfo?.mimetype, + fileSize: messageContent.info?.size.map(UInt.init)) let videoInfo = VideoInfoProxy(source: messageContent.source, duration: messageContent.info?.duration ?? 0, width: messageContent.info?.width, height: messageContent.info?.height, - mimeType: messageContent.info?.mimetype) + mimeType: messageContent.info?.mimetype, + fileSize: messageContent.info?.size.map(UInt.init)) return .init(filename: messageContent.filename, caption: messageContent.caption, @@ -646,7 +659,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { private func buildStateTimelineItem(for eventItemProxy: EventTimelineItemProxy, text: String, isOutgoing: Bool) -> RoomTimelineItemProtocol { StateRoomTimelineItem(id: eventItemProxy.id, body: text, - timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened), + timestamp: eventItemProxy.timestamp, isOutgoing: isOutgoing, isEditable: false, canBeRepliedTo: eventItemProxy.canBeRepliedTo, diff --git a/ElementX/Sources/Services/Timeline/TimelineProxy.swift b/ElementX/Sources/Services/Timeline/TimelineProxy.swift index 93238d41ea..92ff156c7c 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxy.swift @@ -92,7 +92,7 @@ final class TimelineProxy: TimelineProxyProtocol { switch kind { case .live: return await paginateBackwardsOnLive(requestSize: requestSize) - case .detached: + case .detached, .media: return await focussedPaginate(.backwards, requestSize: requestSize) case .pinned: return .success(()) @@ -155,12 +155,14 @@ final class TimelineProxy: TimelineProxyProtocol { } } - func retryDecryption(for sessionID: String) async { - MXLog.info("Retrying decryption for sessionID: \(sessionID)") + func retryDecryption(sessionIDs: [String]?) async { + let sessionIDs = sessionIDs ?? [] + + MXLog.info("Retrying decryption for sessionIDs: \(sessionIDs)") await Task.dispatch(on: .global()) { [weak self] in - self?.timeline.retryDecryption(sessionIds: [sessionID]) - MXLog.info("Finished retrying decryption for sessionID: \(sessionID)") + self?.timeline.retryDecryption(sessionIds: sessionIDs) + MXLog.info("Finished retrying decryption for sessionID: \(sessionIDs)") } } @@ -319,7 +321,6 @@ final class TimelineProxy: TimelineProxyProtocol { return .success(()) } - // swiftlint:disable:next function_parameter_count func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, @@ -580,7 +581,7 @@ final class TimelineProxy: TimelineProxyProtocol { MXLog.error("Failed to subscribe to back pagination status with error: \(error)") } forwardPaginationStatusSubject.send(.timelineEndReached) - case .detached: + case .detached, .media: // Detached timelines don't support observation, set the initial state ourself. backPaginationStatusSubject.send(.idle) forwardPaginationStatusSubject.send(.idle) diff --git a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift index d1520cbbeb..8c6dc6b817 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift @@ -9,10 +9,13 @@ import Combine import Foundation import MatrixRustSDK -enum TimelineKind { +enum TimelineKind: Equatable { case live case detached case pinned + + enum MediaPresentation { case roomScreen, mediaFilesScreen } + case media(MediaPresentation) } enum TimelineProxyError: Error { @@ -32,7 +35,7 @@ protocol TimelineProxyProtocol { func messageEventContent(for timelineItemID: TimelineItemIdentifier) async -> RoomMessageEventContentWithoutRelation? - func retryDecryption(for sessionID: String) async + func retryDecryption(sessionIDs: [String]?) async func paginateBackwards(requestSize: UInt16) async -> Result func paginateForwards(requestSize: UInt16) async -> Result @@ -110,3 +113,9 @@ protocol TimelineProxyProtocol { html: String?, intentionalMentions: Mentions) -> RoomMessageEventContentWithoutRelation } + +extension TimelineProxyProtocol { + func retryDecryption() async { + await retryDecryption(sessionIDs: nil) + } +} diff --git a/ElementX/Sources/Services/UserSession/UserSessionStore.swift b/ElementX/Sources/Services/UserSession/UserSessionStore.swift index 1f4ca5e5b5..8cbdf79170 100644 --- a/ElementX/Sources/Services/UserSession/UserSessionStore.swift +++ b/ElementX/Sources/Services/UserSession/UserSessionStore.swift @@ -130,7 +130,8 @@ class UserSessionStore: UserSessionStoreProtocol { slidingSync: .restored, sessionDelegate: keychainController, appHooks: appHooks, - enableOnlySignedDeviceIsolationMode: appSettings.enableOnlySignedDeviceIsolationMode) + enableOnlySignedDeviceIsolationMode: appSettings.enableOnlySignedDeviceIsolationMode, + eventCacheEnabled: appSettings.eventCacheEnabled) .sessionPaths(dataPath: credentials.restorationToken.sessionDirectories.dataPath, cachePath: credentials.restorationToken.sessionDirectories.cachePath) .username(username: credentials.userID) diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift index cd9e14f329..67a97ad59e 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift @@ -232,7 +232,7 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol { private func finalizeRecording() async -> Result { MXLog.info("finalize audio recording") - guard let url = audioRecorder.audioFileURL, audioRecorder.currentTime > 0 else { + guard audioRecorder.audioFileURL != nil, audioRecorder.currentTime > 0 else { return .failure(.previewNotAvailable) } diff --git a/ElementX/SupportingFiles/Info.plist b/ElementX/SupportingFiles/Info.plist index 39c81a8d9c..1008fa9c4e 100644 --- a/ElementX/SupportingFiles/Info.plist +++ b/ElementX/SupportingFiles/Info.plist @@ -73,7 +73,7 @@ NSMicrophoneUsageDescription To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone. NSPhotoLibraryAddUsageDescription - Allows saving photos and videos to your library. + This lets you save images and videos to your photo library. NSUserActivityTypes INSendMessageIntent diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml index bb92ccae3d..1306c5c91d 100644 --- a/ElementX/SupportingFiles/target.yml +++ b/ElementX/SupportingFiles/target.yml @@ -87,7 +87,7 @@ targets: ] NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera. NSMicrophoneUsageDescription: To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone. - NSPhotoLibraryAddUsageDescription: Allows saving photos and videos to your library. + NSPhotoLibraryAddUsageDescription: This lets you save images and videos to your photo library. NSLocationWhenInUseUsageDescription: Grant location access so that $(APP_DISPLAY_NAME) can share your location. NSFaceIDUsageDescription: Face ID is used to access your app. UIBackgroundModes: [ diff --git a/Gemfile.lock b/Gemfile.lock index f196f469c2..2e3554f267 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -16,20 +16,20 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.992.0) - aws-sdk-core (3.210.0) + aws-partitions (1.1023.0) + aws-sdk-core (3.214.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.95.0) + aws-sdk-kms (1.96.0) aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.169.0) + aws-sdk-s3 (1.176.1) aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.10.0) + aws-sigv4 (1.10.1) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) base64 (0.2.0) @@ -74,7 +74,7 @@ GEM faraday_middleware (1.2.1) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.225.0) + fastlane (2.226.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -114,7 +114,7 @@ GEM tty-spinner (>= 0.8.0, < 1.0.0) word_wrap (~> 1.0.0) xcodeproj (>= 1.13.0, < 2.0.0) - xcpretty (~> 0.3.0) + xcpretty (~> 0.4.0) xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) fastlane-plugin-brew (0.1.1) fastlane-plugin-browserstack (0.3.2) @@ -165,11 +165,11 @@ GEM signet (>= 0.16, < 2.a) highline (2.0.3) http-accept (1.7.0) - http-cookie (1.0.7) + http-cookie (1.0.8) domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.2) - json (2.7.2) + json (2.9.0) jwt (2.9.3) base64 mime-types (3.5.2) @@ -179,11 +179,11 @@ GEM mini_mime (1.1.5) multi_json (1.15.0) multipart-post (2.4.1) - nanaimo (0.3.0) + nanaimo (0.4.0) naturally (2.2.1) netrc (0.11.0) nkf (0.2.0) - optparse (0.5.0) + optparse (0.6.0) os (1.1.4) plist (3.7.1) public_suffix (5.1.1) @@ -198,8 +198,8 @@ GEM mime-types (>= 1.16, < 4.0) netrc (~> 0.8) retriable (3.1.2) - rexml (3.3.8) - rouge (2.0.7) + rexml (3.4.0) + rouge (3.28.0) ruby2_keywords (0.0.5) rubyzip (2.3.2) security (0.1.5) @@ -227,15 +227,15 @@ GEM xcode-install (2.8.1) claide (>= 0.9.1) fastlane (>= 2.1.0, < 3.0.0) - xcodeproj (1.25.1) + xcodeproj (1.27.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) - nanaimo (~> 0.3.0) + nanaimo (~> 0.4.0) rexml (>= 3.3.6, < 4.0) - xcpretty (0.3.0) - rouge (~> 2.0.7) + xcpretty (0.4.0) + rouge (~> 3.28.0) xcpretty-travis-formatter (1.0.1) xcpretty (~> 0.2, >= 0.0.7) diff --git a/NSE/Sources/NotificationServiceExtension.swift b/NSE/Sources/NotificationServiceExtension.swift index 0df8b17c13..3436f9b6fb 100644 --- a/NSE/Sources/NotificationServiceExtension.swift +++ b/NSE/Sources/NotificationServiceExtension.swift @@ -46,7 +46,17 @@ class NotificationServiceExtension: UNNotificationServiceExtension { // Used to create one single UserSession across process/instances/runs private static let serialQueue = DispatchQueue(label: "io.element.elementx.nse") - private static var userSession: NSEUserSession? + + // Temporary. We need to make sure the NSE and the main app pass in the same value. + // The NSE has a tendency of staying alive for longer so use this to manually kill it + // when the feature flag doesn't match. + private static var eventCacheEnabled = false + + private static var userSession: NSEUserSession? { + didSet { + eventCacheEnabled = settings.eventCacheEnabled + } + } override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { @@ -94,6 +104,11 @@ class NotificationServiceExtension: UNNotificationServiceExtension { return discard(unreadCount: request.unreadCount) } } + + guard Self.eventCacheEnabled == settings.eventCacheEnabled else { + MXLog.error("Found missmatch `eventCacheEnabled` feature flag missmatch, restarting the NSE.") + exit(0) + } Task { await run(with: credentials, diff --git a/NSE/Sources/Other/NSEUserSession.swift b/NSE/Sources/Other/NSEUserSession.swift index 6a2d99dbc2..52611ab698 100644 --- a/NSE/Sources/Other/NSEUserSession.swift +++ b/NSE/Sources/Other/NSEUserSession.swift @@ -34,7 +34,8 @@ final class NSEUserSession { slidingSync: .restored, sessionDelegate: clientSessionDelegate, appHooks: appHooks, - enableOnlySignedDeviceIsolationMode: appSettings.enableOnlySignedDeviceIsolationMode) + enableOnlySignedDeviceIsolationMode: appSettings.enableOnlySignedDeviceIsolationMode, + eventCacheEnabled: appSettings.eventCacheEnabled) .sessionPaths(dataPath: credentials.restorationToken.sessionDirectories.dataPath, cachePath: credentials.restorationToken.sessionDirectories.cachePath) .username(username: credentials.userID) diff --git a/PreviewTests/Sources/GeneratedPreviewTests.swift b/PreviewTests/Sources/GeneratedPreviewTests.swift index 33d08949e3..4dc11560a7 100644 --- a/PreviewTests/Sources/GeneratedPreviewTests.swift +++ b/PreviewTests/Sources/GeneratedPreviewTests.swift @@ -53,6 +53,12 @@ extension PreviewTests { } } + func test_audioMediaEventsTimelineView() { + for preview in AudioMediaEventsTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_audioRoomTimelineView() { for preview in AudioRoomTimelineView_Previews._allPreviews { assertSnapshots(matching: preview) @@ -179,6 +185,12 @@ extension PreviewTests { } } + func test_fileMediaEventsTimelineView() { + for preview in FileMediaEventsTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_fileRoomTimelineView() { for preview in FileRoomTimelineView_Previews._allPreviews { assertSnapshots(matching: preview) @@ -281,6 +293,12 @@ extension PreviewTests { } } + func test_imageMediaEventsTimelineView() { + for preview in ImageMediaEventsTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_imageRoomTimelineView() { for preview in ImageRoomTimelineView_Previews._allPreviews { assertSnapshots(matching: preview) @@ -377,6 +395,12 @@ extension PreviewTests { } } + func test_mediaEventsTimelineScreen() { + for preview in MediaEventsTimelineScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_mediaUploadPreviewScreen() { for preview in MediaUploadPreviewScreen_Previews._allPreviews { assertSnapshots(matching: preview) @@ -761,6 +785,12 @@ extension PreviewTests { } } + func test_separatorMediaEventsTimelineView() { + for preview in SeparatorMediaEventsTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_separatorRoomTimelineView() { for preview in SeparatorRoomTimelineView_Previews._allPreviews { assertSnapshots(matching: preview) @@ -905,6 +935,18 @@ extension PreviewTests { } } + func test_timelineMediaPreviewDetailsView() { + for preview in TimelineMediaPreviewDetailsView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_timelineMediaPreviewRedactConfirmationView() { + for preview in TimelineMediaPreviewRedactConfirmationView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_timelineReactionView() { for preview in TimelineReactionView_Previews._allPreviews { assertSnapshots(matching: preview) @@ -977,6 +1019,12 @@ extension PreviewTests { } } + func test_videoMediaEventsTimelineView() { + for preview in VideoMediaEventsTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_videoRoomTimelineView() { for preview in VideoRoomTimelineView_Previews._allPreviews { assertSnapshots(matching: preview) @@ -995,6 +1043,12 @@ extension PreviewTests { } } + func test_voiceMessageMediaEventsTimelineView() { + for preview in VoiceMessageMediaEventsTimelineView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_voiceMessagePreviewComposer() { for preview in VoiceMessagePreviewComposer_Previews._allPreviews { assertSnapshots(matching: preview) diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPad-en-GB.1.png new file mode 100644 index 0000000000..2c18ea9941 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e0cde871c15aa0fadf7c4f36f1e8efaaf1b6e4b183745970521c7e0682cc7ae +size 91919 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..c180bb1ec4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea99daf61180bf74a70fdfcdcf78f775cafbcf06034ef5cd35f887c7ebd09c92 +size 94531 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..95842019ce --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:462fbf7b26d76217a9045ba76a97c5172c63817383caf15e7a82e1db89a36d2f +size 48610 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..a2009a3efe --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioMediaEventsTimelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb2174ebc097d4670f75b14e90074fe5477d9ae364dc40f520e8e3d51f316cd4 +size 50374 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-en-GB.1.png index 77d646e93d..6d8cc72c75 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:11690714e9762d729ca2b9777494f4ffe479ca03b95e282c6dafcbcd0c6e47d1 -size 99579 +oid sha256:d3b53e20f2c6cc50e19de94c8af37e1a0f4b96ed577994d4f5e8e6d2bbda4607 +size 99180 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-pseudo.1.png index 738fbac9c3..d88b448387 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d029be2d41fb70268aafe9e252edea552014545591c9f06ddb5abbb7b872ad88 -size 102503 +oid sha256:48b6f07f5253cb191f6e29bc089f9b53170084b12b2a53fee14421926f59ed06 +size 103858 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-en-GB.1.png index 3d6a58edaf..1a34cae61a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d06795ef84b2f9eef65341825a0dcef00f5c0e646a0a441824b9a656eb57ef7 -size 55300 +oid sha256:c591e0f26fcb14be30b7076970c1bfc32603ab3c88d0ac3390b550c1d252f058 +size 55077 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-pseudo.1.png index 0d6d54cc85..79e18bbf23 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_audioRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:796fe32ebed61725457773d6bc27768f2a38fd5af2c0492fcd488125f8126fd0 -size 57907 +oid sha256:c98cc16ddfe4c0b0f428806446c933bb9a0e0637090e0b525b4a20e89f37f263 +size 59016 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.DM.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.DM.png index 97156a01fe..36bed005d3 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.DM.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.DM.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef2a54b62e2f537e2bd2b430cc899cd0928bf4e825e76bfcc42d96186daa5026 -size 123993 +oid sha256:106d9b668e83752856f44e0cc8c571652f41553e96207a844a44098c56575f4d +size 140208 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Room.png index 0e0ca7e0e3..c6fab72d90 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-en-GB.Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d2557dc6f6c8bf357f8941d5e34eca1bad97930e73ffcb65e747f43edab5ee9 -size 142395 +oid sha256:3b66462d0a4670928b0ee35a8b9abbcf5c2d7617cc3a47717e462e99ad558bc3 +size 143330 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.DM.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.DM.png index 634671c64a..54df42a6c0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.DM.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.DM.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85de72de76d8bdc38d38ebbc0cf9f3cb696aef6b9567e9ee998886601aedc34a -size 124368 +oid sha256:c3ead1253b52306fa36a4d0ee518380e84aaf9cb600c35aa3dee47b77e7c3dd6 +size 140615 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Room.png index 541513992d..1cad79e5bf 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPad-pseudo.Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9ace9ee3ae23e2212560269db976c2667f4e7024c8318cb744770ebf1453242 -size 143790 +oid sha256:e9fd7cf8993348eda6eaf43901d75b1c6a89053de2897c617ff531d4377be1fd +size 144576 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.DM.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.DM.png index 6c9ee54b88..df01f9b08b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.DM.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.DM.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d554256c0bed2b0dec2ab2357fb0b6f44e5f927e8766f5134d0083ebf8b77d6 -size 72733 +oid sha256:7e6403df9877eec093085104f829f6f7a8b07136c5aa3f106baa5bbd7aecdf2d +size 87293 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.Room.png index 0b31a5e511..72f2fa47e2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-en-GB.Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:781c7c0aa241138c17c18ca152815a0476fb9722c174f24dff3afffcea9cb2d5 -size 86998 +oid sha256:0a24f906c2cb55429091f93a459844d4e41159d0c359087122475d75ca58de84 +size 88561 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.DM.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.DM.png index 8386a8730d..3681d3a180 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.DM.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.DM.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:805b359ab4c8880717b6771e0acc049b7a8eed27214d4ef1833183d349e7dfa7 -size 74400 +oid sha256:cea4504bec3a2fe764b6b607c62873d2d2c9c94ab5da03d8538ff14972191eca +size 88943 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.Room.png index 86d56f78f4..d84d2ebe4c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_avatarHeaderView-iPhone-16-pseudo.Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbb2e14c8bf7b0a9b5082db07e123732ac26ef431418e6d3d62011a2100a7e7e -size 91331 +oid sha256:31bcc482e15d4dfdf5e98e471c6214f7476bea7a733ba975597a63169c05ddd3 +size 92845 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-en-GB.1.png index f89035f326..ca2e704440 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29e1c4741fd72fd2c0ce0954c1f860bf7dd9c0590e2991befe4c091581ba8fe6 -size 76921 +oid sha256:ca339c7b9e8185504843fe49a453a8d7b636b73c7936782ccb13f108147f8e64 +size 76775 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-pseudo.1.png index c814599211..0d389fc0a9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b84fbb757ad719d346d5505bf1c373900373e9ef447bfdde1f632b17393326cd -size 78213 +oid sha256:449fd71ec42d3421a439b84f3b91825fdb160dbe5a2159eb034c1246ab5d8ec0 +size 78924 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-en-GB.1.png index 6c008987d9..465108e5cf 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e08654a9df0f2117e49345e45c1e7bb0204af4d5a968b6f317b3d7882692197d -size 35727 +oid sha256:6cfde3cec208907c1540adcc417802d4e021bec98c8bee6b03dfc2cf425057b1 +size 35596 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-pseudo.1.png index 69006cf591..6f0f3ea2c1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callNotificationRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88a0a8ab19e8f42a06e078b6263ea23d2c11e7c9c837d5913b0b922048c21fcc -size 37254 +oid sha256:5f5c6d41e605f934e77104227186c7474d05a12e34e4d3a25fd8d71228132c1c +size 37800 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.1.png index 3b5c200b5d..10ff781d0c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6e63d693948eb3139609c45c2511a6db5213ba6d312082deba2dcca31bb836d -size 92248 +oid sha256:155948313888b1c61e28a992d7bebacfc03254647cde711a48ca3dde2946b7d0 +size 95285 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.1.png index 3b5c200b5d..10ff781d0c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6e63d693948eb3139609c45c2511a6db5213ba6d312082deba2dcca31bb836d -size 92248 +oid sha256:155948313888b1c61e28a992d7bebacfc03254647cde711a48ca3dde2946b7d0 +size 95285 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-en-GB.1.png index 2ad9f0eab3..061b9d8226 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:141cf3859c4b421be24e2409abc2d6bb4b53ff3c9878811cdbb6b67c901251a7 -size 49837 +oid sha256:de6d4602b7f4e588b6ff560ccb98bf45c5395c7f04c50b2a9db259a7f4283783 +size 52760 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-pseudo.1.png index 2ad9f0eab3..061b9d8226 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_completionSuggestion-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:141cf3859c4b421be24e2409abc2d6bb4b53ff3c9878811cdbb6b67c901251a7 -size 49837 +oid sha256:de6d4602b7f4e588b6ff560ccb98bf45c5395c7f04c50b2a9db259a7f4283783 +size 52760 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png index 51071b6860..8315d613c6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8a8066e41d3d84e7aedc675e7991b0dd57fc1f93f363312353bf43a236e3f6a -size 101416 +oid sha256:179231b4119308cd7c00233f00de90e943558d1aabbe94d5107455ccde161e24 +size 98675 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png index fce9df4b14..5400d42bd3 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad795840c41305dbe8028cfea18b8fe25d3be2ab9524bc3322ed77726df25bcb -size 101810 +oid sha256:6c5ca42b4081ae60bff5fda664141e9e7ef654c068ddf2d446de2667a57af844 +size 105323 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png index f293f957b1..03a5f27e4d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8fcc46292a1139dab8462e81a1f91bc177e9a05cbcf8ff6ef5ddbe15707cfdf8 -size 102213 +oid sha256:2b98edfa6801c0208c3c86e52e48c64d2ee54ec5c1085348a8ab8ca5365fa577 +size 99472 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png index 1b2a6cd0d3..330b0b9e9c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:70452fc6801a7a7778992bc40ef49c929744d76f0285e2f1aec33c09a5ae3242 -size 102228 +oid sha256:811aa9b4a3e0ff10a8c6ec5fcc67ea68c761830ee3b61a27e34388f08616c1e3 +size 105741 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Voice-Message.png index 029173618c..82f1734b5f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Voice-Message.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Voice-Message.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ffa98f5f715b47251f816c0fcab5c4ff62d51d60270f8a41a34ca3835c3e0f6 -size 58631 +oid sha256:b23b6fa54712013ff8dbf2b4e79163f3674f5228de362cc7c00a3b8a77b6a441 +size 56148 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.With-Suggestions.png index 322efcd586..2255fb1ae6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.With-Suggestions.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.With-Suggestions.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26b773b1dd1468c8298fc18062e9cc8749698536c19ca643acb1551f9293fb91 -size 57194 +oid sha256:b0df8cc42b1e7837261220333d0b3cde8f2127894a66936c31ed3daac426469a +size 60320 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Voice-Message.png index 2dfa3ceba8..b574f2073b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Voice-Message.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Voice-Message.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b411f75a2ce4d925ee0170cb0956129fd26b1c2d8b64b0741b82699bc058e6b6 -size 59463 +oid sha256:45f1cd517d9a670f11159feab5b07cec1197760449551db46cf33f50b514969b +size 56980 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.With-Suggestions.png index 1e2990cb14..163c28b2e6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.With-Suggestions.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.With-Suggestions.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a952ed17097a7d8d6b16d3a330e1eaf3fdea80dac026618d456b561ff10c39a -size 57608 +oid sha256:185daf8b5e5baf9e119c454d8f4b3f851fa38841a80bfe6c8321fefe17986e4b +size 60734 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-en-GB.1.png index 6ed1bf0056..66e4371376 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:702235a5e846a84f92711a2f6e66e59a06364763e57ee4ae1550b9ab03e8476c -size 103480 +oid sha256:11f8f3369d7cb4475273292b3ac8b136abb9e1938304465d7f6118a3a1fe1ba6 +size 103290 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-pseudo.1.png index 6ed1bf0056..07a6aa4399 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:702235a5e846a84f92711a2f6e66e59a06364763e57ee4ae1550b9ab03e8476c -size 103480 +oid sha256:ee1a11a692057d4cb4456f1a9e016a2430280b36e96f81c5253634bac7ee1e61 +size 105001 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-en-GB.1.png index 9a1092bb2c..268d67fe10 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fde29a6b348b8cdbf3e3d58736d6bcf860c50d8d61a6ba0ab591f507a82a91cc -size 69718 +oid sha256:c6ec4e3014d3a941820a7a8e11d50871331faf4515e7efc85f376a9571b46513 +size 69420 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-pseudo.1.png index 9a1092bb2c..9a14b2a2ec 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emoteRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fde29a6b348b8cdbf3e3d58736d6bcf860c50d8d61a6ba0ab591f507a82a91cc -size 69718 +oid sha256:39903baab7a714bb1cb96d5671153e7eb542d35972b454dded879a9ff269ca2e +size 70663 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-en-GB.1.png index 6973ce6806..b8b6cc1887 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b430f8f6bc48e6a9f2c91fad0b466ce1376858eaf2be4a47388071ecff8da30a -size 118462 +oid sha256:b7723a45c3430cd338b39a20d531280e216c98850da8203225ab9e5df856f007 +size 118002 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-pseudo.1.png index de3ec5f4d5..b91dcb11f6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5fd573e63c1811c8798aa3c2114e57532180a33751dd03d184710e661585472 -size 123432 +oid sha256:5f70eb32caf02c6558bc44f73fc196a3af6ea3d72dc76a92d4a186b67cd0a2ce +size 126874 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-en-GB.1.png index 7c741481ca..e17213bf13 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3e69b21964edc58faa211d7fff2147d3836accb85618cc67a073c01086cb083 -size 80764 +oid sha256:019d83b959e0106972e0a3fee94827fed1a679b881a3d002a63c7ce89f2111d5 +size 80258 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-pseudo.1.png index 95acab62bd..64fb2de5af 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_encryptedRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15e5630704d6949c4f6b53079789db3368db27e215cde7413d79a609d580d0d1 -size 103083 +oid sha256:27e3d1dfcb7d8666aeea233981141da687f92a9ddca514e302a0928c2941accc +size 106227 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPad-en-GB.1.png new file mode 100644 index 0000000000..57a17c8732 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e72e9a0f59a3b8967f7457cdbb2c11214f0793ea89807e3894a316c51b8cdf7 +size 120661 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..bf9d9204b1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddbef7603abfb93c1edd1c78cd3f8d9a6f8f484fca89d92abb8d3d424c185f87 +size 124318 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..ba57b7176a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e737333650f3f467d240e4a7e709fe38ed74f2370a08e54d2286a4b20339499f +size 72725 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..a5d4ce7046 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileMediaEventsTimelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ea15196e740ba28f3818f83a778d9992dacb10b9a9959c0f5edad69121c9212 +size 76629 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-en-GB.1.png index a6a5188237..63e993cff3 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90f04fdb63831afb462488dc0afbcf78e9a2c1f8ccfae3855432d6b23f23f0d4 -size 137263 +oid sha256:e2a98c631c75cda4c23c5526e2afb813aa2c080be3bc67fb6d738bccb67bdb57 +size 136530 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-pseudo.1.png index b981dcc80e..ce1c7f0d7a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:daf4fbf2db6fb4412d80e949cb4374a5aa456bd1458919ee1d90f36fead48d07 -size 141084 +oid sha256:ef3b12f53fb49c4a0a3a11f1abffb21764d7b214b425437dccf572adeabf758a +size 143746 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-16-en-GB.1.png index 0386112477..701cc09d53 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a938ef5e6940b0f3c65a345db8c34b648873a7f2037f154569f22fa35e71aaa6 -size 89747 +oid sha256:3392233ca4467a372098ec75f53e1041490c4a2f721c0a9f547e83e434b6c318 +size 89292 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-16-pseudo.1.png index 4188d70a77..c4101e039a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_fileRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3615b93b61f8eb6baa432734763d405fe3f6b679d67e11a25277e760188f8189 -size 93512 +oid sha256:09c4eed152e1b3fcf6ccda1baa1778577e4cc71d239bc6c30aea17213c1273e9 +size 95252 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-en-GB.1.png index 776f11c899..aae27a6caa 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f10ebfd3b38c9c5f884d8413143c3ee6dd12d96b52de451ce76dd30447c7aa28 -size 322442 +oid sha256:a53cfbfc88026e695e6fffe2b651a8d68bec0a3fee91875ce2c651d8a4d61de5 +size 321468 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-pseudo.1.png index 776f11c899..aae27a6caa 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f10ebfd3b38c9c5f884d8413143c3ee6dd12d96b52de451ce76dd30447c7aa28 -size 322442 +oid sha256:a53cfbfc88026e695e6fffe2b651a8d68bec0a3fee91875ce2c651d8a4d61de5 +size 321468 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-en-GB.1.png index fe1d950a8d..e32799e565 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:657d50373f7aaadceb1928130eb4b03e78c59f306f048f94439f7dcfb97823b7 -size 248336 +oid sha256:0e52762fc68301b3b7a95b6702528d2c1ca6fd7ddbe83bbf730162dd23e59d92 +size 250960 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-pseudo.1.png index fe1d950a8d..e32799e565 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_formattedBodyText-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:657d50373f7aaadceb1928130eb4b03e78c59f306f048f94439f7dcfb97823b7 -size 248336 +oid sha256:0e52762fc68301b3b7a95b6702528d2c1ca6fd7ddbe83bbf730162dd23e59d92 +size 250960 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-en-GB.1.png index f498e2c853..8e3b2d8a9c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec8339fcf606ac520989a6915da4f3a15a43d049e49c3e93524ad70bd8097778 -size 148064 +oid sha256:41267007d7aa9d30a894f9448c841ea3a7ba6f97236803489c31cde388f676ef +size 149257 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-pseudo.1.png index 665b44f58c..317d51943a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa3fb400d0af05b6c81181a040f3746c11fafe82703f7587ae9d98cdcce44386 -size 148467 +oid sha256:ee00bfe537ffa952b156cd261ffd6f6a48fe0193527f371951633cf44e8735d8 +size 149673 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-en-GB.1.png index c585a86568..d5a703f2a5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed42c3e99db34f3dedb33b5faaf768caee7d15d8d5dfb50fbed0f97da2b990f0 -size 85859 +oid sha256:f910646987cb81ea2b1afa072d548dcf4430e1e8caee859b9a7415d9bb0de9d3 +size 86735 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-pseudo.1.png index a82c51c502..98c32855fe 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f33f9d8cc790b5a03c0da8423e948bc9faffa7580e587d509e13fb691a255eaf -size 86196 +oid sha256:5a95a3a75a11c38dfc02c74262ecdd45140f8fb57d9daeadb82bfec9a77dacc8 +size 87054 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-en-GB.1.png index 0d0446d626..01d61ee1ff 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c53dcda54eb95e575116aee3cba95365d7ff511db660a02a48ba99097605821 -size 93632 +oid sha256:dabaf0fb78fe51d87068af315b4f2b92e55aa87d91ccd784841cb22c90299752 +size 94311 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-pseudo.1.png index 0d0446d626..01d61ee1ff 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c53dcda54eb95e575116aee3cba95365d7ff511db660a02a48ba99097605821 -size 93632 +oid sha256:dabaf0fb78fe51d87068af315b4f2b92e55aa87d91ccd784841cb22c90299752 +size 94311 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-en-GB.1.png index 5feca9ddf7..6ce0078f04 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe63f47dea34b2cbeb699e1354e69e2fd16bd74860542e7a44c47599f94f07f8 -size 46985 +oid sha256:f5e2548fd5312f9dea833e26d1e7b3ec92214b6f9fae479f142a149063d63837 +size 47913 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-pseudo.1.png index 5feca9ddf7..6ce0078f04 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_globalSearchScreenListRow-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe63f47dea34b2cbeb699e1354e69e2fd16bd74860542e7a44c47599f94f07f8 -size 46985 +oid sha256:f5e2548fd5312f9dea833e26d1e7b3ec92214b6f9fae479f142a149063d63837 +size 47913 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loaded.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loaded.png index 6ca74c12df..d5bf21960a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loaded.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-en-GB.Loaded.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:495dbe5adefdc1598ec80beea331d0f78de7021992cbca9459060e9956fe006a -size 242329 +oid sha256:d10499f6d659a2d1584370a39c07708637e2ffdfad7a0b858790e0eadd95eccc +size 244272 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loaded.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loaded.png index 756bbda259..c714ec38fd 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loaded.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPad-pseudo.Loaded.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f8540714ee55258a4e4bc904ad249bad76664987a37e43f027fca0fbf88319c -size 245488 +oid sha256:10e904ca1164aba89afcc4206f7f925e3b4e6cb16a87e56bb8563b34d8015ac2 +size 247441 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Loaded.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Loaded.png index d5443fc4e6..c18f31b7e9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Loaded.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-en-GB.Loaded.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f147d11e7430cee9703d6ffd1d77aff7eaaaea933f563391864ea05d7a4ee0c -size 178416 +oid sha256:4ec40a66f53b885e8dbdd5518abb3ed74bd10371dab614b02438104ec14999be +size 180019 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Loaded.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Loaded.png index 981a244a45..1fe873005d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Loaded.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreen-iPhone-16-pseudo.Loaded.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bdf467b1fe27e468487ec97153f7e25b12305c30397b4ebf74e85fe260da576c -size 181049 +oid sha256:fc466d3f59730b45d614b1db16564b0c9dea3055d2c9abcdbe82ecad3f139c28 +size 182674 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-en-GB.1.png index ecb5e6d2eb..f89eaac446 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a992e048e1aac5508ad22d87a7765e44b8a9aee0b6a39b1ba49b11193a2ecaf -size 259331 +oid sha256:3702ab78b2edb32a5df416281ae7f49c3725c2c09a80abc26b2621b293d055d1 +size 261814 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-pseudo.1.png index 201e0ee906..f09e8bfe99 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5197c5a72cb20ed5e560c1066d667baf08430356e7a4c9d4afa8791d43fb2b58 -size 274945 +oid sha256:33dbb6eab331632b1fc617a75e531aad63093675694961355d9ddfd98a69fb9c +size 277753 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-16-en-GB.1.png index 815ed49fb6..3e8946a256 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c5a0737e9311c83483d6c11a80ace664ff9cf6c0f197aa908eea125b524f8e2 -size 175689 +oid sha256:b8a09fc2cb4a0f57a7317ed8b8cffb26dd003674ed1139406a70e41986987635 +size 178089 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-16-pseudo.1.png index 3fe419dde8..85487e521c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenInviteCell-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:553f92fd699ac9280c3f8d5cadbdafd7e79a266e68fcdd0bfdedadc760cd8269 -size 194749 +oid sha256:5affeefabee81ad1e2f35fb4dce63ba61502535ecf77ca89fbb0e78458a115fb +size 197008 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-en-GB.1.png index 22451945c0..82569b97c7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05bd2d1fcf45e1027fcda440616ad6244b6652ce6088d654b27d5ac0461669cc -size 176959 +oid sha256:0b891e22cd7a678a8da8d072c037f5e504bf9c2470667a6922aacfaaae2c3906 +size 178863 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-pseudo.1.png index 792d286ff0..b77758115c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45b8896561b5b8b0dcb899a7a684eb0057383d668076198b3eba38c8fbf8fc17 -size 190293 +oid sha256:6bcbb692468dbc5207b7a8d78d45858362e4c97ae44a0a1dea83e08424f4f0e4 +size 192171 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-en-GB.1.png index 2ac478ebdf..b671528205 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d385a376913dbe1fd2f89357e66be6a93272deeb88ef2c68c4fbcf5626e2bf7 -size 122079 +oid sha256:53edde007daf54308a5ec91f842ebb5dac7ffdc8a88f485f801d867e04d923bb +size 123516 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-pseudo.1.png index e0790c12f4..913d966f6e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenKnockedCell-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9a7709d84f25f4e66acc254ca04eac7a7361f87312bb34297bc88762c3601b5 -size 144308 +oid sha256:a228e6b1c1f945a410073deee6796f198c030389b78c32ab2128290b4f3bf841 +size 145979 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Generic.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Generic.png index ff485cbf3c..fa6ff1eba0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Generic.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Generic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2e64acc7685ad88338cdd6be6158c26c1f3e244f746240d331368026fd4a6a3 -size 220584 +oid sha256:1f2f8729657337139e4e7b8c6bd7d2d14e18b2ff3dfbbac1579105ab4c8bb705 +size 222416 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Notifications-State.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Notifications-State.png index 067aea2cc5..3bc2c52018 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Notifications-State.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-en-GB.Notifications-State.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90f8f8afd3af276369f1ab2fa6444a2fd8f57ce6b264533ee0167c2c20d3b866 -size 740831 +oid sha256:c1f866dbcd274f9176e3e9c7b015774b1d4983e09c4d6a36d2c0e7ef4c7497e0 +size 740365 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Generic.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Generic.png index ff485cbf3c..fa6ff1eba0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Generic.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPad-pseudo.Generic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2e64acc7685ad88338cdd6be6158c26c1f3e244f746240d331368026fd4a6a3 -size 220584 +oid sha256:1f2f8729657337139e4e7b8c6bd7d2d14e18b2ff3dfbbac1579105ab4c8bb705 +size 222416 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Generic.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Generic.png index 29dd6ede1f..385feb2ef0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Generic.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Generic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5603cf5b0486ea13e7044e07a7b9170a8651d1f995c4e225c0b3cc2c3a7b24ce -size 162192 +oid sha256:aca6502389a237bcaafab9a323411b8c90bbe008fdf6913dffa8549d8484133c +size 163851 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Notifications-State.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Notifications-State.png index 18b9503fb1..4b26343f60 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Notifications-State.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-en-GB.Notifications-State.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6a4b11e76d396bcb0ec176064401e6cfe389abeadd23847fbcbbbe439d9aa9a -size 515632 +oid sha256:d5775431191c8f71588376aec8f0d37c645093136ad8c8aca1dd1bafb2b7fa05 +size 516093 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-pseudo.Generic.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-pseudo.Generic.png index 29dd6ede1f..385feb2ef0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-pseudo.Generic.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_homeScreenRoomCell-iPhone-16-pseudo.Generic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5603cf5b0486ea13e7044e07a7b9170a8651d1f995c4e225c0b3cc2c3a7b24ce -size 162192 +oid sha256:aca6502389a237bcaafab9a323411b8c90bbe008fdf6913dffa8549d8484133c +size 163851 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPad-en-GB.1.png new file mode 100644 index 0000000000..84f8e3bef7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cdee3d600b60fdbd1a4ee024a32fcb96aa1acede48816ac44fea31dd6f98b2e0 +size 95367 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..84f8e3bef7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cdee3d600b60fdbd1a4ee024a32fcb96aa1acede48816ac44fea31dd6f98b2e0 +size 95367 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..5e62e5d438 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc9a10f0defb81ffc49b373264d7a427a4586d00d2953474ed52d4750d0cced2 +size 83265 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..5e62e5d438 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageMediaEventsTimelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc9a10f0defb81ffc49b373264d7a427a4586d00d2953474ed52d4750d0cced2 +size 83265 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-en-GB.1.png index 92fed002bb..81288b66e2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82ce96aa44eb950fb131e85d6ceeab485a5985fb48c30b4d954c65602e77686a -size 281497 +oid sha256:07171c89d5ea45b181fb7c1e97e72bf0dab2c0cf1a2672be4524f4280b6b0bab +size 3055431 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-pseudo.1.png index 92fed002bb..9a5ac639a0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82ce96aa44eb950fb131e85d6ceeab485a5985fb48c30b4d954c65602e77686a -size 281497 +oid sha256:02b8d56780b78dc8558ee0a9bdbefabc1b22f629f7f2033c9280b28b616bec9b +size 3054607 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-16-en-GB.1.png index 43321c49a7..d976ef22fc 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d08539366199fb29c4f2b01b6b399426b928a0eaae94306441d0a6cf34be4a13 -size 225250 +oid sha256:9b24b9ca76f87aa2f1af0fd6773ce168f51d884677464b0bd86c7efc916195f5 +size 1504110 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-16-pseudo.1.png index 43321c49a7..9b0410f4c3 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_imageRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d08539366199fb29c4f2b01b6b399426b928a0eaae94306441d0a6cf34be4a13 -size 225250 +oid sha256:592f62573bc89468b58e66a57db6534461597bbae2f3dd4449aafb028f3c369d +size 1501742 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png index f9236284a9..4244a8a644 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Invite.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8927edf5a98a3beae9d1dd2a61985b5402b72ab5688a2960a8c65b726b28e7a8 -size 2016923 +oid sha256:1645515771a470a87b2a6bce077fd4605cbc1bef9eaf5443568b5df90c2de311 +size 176707 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png index 3218c7edd5..34eac97d3a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Join.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9390f013722ba23d3b9ade888bc484e7b276e223f135d6641371d60da690397 -size 1971897 +oid sha256:9631828c623d72046f50e0adde6c5310b53314e62bf29c50341815592ae2d8a6 +size 176333 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png index f900ee4495..fc9554a90c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knock.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:659cf8286eb523208e2fca0ba19578ff4b33a0076dea962fc3f133a089f5bca9 -size 1816652 +oid sha256:ea029779d25f9371956629e00cdbd28555d9f33c965099ae5bea3ccca474ee29 +size 188184 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knocked.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knocked.png index c7919792e2..11379a194a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knocked.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-en-GB.Knocked.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:630995e1d62ff737c63bda878adec6756c0baa5a0136fb898f9cbf07ef52aa43 -size 1987392 +oid sha256:32dbe2fdb963e3f44abed48231db363ebcb2f2792ee5b6e987beeaba4c7d27e3 +size 108943 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png index d793b5ec09..95067ec747 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Invite.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:177f9b216f7716c511037ad044d08c499bc1d33b576d46dbda7d6c67bb513f1e -size 2022040 +oid sha256:c24082811d674e78690542d5ad4447fae4028a1b7d6e3b7182ce348f0422e1bd +size 181607 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png index ae566af5c2..6af318eaab 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Join.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a13076406c868e7b86d89782752c1fe70776151623c18d6fe47e59671120e0d7 -size 1972878 +oid sha256:8d2c3b773eb35ca1938e19eb413edefc154819ad296297d1db52d41bf4244a2b +size 177403 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png index b72d10f4f5..cde7f0b240 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knock.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:563f7440384e75819f985d659108c5e37bd8c5bca2ca79fbdb2c1ee0617ed17d -size 1824851 +oid sha256:6cba375d9786e5f3f60729d90ea80e04512928b1d99c25df5a3e12797e56feab +size 196127 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knocked.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knocked.png index 2a844d9813..6a2be45e61 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knocked.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPad-pseudo.Knocked.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a81a307b980a5e1d950c98d2fe2981d0cf138da722d76007dd2f61693d85c208 -size 2004686 +oid sha256:99e979255bd6e0cdb76ec16cba8522f5610e5a14a80391cfb91875ff576c7237 +size 120516 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invite.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invite.png index 8eb621c81f..0aa8d7e089 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invite.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Invite.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:329b0b5fd32c1e395f969a006d2b56d399292abdee46d6e15df89bf3a8005d89 -size 851720 +oid sha256:bf9575beca228f4ed808a40f5fab5cc49ff3e14b8d4b25bfd5d24bf69a12cb89 +size 121706 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Join.png index f22223291a..acfddaa162 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Join.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Join.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f6a60932fcba3f2bcd0127af134fd7005cc74a3ba02bfa1717466c35e92ad8c -size 823057 +oid sha256:947f1bf8fdc8202333df2a4c11c77856de43bfec3e4c9286df332554f1ecc4f8 +size 118228 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knock.png index 4ea478dc6c..ccd574f81c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knock.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knock.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f3d9a81bc16d26c4048e4bd59fefe56159a10f2a0f32139ee84ecef7f4d001f -size 728704 +oid sha256:5b5261fe4972edfc4056168497f9fe4145cef7b108985d607c4347acd6aeef8b +size 128093 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knocked.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knocked.png index 3f5ee33021..79c6ffc802 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knocked.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-en-GB.Knocked.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72ccc0e3a37d2f8728fc59240b0a11099594e8576a4d89b2ad462ba422a2d38f -size 824019 +oid sha256:c52cde3ef3bd16559d530ed97fee81c163cee4d7b1ab10aaed92ad37e2e33fe0 +size 65335 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invite.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invite.png index 422ad1cbd5..7110aa5017 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invite.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Invite.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2fb7e4c00fd1d30189f80d8abcf05dd3048039ce61a387f98691bfb618c9218e -size 859617 +oid sha256:46731b3bef32a06409ed48eb4b2311a396def898d24c92d7e17c0d289e0a292a +size 128657 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Join.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Join.png index 0920fc6c93..1536243066 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Join.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Join.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd08e040f1aff5e3ca2b50965a2bb368557134e8e3bc5bd6e390a1b4a328ae67 -size 824771 +oid sha256:271c66b0fc2805da5afdf54cec271ef9a9cf269f7e2ba792090908007b19acb8 +size 120239 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knock.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knock.png index f430d91d1d..630ef215da 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knock.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knock.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cbcee4066b91f8649d34a66b1b42dfd036541ed7eb7043bff6618089192ae1a -size 736832 +oid sha256:83bb5f7f5eb52dec7256c42d97623638f866fe885b576f7fcdebdf881f972071 +size 134322 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knocked.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knocked.png index a1596ce245..0c482d82fa 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knocked.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_joinRoomScreen-iPhone-16-pseudo.Knocked.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9482f0f3428f1826ef0e5d7e83d65aa895fc88c8db8a756c8c93c2767300f99 -size 840024 +oid sha256:afb92349fbc394a29020f766a4618b0e1bf993bda0ebdc9f08bf58f13cbf50cd +size 79086 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Multiple-Requests.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Multiple-Requests.png index a8d96c2b2a..434c0ac06c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Multiple-Requests.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Multiple-Requests.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3879eccedadd6ef4dd6ae91070a0271b0fa064c025614933d0ac364ded809340 -size 91991 +oid sha256:cfccc8cc6f248c09748e20cfdf5cb663dccb783b5c4af1eee7e73e925c282a10 +size 92265 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Multiple-Requests.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Multiple-Requests.png index cf3f2802c9..e3a7fe95d0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Multiple-Requests.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Multiple-Requests.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:494a4003821e6bdad2cafeaf1d3403de5801450a268b1a444fa227b3f04ecff9 -size 92830 +oid sha256:b774a8180dd03f6b1d99132c2e240a454ba27d7d562ea18f1fdf5edcc8eccdeb +size 93111 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Multiple-Requests.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Multiple-Requests.png index 7327e9bc9e..ec225234ce 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Multiple-Requests.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Multiple-Requests.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:415af5d4976c78a0ea3d69441cf77498d3c2412592c8c4c920105bc1f5e0805d -size 50054 +oid sha256:5d6532b2e58457f3c6534634134680e2c2365752f3da94dc236f76da3e905cb0 +size 50411 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Multiple-Requests.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Multiple-Requests.png index 71e1663a3d..5215088fd7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Multiple-Requests.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Multiple-Requests.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:69c9eb6ef65eb92d7270002ceaa4a4e3d2326980c8656b6a5ea34f3c3cc62e98 -size 49455 +oid sha256:bbc7b975d03869322a908426a86dba2d8c3e6601bc56cc5ae41c3725288e1228 +size 49774 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.Loading-state.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.Loading-state.png new file mode 100644 index 0000000000..3aeccd4cb6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.Loading-state.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ba63d3fcb12367a3a5c0e940698e71aec8ecfc0ff9c0cb598823860cedee53c +size 37802 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.Single-Request.png new file mode 100644 index 0000000000..09e4658ce2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.Single-Request.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6825687515e2794f01e0f14a350221725379f9f03e70c3fe7a8f6a2c8d1a87ae +size 96599 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.Loading-state.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.Loading-state.png new file mode 100644 index 0000000000..3aeccd4cb6 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.Loading-state.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ba63d3fcb12367a3a5c0e940698e71aec8ecfc0ff9c0cb598823860cedee53c +size 37802 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.Single-Request.png new file mode 100644 index 0000000000..f0346d96c7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.Single-Request.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d3c6d54a59b7c801a771949489fd3624684c87d557f84432da0547b50e7ce544 +size 98936 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.Loading-state.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.Loading-state.png new file mode 100644 index 0000000000..659f19ba83 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.Loading-state.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b649e830e7ab43a1b8828a83886f65904e4efe808d07edc92aaf1b10fb2c065 +size 17355 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.Single-Request.png new file mode 100644 index 0000000000..2f53a3b43e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.Single-Request.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f80a2cff38248a36a08765294fec6d23a84af19f853baf768adef8f529b6ded +size 52364 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.Loading-state.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.Loading-state.png new file mode 100644 index 0000000000..659f19ba83 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.Loading-state.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b649e830e7ab43a1b8828a83886f65904e4efe808d07edc92aaf1b10fb2c065 +size 17355 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.Single-Request.png new file mode 100644 index 0000000000..15e9b1996c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.Single-Request.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ce6690f1099bbc9f5a904dc49edb3a985d9490312565509077f0228df3ac864 +size 60386 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-en-GB.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-en-GB.Bubbles.png index 866db1ede8..45b875ee9e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-en-GB.Bubbles.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-en-GB.Bubbles.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f75b5504a3ee6e3d47737fc0490f0bca3629d80a8fed607a4ca6c35a32c909d -size 1027852 +oid sha256:7fb62383066a45ae514f8736f6ea08b8a5c0bab0c231836613ff57d1ddb95975 +size 1027619 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-pseudo.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-pseudo.Bubbles.png index ac44be9a29..c160964055 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-pseudo.Bubbles.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPad-pseudo.Bubbles.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ada69e2040fab6f2d842df492c4376e154d7990c6398679ba0ab85e3f752cfeb -size 1029365 +oid sha256:8575f49f01e82cbca9366dab9b31954df18e0c8a2fc267225fc3ca9d93286695 +size 1029185 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-en-GB.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-en-GB.Bubbles.png index 535cb3f7ca..a980827104 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-en-GB.Bubbles.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-en-GB.Bubbles.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e98a73d4400299b598412e5b39ab36578ec7340224c2c56827284d6a2d6f32c -size 607551 +oid sha256:667d2b653d460a351e8c9b1adf708532d215b465ecfe3548409a1de3abc12ba5 +size 607504 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-pseudo.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-pseudo.Bubbles.png index abf70f5cb2..c33726c2d1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-pseudo.Bubbles.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_locationRoomTimelineView-iPhone-16-pseudo.Bubbles.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b90878891af72fd14ecea9ca76d39853452ff057bfb2d6b8a30be70048378d9f -size 608331 +oid sha256:547c133de43262b6e4a3a91231af8ed39af98357dd7962df14dc8011379100a7 +size 580526 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-en-GB.1.png index 01a3df526a..1500517ad9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:211cac8155e25dd9beb17751a93bebfd37892c00ff739e863af7f4a91f62bb50 -size 108033 +oid sha256:36982e2a41c8c0714a23cdb36f836ec8cbc27dd358199b903d09bedc9e755e63 +size 108470 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-pseudo.1.png index a049a98ca0..6e1f6079b8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7a41af9a189d0f5f791e0225008d19e11140a9e6af7a672cfef31771663eed8 -size 108741 +oid sha256:756efc0968edd70f952a17e3c9f1e14b74e44addc2d55936e904c004230a7604 +size 109189 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-en-GB.1.png index 1f1b8e36be..8862c7c7fd 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5a42c7bf3d6d632e50cd7b9b9bafe7febcd7d5ba40122f58a7833a3b2866921 -size 67960 +oid sha256:18af56a5cf5677afe99ffa7036616e72674a666fea70dfaeb7165dd06a915171 +size 67436 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-pseudo.1.png index d28527db14..492232cc0f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_longPressWithFeedback-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c8266a83c333124c0baeb82377174eff028fac8cdb9db827d1ba74c3719a3b1 -size 68653 +oid sha256:d6fdbdf4826ecd355d0a85f664e7ebe0631124def0b64a708463aa25ce18e5ca +size 68095 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Empty-Files.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Empty-Files.png new file mode 100644 index 0000000000..73dea32c06 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Empty-Files.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb3769ea66b8dc7312847f35ee71979324ed2f209a295ee0953afee377eb2176 +size 531223 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Empty-Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Empty-Media.png new file mode 100644 index 0000000000..d391e6ac4d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Empty-Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dfa699d21838219f07d90ae7e0b2e1e28cd9dfc96ce7c47eb6c87d5a421c3e4c +size 524500 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Files.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Files.png new file mode 100644 index 0000000000..c1efc8f588 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Files.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51741b607cd001a1a7e8ce7ec03cdcbd35bc294a9b9bb76e05469561542a38f4 +size 146263 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Media.png new file mode 100644 index 0000000000..af0c0932ec --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-en-GB.Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c63ab40372661a448449f81e772cff9e05615a5ed4f027996984a46ee201bf5 +size 779262 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Empty-Files.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Empty-Files.png new file mode 100644 index 0000000000..b50034e36d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Empty-Files.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbf40a036347c7da245c280264420c77f47b924f42027c5639b47dd59648182d +size 548028 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Empty-Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Empty-Media.png new file mode 100644 index 0000000000..293dfd1beb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Empty-Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d600dd3d02c2c90a01e7536d6c68095e8bb666cd84ed4750b63296bde09b1dee +size 539182 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Files.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Files.png new file mode 100644 index 0000000000..b29218930f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Files.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63987ffb9a91d412c7bc6dc813230d21223ae5b91781daede3acbf624ba4f752 +size 148838 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Media.png new file mode 100644 index 0000000000..208393b866 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPad-pseudo.Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d9a1af757a18d9ab7d3ff8d7ac18a29a41ca54f61a6ffc5bea5fdf5692fe8ed +size 786023 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Empty-Files.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Empty-Files.png new file mode 100644 index 0000000000..ebc788856a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Empty-Files.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ce1c43361e481251f9ee846ed645ae89f1de9442a8c52cd5ef1862b860fb91a +size 341032 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Empty-Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Empty-Media.png new file mode 100644 index 0000000000..e8a0ed80be --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Empty-Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c620f731b5af87b9b7477f717ca38f9b556a49d890bc5a78634d27f49eb27b9 +size 337316 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Files.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Files.png new file mode 100644 index 0000000000..394b23c22f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Files.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cfce1624b822fabe439d77f47fcedfbaab78b4b9f5dc20518c47d315f097dcd4 +size 87008 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Media.png new file mode 100644 index 0000000000..c1e0f6eba4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-en-GB.Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71d2fe4ff56b2f7f457f341570aa9b55a61cd699f3969a3841ca8757b0529403 +size 857564 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Empty-Files.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Empty-Files.png new file mode 100644 index 0000000000..1ad118bed2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Empty-Files.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b407d22285115eedcc18300d3227b0834fd5d779f5f1c022dff72a4866f4a476 +size 355876 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Empty-Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Empty-Media.png new file mode 100644 index 0000000000..9adbee63b5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Empty-Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:12fe2c7958a06fbe01ee62ba85289c9fad10263aa86f9639dd50dc741776ba9e +size 348701 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Files.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Files.png new file mode 100644 index 0000000000..3f02404cec --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Files.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa188dd55c8b9cdd46318ab24209a8458a61abe11b9c52fc05086724c4b7fb1d +size 88770 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Media.png new file mode 100644 index 0000000000..f18fb9a5cf --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaEventsTimelineScreen-iPhone-16-pseudo.Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cebdb3063cf19ef4fe6194c6d6cb014bed63daf15580ba7cfdaf1f2ea04d117e +size 863167 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png index 480ef09fe2..b23be47db5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:742693f46cc68c183a0996ef9dd008feb93637ac548db45f202485dc3e8a6849 -size 92357 +oid sha256:2a50f4860f6ce3fc2aff3a3f8a4d72899cda87c25fd4c9ec935cc623c9548c05 +size 89566 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png index 1383459ef5..ede303a1d9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:725f841b450a1246120002770a578df844c3674c3dd782fea8f284f451df408e -size 93411 +oid sha256:2fb4fdb396dd0828f9fa2704f5255663d11dc56986de6b69e5ce5391c33b5cad +size 90595 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.1.png index 9f1fb6b938..c7e3b42db2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2689c49be718d18370c01e0fbcf67a77c358a057a9d6a6d7627930072c22d2e -size 50886 +oid sha256:bfedafcdcf81ac2f74ae00c10d8c04445507a9f64c3b35685958d35099b773c4 +size 48446 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.1.png index a178888568..21d02a9129 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a0cfc0ced4f4ab9bf6944b82217e1ed46f54d2aa2d358d040aa8c67f4a24074 -size 51725 +oid sha256:566f7e7e5f227f2b13a76ffcb876007be5e5e6f06df89a23a6a424f84bf35e98 +size 49303 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.1.png index 1b3feed28c..368739c7bb 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d00776a5033ba2bf44c909bd5c41a422ba3f8675bab60cee885788440f38a34a -size 76078 +oid sha256:edb491f82123d0aec8e2fd8b74c5090398ea470617b53ae6369a00755ad561e0 +size 79686 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.1.png index 1b3feed28c..368739c7bb 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d00776a5033ba2bf44c909bd5c41a422ba3f8675bab60cee885788440f38a34a -size 76078 +oid sha256:edb491f82123d0aec8e2fd8b74c5090398ea470617b53ae6369a00755ad561e0 +size 79686 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-en-GB.1.png index de20826930..215d8126a1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87252ee182a5c1c0c8827b9fbb4679fcac0ad6829d92702f37a94d42ff069e91 -size 35403 +oid sha256:1fa684923490be477d8f0a664721e22eabbf9e14759165c63861ad375616dff8 +size 38769 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-pseudo.1.png index de20826930..215d8126a1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mentionSuggestionItemView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87252ee182a5c1c0c8827b9fbb4679fcac0ad6829d92702f37a94d42ff069e91 -size 35403 +oid sha256:1fa684923490be477d8f0a664721e22eabbf9e14759165c63861ad375616dff8 +size 38769 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying-in-thread.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying-in-thread.png index e7368f76cd..e50cafa1fa 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying-in-thread.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying-in-thread.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71cb80dc579a03031aa4de25bf2af339ddd8670651c0e3a5b4fb5d0423592455 -size 196910 +oid sha256:827a74939755a673e095357a4e827a3519df97d509e58923a9f1865d33a6db4e +size 212428 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png index e7368f76cd..e50cafa1fa 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71cb80dc579a03031aa4de25bf2af339ddd8670651c0e3a5b4fb5d0423592455 -size 196910 +oid sha256:827a74939755a673e095357a4e827a3519df97d509e58923a9f1865d33a6db4e +size 212428 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png index f76ef12797..86f4bdeeb8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:218956837978d0f8f16b8744a064f5ed78be91a8be0a712cae7536f54867319c -size 200002 +oid sha256:8a484f4cb142d33b5bc02554374e2499bb51e6c86aa10c46ed585dae30c3f32a +size 215703 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png index f76ef12797..86f4bdeeb8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:218956837978d0f8f16b8744a064f5ed78be91a8be0a712cae7536f54867319c -size 200002 +oid sha256:8a484f4cb142d33b5bc02554374e2499bb51e6c86aa10c46ed585dae30c3f32a +size 215703 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying-in-thread.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying-in-thread.png index 69aeadc93e..2fc3021b0f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying-in-thread.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying-in-thread.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19d120c20ff2a374d05884e6599032a4a3d4982dd9e2d19bc4e28e95f79cb4e0 -size 136286 +oid sha256:389b5a84f277000e97039887f72f4fb8a104d8021495760c11bdd63d1b797758 +size 150003 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying.png index 69aeadc93e..2fc3021b0f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19d120c20ff2a374d05884e6599032a4a3d4982dd9e2d19bc4e28e95f79cb4e0 -size 136286 +oid sha256:389b5a84f277000e97039887f72f4fb8a104d8021495760c11bdd63d1b797758 +size 150003 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying-in-thread.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying-in-thread.png index 990235129f..e8c446bcff 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying-in-thread.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying-in-thread.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da4f3b1174b24ae18c931db745a788e01793f73693fe132cb29836728db76172 -size 139540 +oid sha256:484fbf46d698d5c278861cd2f73f48030c8f8dc80bd12ae3d395e74268b2e5e6 +size 153383 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying.png index 990235129f..e8c446bcff 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da4f3b1174b24ae18c931db745a788e01793f73693fe132cb29836728db76172 -size 139540 +oid sha256:484fbf46d698d5c278861cd2f73f48030c8f8dc80bd12ae3d395e74268b2e5e6 +size 153383 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-en-GB.1.png index ecac4d2963..9ac4415154 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d2de8898d28006764b1800937cb310b8e1cc0412ee7307c793096f050a80f9a -size 149110 +oid sha256:54e661464dbf0687b5953c95a89a33d9750aa8e601dd038cfc8a04a3ecef8811 +size 150264 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-pseudo.1.png index 00d2660199..5f6dd9fd35 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b071f66bb5f21fb1bb8362dd2814252c648cb096d7018d085677312854942520 -size 150997 +oid sha256:3eac656f64dc1a1ee5d9f6ccffc64f001052297384556f1aaaf8850359728950 +size 152134 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-16-en-GB.1.png index 8c1cbc6d3b..511719a8d9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5399fdd67f117a607c064937bdda1ca9982d22ce19050b7f4cc9cd919f9fc8bd -size 99181 +oid sha256:c53055e14a6b951bd96aa7abf844ab469ee91c6d721d1356bdef8427896892cb +size 100225 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-16-pseudo.1.png index e76c8e5ba8..668949fc82 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageForwardingScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0bdb9abcd374036fed3db3f52a0cce19c645fafd38117b20f986ec1921fc8f32 -size 99018 +oid sha256:63a9a21899df3df687738c914f222f7063de8e8b313a9459eefacdd381502409 +size 100057 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-en-GB.1.png index 74a3c8bd1b..f9bffa86dd 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73ad0722cd99b15f764ee9fc746a478614bc178c75feb11a2fc1fbfbf8669777 -size 106091 +oid sha256:4769be55b76d1424c40d9b273159a58f89ee63cd06dcc22817a9fa1fca690458 +size 105922 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-pseudo.1.png index 74a3c8bd1b..3ea70402bf 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73ad0722cd99b15f764ee9fc746a478614bc178c75feb11a2fc1fbfbf8669777 -size 106091 +oid sha256:dc4573fdd967980ce95ef55241417bdfebf38c8eee8f48a0a2cdb2d17a94a5a9 +size 107424 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-en-GB.1.png index c94f0f1033..b53f8f3e25 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4193f92f0d9465b5ea5579a26317d1451afe3b0ab7d5a5bca86729c0f30e159a -size 72237 +oid sha256:f2bf53015130ce1b7250811033bf1ee537745f83c7874c4de1f639574fa12b37 +size 72220 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-pseudo.1.png index c94f0f1033..8b125aa345 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_noticeRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4193f92f0d9465b5ea5579a26317d1451afe3b0ab7d5a5bca86729c0f30e159a -size 72237 +oid sha256:b1e6ca2eee7bb5fe9bc85fbdd4bd17afb2584567c5285e510d9ae022ea5d0f80 +size 72483 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-en-GB.1.png index 57df78d867..d109ac7b04 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab4641450dc0a1f26391cc96a7c548ae54c2f3f4917ad8f806e62dd23d6cb69f -size 122145 +oid sha256:b9f8070a362eda2dfa9b9c00c91e17b197ed38617ec068587ff21b19e2cc6b81 +size 122764 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-pseudo.1.png index 57df78d867..d109ac7b04 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab4641450dc0a1f26391cc96a7c548ae54c2f3f4917ad8f806e62dd23d6cb69f -size 122145 +oid sha256:b9f8070a362eda2dfa9b9c00c91e17b197ed38617ec068587ff21b19e2cc6b81 +size 122764 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-en-GB.1.png index 90d1e7da2c..27ecbe6d2f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d1f44d77e4ab2510db9c6c85eaebb3d466caad67c336de8ed8eeb391c5163fdc -size 79537 +oid sha256:c05bebe214803f2830d098498885ee76dffceef0947adf6252a4e8e76bd2fc47 +size 80127 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-pseudo.1.png index 90d1e7da2c..27ecbe6d2f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsEditScreenRoomCell-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d1f44d77e4ab2510db9c6c85eaebb3d466caad67c336de8ed8eeb391c5163fdc -size 79537 +oid sha256:c05bebe214803f2830d098498885ee76dffceef0947adf6252a4e8e76bd2fc47 +size 80127 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-disclosed-Bubble.png index 4ff204d996..05bc872ff0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5588f1b5c3673c7637b0d54b1b81f84ebdbcffef54595e13c2769a9ab49ddbbd -size 120582 +oid sha256:f73c154414e982e5b7258cc4242585604f4c45130369263e81d18473e3eeac7e +size 120387 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-no-votes-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-no-votes-Bubble.png index ed293de56c..b436e5fabe 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-no-votes-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Creator-no-votes-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fdd82d802c100ca12b7d7cccc36c4d69950b8908be64abc0365409bd188c9a3c -size 120334 +oid sha256:56e0e12e519182e593a2aece330750538d4051c6d3ec34500f11d725375b88d5 +size 120142 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Disclosed-Bubble.png index b0a705831f..4adfd61eec 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f84ce97f1de03675d8f833127d0da7e8ed1a00aaaf4c3a01a82bd6c174ad9a5f -size 115200 +oid sha256:cd692af1eb55d95c824b3b6cd2d884bde71e95974bd7063e404f54eb9a16eee4 +size 115024 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Disclosed-Bubble.png index 23fa64585b..8d9acca9e2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6af065aa0746db5dd657ad05bff5ca29f48bc3e0d47a776cbbb7199f705f8373 -size 114952 +oid sha256:56d554f45bf6feaddadf292a4196377ccb6d7832bca18f1e9884b110b6e1c75f +size 114770 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Undisclosed-Bubble.png index 23fa64585b..8d9acca9e2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Undisclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Ended-Undisclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6af065aa0746db5dd657ad05bff5ca29f48bc3e0d47a776cbbb7199f705f8373 -size 114952 +oid sha256:56d554f45bf6feaddadf292a4196377ccb6d7832bca18f1e9884b110b6e1c75f +size 114770 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Preview.png index 37d74d55b1..be5c0ca2ab 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Preview.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Preview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e794544b48d147d620fb3d12365d9b265ed03e23dda7f191662555f3431ee595 -size 79267 +oid sha256:a45eda8e78a872de72eb183f405c5d9b8a326bb9ee41995afbba369d1b0060fa +size 79078 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Undisclosed-Bubble.png index 1ab875b97a..4ca39bbec9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Undisclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-en-GB.Undisclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:47365a8ce3aacf6432d147ba27ecee5d55a4b7a7415794761e7387e23c222e78 -size 111787 +oid sha256:f7d30bab10e499e4f523dbe5a5ae29898462554fc431ae8180a152396530b6f3 +size 111631 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-disclosed-Bubble.png index 06461de6ab..03b16b1a02 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f09fd7c993fdb7034a0c52ad1741a5cf05c0d58b32c454cf97fe68a6c8cacca -size 134951 +oid sha256:7efe5cf2876de74b6bcc9adcdaa48db1659cdf995de9182de3bc9c6df0e6b8fa +size 135605 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-no-votes-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-no-votes-Bubble.png index 03d0dc8825..df38b2c664 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-no-votes-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Creator-no-votes-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f9a7e25d1dddfab55108b9894feb4d50adfe5e9f33475d494581df2877b36d9 -size 134501 +oid sha256:c012824d0c46609c270429e7e2ca9af89438eb56e6cb2ef5a599dc055a08b4cd +size 135157 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Disclosed-Bubble.png index e701ba3b70..9958c9e5b0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aed6092acae427341404cb3c3203fa920544f936de5fb0bff9c4a3150f9af56b -size 130082 +oid sha256:0ecfb6c9ca94278e784efad7698fd7af3262d0961231f5b0a4cdff99fabfdccc +size 130686 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Disclosed-Bubble.png index 6a81f698ff..3a8b8b1c9d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33442a0da97a6b366f9efe8e7fea603ad0de39bd8bf352d6e219435050b3c4b9 -size 128547 +oid sha256:392619b11a7dacf37566ce18b99d603238fa48c1ca592149a07a2cf393af9f55 +size 129161 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Undisclosed-Bubble.png index 6a81f698ff..3a8b8b1c9d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Undisclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Ended-Undisclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33442a0da97a6b366f9efe8e7fea603ad0de39bd8bf352d6e219435050b3c4b9 -size 128547 +oid sha256:392619b11a7dacf37566ce18b99d603238fa48c1ca592149a07a2cf393af9f55 +size 129161 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Preview.png index 37d74d55b1..50948ae055 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Preview.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Preview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e794544b48d147d620fb3d12365d9b265ed03e23dda7f191662555f3431ee595 -size 79267 +oid sha256:b415b6a13df504c10c4e39c1eb53f3ec4456aa5d256328d4cd559a9510c6ff0b +size 79935 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Undisclosed-Bubble.png index be9a98a081..209fb31d4f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Undisclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPad-pseudo.Undisclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:03257dc02e700e403d229736219ac6e9ff22c37756a7f90a60134a1e3ee58848 -size 117042 +oid sha256:2fa853f8e26b15544b3c558e7eb0b5de16d36fbbe55931815bf6ef34becd7cd3 +size 117677 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-disclosed-Bubble.png index 155a221c9f..da0d463b6e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9898c8ed3dca614fcd1a0cc5dc8245057e4c098312c8f7d5a27e32642bb68293 -size 73383 +oid sha256:4f224e513ab605d93e7a2ff29336d725902c07f029fc32b9be82c2c8eeefe6d8 +size 73271 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-no-votes-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-no-votes-Bubble.png index aaff342f70..f6e8a9892d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-no-votes-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Creator-no-votes-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d45a079df17a7e9bda5bfacdbdcafedba7e7f2863ecd32fe7781ecf65153f11 -size 73162 +oid sha256:84180502601af16e30bcebbe95442728d02ebdc70885400228174120607deb39 +size 73050 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Disclosed-Bubble.png index 6e0dfe2f25..92a526556d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c00cde6d7bbcf3b8c295cddcc755adc1a1ec47a38624eda37b0a73f03c455c0 -size 68530 +oid sha256:0bb69c9393f6d5c6fd820ad578b9d37bead0bac60387bb0a41ff1bb1b0dc4c0d +size 68410 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Disclosed-Bubble.png index a66d78853b..fefa63d666 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40eda3506181416da579a84b715a5602f1b0c7397eb54e56215c90c6f8f1d0a4 -size 68166 +oid sha256:dd39e7f4a106d9a691947393474f5dd5bd602fc89f0b11d7539a047caae28707 +size 68069 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Undisclosed-Bubble.png index a66d78853b..fefa63d666 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Undisclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Ended-Undisclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40eda3506181416da579a84b715a5602f1b0c7397eb54e56215c90c6f8f1d0a4 -size 68166 +oid sha256:dd39e7f4a106d9a691947393474f5dd5bd602fc89f0b11d7539a047caae28707 +size 68069 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Preview.png index b3d5d0a0dd..97d740a4d6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Preview.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Preview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3fb34cdbfd8b96f150febcf956c6dde8bc28052679ad8d216dcd47bda58c1adf -size 39188 +oid sha256:dd07464a88c257b6edecdbf7022c477888a772e774392d5d9f3ef4800016da9e +size 39051 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Undisclosed-Bubble.png index 480292a7e0..02498fb51a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Undisclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-en-GB.Undisclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a67811455cada6f94ac7888ef2759d30f3d0aa002ce566f6f24cfcf3c26d89b -size 67083 +oid sha256:628163b90188642c7dacdf80749f481e511b607f7deccbba5d2cde2b43d0d642 +size 66981 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-disclosed-Bubble.png index baf03bd952..73962e2fc4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:771f11cd8317781b17a52cd09af602198ee49e0c57f3248572c48b7a149aeb9b -size 86548 +oid sha256:309a859e1fa5d7ba54044b089a378551c5dd4dcd56b1cf560746f5d4563c68ee +size 87114 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-no-votes-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-no-votes-Bubble.png index 48fae3f985..553d050106 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-no-votes-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Creator-no-votes-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b78407f39f5f594ab4d2abc44e78b0174f65f7985ef6fc5b2698072047e06d24 -size 85908 +oid sha256:ddb6bced7750335ec2197af4d0cb336ecf395d7c02be7d0a93df9d0aaa03c213 +size 86469 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Disclosed-Bubble.png index 620a8b93d1..58097191ad 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d804f0beb15981af0fc1944ad13e7fa508282211116f23a4774d8e56d6f16f89 -size 81762 +oid sha256:9f07fa9ded418aa919a2d920388ba56b2ab5d95b8610aff944aca0703125fa24 +size 82314 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Disclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Disclosed-Bubble.png index 017801eeb9..2916abc858 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Disclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Disclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:050679f93ac6565b363a1118a0f40c8f2ba353a5e3a0db81a5425e5949b24b2f -size 86709 +oid sha256:671eec733fe7949fea65febe40d1d3a214fb94d2c44e687d4bd04ea634e5ee1e +size 87228 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Undisclosed-Bubble.png index 017801eeb9..2916abc858 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Undisclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Ended-Undisclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:050679f93ac6565b363a1118a0f40c8f2ba353a5e3a0db81a5425e5949b24b2f -size 86709 +oid sha256:671eec733fe7949fea65febe40d1d3a214fb94d2c44e687d4bd04ea634e5ee1e +size 87228 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Preview.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Preview.png index b3d5d0a0dd..b451fc4fd9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Preview.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Preview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3fb34cdbfd8b96f150febcf956c6dde8bc28052679ad8d216dcd47bda58c1adf -size 39188 +oid sha256:d69af2841367e56ac62217679a8a77473cbef649779a74955eb2210abbb1e2c7 +size 39739 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Undisclosed-Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Undisclosed-Bubble.png index 96c04b9d68..70fe4f38d4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Undisclosed-Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollRoomTimelineView-iPhone-16-pseudo.Undisclosed-Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a36febee4c51f0ca52d880e85ddd73cb3ad52ed653546f5b96ea5615bc0257d -size 73227 +oid sha256:934eba56680bdf26bc59f36e16ec8dd162681306db0c9ef63ae6d11781c12a58 +size 73783 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-en-GB.1.png index aadf992c5c..027ee22c67 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef68a43c07f86b597f3a011d7872f91bbec7688c98c8d917c405450472fc568b -size 85533 +oid sha256:5caa285f573ff5ed5a8c1c7e4df0015421b415fbb985865c0500c71814cce511 +size 94735 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-pseudo.1.png index 5647ecc1fc..415629f946 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98925e5447fa98aa05364f7efa1e133e696358e5d815120cc909fccfd6210dfa -size 86250 +oid sha256:a834120a6cb86890e9a04130f722c45a184b232d8cecc982284b8b216848b228 +size 97871 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-en-GB.1.png index 29de45ee44..3437d04c54 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a391634dcd3a04aef94a7cefdd840bfa8b0321ba95caf869821f77ed0d06a9f -size 43970 +oid sha256:f5a8955e619a6eb923d9504da81039e28a8e4ab14d570b33154b997c9311804e +size 51927 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-pseudo.1.png index a838a76b0d..b6e2b40471 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readMarkerRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21cd5cbdf3e3fbff2f44bb649e1ef7d389da4702375eb7c6e6146ca82dd6fe0c -size 44776 +oid sha256:d682c9f79ae6ff7271c46f62f3fd453c30e65962efb5aa4bcdacf5566e99278c +size 55130 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.With-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.With-Image.png index 9dfa406a12..93276fad8e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.With-Image.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-en-GB.With-Image.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b6f71e4c5caef9d16e44bb90c0e2051db32467c190479271e9e9f50f249bad4 -size 79950 +oid sha256:8c6c80cbb7465534d3455f95a968541f44eb73be9735b6d0aceef27f4995d5a2 +size 83329 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.With-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.With-Image.png index 9dfa406a12..93276fad8e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.With-Image.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPad-pseudo.With-Image.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b6f71e4c5caef9d16e44bb90c0e2051db32467c190479271e9e9f50f249bad4 -size 79950 +oid sha256:8c6c80cbb7465534d3455f95a968541f44eb73be9735b6d0aceef27f4995d5a2 +size 83329 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-en-GB.With-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-en-GB.With-Image.png index 485685cc39..cf57ca49da 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-en-GB.With-Image.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-en-GB.With-Image.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:951bde2a3cc7a130218d8123e8d91469efdd14f66ff251154f0b803d9e378ffb -size 39094 +oid sha256:5775074a245d9f26eefef3311658bf6056ec1792a76f645586a0fcf638ce312a +size 42291 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-pseudo.With-Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-pseudo.With-Image.png index 485685cc39..cf57ca49da 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-pseudo.With-Image.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptCell-iPhone-16-pseudo.With-Image.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:951bde2a3cc7a130218d8123e8d91469efdd14f66ff251154f0b803d9e378ffb -size 39094 +oid sha256:5775074a245d9f26eefef3311658bf6056ec1792a76f645586a0fcf638ce312a +size 42291 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-en-GB.1.png index 968efe0751..dd56834657 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a628befaf09d4dabc75fc33590a6c8c0362a084d7eace41b81497a19112db25 -size 118429 +oid sha256:b2c6fe35083c88b3de4439c452f7253293c150020bfc093ffd10592d60e85261 +size 121851 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-pseudo.1.png index 147a3f7b01..4a7dab878c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:998078e7c7a20a3d895cdd56a09772708d82e5cb94c748d36a064cb1d57ed141 -size 118722 +oid sha256:02819b26132450f5de2b6c25568616d65d0c26f93d3f9111fb526d9dcd56ecd5 +size 122147 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-en-GB.1.png index 5798c01f2d..2bce3e46b3 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cacfad567564b0d58b8261669904e2708c4155dd63892401a32e009b16773f2b -size 70069 +oid sha256:8b8aed3fbbc15d22a0774c7216adbf477710ef78945c1a33fe1f939a4803f40b +size 73656 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-pseudo.1.png index 7eb2ef6852..83d64b334c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_readReceiptsSummaryView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:345cbfc8fae6ae8b26fa012777826c59ebb117f5b4075aaa37f1af9478da4d21 -size 71140 +oid sha256:dc9be24c559c3b75d56c4a92c54d579f65515a46eeedb2563f8c5a979352dc73 +size 74938 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-en-GB.1.png index b5e9ca4142..db71d37f7f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:297eb31a94ac45c772934de2406599c558c7f221bc4327774780ead71afcbe7e -size 77496 +oid sha256:9b4be50c2f955e3615b1e334a1f3ae50b164fba534f88fa1459969808b595615 +size 77355 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-pseudo.1.png index e27132b258..cb19de2fe9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5cf6ee5b20bb8b479150fffe6601ed0612a4007b289049729aa413339873c170 -size 78715 +oid sha256:7ddee1da0e141f3c2bb574e3c06c63b4bac9ff4d03b3608da72bd6e8c6be9938 +size 78520 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-en-GB.1.png index 425d708bd9..6358b3d7d5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:578d872f847b6eda7f3f9f6eb3517e75392f96f631d2e1a08826a60d11e55a3b -size 37044 +oid sha256:fbc0b8e7226b38cee32ca87399d944ca5bb74c26f993d15aa9e41ab03e63b6d4 +size 37076 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-pseudo.1.png index 5cb631b42d..5f87258a80 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_redactedRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0223da6b532ca30282d13067d5629db455f2a9472a4bbca3335641ef4249f83 -size 42406 +oid sha256:c9ee0b982769c6fd9d95cffa0d10bd29d43dd5cd0f9e5ea646f692b33565ecd1 +size 42526 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-en-GB.1.png index 2fffafe5d1..dd8f22a8b1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d3beabf38513b0da6624578238e6e3b84a530b4972fe9fd3e4cf98304bc756e -size 92384 +oid sha256:7faf2e353443a770ed911876059e3be9de383073e9b457bc9252980cc7a050b3 +size 93673 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-pseudo.1.png index 2fffafe5d1..dd8f22a8b1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d3beabf38513b0da6624578238e6e3b84a530b4972fe9fd3e4cf98304bc756e -size 92384 +oid sha256:7faf2e353443a770ed911876059e3be9de383073e9b457bc9252980cc7a050b3 +size 93673 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-en-GB.1.png index b60ccb26a1..491f26e327 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9cd0658dc201ef520932c9b22290448bd12fc100329695c22ffda4723e2411d5 -size 50618 +oid sha256:aa66eccc3882e1e51be5be1e821d5233c7f16282f2d14e10a1653124e2d77e5c +size 51773 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-pseudo.1.png index b60ccb26a1..491f26e327 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomAvatarImage-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9cd0658dc201ef520932c9b22290448bd12fc100329695c22ffda4723e2411d5 -size 50618 +oid sha256:aa66eccc3882e1e51be5be1e821d5233c7f16282f2d14e10a1653124e2d77e5c +size 51773 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Administrators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Administrators.png index f2049aea96..65fd8186bb 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Administrators.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Administrators.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa40acc4d971eb7adbc9f31a8a4921af1c22b6173a57805a4c0067a8a2dab4d4 -size 189949 +oid sha256:f2ffed81c3d82f9c36bac5ae253a8c6dc655ec964416d12332ab93b9f8c4aa4e +size 206520 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Moderators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Moderators.png index ace239f78e..84eea6ef24 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Moderators.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-en-GB.Moderators.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de6759b723c8b82abec292e26432c589408e883afe5c07b342487045476e1157 -size 175236 +oid sha256:e4e342b26202e3e2f52d97c8237f8bf7ef9d256e888f07c9fca9e79ad893667d +size 179925 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Administrators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Administrators.png index 0d56b1674a..3c9ffdc4d4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Administrators.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Administrators.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:596a2aea404884e9deaa097c953e5504b6dacfbc1749ddaad75dd4b5beaa97c0 -size 196256 +oid sha256:04b80f8cf74356e5947bebf09895229b23503d3625c6c2d097fa57a147e7996b +size 212892 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Moderators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Moderators.png index 020e1fa895..a1e8c95935 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Moderators.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPad-pseudo.Moderators.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c66c41ceec7479076a4812dbcc3400a061d1cb12c13401a5847851fd85621879 -size 185926 +oid sha256:ecd503b3e928f5d3a0df450d417f95018acae378492901d86855c4d76e5ae06f +size 190580 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-en-GB.Administrators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-en-GB.Administrators.png index 3db96d2b6a..507284338f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-en-GB.Administrators.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-en-GB.Administrators.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0ddd29baf3219e5fb197671e5c647588e5a155c2d2d1883bddb61f27cb00420 -size 141618 +oid sha256:af61131696d988f04cf314b6a16eef59f7484089ac8435411f596cc2044bd25a +size 159065 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-en-GB.Moderators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-en-GB.Moderators.png index 9144f26602..80e2a9f5c5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-en-GB.Moderators.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-en-GB.Moderators.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cab72ba2a03b47458fb68bbd6fd092c06e3a36861f13b67ccb69c839dd4cc292 -size 129780 +oid sha256:2d2fca97c75a080dc23ff162e992e8d35f5803f753a1b4a7b4b6939c09a1f182 +size 137919 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-pseudo.Administrators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-pseudo.Administrators.png index b6670f8f9c..72a370a9d5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-pseudo.Administrators.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-pseudo.Administrators.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bbcc2243df8595b1b2b52b62a71dbdb6347fa6f727c944316b735d8f8ab0d1a2 -size 147223 +oid sha256:7f9001b8cbb67dd17794cb0e5709b28eedb5f115abf31464de48a4f4d123e713 +size 164720 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-pseudo.Moderators.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-pseudo.Moderators.png index 9276b3912e..0cc186f300 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-pseudo.Moderators.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreen-iPhone-16-pseudo.Moderators.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2271fe92abc4118359f988344ea6f9ab86c41820780abe657881e72949003537 -size 138953 +oid sha256:c7a55cea85cb216670b8cab0ee5e96455920e866703915a2815ee1149208f74c +size 147228 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-en-GB.1.png index 03a56f287b..0a92279e3b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0e0d75e303823aa3bd0472770f17ce79f112b7d2eb36f94652155692fbcc115 -size 46050 +oid sha256:85f8c442a04a63743c024a28d57cd875e73ca0f3f57d31e77d25d306e1171288 +size 54694 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-pseudo.1.png index 03a56f287b..0a92279e3b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0e0d75e303823aa3bd0472770f17ce79f112b7d2eb36f94652155692fbcc115 -size 46050 +oid sha256:85f8c442a04a63743c024a28d57cd875e73ca0f3f57d31e77d25d306e1171288 +size 54694 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-en-GB.1.png index 896a10fa34..d671bc6071 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a06657c9c3bd5b4dc8f3aff47b7e6cf6dba39590087ccf8a568929fba34a95f9 -size 36376 +oid sha256:93a46812b1a40900aa6c96aca4306d93cce68fd75a62bf98627e809224b5e9b4 +size 45138 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-pseudo.1.png index 896a10fa34..d671bc6071 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomChangeRolesScreenSelectedItem-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a06657c9c3bd5b4dc8f3aff47b7e6cf6dba39590087ccf8a568929fba34a95f9 -size 36376 +oid sha256:93a46812b1a40900aa6c96aca4306d93cce68fd75a62bf98627e809224b5e9b4 +size 45138 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.DM-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.DM-Room.png index 6e0f797d4d..2eb2a00b78 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.DM-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.DM-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccbc97e0c7c93037173dd2096568f862c2fbea2ab088fed7a50c2fca57f082b7 -size 196689 +oid sha256:94c47ee747ccae418bfb137fa8d7c3dfe9ff0a213d750cfa6c4e7267921b9f73 +size 233395 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Generic-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Generic-Room.png index a633075f0d..8069346fd1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Generic-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Generic-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:69c8d1611151cd7356e8595eb8c320cea39469b162f8608a513d19b842b9fc14 -size 174237 +oid sha256:2f3606c69ef13c10455f16b0dbe0f0ca0949e9b8d098a3e8f55db5e637cec5c9 +size 174737 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Simple-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Simple-Room.png index 76a13ede2e..a2d020632c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Simple-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-en-GB.Simple-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f149aa6746040c30b0d07e75ea2594f2e98befd365421cd466031152835ee40 -size 149948 +oid sha256:4d617ee77bb0c28caa1f497a5eb686da939efcc4cdcf65090a677ad85784e951 +size 150733 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.DM-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.DM-Room.png index 9c08304fed..e14ef85718 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.DM-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.DM-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd1ea55f817dc1d283dc713cf400e73e43455b9d71bb8283b9c126488e852f23 -size 201104 +oid sha256:a9a91f791358737b68ab3695f523c6b821ab84387d6857ed6cf0b01c824d68cc +size 238682 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Generic-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Generic-Room.png index 10972ab92f..4ccfbfcb69 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Generic-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Generic-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98b2d3b1922ed3fdb9ae9f23f0801d4c6cc1c47eb22118a1c673028e3c3064b1 -size 180087 +oid sha256:2fd20f58c64f70ad239a1931bd641d5dae44fac435019bf7636a8242bb8ecf17 +size 181091 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Simple-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Simple-Room.png index b601720ab5..b3d8ffca8c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Simple-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPad-pseudo.Simple-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1fadb3e09d55ba1c9e0ba4082eea366422642c76ae731cad3172c522c57734d5 -size 160375 +oid sha256:ebe7c2ae984e6708d2bb380de749bed6cf6ad057617f2376a8eb732cfdf4c82b +size 161418 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.DM-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.DM-Room.png index d58a4e5fb6..af9e87b6d9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.DM-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.DM-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3f3c59007c7154f7121a3a5b3a6a05fd5e389c7ac9f922d4c93ef5084090b55 -size 139781 +oid sha256:dbad14cfc4ef11542ce1fcd25a63c4206326b9db1eb4ef4ecb4c9d07ae96ad3c +size 169529 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Generic-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Generic-Room.png index c986f93ed7..8b6229eb1e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Generic-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Generic-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84e62d4e5808da5e807e076179538e6cb42dafae0c1c1aabf3732dbc4bb7c8a0 -size 112044 +oid sha256:c5b278b47754dd51580e98cf1941f48137662acab38c29c804bae6b0cf90b28e +size 112164 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Simple-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Simple-Room.png index c4d851f7eb..03e1d94116 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Simple-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-en-GB.Simple-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f86bc2dd442d2a0c9ab5179a19dff28a24716b188d3267d8c64aecea6856a328 -size 97074 +oid sha256:9fe74e979217cc6b8290a9600cd419c97111872bc28cef02ddc5c72c5a726e28 +size 97542 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.DM-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.DM-Room.png index a1f4a62f6a..97ecf093ed 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.DM-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.DM-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ac29c1a44d4f8805ee35dc66cade4ba3c5dca673fd95079dd5e5b8346e350314 -size 152666 +oid sha256:f3f7e031b232f5b3e3222f689038c935f2d4e2625bf5ae2e8097525da4e49102 +size 181635 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Generic-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Generic-Room.png index 846f2565a2..0944f23bc8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Generic-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Generic-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3937e498c27177646dae584d63ba4ee8eae44098956bab21d7869305ff32639 -size 124185 +oid sha256:8d89c461638b63209b79f5c4161fa87fb2bb95a6f1d340a5157a0fdafa32a28c +size 124126 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Simple-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Simple-Room.png index f521e5bba8..92da8eadc5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Simple-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsScreen-iPhone-16-pseudo.Simple-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be13972396c7ed858d62628c251234f033af3f1e585118c092f039b94eaf133b -size 111276 +oid sha256:00cb4122a842fcad06774e2887681531bed4968b536c677fd010ebe223488086 +size 112130 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.1.png index f00ad52876..11ee7ed14d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24e6713edd0b7d1d95b99351f5b9791ae8f7e049c155cbfc5e66a9e3b9f72606 -size 16308 +oid sha256:362d8f2f1cbcc790676931efc0c69a1ce2d4b1d26a388ae0603c753533b980fd +size 17182 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.1.png index f00ad52876..11ee7ed14d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24e6713edd0b7d1d95b99351f5b9791ae8f7e049c155cbfc5e66a9e3b9f72606 -size 16308 +oid sha256:362d8f2f1cbcc790676931efc0c69a1ce2d4b1d26a388ae0603c753533b980fd +size 17182 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-en-GB.1.png index 03a71d210a..ca408de377 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22da22f2fe62f66dd68084f9590079e0630477697bed4913ebaee4568d7d3db8 -size 12472 +oid sha256:00e32f7e0d5d931b5fa1627f16cf2b45addd4d38a5fb39d08641efb70358dc85 +size 13285 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-pseudo.1.png index 03a71d210a..ca408de377 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomHeaderView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22da22f2fe62f66dd68084f9590079e0630477697bed4913ebaee4568d7d3db8 -size 12472 +oid sha256:00e32f7e0d5d931b5fa1627f16cf2b45addd4d38a5fb39d08641efb70358dc85 +size 13285 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-en-GB.1.png index ee923355ee..741d5fff26 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bfca845384d5d0a44aa1a3e322c7aa059c4286750d2e0ff2a47632096b95c926 -size 108298 +oid sha256:a311f5ccc53c5c1816497712f40f3a7f8243eeb6a8b865c71cb416d090620cd0 +size 109133 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-pseudo.1.png index c6aaf315f1..9796caeae0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd1441564319b3f2a6028ac242063014964d601913ea1f8a7ccd86d1d7d4ef4f -size 121015 +oid sha256:7ab3ef23780ee387eb3062d4ada9aebaf9604f65903e67f96f909c930af3a0cd +size 121976 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-en-GB.1.png index 40d6e7a7f8..d52b520895 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0aa045fa03babdf4b7eb051cc1befb486524ef0a904fb5f55d8f41633dd06f20 -size 63819 +oid sha256:9b1d6814a9d5d68348095ea0252f1ca7f3e78358cf4b83239d7c191b2be56908 +size 64554 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-pseudo.1.png index db2ae7f7c6..9c8d1b8b69 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomInviterLabel-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56a4cb633080ff6f57162246d43e6dc2f8dbddd718c84181f348af1e1efeb47f -size 79274 +oid sha256:3a919eef75a060f8d31dd05089734a28bfa211f98de67e4fb2f5142fc09c319c +size 80118 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-en-GB.1.png index 753a7cfc5a..618fc0052e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1173c074827ba7a43888c57197c36c730cc1d445de0788e503ea7b2aa72e5cda -size 162259 +oid sha256:67c41f94a969c49bb95c6b7a4ded36f977a48909935ffd900104b5d70fc79cd2 +size 162378 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-16-en-GB.1.png index 9d38d07596..2878881c0b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomListFiltersEmptyStateView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0555df189ae2619cb56d37762896b6e9d1f9d6d0eeb2551127a31753681d5ed -size 148195 +oid sha256:4f4dc44555b904b2c9805608dfe0134f36c33d6a0861d607d5d576db3bb82516 +size 148274 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Account-Owner.png index 0256209ad3..a6d5398253 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Account-Owner.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Account-Owner.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b41cdd506a958fd414026f3ed9112c98f075b02385f770f535b07026d8d5569 -size 132041 +oid sha256:d7a95b80d28e2707eeb8c910ad9d2179a7190bcecde4dbf4042f54f6a96be79a +size 156475 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Verified-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Verified-User.png new file mode 100644 index 0000000000..f4ae1fb75b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-en-GB.Verified-User.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c11d3f85d7be3aab12b88b7fc4bb78440eea78aaaee8744ea89c88f4698fb3a1 +size 175615 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Account-Owner.png index 27fdb8e049..0763677f1e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Account-Owner.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Account-Owner.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:452f6187317b72d667279a1d804a461953c09f4241c27dbf07179c6b857bfa28 -size 132294 +oid sha256:83c9dc4063303bbfc0da528b21ceabfb3b93202596ce717b683c756bc0c418fa +size 156740 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Verified-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Verified-User.png new file mode 100644 index 0000000000..36ebb000b7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPad-pseudo.Verified-User.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63f174c48e935c0c0a7144a2bed29fc17d60670abc96037631e28ed1990c94eb +size 177168 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Account-Owner.png index f81e58c7e7..c442ba9576 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Account-Owner.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Account-Owner.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdb37c77944c118ff3e4d2eb5327144c6a4085cd3a8a603288125c1d757b3d72 -size 79545 +oid sha256:9c8df11551ba6223e5f6d879c3bd9f940b903278ec4906dd2c7a0ebdceedf273 +size 101073 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Verified-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Verified-User.png new file mode 100644 index 0000000000..320bba3a79 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-en-GB.Verified-User.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f45a31dad10c8d7319e971890255daee11d447dae8916b507ee23473c4b601fa +size 117602 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Account-Owner.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Account-Owner.png index 6d93040f3a..acfb04c0bd 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Account-Owner.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Account-Owner.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6673e9d271cad269d14ec61989a46acbddee4ab23c128a17fbdb7e1522535f0 -size 80147 +oid sha256:025a8e5d52cf28d4f519b8b5dbe335df4ae78c96965556a93193634f7d6bb7b8 +size 101659 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Verified-User.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Verified-User.png new file mode 100644 index 0000000000..7c963d3673 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMemberDetailsScreen-iPhone-16-pseudo.Verified-User.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88ee7b6dfc9fb3457cd013e06afef478e80bf9ef48732d6b9437cc67e41cda13 +size 125950 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Joined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Joined.png index 798b60ea34..c1865e4040 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Joined.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-en-GB.Joined.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b4b31fd0104de2bdd8124db880c5cfa1815624e19427cf3fbc94f4b1f0f75f4 -size 148904 +oid sha256:f5597c9426b4b3e3ff0871fa54c32ebc01bb7e4db9e16f8b1140416dbb073970 +size 172782 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Joined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Joined.png index 10fcd416da..187ef7c6d8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Joined.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPad-pseudo.Joined.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdf3d72b49bc2749d135c679411934ff4dbc94aa362f79731729dfcfc869bb7a -size 151755 +oid sha256:36772500ca3fab247bb82d3688c237884cc2d8a7204c7cbea3ff18a91864d8c9 +size 175633 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-en-GB.Joined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-en-GB.Joined.png index ae39c120c8..cc8752f86b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-en-GB.Joined.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-en-GB.Joined.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0a234fd3fa7675804e5c639ce4bbd1b7d69d1d7d4c82bc856125cb5d5de1b5cb -size 94324 +oid sha256:605412c346e6809e5392545c786d76b2e7972712420e315404dd9ae5a7c19455 +size 115938 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-pseudo.Joined.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-pseudo.Joined.png index a25c85d1c8..c1445c98c1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-pseudo.Joined.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListManageMemberSheet-iPhone-16-pseudo.Joined.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b862604378f2f4453b0937df462cd0394645298bb56faf64a10b5f7facb5f50 -size 103880 +oid sha256:7c89940a2a7e3d825b7dafbe33f23ad79e225e28ca12a12a76830e053c4898e9 +size 125505 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-en-GB.1.png index cc1a252627..fef6b315fd 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:856c6765b1b094095b58ff420287e53da9c0c4b81223ad1626d210318b8d1612 -size 157536 +oid sha256:90066a718279683a4c695432b9551beb111aa535ac71cf649ebffc941a84a431 +size 163895 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-pseudo.1.png index f1cf44e9ff..b66626313d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de681676b70315efa05d12f627df09cd46475e72803636f9999606ca6ab90276 -size 161285 +oid sha256:a20d88e23c51ecae8265488e6a57270540d3517dc96b1d983138031b0b317821 +size 167670 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-en-GB.1.png index 8e50ef6050..bcc9c962a1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa2bce323be5587c82db9e4939d7e8c71ae2c372aef069f5a924f93137375d23 -size 103394 +oid sha256:acc409f85d13d7ea8f3c2c130884171e56c300cc9468a74d6e4c13172ef46556 +size 108036 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-pseudo.1.png index 8e275e596a..743e1db799 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListMemberCell-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c826f78606eaaedb7e4d91e91f35cd615afb856820bd138fff37657e8ecf4728 -size 107798 +oid sha256:b6cae10261481c43bb86d5bf6cae1eaac49cc769ecb0179f1714d2e0c1631e97 +size 112314 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png index 742befb2f7..5e287266dc 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:906409795a47057b2da67dc7a50221b6a9be839309cf434899d3ee7c19735c83 -size 295656 +oid sha256:d19fdc59c123919099ce464a0bb5478edb8df05e23609cd5dae1b430bcd469d1 +size 295900 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png index 76fe17dfea..092ac6fcc4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38a6eea96f81ab5acd88b75823745cc7bb71c237ff0ca181e05e0263abc487d9 -size 297761 +oid sha256:015366f6fe40da0753b014c0be10d6f46478d36e76fef8ac0d03608c44c8665d +size 304454 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-en-GB.1.png index 037e6f2eee..14f263242f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b8ab1d9311c44e85d8e145a9290e97aa2b37070a3104402332479ec8c2fd739 -size 180530 +oid sha256:e5fe32d96cc563369893c88d566260a465e5ae7f372b10f75f1cd6b9fa93877e +size 181804 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-pseudo.1.png index d1aac8e161..caf86ca422 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5843af5ad8774b2d73bc57b18caacb79cfa46abc54c797b5c17948f961ded06 -size 178598 +oid sha256:6332e9688b6bc74fd053be710d9fc160016ff08fe08d755420871e5a79ad6c24 +size 180191 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-en-GB.1.png index 5f64fb3646..089ca78c77 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c3f1273fccab87cd7cf2eaa9780feaff32c0bb7e2e2bb9328cd21d1b7ccbf79 -size 146341 +oid sha256:59ab0ed8bcc6b7b0e428a1cac7e2e3315914eece4bd469dd542f393a078c8e29 +size 147483 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-pseudo.1.png index 932f8c2089..2be941f594 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e1c59056fc8a6913b8b4c78544dab180d571f90235d8b7dddbac3b61fa64f9e -size 147763 +oid sha256:916737a59bb769abc928e5c3c2388e904869dba6d1d0efe6e2c2ad9c408e3f74 +size 148900 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-en-GB.1.png index bf88fe51e2..c36a3a804c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd18cb33817fb2f7320067d3c8e3e0d6f4c66fac6d255a7ae962062025442f6e -size 97052 +oid sha256:cc1b04d5b1134b1a638b5e16951cada1d1725ce4a5499ce4a9807cfd65932a32 +size 98032 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-pseudo.1.png index 9a15976c9c..e5820587d9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:436c1029eab8620c56caa7f38f0dcea3487a7fdb17cb7d40e75e8e619ed63766 -size 98326 +oid sha256:dab6f6225c509b918acee0d595e31b42e6fa5bb954f8ec19f2c1a917a4b6ec73 +size 99345 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPad-en-GB.1.png new file mode 100644 index 0000000000..42f8aeaf1e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f106042c8e2bd09f7dd7c2e500d9cd51f795eb84e59b038b532ca8ab86ae3e3 +size 68347 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..42f8aeaf1e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f106042c8e2bd09f7dd7c2e500d9cd51f795eb84e59b038b532ca8ab86ae3e3 +size 68347 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..d4026a22ed --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0a1a4493ccddb0149b095ab2eaa7ca14043436d80584a5244db7d9899977fe0 +size 27936 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..d4026a22ed --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorMediaEventsTimelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0a1a4493ccddb0149b095ab2eaa7ca14043436d80584a5244db7d9899977fe0 +size 27936 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-en-GB.1.png index d3ff239180..938b2c1e6b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6180f57ce6e161d79a0c52d1ab86518ae2227979fa806011f66c30869fbee81f -size 70278 +oid sha256:25fcc57afb1f80279f98ab65aa5e4ed741764e54407034aba329334c65e9878b +size 71653 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-pseudo.1.png index d3ff239180..cda581b1f7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6180f57ce6e161d79a0c52d1ab86518ae2227979fa806011f66c30869fbee81f -size 70278 +oid sha256:4c244c3d942e34e4a54a07fef6d90f8e6b292ea4f8a79d88c14dd4a38ea0e8dd +size 70977 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-en-GB.1.png index 47d8a2aee2..45a15eeb11 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b586f05cc0eabe44fbc3a1f9181ebf69b2593d6f9e046c115405d955dee5aff8 -size 29598 +oid sha256:74d80c2fe62ebd088356b29f3fde14d32f81299a6a1b385ebdff4e115b600395 +size 30361 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-pseudo.1.png index 47d8a2aee2..2737af5e10 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_separatorRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b586f05cc0eabe44fbc3a1f9181ebf69b2593d6f9e046c115405d955dee5aff8 -size 29598 +oid sha256:7647c90ac369edd5bbfd9e0cbe5a871791f871d16c8db511f1d4b95a6bbb24a1 +size 31058 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-en-GB.1.png index dea3683a8d..33e3d55735 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26f2e07fa87d8ae6a910f30e992cf45e528715093663f40739e085c1349a6b31 -size 218285 +oid sha256:eeed9ecb3e5ca6b010a32358b80db9fee7b12eae477ace8026084cf7e850aa86 +size 1520149 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-pseudo.1.png index dea3683a8d..3aa1bdaec7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26f2e07fa87d8ae6a910f30e992cf45e528715093663f40739e085c1349a6b31 -size 218285 +oid sha256:1cd10d3a143873e2c5715911fe758f39097681b28c1a91312ee5bc9d9a43c7f0 +size 1518489 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-16-en-GB.1.png index 7ab6b4378a..d55c3e14c4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23b75089dd40fc4c0c8cbaeb97f9659b19c22621133442e09ec7fc962cbae091 -size 167471 +oid sha256:98e324122785fc632fef2c819d1d8773fe17e926c9904798e8eb37d9c6fe9565 +size 776785 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-16-pseudo.1.png index 7ab6b4378a..bef2834c61 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stickerRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23b75089dd40fc4c0c8cbaeb97f9659b19c22621133442e09ec7fc962cbae091 -size 167471 +oid sha256:a18e171436f7991bd491748a6b0b7e7848d088a5abafe2ad9346273c1d7244a4 +size 775850 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-en-GB.1.png index 100a9ae350..95f12f2002 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f81022274eac7cc96fa6279f08cac8f336cd6d8e9ced519e10b60c076376c50 -size 82910 +oid sha256:757eaa2c262ef6217b62b55bde424a7d26efa8db632956003c503a04eb35ebf1 +size 82883 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-pseudo.1.png index f45ac3e749..d168245808 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2077a6e4ee0d8027e93c99fd683ca3ec97b29564bfe48734c76677fac5f729f -size 83609 +oid sha256:90ce8d0ce47578fcc75c13cd6fc2794b4854e5ecc1a9c76e6b78a7837de659d7 +size 86648 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-en-GB.1.png index b8e0e0e304..c388f7217e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f78ee127159f80ba7a11d2843d2405b2060648c411a9882e0dccf65c03981e6 -size 43884 +oid sha256:f05c62690e9e8b3e89a5da3e18b7713f0ceeeaa25a635c56e5a19c58c66479e3 +size 43757 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-pseudo.1.png index 259a343081..c25a50b96c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_swipeRightAction-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b07c5cdf2cc83bc512f88134fb15701737655eddafe59e166ef0409787213857 -size 44603 +oid sha256:704b1ff8cf1fff2a3d46f6631031c2eb1b70ccd5d4deb9c57e4a5ae227e9784b +size 55271 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble-RTL.png index 6738534e79..e25a552146 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble-RTL.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble-RTL.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0620fd344b8286f1ba2bebe8b58ea591a948a80c083006556cb8900ee9aab728 -size 168615 +oid sha256:fc7e4b984e7d0a9d9f98f7d57713a5c79fd58449b958cd7b6e73b90617e0672c +size 168251 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble.png index dd4d5736cf..e16ebbfbc0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-en-GB.Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ecf9a72d091d89a028dd7e623497974ed806458a39c566ad6e52c82a7095c84d -size 170184 +oid sha256:445275865d4a492749e691e8c9314ab83d76d5f8ac9e4f1772b581e27b7421e3 +size 169498 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble-RTL.png index 6738534e79..6897817cab 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble-RTL.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble-RTL.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0620fd344b8286f1ba2bebe8b58ea591a948a80c083006556cb8900ee9aab728 -size 168615 +oid sha256:c7ddc1ca335f9ba8cb831c4f89830e28d0f2f0cb10d1af760699978738e8cb83 +size 174116 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble.png index dd4d5736cf..f310dbb52c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPad-pseudo.Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ecf9a72d091d89a028dd7e623497974ed806458a39c566ad6e52c82a7095c84d -size 170184 +oid sha256:e900018eef7e7fa35b766f6c5b06d99b547d360013cf0ff3f28f549ffc84c95b +size 175241 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble-RTL.png index eb5f372990..93007c06e5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble-RTL.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble-RTL.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:07c812d5a591d7ff93f94eed80d16fbd13073123354038054f4c49966879cd71 -size 128099 +oid sha256:e934278b5e887273313127de4b8975fff58ceb5c3e2cdd77b0ecede0fd8969ee +size 127477 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble.png index 6f26be1bb7..eece5bb427 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-en-GB.Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d29134e8ca20ab427e283ffde97d0d0910bd5ed4e7f78108757198ceb3e6c412 -size 127617 +oid sha256:5b41bb83e83efc9236fec34bd546d21ca42a1652c949ceac870cc1aacf7564ba +size 126890 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble-RTL.png index eb5f372990..4f069ea0f2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble-RTL.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble-RTL.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:07c812d5a591d7ff93f94eed80d16fbd13073123354038054f4c49966879cd71 -size 128099 +oid sha256:03ad377e66461582b568d9963aa075dc02ca1a091158564ddda26f793831ba16 +size 131449 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble.png index 6f26be1bb7..3f9d9e51ae 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_textRoomTimelineView-iPhone-16-pseudo.Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d29134e8ca20ab427e283ffde97d0d0910bd5ed4e7f78108757198ceb3e6c412 -size 127617 +oid sha256:8f064f55b5fc411c9a6e10c82e75d752d5cb79ff751923d92e28fb7ca3691a38 +size 130454 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline-RTL.png index 7b7cf7d2f3..72b6271916 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline-RTL.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline-RTL.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7222cb8f9b8d5f35d70b7c9d6498825271f2f4701328789f29ce4434060df93b -size 285869 +oid sha256:562da5417d3d83843b934293c59fd15c729c947a11d85ee223f4e2884e575a80 +size 285688 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline.png index dff6e61c8c..8f73d4828f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Mock-Timeline.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c52b5f33ef60a009368a4f69841c64596c4cd3c0597206f7c6e77159b3182b9 -size 284251 +oid sha256:9288fe8187bc7943a7523e0d161cbb74f4cd73a09c06e1e5cf3f19366a3e8084 +size 284078 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Pinned-messages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Pinned-messages.png index 305ad5bb7b..ee320b21cc 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Pinned-messages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Pinned-messages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31312441ddb1fe7fa2676ec39ae63baded5f37dfb15885a4b1ba60c57bd2aa6f -size 779529 +oid sha256:7d51b385f71b84074878e9145752ffd96cd0d9221de758c7cfbde7ce0298b696 +size 2081577 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Thread-decorator.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Thread-decorator.png index 20743368bd..6b058de644 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Thread-decorator.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-en-GB.Thread-decorator.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dcfa8241cb8d5e245905a542a42ab355468dbfad3c98d2470ddcc777de7cd877 -size 186237 +oid sha256:9122b2a2e8e953518dadd09954758f8bfea29d9c3078b6a417947ec0a768ce2a +size 2197095 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline-RTL.png index c9a94af864..d6c9641671 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline-RTL.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline-RTL.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72f66b7d7cf29690fe5cbf3c7a624462369735231ffdab3d196c31eb285c1a3c -size 287531 +oid sha256:9c84f555adb18536c418b82b978cb7ef9175fbae00f18e40d7200f8d69a20533 +size 292926 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline.png index cfb579b34c..ce2c01d3c7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Mock-Timeline.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c65adc9249fe0e725160eed2ad5854e7b719b7d3c5fad3b5501b9259db582c2 -size 285667 +oid sha256:a75402f09fcec7dcb1132c47ca71e0a08e09e9898b2b10389aeed7bae75c4a46 +size 291518 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Pinned-messages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Pinned-messages.png index 305ad5bb7b..c8fff70800 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Pinned-messages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Pinned-messages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31312441ddb1fe7fa2676ec39ae63baded5f37dfb15885a4b1ba60c57bd2aa6f -size 779529 +oid sha256:a978fab354e4b360e81da55cd7e5f48c310ed4ec3c6ef7ad635c048425990dfb +size 2082605 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Thread-decorator.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Thread-decorator.png index 6af4c09f5b..c43834c5da 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Thread-decorator.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPad-pseudo.Thread-decorator.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53bfc5618c802866c2c1d611940c608cc444cd4f190043d2419ef639b134025c -size 193601 +oid sha256:39feefa42a79f179b3a2cd961ef1bacef531ff04709a8acb073bfd8bd4388e03 +size 2211971 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline-RTL.png index ef759681c5..593383c128 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline-RTL.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline-RTL.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd5ce3f8ce6de79110a64880e7d65132bd4eeb689562e65dda79b9fe39ef8148 -size 190473 +oid sha256:50f4a76320c1519daa984dd0b19fb965db8199dfd6786a8cf528228799585aeb +size 226204 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline.png index a284470ca0..d3a4a40481 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Mock-Timeline.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2edda65eb2b77d65105f17dada5fbe8be1f7610cce462e967ffe1513fdd878b0 -size 188590 +oid sha256:95f55f16898bbcdfd599633456eb3436e4a79777fb9c6b93064a5b3e0bcd5dd4 +size 223638 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Pinned-messages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Pinned-messages.png index bbb97786f6..fce117c6bd 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Pinned-messages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Pinned-messages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8cf67596ee0f149f600c1d5f4a61916683e56fbe303db96259f3b8d610d9afd0 -size 437588 +oid sha256:a4c100a1e5a919919a79f08d52402f2bf18985dfbbd8ccbda7d309f75bb2fd83 +size 891050 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Thread-decorator.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Thread-decorator.png index 6f7eec15b4..fbdd7529e9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Thread-decorator.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-en-GB.Thread-decorator.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04e188585bab8bcd1865df322954ca66db33162a534d9fa4e8066639fb509789 -size 135546 +oid sha256:e7e38f1e27a86f8e355ff5b9a4b34d66433749e27a29ae7d5c3342c83f370303 +size 1004157 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline-RTL.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline-RTL.png index 60f0aa2585..888cedc313 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline-RTL.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline-RTL.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:989002cd49c3455efc5d1f3982cf5b8efbe9527d6bef80464e01ac11452fe1c6 -size 188265 +oid sha256:d2b324da8fb2eb1d0e3a7ed3e9a4c2796622889d964645da75878e7ec2c53ef5 +size 232096 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline.png index c67b5b9bc4..f7d77c443d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Mock-Timeline.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0bce781f1031c33a6f2161d11f572ded92262d9e394bb82b4fdbfed15a9c41b -size 186270 +oid sha256:a6b94fda33826a8bd56cc220f95496729df82fb17b2c5d34c76f07697010d670 +size 229096 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Pinned-messages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Pinned-messages.png index bbb97786f6..fda7d52b38 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Pinned-messages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Pinned-messages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8cf67596ee0f149f600c1d5f4a61916683e56fbe303db96259f3b8d610d9afd0 -size 437588 +oid sha256:a61217ebfe902b3008eb01c6739d72cf85f54a89cc6d94b4d75efa514d3c98bb +size 890512 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Thread-decorator.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Thread-decorator.png index 7f3c6b2b55..441bbcc2e0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Thread-decorator.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemBubbledStylerView-iPhone-16-pseudo.Thread-decorator.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4cdcf82c941481d377b72600aa68130fe1bdd81f459a6d60f10cf61366a6e862 -size 138005 +oid sha256:75e0d87e2ee0812325bf26d35ca471a28c1b90cbee297dc30148941d64c69e84 +size 1010197 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Authenticity.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Authenticity.png index c93414d20c..b8de411298 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Authenticity.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Authenticity.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42992a72deec6d6cc0a3268f4619db58fb44ba869b6cca0c9937ee70a0effd7e -size 147883 +oid sha256:c86a7c06f58e38074a93b808f68ab64b5c002b7b8bcaea0c2c75334da6e1bd65 +size 147176 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Button-shapes.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Button-shapes.png index d3a797f89f..920c61cab1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Button-shapes.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Button-shapes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0868feab75e9ac054da551d7ebcc17d7cb8e2cfb3c4ab540f5d05753a273aea -size 154967 +oid sha256:d02c8c21850591b42621ac5bf236e422d82745dc6112fcce27af4f3deebab010 +size 154043 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Identity-Changed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Identity-Changed.png index c4a29de515..bc282b8f6f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Identity-Changed.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Identity-Changed.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a57163af2dbcb6af527279ee9959aaf4ac5830424b14deede615891b8da411c4 -size 146496 +oid sha256:db97cab6f9bce28eab4f9f24e836695487307323d40076b4ebf9870006b88d94 +size 145956 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media-with-Caption.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media-with-Caption.png index d0b6409961..f685f95465 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media-with-Caption.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media-with-Caption.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8dfdb1408f464b7570b1c587e03dec72be0cc02ad28af2475c7f13eabfecfdea -size 143529 +oid sha256:49ac91ef285233823a3726ba3cb207bcafefcb404c0f3d1d1de066f5531cd95a +size 142756 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media.png index b34a3b3ca5..d59f1989e5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8bad202aa9c390b47af7d1e35f3e65c731a3f3ae659c943c7f1ae63581590ec -size 133449 +oid sha256:8572818adebef1563717d139959733ea1810a98045fc89ecfec2ea8691686d1d +size 132447 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Normal.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Normal.png index 839ae5df7d..526271397e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Normal.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Normal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccec869066425d2bcb107a1dae131d0a87bd2f1c8b345edd8fe77edfe3f779a1 -size 136131 +oid sha256:5e61bd24f04fc1f666f3f139ced0c67e11fbc21539992e3e432e72730b762b5c +size 135133 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Own-Unsigned-Devices.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Own-Unsigned-Devices.png index 5cf9b34abd..2fcc81aa65 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Own-Unsigned-Devices.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Own-Unsigned-Devices.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4448552425a8dde78ee792f3915d76721d548d38daa3b59854e56d692b15286 -size 147056 +oid sha256:39ec62f72cc9fba4f192f9e76f4f8e15466a11d76416c59b4d214227e3b115de +size 146565 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unencrypted.png index 5df36e3645..f42a126791 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unencrypted.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unencrypted.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9845682cd8bc72244d05d872a5212735890703a5e65400667986f1d158a991d -size 141448 +oid sha256:6afbe4ba26f7ec22df84f6a67ae568a8d57103615a280dd6f4bbdc210ab0e575 +size 140623 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unknown-failure.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unknown-failure.png index 839ae5df7d..526271397e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unknown-failure.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unknown-failure.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccec869066425d2bcb107a1dae131d0a87bd2f1c8b345edd8fe77edfe3f779a1 -size 136131 +oid sha256:5e61bd24f04fc1f666f3f139ced0c67e11fbc21539992e3e432e72730b762b5c +size 135133 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned-Devices.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned-Devices.png index 5c5b13d3ca..d4056e3735 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned-Devices.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned-Devices.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2d5f335b38cdde8f4e5e8c40e7c2c95bee523d353d880e026c7c012c0f86284 -size 146268 +oid sha256:c1074f3d5ba827cf0ed7f7ddc304f3abd2be8d2825e6de22b7f249529aa5be75 +size 145706 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned.png index 98d7bb1f03..cb3dae06c6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Unsigned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bcb1cf3a950c99e05559cb2cf2162e5b96cbccdebbe42e3b09efa2256a5c53c -size 145195 +oid sha256:c44abe9eea51fe421daa71c34fadedd520d46ee71db213f19c52d271686b495e +size 144549 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Authenticity.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Authenticity.png index fa99fad4f2..d4ea61b630 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Authenticity.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Authenticity.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75219b465e5332f12fada6b5c507c9ee6c62c409b06167824310cb7dfbb068f7 -size 156450 +oid sha256:508506f1b24800e6de537875204dc067ddcc271b56d0424d052c43616edb0872 +size 156449 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Button-shapes.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Button-shapes.png index 50382b6028..ff6ef98ceb 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Button-shapes.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Button-shapes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e950f852539eccca04f68060e56787413f90a6c2481df251e8ab315cf5b659d1 -size 158242 +oid sha256:b93b88c2fb0ef5ce881ff8df776d6ad00155b5d524d72986b01a87c3d6c74ee4 +size 158267 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Identity-Changed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Identity-Changed.png index 90a3935d12..565741b553 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Identity-Changed.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Identity-Changed.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:065d14de719ede0234e865a45119a2731da20e7982249db240180db9b7dafe71 -size 155522 +oid sha256:c57bf2acb0e8e46fed87e8db5a93034e96542a2dbeadaa407a32744a56143122 +size 155484 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media-with-Caption.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media-with-Caption.png index 8cbff9be9e..1137d19a5e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media-with-Caption.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media-with-Caption.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c33873265e2e90314f656d95668da81ab86e7461fea51bfbff083eaea512b52 -size 148202 +oid sha256:a3e696131497f695f81b1b4fc6288f06effb668a19aafdde508a04cfcd3f92f2 +size 148259 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media.png index e8f58be7fa..eb73fb77cf 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:001894f533a0619f577647f55a790769d50f5200d4664d027a6b4337e7c8fc25 -size 136972 +oid sha256:160018c55300e2d84dc877b3e225782b352943e055b697d85f4111b7aaf075c5 +size 136712 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Normal.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Normal.png index 883b6c33ac..c3c7ccc9c1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Normal.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Normal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9bd0e980e02351fdcc69c1e2e71c6c579ee9223b671aedbb8b906d82f0a6da6 -size 139535 +oid sha256:b9c28a360093e1f35cd972096b4c40734ba8e4476234c55ec42beeff0c8a99f5 +size 139569 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Own-Unsigned-Devices.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Own-Unsigned-Devices.png index ad09b6c549..9eb16b0873 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Own-Unsigned-Devices.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Own-Unsigned-Devices.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e28d69132bf0d7c6e2380916185df3e5bc0bcf858eda4418cbf561e19b0cfa91 -size 154495 +oid sha256:ae1df102085ba1bbe8bdc398b2d595e2316eb5c852b0e2f52b31bfb2bdbee48d +size 154472 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unencrypted.png index 60922e7054..b3d1c96c10 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unencrypted.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unencrypted.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0451dcad4c79972172c171622e32af923db17278bb59d8858ed538ef2e5acb8 -size 146847 +oid sha256:d99f435700232ceb21bb26799e2560048fde545090992b3015d3d3d722927b34 +size 147069 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unknown-failure.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unknown-failure.png index 883b6c33ac..c3c7ccc9c1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unknown-failure.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unknown-failure.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9bd0e980e02351fdcc69c1e2e71c6c579ee9223b671aedbb8b906d82f0a6da6 -size 139535 +oid sha256:b9c28a360093e1f35cd972096b4c40734ba8e4476234c55ec42beeff0c8a99f5 +size 139569 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned-Devices.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned-Devices.png index 5db052a2f9..e1257eea50 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned-Devices.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned-Devices.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc893c5f8cfe7a247818288ec6e551ff9ee4c02971cde61d6bb5502f7af139d5 +oid sha256:4cbbdbaa199785909fc584dd3e50d8a276d8aedf48ad6fdb9a85e389206ba76d size 153853 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned.png index 2042c2f77e..6c48675233 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Unsigned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d8fb938c99c65f5884636f8806bf3fe9a5de5b6877cf0a2899529df29e30679 -size 152908 +oid sha256:855cc4f23431af74efd4ab7779832f68ec1fa7e5f17194308f283c716717d21e +size 152971 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Authenticity.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Authenticity.png index e2a88dcb56..aeae682542 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Authenticity.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Authenticity.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:914c77c473286e62ff5fabd0d62ce7bd0a71c0755a8d2e99ceabb102bdd7f7f0 -size 99760 +oid sha256:6fc3f6bffd8d0aab6fd5b8b3ab18b36e1db9aa35336613a9522c8552b9d6db4f +size 98812 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Button-shapes.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Button-shapes.png index 3ef2032d0d..e8a0ec637b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Button-shapes.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Button-shapes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6224e94342cbe0303473eb91f16f97e85e67e43ab74be0d6b68868e3a428d1ea -size 103095 +oid sha256:657a5625954c354a20b5a4b4e2d4a9b3867c75dda0d7dcc5198f2cf62071848c +size 102572 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Identity-Changed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Identity-Changed.png index 8b21398133..f258e105d3 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Identity-Changed.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Identity-Changed.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db0cc945ae881ff0979376ebe01eda05899100557c0778164a0b43f54f8ae6c5 -size 98124 +oid sha256:51d396a4b74d557378b77177b0ab3302ba683b0501a8100d22fced8a05778dd6 +size 97576 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media-with-Caption.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media-with-Caption.png index 494a4efc7e..10e4210e2b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media-with-Caption.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media-with-Caption.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10701f9bcc6d6906d8b1063b145fd754c0af3928e5d5664cb35b1aa4d79aa999 -size 95921 +oid sha256:001705e90b08b66cc6ec4e0935c8f5f6aec64f49a14ed97b7db93253e1836438 +size 95470 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media.png index 50924d695d..f682a7f38f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01dd4d77411e87302bb5b4b152de7e5eb761c7f4b367a84f36a31fc5e141fa9d -size 87399 +oid sha256:3eac0b711c28c9b4972efad08908fb567d28ceb769ffaef024596cf4dcbcb6a2 +size 86687 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Normal.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Normal.png index 8010c1fc28..7b4aa97406 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Normal.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Normal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:841d4f5f4f5a4e3eac938f2fcd4b0bb94561eebd6179c91cb84816f3ae7df8b8 -size 89445 +oid sha256:362bd490e10b25967bba6dd8153e7bd877c3921dfafa5cd82bf4bd47a689033e +size 88871 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Own-Unsigned-Devices.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Own-Unsigned-Devices.png index 26ee5627dd..f8786315f0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Own-Unsigned-Devices.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Own-Unsigned-Devices.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6383d2c6351a4833a6ce83a71c6c57c2297d3a8b19c2a818211e21ce61cb7c96 -size 99003 +oid sha256:01021c658d24ccd4f6cbd9e8756420f803f53c000a54ca4508fed64dfb282f35 +size 98388 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unencrypted.png index ee8f8bda2f..3fc02dff8c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unencrypted.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unencrypted.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3068613a53a7634432c201ee51c5bd5e066d93a524019ee7f0b7c6b7199842b -size 92207 +oid sha256:af4b3f623aa90fc0333b58ffa1e6b65f16172d6012b318dbb0961c231ac01bdd +size 91645 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unknown-failure.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unknown-failure.png index 8010c1fc28..7b4aa97406 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unknown-failure.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unknown-failure.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:841d4f5f4f5a4e3eac938f2fcd4b0bb94561eebd6179c91cb84816f3ae7df8b8 -size 89445 +oid sha256:362bd490e10b25967bba6dd8153e7bd877c3921dfafa5cd82bf4bd47a689033e +size 88871 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unsigned-Devices.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unsigned-Devices.png index 2eb2514307..4f6106e85f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unsigned-Devices.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unsigned-Devices.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0dac8094cdadc60b5bf9fb5057b910a51d34598ca207acedac4af329ebe61b3 -size 97569 +oid sha256:255f65cc551f66b6f8abac2d25dc9392d571ec817ac35faeffb3edf5afe041b0 +size 97161 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unsigned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unsigned.png index d84a6afc5e..c646f44fd2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unsigned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Unsigned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f008b5f6b5015caa5102ee2e3368072b89dc8d369b43d229776b2c4d3a7ec119 -size 95442 +oid sha256:af341cdd7b939305d12bdc708038261e69b20d226fba26b1e3e962d40eb5632c +size 94896 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Authenticity.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Authenticity.png index 87fda90f0a..1ff2927bfd 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Authenticity.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Authenticity.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2214c2b47d33f7e71ebe4b113d8c57461977d0e5558b4851e54be67bfc613bc1 -size 120917 +oid sha256:2ff50d376ed003e1ed74d1280e925ac5ad7a6b6c40e90d8380942a6ba00e01c1 +size 120895 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Button-shapes.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Button-shapes.png index 964cce30dc..756a4b0966 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Button-shapes.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Button-shapes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0ca91f7036a9b588ae5cfaa98df46fad4a0c546a815646bcc93b60f5cc04b96 -size 114129 +oid sha256:214ac5fd136bdb59309d1888c457414805d21b8933c48cacec77d6b6d1d385bb +size 114155 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Identity-Changed.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Identity-Changed.png index 50d2b28ef6..49df63aa8d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Identity-Changed.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Identity-Changed.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:224c0a2a1a180bb0f769690986615b42670eaeba5da36c136a194a9b649392a4 -size 119359 +oid sha256:db3e76eeffddb941800e0223114aef12348eedbec814260438b2473b17114b0b +size 119303 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media-with-Caption.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media-with-Caption.png index e3bf6ea23a..68177f893b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media-with-Caption.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media-with-Caption.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ff91b2679413fe8a068f82306eeaa78de5db89edacc910443fd03a9200ac42c -size 111302 +oid sha256:ecd3d6006f5d70672f6d498672ec58cc15f29c8bf2a822eee72ff2d6750c11b3 +size 111270 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media.png index b87398e005..93bee889a0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f083235302db13e888d8c1fdd9cf6746acba7c6b25e6066f225514b78963bc7 -size 99585 +oid sha256:31272d735d59f0f4fcc533a21428fa0d75497cc78dcce346968f16002929d977 +size 99538 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Normal.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Normal.png index 31e7b33399..a5cb5e66a8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Normal.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Normal.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28feeb86b0c09df9a9bc37b3523adbd9145c24372ba3f0d1e46e3b7811d56339 -size 100926 +oid sha256:d26f83ab4865c041c99cd21dd860a11d07fa2e2aed0468bda49a1cccb57458b0 +size 100965 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Own-Unsigned-Devices.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Own-Unsigned-Devices.png index 23c68ebfd9..2c39b4282f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Own-Unsigned-Devices.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Own-Unsigned-Devices.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68ba46257a66431778c6fd648be80e65bd724f451cc4bbd05a92c8dd6eca3ab3 -size 121585 +oid sha256:a81ee898f11f596924e241c787c1b43ef2fb8bdd62b81fb15cb7389ba1ce79dc +size 121700 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unencrypted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unencrypted.png index 28e552dc35..0fe42971d9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unencrypted.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unencrypted.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a3212f9f5ccb198f4bb9770ea232b700cf635a0a3d37ecb7b8297c0496c12f4 -size 105456 +oid sha256:473c68d634cc59fc15797dc34abd2a12be2734d492f3bc662297bd26f2309cfa +size 105735 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unknown-failure.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unknown-failure.png index 31e7b33399..a5cb5e66a8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unknown-failure.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unknown-failure.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28feeb86b0c09df9a9bc37b3523adbd9145c24372ba3f0d1e46e3b7811d56339 -size 100926 +oid sha256:d26f83ab4865c041c99cd21dd860a11d07fa2e2aed0468bda49a1cccb57458b0 +size 100965 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unsigned-Devices.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unsigned-Devices.png index eb0e274347..1dde21eaa6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unsigned-Devices.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unsigned-Devices.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e084c9628684fe7b383b72a2f5906e47f9d65ba2de12a374b728ece3be37c68 -size 117656 +oid sha256:bfb8fb7e8a2969f4d98331e28dd407f3e27b9e1f867c2800b3bc17a4e8a24b6c +size 117597 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unsigned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unsigned.png index 80225d3ad1..eb695c1aed 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unsigned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Unsigned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec4a30d3db9d84514c116964209d741a6179b11c0992b0e92e9e98a8d5e050eb -size 112532 +oid sha256:ebdd860109bc016112ee7c3b32c3cc101827c503f348df694271e6cdca9bbda2 +size 112788 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-LTR-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-LTR-with-different-layout-languages.png index 7294e32178..7994c84249 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-LTR-with-different-layout-languages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-LTR-with-different-layout-languages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ce6c1fa987c2d44f36b12d972ff332a3b082aa0ae7215a150722a1b0bd5042c -size 105696 +oid sha256:0c116146af61a38f0a7694d107b1f4fb69d8a51819e11f76b581810acd62d468 +size 104654 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-RTL-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-RTL-with-different-layout-languages.png index ee39908479..b3bf1cc4d1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-RTL-with-different-layout-languages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles-RTL-with-different-layout-languages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba92afd28fb45fec74cd26f613068244c4d425be6fd8f59e7df8053137b9cda0 -size 104480 +oid sha256:04b3178f8151ea032dcfc741d8fc1c1826c64f1e63c1c201c6cb304a52407a4e +size 103663 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles.png index 26577c12c2..ca31b65583 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-en-GB.Bubbles.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74db463c2fa526d7cfd153b73735c866de82571a09ba0e77494120dc53f4847a -size 93959 +oid sha256:84054b8cd5ac7fd3475dd0bcf5f4cf683ea278f606b88f8e72adefc12a1f89cb +size 92899 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-LTR-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-LTR-with-different-layout-languages.png index 7294e32178..b0dda57bd0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-LTR-with-different-layout-languages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-LTR-with-different-layout-languages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ce6c1fa987c2d44f36b12d972ff332a3b082aa0ae7215a150722a1b0bd5042c -size 105696 +oid sha256:61c9e7095691028a06c241195e931a092e01c68457568d7c1c19fe5e5395e2be +size 109824 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-RTL-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-RTL-with-different-layout-languages.png index ee39908479..946cae4289 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-RTL-with-different-layout-languages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles-RTL-with-different-layout-languages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba92afd28fb45fec74cd26f613068244c4d425be6fd8f59e7df8053137b9cda0 -size 104480 +oid sha256:230d09bb33e4df6698b4ba3da803b7729f91817d4b4c517bb6ded0838c8bcd37 +size 108827 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles.png index 26577c12c2..ea1287da25 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPad-pseudo.Bubbles.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74db463c2fa526d7cfd153b73735c866de82571a09ba0e77494120dc53f4847a -size 93959 +oid sha256:a579e4642d85bc17a22d934d5456b90c0c7d83af993ad554e1bad7ecb88d54bf +size 98178 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-LTR-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-LTR-with-different-layout-languages.png index c40218cfed..49da79af5e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-LTR-with-different-layout-languages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-LTR-with-different-layout-languages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53a157e62c4238820ece12d16e3d6e23c445149baadbb5e450fb84eece6e3742 -size 61906 +oid sha256:62e90606088e083d37220bf9a657416c590e4e812d67b021d7e6a29c18f1e044 +size 61295 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-RTL-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-RTL-with-different-layout-languages.png index 334c0c1bb5..d559c9362a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-RTL-with-different-layout-languages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles-RTL-with-different-layout-languages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85f615aef9369ddbd37254f7ed48f8bc86636d51edb2d6a707a0fae1e59338d2 -size 60992 +oid sha256:bb02c105f9558f0532da9764fdde6e31440a383febe2cbc519ceceb2709f7ffb +size 60322 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles.png index b1e92bb4cb..75a4497078 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-en-GB.Bubbles.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f96ee6bbd8d118ccb95b6d45fbf6ef2889f56094f59aabe9d51f6302f498ed1 -size 51450 +oid sha256:43ffe4f504a6b999c999a0f50ef77077c4b28a6e95b46e7b5e7028af5824943d +size 50373 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-LTR-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-LTR-with-different-layout-languages.png index c40218cfed..76287e58c6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-LTR-with-different-layout-languages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-LTR-with-different-layout-languages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53a157e62c4238820ece12d16e3d6e23c445149baadbb5e450fb84eece6e3742 -size 61906 +oid sha256:efb165cf8137d98147a4ca9a5c7f8accb684491c05d2beb78c0ecab7fe568a9c +size 64909 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-RTL-with-different-layout-languages.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-RTL-with-different-layout-languages.png index 334c0c1bb5..7dc772dc39 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-RTL-with-different-layout-languages.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles-RTL-with-different-layout-languages.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85f615aef9369ddbd37254f7ed48f8bc86636d51edb2d6a707a0fae1e59338d2 -size 60992 +oid sha256:67876b47e3632216798d52d7fc0b85ceabf81cd4dcc113474ab32851ad64c0b2 +size 63848 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles.png index b1e92bb4cb..bc08d44071 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemStyler-iPhone-16-pseudo.Bubbles.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f96ee6bbd8d118ccb95b6d45fbf6ef2889f56094f59aabe9d51f6302f498ed1 -size 51450 +oid sha256:a008bd635226c942af057304516349184dedcc3161277d61078d3a25369a8cd8 +size 55022 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-en-GB.Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-en-GB.Image.png new file mode 100644 index 0000000000..e85193f21a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-en-GB.Image.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a30bdebdc1c816e6ca11cc4259749ec3e7f873e89c38e5cc64b23b5b7dcf7ebb +size 129684 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-en-GB.Incoming-on-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-en-GB.Incoming-on-Room.png new file mode 100644 index 0000000000..3b6efef5c5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-en-GB.Incoming-on-Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f6ff841733941f55b065477a234c318de67cc068870ea560d8650093556e385 +size 106118 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-en-GB.Unknown-type.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-en-GB.Unknown-type.png new file mode 100644 index 0000000000..80641257d5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-en-GB.Unknown-type.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6045b90ca6ad9b362f26505caeda788504d98461a4bdc6003603f79ae25cc45 +size 112315 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-pseudo.Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-pseudo.Image.png new file mode 100644 index 0000000000..65629de67c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-pseudo.Image.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:90f32840b85ff12b6de880e8ab1890f4442b873fac71083093324fc02e9700d3 +size 128067 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-pseudo.Incoming-on-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-pseudo.Incoming-on-Room.png new file mode 100644 index 0000000000..9812d53914 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-pseudo.Incoming-on-Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a1466df7ac398bb7f47bad54aeb8f6a3c6fb7ed29bcfa839feb4c39969afe19 +size 106123 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-pseudo.Unknown-type.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-pseudo.Unknown-type.png new file mode 100644 index 0000000000..8c65e32f4a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPad-pseudo.Unknown-type.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ac674ce8b1e9f8c508ed259d9dc50a4b58f2304d9a3e2d9903121676502091d +size 111333 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-en-GB.Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-en-GB.Image.png new file mode 100644 index 0000000000..e4d0518d1e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-en-GB.Image.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:339faa15c493a6e36f0c567b89eb6d036010c5637a0be03f15f7915306612320 +size 82212 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-en-GB.Incoming-on-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-en-GB.Incoming-on-Room.png new file mode 100644 index 0000000000..cebaf17fa8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-en-GB.Incoming-on-Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:444149b32adb1da10c83c3f6a19da8bff11b26be4cda4a88e90d5ed50ac61b3d +size 59813 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-en-GB.Unknown-type.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-en-GB.Unknown-type.png new file mode 100644 index 0000000000..23706e04a9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-en-GB.Unknown-type.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0cd944ccb9183bfa3c39e7a866b38835baa6c158338c74e05f816f99268d892e +size 66083 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-pseudo.Image.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-pseudo.Image.png new file mode 100644 index 0000000000..009ea838a8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-pseudo.Image.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04241b16f28aa03f42de4e365eadf80fca0637494e891eb5c81a337d7693f476 +size 80107 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-pseudo.Incoming-on-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-pseudo.Incoming-on-Room.png new file mode 100644 index 0000000000..309a948b60 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-pseudo.Incoming-on-Room.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce1be4e6bf0c06b2a1d0046d3c8eed0830292880365a10b048f02bdd15688246 +size 59774 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-pseudo.Unknown-type.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-pseudo.Unknown-type.png new file mode 100644 index 0000000000..e0472b5480 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewDetailsView-iPhone-16-pseudo.Unknown-type.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:54f7a21d3defe67d94c06aa226b503fcc30de8717043e5ca13242c76a4272bc4 +size 64878 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPad-en-GB.1.png new file mode 100644 index 0000000000..4ed1d5e03d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:32ab5b9833a9213daf0a9688ac7d9db6fd112a312e725afe194d813951bb4268 +size 119892 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPad-pseudo.1.png new file mode 100644 index 0000000000..47bf957234 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7b3fc983e75283a83041f37db96689af1487828d249a989d7ff10ec5c73f0f2 +size 128217 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..5a795a925a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:825917a093ef369a8b6583d825d675c9a44c96f2f6ab9cab2ec5c19e7508b425 +size 74696 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..646e6fde05 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineMediaPreviewRedactConfirmationView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebc3ba85ab3bbd09db0a002fb3b729ebe1390d975061c6804c35d3da5822a1b7 +size 87336 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-en-GB.1.png index fa8384596b..4013440426 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f2494ad1a4901b35871ce292dec58390604264dfd6059d17d49949db807e483 -size 149949 +oid sha256:8efa2361eaed6333334f2fd6c2b07d2fcaeb9b7f3131b0cd6bab29ad105a418f +size 176085 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-16-en-GB.1.png index 5303a917df..b9255a0396 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReplyView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd8fe0c2f43d5e233e02280e4b786f51479e1259c910e6d5919538f9e609a114 -size 100667 +oid sha256:c5ceb7ffe4fbc07bb555c3ee43c7e809222aedc3a410ac26b173e5e1c4d7c057 +size 125497 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png index 742befb2f7..5e287266dc 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:906409795a47057b2da67dc7a50221b6a9be839309cf434899d3ee7c19735c83 -size 295656 +oid sha256:d19fdc59c123919099ce464a0bb5478edb8df05e23609cd5dae1b430bcd469d1 +size 295900 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png index 76fe17dfea..092ac6fcc4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38a6eea96f81ab5acd88b75823745cc7bb71c237ff0ca181e05e0263abc487d9 -size 297761 +oid sha256:015366f6fe40da0753b014c0be10d6f46478d36e76fef8ac0d03608c44c8665d +size 304454 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-en-GB.1.png index 037e6f2eee..14f263242f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b8ab1d9311c44e85d8e145a9290e97aa2b37070a3104402332479ec8c2fd739 -size 180530 +oid sha256:e5fe32d96cc563369893c88d566260a465e5ae7f372b10f75f1cd6b9fa93877e +size 181804 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-pseudo.1.png index d1aac8e161..caf86ca422 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5843af5ad8774b2d73bc57b18caacb79cfa46abc54c797b5c17948f961ded06 -size 178598 +oid sha256:6332e9688b6bc74fd053be710d9fc160016ff08fe08d755420871e5a79ad6c24 +size 180191 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-en-GB.1.png index d9991c1d13..fed87be5c5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0afe99b360ddd2a6562504c84ecaeeb958797284692bab7563d9e4da316bd942 -size 98225 +oid sha256:0d5a45556b8322972a0868231e6d37a66a861faca86aee0d3a91b34acc445570 +size 98001 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-pseudo.1.png index 3670eddcc5..f8bc7a5281 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c7ec2c8b317744fe7c100c372446b6d9b9527416e0468155c84ed201b5158e3c -size 100913 +oid sha256:83990b911f0c49a8605dffc30ea7de0fd0e94daa76c743d7a19d608a35024ec1 +size 102211 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-en-GB.1.png index 8e634f486f..951d9d297a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3a97b9437ecb510ec136a8f6529e9cff38e9ecf3563e6259ea316dfe7ff12c3 -size 58379 +oid sha256:e99377478c8c0954d06cf85dc72124f7adfcc0d7925f8d202388888e48a79817 +size 58102 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-pseudo.1.png index 98e2434fbc..ddfb055e30 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_unsupportedRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:004431ca0ade6711906570ca4f40b90a13bb3d9ca1554e1f1825d9de7db775f9 -size 60841 +oid sha256:59338be4cf9afc6619a5fa1867e8c406c14d45da7a06fc541a9c2149732b6814 +size 62890 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPad-en-GB.1.png new file mode 100644 index 0000000000..96a62f0d24 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a50a7265055b6ffceed4ee63d3d162c32eeb922629d40a40dcda275d836a238 +size 119650 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..96a62f0d24 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a50a7265055b6ffceed4ee63d3d162c32eeb922629d40a40dcda275d836a238 +size 119650 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..6714cf5736 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:951340c103ad1445e8ca3c40f7f46388e0ed7f301bfea84cebad63240862221c +size 109436 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..6714cf5736 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoMediaEventsTimelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:951340c103ad1445e8ca3c40f7f46388e0ed7f301bfea84cebad63240862221c +size 109436 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-en-GB.1.png index c11fbddd93..bbff3fe7de 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba0a7cbad0cae44f11230bfd240445eeca207ddf22d6e3b5882e69d448cf2a9b -size 95167 +oid sha256:85676cab794704008963ddbbef163b368257d3ec5c0ff334f6707400a0cec944 +size 6059480 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-pseudo.1.png index c11fbddd93..27b607a974 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba0a7cbad0cae44f11230bfd240445eeca207ddf22d6e3b5882e69d448cf2a9b -size 95167 +oid sha256:79ee95fbcb1fa86a97c992a8840e99ba359902dcf93302198e7fb8dbda7d6f9f +size 6047683 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-16-en-GB.1.png index 4bb5d6f1f0..10183e760f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d74e45a7d9ceb6b72d3c64aa300fbc122f18aef4c3b6cef630850c3cd242a8c4 -size 52016 +oid sha256:b7c2571777d39e41eb885944aba32297c6b371c48ae018e0276b265ca07b1217 +size 1767084 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-16-pseudo.1.png index 4bb5d6f1f0..970d587248 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_videoRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d74e45a7d9ceb6b72d3c64aa300fbc122f18aef4c3b6cef630850c3cd242a8c4 -size 52016 +oid sha256:74e3b5bfa5c7f5ad3bc917882e56034f46f8ef4ebc9460b08e408dfcf0da6a8b +size 1751575 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPad-en-GB.1.png new file mode 100644 index 0000000000..f63a1bb2ba --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16c155fc0209dad7f822280f935baf1b7558ca92a96316a43221fbb6e7209854 +size 74031 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..f63a1bb2ba --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16c155fc0209dad7f822280f935baf1b7558ca92a96316a43221fbb6e7209854 +size 74031 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..03c3910f3e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67319c74089339e445ea194e10db087268c7c1d6b2832877f2ad698803e56875 +size 32851 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..03c3910f3e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageMediaEventsTimelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67319c74089339e445ea194e10db087268c7c1d6b2832877f2ad698803e56875 +size 32851 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-en-GB.1.png new file mode 100644 index 0000000000..36228f2655 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f518c5ce36c085ec697501297d0303044042b8df1341fcf0d02b08b3eef58959 +size 77812 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-en-GB.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-en-GB.Bubble.png index f031decd3b..53a695bc6d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-en-GB.Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-en-GB.Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4598703d5671e098a17cce67e465bce7835f163aa997ad3500a715c3da66de8d -size 77897 +oid sha256:3f4f1266f8f571fb61056f8c58d75f8dbb9653b916168b7ff08e457c9f55b562 +size 78247 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-pseudo.1.png new file mode 100644 index 0000000000..9439295081 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d456a81d249a01c6817c0bb35bf2a501ca641918009533c3a8dbb9db2739456 +size 78571 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-pseudo.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-pseudo.Bubble.png index f031decd3b..8e54f887bb 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-pseudo.Bubble.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPad-pseudo.Bubble.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4598703d5671e098a17cce67e465bce7835f163aa997ad3500a715c3da66de8d -size 77897 +oid sha256:5be910490972939e7dc064fa8bbcfc2ba9f3c50d2183836a66ef887eb7bd59b1 +size 79781 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..65b8e5e82a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cef3e1dc07041a0624fe8f900b36c61962dc6d0f956fc532deb3262853448c10 +size 36670 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-en-GB.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-en-GB.Bubble.png deleted file mode 100644 index 308cf38431..0000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-en-GB.Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f1b90d3e6a1b4bbc42e37469a1d3b352a0de74199e9318110994300f9a475831 -size 36896 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..1ef5162802 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:abf4ef40082a65fa07969637dfdaf2b218953fa45281a7b0d62dd532889c9e44 +size 37417 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-pseudo.Bubble.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-pseudo.Bubble.png deleted file mode 100644 index 308cf38431..0000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_voiceMessageRoomTimelineView-iPhone-16-pseudo.Bubble.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f1b90d3e6a1b4bbc42e37469a1d3b352a0de74199e9318110994300f9a475831 -size 36896 diff --git a/TchapX/main/Sources/Generated/TchapAssets.swift b/TchapX/main/Sources/Generated/TchapAssets.swift index fdc5d22e14..016b5164a5 100644 --- a/TchapX/main/Sources/Generated/TchapAssets.swift +++ b/TchapX/main/Sources/Generated/TchapAssets.swift @@ -2,14 +2,14 @@ // Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen #if os(macOS) -import AppKit + import AppKit #elseif os(iOS) -import UIKit + import UIKit #elseif os(tvOS) || os(watchOS) -import UIKit + import UIKit #endif #if canImport(SwiftUI) -import SwiftUI + import SwiftUI #endif // Deprecated typealiases @@ -19,21 +19,20 @@ import SwiftUI // MARK: - Asset Catalogs // swiftlint:disable identifier_name line_length nesting type_body_length type_name -enum TchapAssets { } - +internal enum TchapAssets { +} // swiftlint:enable identifier_name line_length nesting type_body_length type_name // MARK: - Implementation Details // swiftlint:disable convenience_type private final class BundleToken { - static let bundle: Bundle = { - #if SWIFT_PACKAGE - return Bundle.module - #else - return Bundle(for: BundleToken.self) - #endif - }() + static let bundle: Bundle = { + #if SWIFT_PACKAGE + return Bundle.module + #else + return Bundle(for: BundleToken.self) + #endif + }() } - // swiftlint:enable convenience_type diff --git a/TchapX/main/Sources/Generated/TchapStrings+Untranslated.swift b/TchapX/main/Sources/Generated/TchapStrings+Untranslated.swift index e8ce0a700c..d4bb6ab5bb 100644 --- a/TchapX/main/Sources/Generated/TchapStrings+Untranslated.swift +++ b/TchapX/main/Sources/Generated/TchapStrings+Untranslated.swift @@ -9,20 +9,20 @@ import Foundation // swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length // swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces -enum TchapUntranslatedL10n { } - +internal enum TchapUntranslatedL10n { +} // swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length // swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces // MARK: - Implementation Details extension TchapUntranslatedL10n { - static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { - // No need to check languages, we always default to en for untranslated strings - guard let bundle = Bundle.lprojBundle(for: "en") else { return key } - let format = NSLocalizedString(key, tableName: table, bundle: bundle, comment: "") - return String(format: format, locale: Locale(identifier: "en"), arguments: args) - } + static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { + // No need to check languages, we always default to en for untranslated strings + guard let bundle = Bundle.lprojBundle(for: "en") else { return key } + let format = NSLocalizedString(key, tableName: table, bundle: bundle, comment: "") + return String(format: format, locale: Locale(identifier: "en"), arguments: args) + } } // swiftlint:enable all diff --git a/TchapX/main/Sources/Generated/TchapStrings.swift b/TchapX/main/Sources/Generated/TchapStrings.swift index c2aaedec7b..caf359654f 100644 --- a/TchapX/main/Sources/Generated/TchapStrings.swift +++ b/TchapX/main/Sources/Generated/TchapStrings.swift @@ -9,33 +9,41 @@ import Foundation // swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length // swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces -enum TchapL10n { } - +internal enum TchapL10n { + /// Frequently Asked Questions + internal static var commonFaq: String { return TchapL10n.tr("TchapLocalizable", "common_faq") } + /// Legals + internal static var commonLegal: String { return TchapL10n.tr("TchapLocalizable", "common_legal") } + /// Privacy policy + internal static var legalPrivacyPolicy: String { return TchapL10n.tr("TchapLocalizable", "legal_privacy_policy") } + /// Terms of use + internal static var legalTermsOfUse: String { return TchapL10n.tr("TchapLocalizable", "legal_terms_of_use") } +} // swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length // swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces // MARK: - Implementation Details extension TchapL10n { - static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { - // Use preferredLocalizations to get a language that is in the bundle and the user's preferred list of languages. - let languages = Bundle.overrideLocalizations ?? Bundle.app.preferredLocalizations - - for language in languages { - if let translation = trIn(language, table, key, args) { - return translation - } - } - return Bundle.app.developmentLocalization.flatMap { trIn($0, table, key, args) } ?? key - } + static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { + // Use preferredLocalizations to get a language that is in the bundle and the user's preferred list of languages. + let languages = Bundle.overrideLocalizations ?? Bundle.app.preferredLocalizations - private static func trIn(_ language: String, _ table: String, _ key: String, _ args: CVarArg...) -> String? { - guard let bundle = Bundle.lprojBundle(for: language) else { return nil } - let format = NSLocalizedString(key, tableName: table, bundle: bundle, comment: "") - let translation = String(format: format, locale: Locale(identifier: language), arguments: args) - guard translation != key else { return nil } + for language in languages { + if let translation = trIn(language, table, key, args) { return translation + } } + return Bundle.app.developmentLocalization.flatMap { trIn($0, table, key, args) } ?? key + } + + private static func trIn(_ language: String, _ table: String, _ key: String, _ args: CVarArg...) -> String? { + guard let bundle = Bundle.lprojBundle(for: language) else { return nil } + let format = NSLocalizedString(key, tableName: table, bundle: bundle, comment: "") + let translation = String(format: format, locale: Locale(identifier: language), arguments: args) + guard translation != key else { return nil } + return translation + } } // swiftlint:enable all diff --git a/Tools/Sourcery/AutoMockableConfig.yml b/Tools/Sourcery/AutoMockableConfig.yml index f1cc89371a..fb81d99399 100644 --- a/Tools/Sourcery/AutoMockableConfig.yml +++ b/Tools/Sourcery/AutoMockableConfig.yml @@ -9,4 +9,4 @@ output: ../../ElementX/Sources/Mocks/Generated/GeneratedMocks.swift args: automMockableTestableImports: [] - autoMockableImports: [AnalyticsEvents, AVFoundation, Combine, Foundation, LocalAuthentication, MatrixRustSDK, SwiftUI] + autoMockableImports: [AnalyticsEvents, AVFoundation, Combine, Foundation, LocalAuthentication, MatrixRustSDK, Photos, SwiftUI] diff --git a/UITests/Sources/Application.swift b/UITests/Sources/Application.swift index 2c208450d6..acd675a598 100644 --- a/UITests/Sources/Application.swift +++ b/UITests/Sources/Application.swift @@ -47,6 +47,9 @@ enum Application { guard deviceModel == requirediPhoneSimulator || deviceModel == requirediPadSimulator else { fatalError("Running on \(deviceModel) but we only support \(requirediPhoneSimulator) and \(requirediPadSimulator).") } + guard UIDevice.current.snapshotName == "iPhone-18.1" || UIDevice.current.snapshotName == "iPad-18.1" else { + fatalError("Running on a simulator that hasn't been renamed to match the expected snapshot filenames.") + } } } @@ -91,15 +94,7 @@ extension XCUIApplication { } private var deviceName: String { - var name = UIDevice.current.name - - // When running with parallel execution simulators are named "Clone 2 of iPhone 14" etc. - // Tidy this prefix out of the name to generate snapshots with the correct name. - if name.starts(with: "Clone "), let range = name.range(of: " of ") { - name = String(name[range.upperBound...]) - } - - return name + UIDevice.current.snapshotName } private var localeCode: String { @@ -118,6 +113,20 @@ extension XCUIApplication { } } +private extension UIDevice { + var snapshotName: String { + var name = name + + // When running with parallel execution simulators are named "Clone 2 of iPhone 14" etc. + // Tidy this prefix out of the name to generate snapshots with the correct name. + if name.starts(with: "Clone "), let range = name.range(of: " of ") { + name = String(name[range.upperBound...]) + } + + return name + } +} + private extension UIImage { /// Adjusts the image by cropping it with the given edge insets. func inset(by insets: UIEdgeInsets) -> UIImage { diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index b782a02574..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:985a32a8c09e4c4743fa1df38f7929d166c845101cdf6dc42673297de2ff9ccd -size 1297240 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPhone-16-en-GB.UI.png deleted file mode 100644 index 4dc972efa8..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:10f4b586e2c65793dce21bf7a39a8de9eb6e4e343c9ac6c0bf3cbd0dbdef22bc -size 948002 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 34d4bd11ba..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6b16d8bffe575dbb20cd9ec78ef4750edcbbe75f7e9726771584b272935a1eff -size 107103 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPhone-16-en-GB.UI.png deleted file mode 100644 index 8947d2df1f..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ac234a621cd49620ebf3556383029c31b8df4e7f8eb0760fc8bb4138b18c5e82 -size 119243 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 6e8844768e..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7ece1e4397aca92f8394aafdf7495ffeaaec3621bb31cc49cd5645e0b134f11f -size 108257 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPhone-16-en-GB.UI.png deleted file mode 100644 index 8126852d55..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ab044057eac0d4b8d1461374ab2192af0897e58efedc216f775b5572e7f3d5ea -size 120324 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 8e2cc629d8..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:907d3be4bef23d70e41249c6b73006309822a8fb4a67e3b06382d2ee803392f3 -size 245970 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPhone-16-en-GB.UI.png deleted file mode 100644 index eab5cc9a0e..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b058a219396efea34311df04c53480ebd6efc77882aece4bf384a92844b0de6a -size 387177 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 4b502c2880..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dc2860c28f52e0b81954dd2f340f685d419d3e64dab2b5b22d67ffaa1167595b -size 118917 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPhone-16-en-GB.UI.png deleted file mode 100644 index 9a4b90892f..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4e733a3e34ad883d23ced9f6f7002d79ded0f1a2831f487f67ce95f41c790f2a -size 134493 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index e51d4ec098..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:76afd660423ad6e16d5f489f253bd6f02c3c373369251f8ddbed18de85408563 -size 64852 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPad-18-1-en-GB.UI.png index 565c1905d2..83ca611ef8 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:180743191fcf9af0de19525e3fa649e89cb24c9e5be1cd77b6da96272c71aa14 -size 66254 +oid sha256:1246f8b0f5a56918a8a0dc11436fc44f981eece24b8876ebce1ef9922fd93d67 +size 64833 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPhone-16-en-GB.UI.png deleted file mode 100644 index 4619eeff9f..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7005a049ae9f492ccfec1918d4ff73e349c7c801e531436c63729acb7d6e6c32 -size 57132 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 0309dcb73d..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c452ed8a368a75805d97ead98fd3b4121ac7ae6068ab2e07c7d099ab790bbb04 -size 154940 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPhone-16-en-GB.UI.png deleted file mode 100644 index ff974aece2..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2297bd3166f13e83470754d0b2243d16bfa5815e267c0b43a19fc06db4197e2d -size 93888 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 5132b4c4e4..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2dacead149de65e74fc44b308ce2ce0b97c5c442b013910da155fa6b128928b3 -size 82353 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPad-18-1-en-GB.UI.png index 029a8b6f81..ec88f2c5d3 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef84d325ff4f091c6e136f16416d90c3542ad358a70f08e4436ffd9946f5a999 -size 82486 +oid sha256:5aed69f396bc913e16ec6b2d856361f9d7a7d42091815eddfaa4358e10ee4afe +size 82002 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-16-en-GB.UI.png deleted file mode 100644 index de4daac7fa..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:34bddc89446a55313c707c45c901d76ca670ddeb52a47455a8b462383416a9b7 -size 83394 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-18-1-en-GB.UI.png index 758394a12b..b28aa5e44e 100644 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7378f5adfd525aaee8a4ab42f2ed0cc98c54ca0a1c87faa9c61c5d1f824f960 -size 83655 +oid sha256:07602a525908e815130f04e834004d6139ae49027928eafc8127e064b4f51c57 +size 82783 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index e51d4ec098..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:76afd660423ad6e16d5f489f253bd6f02c3c373369251f8ddbed18de85408563 -size 64852 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPhone-16-en-GB.UI.png deleted file mode 100644 index edda5df599..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a7e03a28552e7377492817fd9f06918582d6b05ff2b23cb208d726f5e30e19cc -size 56207 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 52e1293a50..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:efbe245aca461954d911e0c67a81c684e390e1730ce4416964490c7ba8213a6e -size 96179 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-16-en-GB.UI.png deleted file mode 100644 index 0560e34a44..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a90145ce7432b3d17a33b640ed01676e7e2438f77bd46ae462343eb889edee34 -size 92579 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 1821a898d0..0000000000 --- a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:66cb7271423fb9653f290c444cee8b84db8692eeca2d2643739246e84d5a6540 -size 140508 diff --git a/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPad-18-1-en-GB.UI.png index 0530823155..cc6eef7a2e 100644 --- a/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1cd647578cb93945cc07cbeb2273e99c4a5d39c8e02e9e2d5dfde272d59d60b -size 166908 +oid sha256:eca0528523edae6dfae1cb8087c1aeb12224102c26b0fa7db99a17729fb22740 +size 167101 diff --git a/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPhone-18-1-en-GB.UI.png index 6859f0e427..fa53f300f0 100644 --- a/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f322df60c0efebd8a72cdde5653ebbb47100cf1afb736749715c9b0bbe55a3e4 -size 266989 +oid sha256:d4c1065c8cbd078860b9a8ab1c8579e48488794c23c6c1895c5b275c9c0ba0b6 +size 266840 diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-0-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-0-iPad-18-1-en-GB.UI.png index 9cd7690959..2d7bf98c57 100644 --- a/UITests/Sources/__Snapshots__/Application/bugReport-0-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/bugReport-0-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4513735733d5bd1cf618f5f698c05cf3bfc9e3f7e1d8d2f0f16f59473228b9d2 -size 137089 +oid sha256:c9a40262e1c2588be6f35f09c6e1974fc925f9edf899be056e45ffcdf5e2ac71 +size 137444 diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-18-1-en-GB.UI.png index b02a22a4cc..d4bf4f06bf 100644 --- a/UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad2fdc22c0f151aac2550afc480759f8d944bf1dab858648c88482a19675b0d9 -size 172949 +oid sha256:1bf80e63f574f22ddfe4f045c0a0a57b67ef4ababefafe4be8820ae59f35ce8e +size 172930 diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-3-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-3-iPad-18-1-en-GB.UI.png index b0e7f98397..8a86d5a176 100644 --- a/UITests/Sources/__Snapshots__/Application/bugReport-3-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/bugReport-3-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea346e28081c79301e2787150a5107049307c89834d7fc42532dafd5b9fc93d5 -size 207252 +oid sha256:56860531fa683fe7be9e90a2a4c41ffc3e207b7bb1ad7d993ae5c1a3e7442fd5 +size 208800 diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-18-1-en-GB.UI.png index fa7e1a940a..785f0f2e1e 100644 --- a/UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f0004b008911fb30aa37abe05843a068d52d627d95302cf77296cd2c1d410690 -size 201890 +oid sha256:9a20a079f678aceeaa514b478a6222a03722047658c109a5a9a60e02477c9d7a +size 204134 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-18-1-en-GB.UI.png index 16adadcb2e..3e5389b64b 100644 --- a/UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc0378adcd08c8a81fbf79169cb2980ba8b948f484174e847f274244c33d2a1d -size 191811 +oid sha256:f917c5025edb6d96857a824a4686eafee33aed4759b0427f488cde8b0e4a0214 +size 195197 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-18-1-en-GB.UI.png index a62fa153ae..bdcf740321 100644 --- a/UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8be3fb5f322bd4028ce149fd51c28a86cb60e78cca8962b375a0c37819d87844 -size 315126 +oid sha256:a4e8333429b76cc93561150b4c604214bbccfd283c4305ad32b00a7263249494 +size 299629 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-iPad-18-1-en-GB.UI.png index 3635ba5185..9a2b039f63 100644 --- a/UITests/Sources/__Snapshots__/Application/createPoll-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/createPoll-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62bfb31ceedb4a68fd7be3a1ba02b62de8c424bce5bc47326c55e746018a6ef7 -size 100266 +oid sha256:b0ce9363f981f779c0e8ac3d4e7a08171c3b4fac3f9bb4d9df35f6ae5f88efd5 +size 100574 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-iPhone-18-1-en-GB.UI.png index 0df96ed7aa..90d551b2bf 100644 --- a/UITests/Sources/__Snapshots__/Application/createPoll-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/createPoll-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3d1e04abea59afd29cbe35b09ccc0f52e6e53dd4dbb60200460b9d4dd140dc9 -size 113207 +oid sha256:1ebd8664d4f9e7342b3de70d28c6910aabd712a26f57eeaa230b34232e4620f2 +size 114467 diff --git a/UITests/Sources/__Snapshots__/Application/createRoom-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoom-1-iPad-18-1-en-GB.UI.png index 745e3b3d0e..de46c5bc53 100644 --- a/UITests/Sources/__Snapshots__/Application/createRoom-1-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/createRoom-1-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8864c6394f1b76a8bd23e6082d91028d540ac921395de23e3e3259f95f0b7a89 -size 137279 +oid sha256:ea454317e445b45d5b53b80df27a340c2e688aa05b980f516ae63f13cb390117 +size 137394 diff --git a/UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-18-1-en-GB.UI.png index d491194b7e..de65c33654 100644 --- a/UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e5d2f5b6d9d011f562b14a4cdf1e7aba531dc021c791a85d3f87a3179fb3fa5 -size 169105 +oid sha256:6601de73bb862d6bc7884454f0a5c5853af52508fccb34e9e3fa594a20ac8e76 +size 169179 diff --git a/UITests/Sources/__Snapshots__/Application/createRoom-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoom-iPad-18-1-en-GB.UI.png index 13d32967c3..0cbf83aec1 100644 --- a/UITests/Sources/__Snapshots__/Application/createRoom-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/createRoom-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2176064b78a69e98258825bba091872ea1067f5c64de31d7085a6c8838079f01 -size 141319 +oid sha256:c4b4403f6788ebb6d758b2dfd9888446b71062c0aeee3457ff43e191f50a5b67 +size 140119 diff --git a/UITests/Sources/__Snapshots__/Application/createRoom-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoom-iPhone-18-1-en-GB.UI.png index 826b183c40..b506b02a8a 100644 --- a/UITests/Sources/__Snapshots__/Application/createRoom-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/createRoom-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c44af2a13202b66ade79afb7047638280744d487f39b096ae947a35e4e11165 -size 174442 +oid sha256:aba0836ae9da833a01cb5e2a63667a526a9780dd04a2070380674c6871a1e9f5 +size 174946 diff --git a/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPad-18-1-en-GB.UI.png index f5eeb8955b..8bb960908f 100644 --- a/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b927cde4aeaf48a0e9305d083c371dc3e29e5ce3751ebe15deea73087963c8fa -size 122104 +oid sha256:72fdd9d0401b35474fd19dd4d019b7ab859804eb2da7d9d4e45e13d130dffb66 +size 120870 diff --git a/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-18-1-en-GB.UI.png index ff9c3de51b..d6f69b7490 100644 --- a/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77c3d1f0c3f779a35f5551afaf663540921598a642d9870f08f77e5b89696d85 -size 146875 +oid sha256:19b5bfccc057323b2cbb8cec0e991f99cc4164b46001b075438fcaee7d9b40b9 +size 147319 diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPhone-18-1-en-GB.UI.png index 7149f053b2..72cb8d5020 100644 --- a/UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cfb972eed3d11d9ebe4e13f106e4add77b44c928a8df5f140334a28b157a9de5 -size 142884 +oid sha256:9c7753ecb9a032c14ac1b53ec94dfaf055da89c3d053b0dd095b15b291129730 +size 141912 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index f4d5dee0af..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2a3cddf27c919a33e268efbc56584e069848b9b8d773bcbce30b8bf9ec56f460 -size 323389 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-18-1-en-GB.UI.png index f4d5dee0af..b048122a92 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a3cddf27c919a33e268efbc56584e069848b9b8d773bcbce30b8bf9ec56f460 -size 323389 +oid sha256:84b6700fb32ee26c3e02cda232e1f90cce43d9e98cc2c3a50fcbb20552d4c234 +size 313586 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-16-en-GB.UI.png deleted file mode 100644 index 612652406f..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9f2b1bb7cd121631f9064509e6d7be090abd62c5a4afb09d083ab0b33d67a355 -size 329861 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-18-1-en-GB.UI.png index 612652406f..ad824ce185 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f2b1bb7cd121631f9064509e6d7be090abd62c5a4afb09d083ab0b33d67a355 -size 329861 +oid sha256:5d49505e04f1234e53a4b294a176f3f319e4c88755a9dfab89099b8aa0b23763 +size 330909 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 5134b0c0bf..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e31cc2b4c2f0fc0a931ec0a1ba4f8531d0435afa02565cca400c06bef2db9243 -size 328875 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-18-1-en-GB.UI.png index 0d626f39e6..e30d3b8986 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:25540c75506376d5fbeb195541710ea0c33a68150fcb316c309aa74dc0535d76 -size 328838 +oid sha256:6aee4dc5c5a76694f9413f4aea19552c3e5eb228c801d76e1e152d4bcfb58bd7 +size 322208 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-16-en-GB.UI.png deleted file mode 100644 index d845bb2177..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0805c9072d8de90ff269e80be6c245d1bff4a0f5dc143d19bfaf59a05b170148 -size 317722 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-18-1-en-GB.UI.png index c8ddc5e371..bfc267c82c 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9f2ef1657b0af2a483f2ebfcce728ceb0df29f2ac38f1f67f1a794b54e6130f -size 317795 +oid sha256:0ac4df8100ade531c36aac98e83e88c4091a8191ab5322a42276da86e272fe22 +size 318751 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 2aa6e0a8a3..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5c767089cde753c220be4155f44f5a80596ee2b12d452665e65d1310c2f2782a -size 232850 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-18-1-en-GB.UI.png index 2aa6e0a8a3..3a3ae4dd0f 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c767089cde753c220be4155f44f5a80596ee2b12d452665e65d1310c2f2782a -size 232850 +oid sha256:b335f6a50c0e5d4e68cc899b3f504bc0e8a22ed65cadaef57b86921c8882c2d4 +size 220961 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-16-en-GB.UI.png deleted file mode 100644 index 292642f97e..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f5a0569910e56f38be84e6d14bc721d5ab09ac90229a46eccbadcf54b2b88eec -size 326819 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-18-1-en-GB.UI.png index 292642f97e..c0442db6df 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5a0569910e56f38be84e6d14bc721d5ab09ac90229a46eccbadcf54b2b88eec -size 326819 +oid sha256:c71f6a7744288f0b653e61fcaacb9c4c610431a2b97f2bd0ca1ab8f23e576a03 +size 309964 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPad-18-1-en-GB.UI.png index b023078524..e20db9b159 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd7ba6f117201899454d8f013219d246cda951654be4727cc218f5e2ce0a6657 -size 334367 +oid sha256:f4a867359461f4e01e45abcb953c942b91fc61e42b4297ca3d5715a99821abd4 +size 325000 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-18-1-en-GB.UI.png index c78df95e32..003c07d408 100644 --- a/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ecca3b6f3357d2e5868224b6005079c33543564d08f1b6c32c5b4cde291183eb -size 341217 +oid sha256:3f572c105765aef0e0773be4f7a4e015f7491fbd1dd11eebc90a8b4fcc373609 +size 344334 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index a5063ef744..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:63208fa6696f715d23a3820e156f5e7a5b829dd6b738acea4596a6d061d1b047 -size 92354 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPad-18-1-en-GB.UI.png index 4e9abf67b7..83292736be 100644 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45e3a2173dc9b142b62c0209823c6d7fb1cfd15d9cfe93d54698ed654151e3ce -size 74611 +oid sha256:ee1debbb45e1bcc7880f3f99458bbbd831c57330076310c1645a9449b642e9f7 +size 74660 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-16-en-GB.UI.png deleted file mode 100644 index 404f1ee6ac..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:45441951bcf108f21ddd690f18ebe90c70dd5d85b3fe10672688dbd5dff7787b -size 73047 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-18-1-en-GB.UI.png index a44af6322a..4e4fb0cf8f 100644 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a260107ff9eab5f8efdc2a83225b48730fcb1d5526321a37fbe00c622adbd29 -size 72978 +oid sha256:65097a2250f5b1b6de9e45a5e8d5afb97cc25f13ca17c010a9678b554e0c5639 +size 73055 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index b1e994bed0..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3ea7c39995c56335caebd878ee313bfe652e17f4364b0d280415f46dbca7be0c -size 92452 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPad-18-1-en-GB.UI.png index 61a5643d77..f66a2bc9bc 100644 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eceaa9d579094a7fb6678fac242359dd9aedfdf362f149ccf5ce3f06b819ddd0 -size 74151 +oid sha256:ee7178bb1bb2be922f1793948a84412ef8d115b9b89ccaa8605666653243054e +size 74201 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-16-en-GB.UI.png deleted file mode 100644 index 9a63ba3cd4..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:34c734fc5c037189a1c217237b9e4fa2a8fcf51f6d54b9120e17f6f030eadff0 -size 71663 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-18-1-en-GB.UI.png index d308a5382b..390b8dfb82 100644 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43ac02669327b7810031808e01159734dab7076a5c0cd5bdfabd69b3e9e9b1fd -size 71605 +oid sha256:714bb755bd9d9c69ffbbabe3d54fa95e450055f2697a3a9c1bf9abf47d7e15de +size 71673 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 14f7f2e74d..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:490c3d4bed3415a01d9553ce841fcdb6058a5314484af1731df3177ea5b190c2 -size 95955 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPad-18-1-en-GB.UI.png index 018237d628..e00f87ecc8 100644 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf3e8b383f3e59aab88fe5872c6ac1e9b75079999246c255443f50b4f8a8e257 -size 97711 +oid sha256:60fd6b014cc81d8a7df1f8e95a6748ff9b62b1b731a1dac93a81d74133bd8ed8 +size 97849 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-16-en-GB.UI.png deleted file mode 100644 index 1df055cb97..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:117eaf5f66bc6ef3ce63affff131be64066bd08341029fc32f52efda8ca775ad -size 104831 diff --git a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-18-1-en-GB.UI.png index 9f5fc4ba47..0a1e32e1f4 100644 --- a/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5c5a6c6e4324308a23cd68ac4a8ffa16703ad7c4a2eb993f6a6b39850ee259d -size 107464 +oid sha256:9bce10d9b3e28d256316285eabcc8d56a9f74234ba7fecbf108a9e7e09551ae3 +size 108143 diff --git a/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPad-18-1-en-GB.UI.png index 5a3e67c0b4..361824b69c 100644 --- a/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c68739d109d5bb560a60bed2bc20dab57c0f09324e52c63f9a732423d684e79 -size 292066 +oid sha256:479b7eedb90b238436d89ff1c42ad786796692df62c02775c74475742fa3b386 +size 295544 diff --git a/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-18-1-en-GB.UI.png index 2c15481ece..741c5a3061 100644 --- a/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d93c86fe9c295fe9cc8b9c8fffb0768211a63c75de990aba029cf64a386789a -size 370242 +oid sha256:d02ff8334acfb26b5da2948d4b16a6418bdbd221f25d1366d4ef61038bf66d86 +size 372224 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index a7eeba7447..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5e058fbd44b9a70bdb5dd9de4cad2aa09f74d442375e945af9c1211ab661a0db -size 113754 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPhone-16-en-GB.UI.png deleted file mode 100644 index 71dd73811a..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:73ab8c640be946e740190429053bfbe5c2885a16086a99d602b76b16b855c9a3 -size 133468 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 3763571d57..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e2d4e386414e20d561952acf5146b86b33519cdac64422f72f430bb2cffb920c -size 193769 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPad-18-1-en-GB.UI.png index 55ff85893b..4c11cb835c 100644 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3c22b8ccc407b58b26c4ccc8652a9ceb3dca67bebf00df27cc2b1fc47ab8e16 -size 193781 +oid sha256:41d6746971eac6a174c4430d911dd21c365b3ca8933317496f0097b27d34b929 +size 210186 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-16-en-GB.UI.png deleted file mode 100644 index d2671c3d24..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:794a8682899ea72300576908643ad0f3d69215ac0cce5f82221d6c7a70b0040a -size 222074 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-18-1-en-GB.UI.png index 3b993d967c..572a3caea3 100644 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8028502d3db47f9c64e2aba1a9a08a62de878853a6e967953c3599e0171dede9 -size 222509 +oid sha256:578e78588c959fc634d9141da93a61ccd142f4ed808bdcb5eea2a996cf364783 +size 259119 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 6e940f9125..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3bb325888a115cb360a4a7bb4d84fd22ea71614c0807e3f90045abdfb26b67f9 -size 187518 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPad-18-1-en-GB.UI.png index 7050aa564f..a57b32a0b2 100644 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b39b803f6063e112d1d4666efad916821fd4f6dc93ea96d1ddc72b7a5b0f347a -size 187175 +oid sha256:63f479b947420f9896b3b2e82f4a4bbc6fb9862e6f27d7a05e36edeef9445230 +size 195763 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-16-en-GB.UI.png deleted file mode 100644 index d37851811b..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4bf1373234d865555c3166c3347eed7d027da19e1e34bb5e28ef6928c7f94d1c -size 194734 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-18-1-en-GB.UI.png index c13deb9596..8c02f2ac33 100644 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d48281b6ed613203ff01f454558546603e9d7d43436481ee873fe36888bfcc1f -size 194702 +oid sha256:b35dd0afd5d4a5fcd003bd941e0c3c8ae0f8c3ba12f59ee77a19810236952d12 +size 208425 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 5bb88c890c..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:997e72d0c330511b1aca676cf316579413633595d5f47ab7bd3a244629f8f42f -size 119861 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPhone-16-en-GB.UI.png deleted file mode 100644 index cff3183276..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fb399a39075a5e7e8b8c34bb972aacf72474442725649b0ae3ec4f7ab7f0d037 -size 135827 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index d0bb19b63f..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:96b5e66a23be685c7d7181b28de1c9e99036a402bff51aa1d369ec77b150ec91 -size 101661 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPhone-16-en-GB.UI.png deleted file mode 100644 index 464d8a4f4e..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2fc3d0f4942630790d8e88059359e073c077bf52e2ee47b98745eaf0fbfa6b7d -size 110986 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 22578d193c..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e9625647685944a27bf16496c5cbe3e7149539d03616ab738f2c66d0b8b25252 -size 116624 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPhone-16-en-GB.UI.png deleted file mode 100644 index 03fd01c691..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5854adff8f6d9b43b01fbeaeb557c37b702cf34dc2429eb28f239e59884b8ec4 -size 130372 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPad-18-1-en-GB.UI.png index c754293037..3faf4040bf 100644 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e95f468f417f14e84c2d91253d06fec9058b188fead7841975faeb30b59d62d -size 110487 +oid sha256:52b09fbadab70e23b4120e02f890630bb154e4f871c9271787994bc0c753ad95 +size 111604 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-18-1-en-GB.UI.png index 5c51abfbcd..cf4c2604c1 100644 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1fd4349c47465504cae19187ac770f5f72a9ebd139d6635e88e4f780c3766a88 -size 180406 +oid sha256:80a631a3cf7dcea93498c2dddab68542b7119f604f09bcb7b873bda05b7078eb +size 179037 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 26adee6218..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1a0011a448b569a6a143de24296b3cf2559fdb485237cc143563bb7f2c9b0798 -size 133652 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-18-1-en-GB.UI.png index 26adee6218..452ad174c2 100644 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a0011a448b569a6a143de24296b3cf2559fdb485237cc143563bb7f2c9b0798 -size 133652 +oid sha256:5fbc188332144b953e0bca153b63bd6d4344df68f18366eac59f568206e29d8f +size 134658 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-16-en-GB.UI.png deleted file mode 100644 index 9ad65331e0..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b7816944b84404a010641d131a766b06a8bddab609204ebb58b9b8f13e94562e -size 216901 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-18-1-en-GB.UI.png index 9ad65331e0..461a6776ae 100644 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7816944b84404a010641d131a766b06a8bddab609204ebb58b9b8f13e94562e -size 216901 +oid sha256:bb91206261c80ec455c34b0f64762b0c6c10769a521d7a744985d3dc69d3f469 +size 212810 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 4ca9322f85..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:46a30b63dd8fe655bdd33f2d9d4d2d638bc62f5ddea1d2fddc168b07cf9775d9 -size 330970 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-18-1-en-GB.UI.png index 4ca9322f85..afe986a69c 100644 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:46a30b63dd8fe655bdd33f2d9d4d2d638bc62f5ddea1d2fddc168b07cf9775d9 -size 330970 +oid sha256:0b409d3118a4c4a100032bfb60e8a6829e4b55587ec1cab9126d2594eb1da2ca +size 320460 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-16-en-GB.UI.png deleted file mode 100644 index 26e12acc16..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3a083dfcee55c1be624d228589a041712b8d8f5669bd167fefb92aa8e203a6a4 -size 342283 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-18-1-en-GB.UI.png index 26e12acc16..5359b810f8 100644 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a083dfcee55c1be624d228589a041712b8d8f5669bd167fefb92aa8e203a6a4 -size 342283 +oid sha256:83d4a0d09bf30ed1b6da020574f9908be29c669fe38b85b754e0eeed6a3f9398 +size 334154 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 5d4ea9ccb2..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0d0631f21e06cf6571bf6ebd48fb252019747d26695a28629d9dbc33bdc27ffe -size 131673 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-18-1-en-GB.UI.png index 0430561c19..e5ede0e398 100644 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44d8f128567adb45ddba5e30b181184641c2818498af165aa9135139b5eed891 -size 131897 +oid sha256:e93e0c475e0be9d715ff092131c73fca84a221b2d24879146fe0b7b2b46e88fb +size 133014 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-16-en-GB.UI.png deleted file mode 100644 index 6db7ab36bc..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9d78cbc723080c15e1ae3e5ce518517ac329d11a77e959179c84d275411ed976 -size 212177 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-18-1-en-GB.UI.png index 1313e8699d..7ee40f65eb 100644 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd37d5f0deee1e90a8fe2e1de121503e522de43cebd407eaad5da19b6f5adf37 -size 212425 +oid sha256:e38950a5cba515ac17f4cf2b032adf52a0f5e1f6e81420881e46caed3447f3cc +size 208756 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-18-1-en-GB.UI.png index be569943f3..f0bb8c8535 100644 --- a/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f5086c2ea0fc8186cfa08deb9293401f5c41315c35376598feb1f47639e65fd -size 178419 +oid sha256:98ce5e14c8845e1c0d59200ed796ad023a816e16a75410bbc17793366ec5ff34 +size 179550 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-18-1-en-GB.UI.png index 84e852be2c..39e957ae8d 100644 --- a/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21a4406c80a619c4a7f97b39200d565f8cb9d84f47ce4bb8bb847fa3de187c09 -size 286492 +oid sha256:d573d5c7889cc221457a2013c4fe238769c5f1fd12ce031186e6b344d7bd7fb7 +size 287489 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-18-1-en-GB.UI.png index 807392ada3..6bb58a30d9 100644 --- a/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b26264c2d7d27954ab7aaa00960f29342555e926f034891f77811fe97d81dca -size 142642 +oid sha256:91d5f0947bf21b9ae98c237140fbb4f0353268e41c3279d5ab693bd1c1212e2c +size 143765 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-18-1-en-GB.UI.png index 9016d3624b..5d2ec053f6 100644 --- a/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b8d92e74b63fd664d19b8757336b32fe6b01fe7301a30ea591eee0e98e8a99e7 -size 228856 +oid sha256:ae8c55c2f0b8d94bd3ab87ca983dbbd57be775c872b21f75c41be5369dee372d +size 230010 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-18-1-en-GB.UI.png index ae477b2bba..bb72443071 100644 --- a/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:328fb6ec2d8637e95a19dc5018198dc2d968fd4f4d03f6ff2b751d22e37f748b -size 175169 +oid sha256:7dcbfdc4ea9e4cf95adcc8927deabb7d51ec6b6c4e1d2c26c9b9c7e641c4e4a9 +size 176316 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-18-1-en-GB.UI.png index 2d5830db65..b85087db0c 100644 --- a/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4fce73fbf4e5c70b18fe8cd4c4d0ffbb2507c8da30a34d8eaa5d16513343e6e0 -size 282805 +oid sha256:eda6f260a4f2f6cbe147a444df434fde3c19d1fcfb3539fb24ad2db88a7c4341 +size 283712 diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPad-18-1-en-GB.UI.png index a1ed7d76ad..dc09fb8c88 100644 --- a/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f10c10b83869bd9dcab608f3b234270a0dc062ba6937519852f53a6d3c9d2d07 -size 105094 +oid sha256:56c5eef68d4fbc9ff878efb77940dbdf6d088b117a4902f23c997bac4dc3eeda +size 103993 diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPad-18-1-en-GB.UI.png index 1f1e01833a..e61deb2e7e 100644 --- a/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aeaf5705a6f473df0bcd6a0fc0f8c6468167bf7ca127d115d7b66fc3a8a41e42 -size 176945 +oid sha256:572548ef639288f82b2b9060e96daa6522226587d097329364bdb3f424accaa3 +size 176934 diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-18-1-en-GB.UI.png index 3454a2e75d..d6d59f9c03 100644 --- a/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c565f358656384dddde59f62ee5485730d610a4d3642a77f1e3c9193ce0d4164 -size 179685 +oid sha256:745c02e081ef546ac0c918fc80b80f701ccde6d54beba8527a2086f5655bc621 +size 179836 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-18-1-en-GB.UI.png index 1d64e09494..3e66ca2c58 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57bb3ef3d039c2017d8bb6a7c9953b0f171d636544c9580668a0de1ff64eebe1 -size 92312 +oid sha256:e99fc8db5cc8c6b19986913f62b22479ce8279d5822c16d51eeb0de07d37fd6c +size 91224 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-18-1-en-GB.UI.png index 586f2fcfc7..aaf17fd84a 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f00671f198ade30eabc3447ad8385a2ba59001e739b62765753c9187a5d867c -size 89264 +oid sha256:c38f676abce80dd515607cc5f894c5d4848f35d6225a54235d733fdb2061251d +size 88120 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-18-1-en-GB.UI.png index 3c8fdb5a18..caa1abedb8 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9cd59cc028d74b4a4357483c1cb3ff73a4d3d5add61994ce30c91003943a305 -size 84163 +oid sha256:8dcd756e7e80c4a8d49f542083b672a713068fdc12914d923fc10bb7d936aa4b +size 83046 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-18-1-en-GB.UI.png index da0f3a4788..34bb09c21a 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5fc095ecf4181b2fff162ef5d467008de764cc2025dde1046ef872cf6ce80e36 -size 64615 +oid sha256:56c987c9acf140105a08e34fcebdec9827befd8b2d13100115d7a532fb33a082 +size 63514 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-18-1-en-GB.UI.png index 2b6cd16c85..69dadd20f1 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ead3eef56f6049cf3842109963655b09a82640de3eae21f8a2cefd0a4fd3df4b -size 147648 +oid sha256:f7377e97c8da85ed52887c06816fb0ae445a241c89bf857fe92b40546533f8bd +size 146619 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-1-iPad-18-1-en-GB.UI.png index d958b67e27..28796dd5dc 100644 --- a/UITests/Sources/__Snapshots__/Application/startChat-1-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/startChat-1-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88e8193b05536f647a147f2cc206d2266fe6783373bff80d4854b149f23c3f0b -size 71653 +oid sha256:d1899b3be5a1344a59da82cb7cd3e2a8bab0ca376af09e0c1274adf9229ae653 +size 71695 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-18-1-en-GB.UI.png index 762d405983..ee25be16f1 100644 --- a/UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0892b6f31d8b6b1bde00cf0deb9e5717d7d029e50a5d05ff1d9427ad1c3aebf8 -size 66914 +oid sha256:5005f1006dc82fd3b238fae6d159d50ea9e9cdb3770292d238d6d65f2ee9e12a +size 66922 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-2-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-2-iPad-18-1-en-GB.UI.png index 55b64b6654..f90c064542 100644 --- a/UITests/Sources/__Snapshots__/Application/startChat-2-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/startChat-2-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca3610ee7a4e07c97e346a7b2ce4e88f1f133643751281c98694433a80c9cb3d -size 85526 +oid sha256:9214383adabcdb2dc7ce19b7f5da0abc18c21551cb4a5ee89dfb0d90b774baea +size 85548 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-18-1-en-GB.UI.png index 434f7a7007..e76032cb9d 100644 --- a/UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5c2b8283fb54af48fad4f860077f0a36326660f3f646f8d78f2012bd27cdaee -size 86290 +oid sha256:3bf98fa549a065fb042458d46593627f6126a5ba7172ed4f3e847f7cae40db13 +size 86289 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-iPad-18-1-en-GB.UI.png index 83528b0e54..cb877ecadc 100644 --- a/UITests/Sources/__Snapshots__/Application/startChat-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/startChat-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e46a8df777fe9496fa53e43d45d6fd812b6fb813767e38da512e58d3c1ff8a6 -size 82066 +oid sha256:36a6971acfde6818d37be61a0cbfa844ee45c947802c5209e60317e2b8942b9f +size 82156 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-iPhone-18-1-en-GB.UI.png index 4e6b7c19a4..b97df79ed2 100644 --- a/UITests/Sources/__Snapshots__/Application/startChat-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/startChat-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:875c6e4d9f5202a13b6396d067c4272c3df21603f5baf593fe21f46c651008f8 -size 83293 +oid sha256:55552bb8b0c7b89c1446789915f397b0e6f0a5da5fb20e286108dced387f50c7 +size 83422 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index ab91f912e8..0000000000 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b2f921a9f3613e93a12410d1762e4cba1e557ee47ace34ec43100deeccbd9d40 -size 316350 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-18-1-en-GB.UI.png index 0ad0f4e475..fbee8efd60 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b705d6bf2dfe32cd18751f7a72c524047face164c63faf7d0e276f4097aabe0 -size 316315 +oid sha256:bcbe1e62c67fba3ff9b7c80298a25187225e7be065704436166a995b9244b70b +size 317689 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-16-en-GB.UI.png deleted file mode 100644 index 1fa07f5f49..0000000000 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:672046d4289a23075b82789d5fca2b6b4f1cab3b75147cd2a5eec5d5dd79c398 -size 299984 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-18-1-en-GB.UI.png index 73ca50197e..10a9cb8b68 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4cb185b178ebb46a41234ae11723446627393ecc1022f52f0ce72c3adb0a363 -size 299987 +oid sha256:187a113497d36d352d2bbbe5f1cc90f4cbf29c21ead8dcd37dad01995ecb74c2 +size 301967 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index e4dd9086d8..0000000000 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4ab055b4aed25baff5715521523bbebd9bf91d563914ebcca885b15a8f6a98de -size 461977 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-18-1-en-GB.UI.png index e4dd9086d8..6b1c2fc6cc 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ab055b4aed25baff5715521523bbebd9bf91d563914ebcca885b15a8f6a98de -size 461977 +oid sha256:9709665dbe2280bf202a9e54ebb0b6425cb545357eede2da4577521fe66cbb19 +size 454897 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-16-en-GB.UI.png deleted file mode 100644 index 1d3c6639a2..0000000000 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d278754af0afafa46e569e62ed34652660be8c407761df16fe7a9313d6c24a96 -size 346291 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-18-1-en-GB.UI.png index 5f12a52f95..80a042006a 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:deddf48697d6fa5f8ff44e54ef41201accf59de271aaa092ef2af20e3a94cd63 -size 346116 +oid sha256:928f899b0fc9b5b9ca12cb1a41fbae6c46b5ef154fd33f179907c11855a897b7 +size 339024 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index b48dad3f22..0000000000 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ede54c8caf251097eacab4da82359978233aeb7f9cc5c9e4024894ede70dcf77 -size 746883 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-18-1-en-GB.UI.png index b48dad3f22..80d04b3d60 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ede54c8caf251097eacab4da82359978233aeb7f9cc5c9e4024894ede70dcf77 -size 746883 +oid sha256:b9cec93d80671ab506a53624a31f4d304e9d2719e3d11af79e18ad0950ad9fc1 +size 739746 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-16-en-GB.UI.png deleted file mode 100644 index 5a077d2d64..0000000000 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b03923620460adf38f959544ee655df6215f83d5937536b38f9f97aa3a0f8392 -size 867141 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-18-1-en-GB.UI.png index 3c527200c2..cc20f7bc26 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16e3b6828475d9263b50bddca1b124c0f667ffeb14ad918e259ff0c3b6a8ade0 -size 869012 +oid sha256:ae1315e6a62518c1dd9026af49cb3671c21cd97a64ccdb0f94600b744943a261 +size 864551 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPad-18-1-en-GB.UI.png index ffb38ecef4..0f4d65f5aa 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPad-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPad-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0bbe68370f35930d0c2cb1fb3f739cbab8d8f1c095e22e1ac5cd605327ede89 -size 461903 +oid sha256:3fdde5f9d9d6f237f73784f285383c6a3e0420e73f3dada8143d08c9ab6fcaac +size 457425 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-18-1-en-GB.UI.png index 40307c846b..75f044dde7 100644 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-18-1-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-18-1-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ea90452a2924f7872bd307dfbf7aa10bdf772758bf74171ade7b5bc5cb20e36 -size 334104 +oid sha256:4a00a09e450dcc79cc498ba728757d9867a8784e972abfe689ad11052a0aba93 +size 331360 diff --git a/UnitTests/Sources/AttributedStringBuilderTests.swift b/UnitTests/Sources/AttributedStringBuilderTests.swift index 3c9b31bcf8..5b32fc38cf 100644 --- a/UnitTests/Sources/AttributedStringBuilderTests.swift +++ b/UnitTests/Sources/AttributedStringBuilderTests.swift @@ -79,7 +79,7 @@ class AttributedStringBuilderTests: XCTestCase { XCTAssertEqual(attributedString.runs.count, 3) - let link = attributedString.runs.first(where: { $0.link != nil })?.link + let link = attributedString.runs.first { $0.link != nil }?.link XCTAssertEqual(link?.host, "www.matrix.org") } @@ -96,7 +96,7 @@ class AttributedStringBuilderTests: XCTestCase { XCTAssertEqual(attributedString.runs.count, 3) - let link = attributedString.runs.first(where: { $0.link != nil })?.link + let link = attributedString.runs.first { $0.link != nil }?.link XCTAssertEqual(link?.host, "www.matrix.org") } @@ -113,7 +113,7 @@ class AttributedStringBuilderTests: XCTestCase { XCTAssertEqual(attributedString.runs.count, 3) - let link = attributedString.runs.first(where: { $0.link != nil })?.link + let link = attributedString.runs.first { $0.link != nil }?.link XCTAssertEqual(link?.host, "www.matrix.org") } @@ -130,7 +130,7 @@ class AttributedStringBuilderTests: XCTestCase { XCTAssertEqual(attributedString.runs.count, 3) - let link = attributedString.runs.first(where: { $0.link != nil })?.link + let link = attributedString.runs.first { $0.link != nil }?.link XCTAssertEqual(link, "https://matrix.org") } diff --git a/UnitTests/Sources/BlockedUsersScreenViewModelTests.swift b/UnitTests/Sources/BlockedUsersScreenViewModelTests.swift index 0852dede1e..1fff597533 100644 --- a/UnitTests/Sources/BlockedUsersScreenViewModelTests.swift +++ b/UnitTests/Sources/BlockedUsersScreenViewModelTests.swift @@ -20,7 +20,7 @@ class BlockedUsersScreenViewModelTests: XCTestCase { mediaProvider: MediaProviderMock(configuration: .init()), userIndicatorController: ServiceLocator.shared.userIndicatorController) - let deferred = deferFailure(viewModel.context.$viewState, timeout: 1) { $0.blockedUsers.contains(where: { $0.displayName != nil }) } + let deferred = deferFailure(viewModel.context.$viewState, timeout: 1) { $0.blockedUsers.contains { $0.displayName != nil } } try await deferred.fulfill() XCTAssertFalse(viewModel.context.viewState.blockedUsers.isEmpty) @@ -35,7 +35,7 @@ class BlockedUsersScreenViewModelTests: XCTestCase { mediaProvider: MediaProviderMock(configuration: .init()), userIndicatorController: ServiceLocator.shared.userIndicatorController) - let deferred = deferFulfillment(viewModel.context.$viewState) { $0.blockedUsers.contains(where: { $0.displayName != nil }) } + let deferred = deferFulfillment(viewModel.context.$viewState) { $0.blockedUsers.contains { $0.displayName != nil } } try await deferred.fulfill() XCTAssertFalse(viewModel.context.viewState.blockedUsers.isEmpty) diff --git a/UnitTests/Sources/ComposerToolbarViewModelTests.swift b/UnitTests/Sources/ComposerToolbarViewModelTests.swift index fbecde99de..437881a0a8 100644 --- a/UnitTests/Sources/ComposerToolbarViewModelTests.swift +++ b/UnitTests/Sources/ComposerToolbarViewModelTests.swift @@ -54,10 +54,10 @@ class ComposerToolbarViewModelTests: XCTestCase { .map(\.composerMode) .removeDuplicates() .dropFirst() - .sink(receiveValue: { composerMode in + .sink { composerMode in XCTAssertEqual(composerMode, mode) expectation.fulfill() - }) + } viewModel.process(timelineAction: .setMode(mode: mode)) diff --git a/UnitTests/Sources/HomeScreenRoomTests.swift b/UnitTests/Sources/HomeScreenRoomTests.swift index 1cbe828d23..db25bf57a3 100644 --- a/UnitTests/Sources/HomeScreenRoomTests.swift +++ b/UnitTests/Sources/HomeScreenRoomTests.swift @@ -23,7 +23,7 @@ class HomeScreenRoomTests: XCTestCase { hasOngoingCall: Bool) { roomSummary = RoomSummary(roomListItem: .init(noPointer: .init()), id: "Test room", - joinRequestType: nil, + knockRequestType: nil, name: "Test room", isDirect: false, avatarURL: nil, diff --git a/UnitTests/Sources/JoinRoomScreenViewModelTests.swift b/UnitTests/Sources/JoinRoomScreenViewModelTests.swift index 2f8b6e0521..a14ad28e2d 100644 --- a/UnitTests/Sources/JoinRoomScreenViewModelTests.swift +++ b/UnitTests/Sources/JoinRoomScreenViewModelTests.swift @@ -84,7 +84,7 @@ class JoinRoomScreenViewModelTests: XCTestCase { topic: nil, avatarURL: nil, memberCount: 0, - isHistoryWorldReadable: false, + isHistoryWorldReadable: nil, isJoined: false, isInvited: false, isPublic: false, diff --git a/UnitTests/Sources/KnockRequestsListScreenViewModelTests.swift b/UnitTests/Sources/KnockRequestsListScreenViewModelTests.swift index fba35e93f7..3abed7ce92 100644 --- a/UnitTests/Sources/KnockRequestsListScreenViewModelTests.swift +++ b/UnitTests/Sources/KnockRequestsListScreenViewModelTests.swift @@ -18,6 +18,209 @@ class KnockRequestsListScreenViewModelTests: XCTestCase { } override func setUpWithError() throws { - viewModel = KnockRequestsListScreenViewModel(roomProxy: JoinedRoomProxyMock(.init()), mediaProvider: MediaProviderMock()) + AppSettings.resetAllSettings() + } + + func testLoadingState() async throws { + let roomProxyMock = JoinedRoomProxyMock(.init(knockRequestsState: .loading, joinRule: .knock)) + viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock, + mediaProvider: MediaProviderMock(), + userIndicatorController: UserIndicatorControllerMock()) + + let deferred = deferFulfillment(context.$viewState) { state in + !state.shouldDisplayRequests && + state.isKnockableRoom && + state.canAccept && + !state.canBan && + !state.canDecline && + state.isLoading && + !state.shouldDisplayEmptyView + } + try await deferred.fulfill() + } + + func testEmptyState() async throws { + let roomProxyMock = JoinedRoomProxyMock(.init(knockRequestsState: .loaded([]), joinRule: .knock)) + viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock, + mediaProvider: MediaProviderMock(), + userIndicatorController: UserIndicatorControllerMock()) + + let deferred = deferFulfillment(context.$viewState) { state in + !state.shouldDisplayRequests && + state.isKnockableRoom && + state.canAccept && + !state.canBan && + !state.canDecline && + !state.isLoading && + state.shouldDisplayEmptyView + } + try await deferred.fulfill() + } + + func testLoadedState() async throws { + let roomProxyMock = JoinedRoomProxyMock(.init(members: [.mockAdmin], + knockRequestsState: .loaded([KnockRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org")), + KnockRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org")), + KnockRequestProxyMock(.init(eventID: "3", userID: "@charlie:matrix.org")), + KnockRequestProxyMock(.init(eventID: "4", userID: "@dan:matrix.org"))]), + ownUserID: RoomMemberProxyMock.mockAdmin.userID, + joinRule: .knock)) + viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock, + mediaProvider: MediaProviderMock(), + userIndicatorController: UserIndicatorControllerMock()) + + var deferred = deferFulfillment(context.$viewState) { state in + state.shouldDisplayRequests && + state.isKnockableRoom && + state.canAccept && + state.canBan && + state.canDecline && + !state.isLoading && + !state.shouldDisplayEmptyView && + state.displayedRequests.count == 4 && + state.handledEventIDs.isEmpty && + state.shouldDisplayAcceptAllButton + } + try await deferred.fulfill() + + deferred = deferFulfillment(context.$viewState) { state in + state.shouldDisplayRequests && + state.handledEventIDs == ["1"] && + !state.shouldDisplayEmptyView && + state.displayedRequests.count == 3 && + state.shouldDisplayAcceptAllButton + } + context.send(viewAction: .acceptRequest(eventID: "1")) + try await deferred.fulfill() + + deferred = deferFulfillment(context.$viewState) { state in + state.bindings.alertInfo?.id == .declineRequest + } + context.send(viewAction: .declineRequest(eventID: "2")) + try await deferred.fulfill() + + guard let declineAlertInfo = context.alertInfo else { + XCTFail("Can't be nil") + return + } + deferred = deferFulfillment(context.$viewState) { state in + state.shouldDisplayRequests && + state.handledEventIDs == ["1", "2"] && + !state.shouldDisplayEmptyView && + state.displayedRequests.count == 2 && + state.shouldDisplayAcceptAllButton + } + declineAlertInfo.primaryButton.action?() + try await deferred.fulfill() + + deferred = deferFulfillment(context.$viewState) { state in + state.bindings.alertInfo?.id == .declineAndBan + } + context.send(viewAction: .ban(eventID: "3")) + try await deferred.fulfill() + + guard let banAlertInfo = context.alertInfo else { + XCTFail("Can't be nil") + return + } + deferred = deferFulfillment(context.$viewState) { state in + state.shouldDisplayRequests && + state.handledEventIDs == ["1", "2", "3"] && + !state.shouldDisplayEmptyView && + state.displayedRequests.count == 1 && + !state.shouldDisplayAcceptAllButton + } + banAlertInfo.primaryButton.action?() + try await deferred.fulfill() + } + + func testAcceptAll() async throws { + let roomProxyMock = JoinedRoomProxyMock(.init(knockRequestsState: .loaded([KnockRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org")), + KnockRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org")), + KnockRequestProxyMock(.init(eventID: "3", userID: "@charlie:matrix.org")), + KnockRequestProxyMock(.init(eventID: "4", userID: "@dan:matrix.org"))]), + joinRule: .knock)) + viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock, + mediaProvider: MediaProviderMock(), + userIndicatorController: UserIndicatorControllerMock()) + + var deferred = deferFulfillment(context.$viewState) { state in + state.shouldDisplayRequests && + state.isKnockableRoom && + state.canAccept && + !state.canBan && + !state.canDecline && + !state.isLoading && + !state.shouldDisplayEmptyView && + state.displayedRequests.count == 4 && + state.handledEventIDs.isEmpty && + state.shouldDisplayAcceptAllButton + } + try await deferred.fulfill() + + deferred = deferFulfillment(context.$viewState) { state in + state.bindings.alertInfo?.id == .acceptAllRequests + } + context.send(viewAction: .acceptAllRequests) + try await deferred.fulfill() + + guard let alertInfo = context.alertInfo else { + XCTFail("Can't be nil") + return + } + + deferred = deferFulfillment(context.$viewState) { state in + !state.shouldDisplayRequests && + state.handledEventIDs == ["1", "2", "3", "4"] && + !state.isLoading && + state.shouldDisplayEmptyView + } + alertInfo.primaryButton.action?() + try await deferred.fulfill() + } + + func testLoadedStateBecomesEmptyIfTheJoinRuleIsNotKnocking() async throws { + // If there is a sudden change in the rule, but the requests are still published, we want to hide all of them and show the empty view + let roomProxyMock = JoinedRoomProxyMock(.init(members: [.mockAdmin], + knockRequestsState: .loaded([KnockRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org")), + KnockRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org")), + KnockRequestProxyMock(.init(eventID: "3", userID: "@charlie:matrix.org")), + KnockRequestProxyMock(.init(eventID: "4", userID: "@dan:matrix.org"))]), + ownUserID: RoomMemberProxyMock.mockAdmin.userID, + joinRule: .invite)) + viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock, + mediaProvider: MediaProviderMock(), + userIndicatorController: UserIndicatorControllerMock()) + + let deferred = deferFulfillment(context.$viewState) { state in + !state.shouldDisplayRequests && + state.shouldDisplayEmptyView && + !state.isLoading && + !state.isKnockableRoom + } + try await deferred.fulfill() + } + + func testLoadedStateBecomesEmptyIfPermissionsAreRemoved() async throws { + // If there is a sudden change in permissions, and the user can't do any other action, we hide all the requests and shoe the empty view + let roomProxyMock = JoinedRoomProxyMock(.init(knockRequestsState: .loaded([KnockRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org")), + KnockRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org")), + KnockRequestProxyMock(.init(eventID: "3", userID: "@charlie:matrix.org")), + KnockRequestProxyMock(.init(eventID: "4", userID: "@dan:matrix.org"))]), + canUserInvite: false, + joinRule: .knock)) + viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock, + mediaProvider: MediaProviderMock(), + userIndicatorController: UserIndicatorControllerMock()) + + let deferred = deferFulfillment(context.$viewState) { state in + !state.shouldDisplayRequests && + state.shouldDisplayEmptyView && + !state.canAccept && + !state.canBan && + !state.canDecline && + !state.isLoading + } + try await deferred.fulfill() } } diff --git a/UnitTests/Sources/LoggingTests.swift b/UnitTests/Sources/LoggingTests.swift index dc7389e969..69f3291bc9 100644 --- a/UnitTests/Sources/LoggingTests.swift +++ b/UnitTests/Sources/LoggingTests.swift @@ -80,7 +80,7 @@ class LoggingTests: XCTestCase { let heroName = "Pseudonym" let roomSummary = RoomSummary(roomListItem: .init(noPointer: .init()), id: "myroomid", - joinRequestType: nil, + knockRequestType: nil, name: roomName, isDirect: true, avatarURL: nil, @@ -116,7 +116,7 @@ class LoggingTests: XCTestCase { // Given timeline items that contain text let textAttributedString = "TextAttributed" let textMessage = TextRoomTimelineItem(id: .randomEvent, - timestamp: "", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -125,7 +125,7 @@ class LoggingTests: XCTestCase { content: .init(body: "TextString", formattedBody: AttributedString(textAttributedString))) let noticeAttributedString = "NoticeAttributed" let noticeMessage = NoticeRoomTimelineItem(id: .randomEvent, - timestamp: "", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -134,7 +134,7 @@ class LoggingTests: XCTestCase { content: .init(body: "NoticeString", formattedBody: AttributedString(noticeAttributedString))) let emoteAttributedString = "EmoteAttributed" let emoteMessage = EmoteRoomTimelineItem(id: .randomEvent, - timestamp: "", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -142,7 +142,7 @@ class LoggingTests: XCTestCase { sender: .init(id: "sender"), content: .init(body: "EmoteString", formattedBody: AttributedString(emoteAttributedString))) let imageMessage = ImageRoomTimelineItem(id: .randomEvent, - timestamp: "", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -153,7 +153,7 @@ class LoggingTests: XCTestCase { imageInfo: .mockImage, thumbnailInfo: nil)) let videoMessage = VideoRoomTimelineItem(id: .randomEvent, - timestamp: "", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, @@ -164,7 +164,7 @@ class LoggingTests: XCTestCase { videoInfo: .mockVideo, thumbnailInfo: nil)) let fileMessage = FileRoomTimelineItem(id: .randomEvent, - timestamp: "", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, diff --git a/UnitTests/Sources/MessageForwardingScreenViewModelTests.swift b/UnitTests/Sources/MessageForwardingScreenViewModelTests.swift index 3076a40aa7..a61a9397ea 100644 --- a/UnitTests/Sources/MessageForwardingScreenViewModelTests.swift +++ b/UnitTests/Sources/MessageForwardingScreenViewModelTests.swift @@ -34,7 +34,7 @@ class MessageForwardingScreenViewModelTests: XCTestCase { } func testInitialState() { - XCTAssertNil(context.viewState.rooms.first(where: { $0.id == forwardingItem.roomID }), "The source room ID shouldn't be shown") + XCTAssertNil(context.viewState.rooms.first { $0.id == forwardingItem.roomID }, "The source room ID shouldn't be shown") } func testRoomSelection() { diff --git a/UnitTests/Sources/PollFormScreenViewModelTests.swift b/UnitTests/Sources/PollFormScreenViewModelTests.swift index af92477aca..2bfbdf508a 100644 --- a/UnitTests/Sources/PollFormScreenViewModelTests.swift +++ b/UnitTests/Sources/PollFormScreenViewModelTests.swift @@ -29,7 +29,7 @@ class PollFormScreenViewModelTests: XCTestCase { XCTAssertFalse(context.viewState.bindings.isUndisclosed) // Cancellation should work without confirmation - let deferred = deferFulfillment(viewModel.actions, until: { _ in true }) + let deferred = deferFulfillment(viewModel.actions) { _ in true } context.send(viewAction: .cancel) let action = try await deferred.fulfill() XCTAssertNil(context.alertInfo) @@ -45,7 +45,7 @@ class PollFormScreenViewModelTests: XCTestCase { XCTAssertFalse(context.viewState.bindings.isUndisclosed) // Cancellation should work without confirmation - let deferred = deferFulfillment(viewModel.actions, until: { _ in true }) + let deferred = deferFulfillment(viewModel.actions) { _ in true } context.send(viewAction: .cancel) let action = try await deferred.fulfill() XCTAssertNil(context.alertInfo) diff --git a/UnitTests/Sources/RoomChangeRolesScreenViewModelTests.swift b/UnitTests/Sources/RoomChangeRolesScreenViewModelTests.swift index b78bb60c88..5626a218ee 100644 --- a/UnitTests/Sources/RoomChangeRolesScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomChangeRolesScreenViewModelTests.swift @@ -161,8 +161,8 @@ class RoomChangeRolesScreenViewModelTests: XCTestCase { // Then no warning should be shown, and the call to update the users should be made straight away. XCTAssertTrue(roomProxy.updatePowerLevelsForUsersCalled) XCTAssertEqual(roomProxy.updatePowerLevelsForUsersReceivedUpdates?.count, 2) - XCTAssertEqual(roomProxy.updatePowerLevelsForUsersReceivedUpdates?.contains(where: { $0.userID == existingModerator.id && $0.powerLevel == 0 }), true) - XCTAssertEqual(roomProxy.updatePowerLevelsForUsersReceivedUpdates?.contains(where: { $0.userID == firstUser.id && $0.powerLevel == 50 }), true) + XCTAssertEqual(roomProxy.updatePowerLevelsForUsersReceivedUpdates?.contains { $0.userID == existingModerator.id && $0.powerLevel == 0 }, true) + XCTAssertEqual(roomProxy.updatePowerLevelsForUsersReceivedUpdates?.contains { $0.userID == firstUser.id && $0.powerLevel == 50 }, true) } func testSavePromotedAdministrator() async throws { @@ -189,7 +189,7 @@ class RoomChangeRolesScreenViewModelTests: XCTestCase { // Then the user should be made into an administrator. XCTAssertTrue(roomProxy.updatePowerLevelsForUsersCalled) XCTAssertEqual(roomProxy.updatePowerLevelsForUsersReceivedUpdates?.count, 1) - XCTAssertEqual(roomProxy.updatePowerLevelsForUsersReceivedUpdates?.contains(where: { $0.userID == firstUser.id && $0.powerLevel == 100 }), true) + XCTAssertEqual(roomProxy.updatePowerLevelsForUsersReceivedUpdates?.contains { $0.userID == firstUser.id && $0.powerLevel == 100 }, true) } private func setupViewModel(mode: RoomMemberDetails.Role) { diff --git a/UnitTests/Sources/RoomDetailsViewModelTests.swift b/UnitTests/Sources/RoomDetailsViewModelTests.swift index 0908be9190..e02fd2cb35 100644 --- a/UnitTests/Sources/RoomDetailsViewModelTests.swift +++ b/UnitTests/Sources/RoomDetailsViewModelTests.swift @@ -21,6 +21,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase { var cancellables = Set() override func setUp() { + AppSettings.resetAllSettings() cancellables.removeAll() roomProxyMock = JoinedRoomProxyMock(.init(name: "Test")) notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()) @@ -33,8 +34,6 @@ class RoomDetailsScreenViewModelTests: XCTestCase { attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings) - - AppSettings.resetAllSettings() } func testLeaveRoomTappedWhenPublic() async throws { @@ -672,4 +671,99 @@ class RoomDetailsScreenViewModelTests: XCTestCase { XCTFail("invalid state") } } + + // MARK: - Knock Requests + + func testKnockRequestsCounter() async throws { + ServiceLocator.shared.settings.knockingEnabled = true + let mockedRequests: [KnockRequestProxyMock] = [.init(), .init()] + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, isPublic: false, knockRequestsState: .loaded(mockedRequests), joinRule: .knock)) + viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, + clientProxy: ClientProxyMock(.init()), + mediaProvider: MediaProviderMock(configuration: .init()), + analyticsService: ServiceLocator.shared.analytics, + userIndicatorController: ServiceLocator.shared.userIndicatorController, + notificationSettingsProxy: notificationSettingsProxyMock, + attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings) + + let deferred = deferFulfillment(context.$viewState) { state in + state.knockRequestsCount == 2 && state.canSeeKnockingRequests + } + try await deferred.fulfill() + + let deferredAction = deferFulfillment(viewModel.actions) { $0 == .displayKnockingRequests } + context.send(viewAction: .processTapRequestsToJoin) + try await deferredAction.fulfill() + } + + func testKnockRequestsCounterIsLoading() async throws { + ServiceLocator.shared.settings.knockingEnabled = true + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, isPublic: false, knockRequestsState: .loading, joinRule: .knock)) + viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, + clientProxy: ClientProxyMock(.init()), + mediaProvider: MediaProviderMock(configuration: .init()), + analyticsService: ServiceLocator.shared.analytics, + userIndicatorController: ServiceLocator.shared.userIndicatorController, + notificationSettingsProxy: notificationSettingsProxyMock, + attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings) + + let deferred = deferFulfillment(context.$viewState) { state in + state.knockRequestsCount == 0 && state.canSeeKnockingRequests + } + + try await deferred.fulfill() + } + + func testKnockRequestsCounterIsNotShownIfNoPermissions() async throws { + ServiceLocator.shared.settings.knockingEnabled = true + let mockedRequests: [KnockRequestProxyMock] = [.init(), .init()] + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, isPublic: false, knockRequestsState: .loaded(mockedRequests), canUserInvite: false, joinRule: .knock)) + viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, + clientProxy: ClientProxyMock(.init()), + mediaProvider: MediaProviderMock(configuration: .init()), + analyticsService: ServiceLocator.shared.analytics, + userIndicatorController: ServiceLocator.shared.userIndicatorController, + notificationSettingsProxy: notificationSettingsProxyMock, + attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings) + + let deferred = deferFulfillment(context.$viewState) { state in + state.knockRequestsCount == 2 && + state.dmRecipient == nil && + !state.canSeeKnockingRequests && + !state.canInviteUsers + } + + try await deferred.fulfill() + } + + func testKnockRequestsCounterIsNotShownIfDM() async throws { + ServiceLocator.shared.settings.knockingEnabled = true + let mockedRequests: [KnockRequestProxyMock] = [.init(), .init()] + let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockAlice] + roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isPublic: false, members: mockedMembers, knockRequestsState: .loaded(mockedRequests), joinRule: .knock)) + viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, + clientProxy: ClientProxyMock(.init()), + mediaProvider: MediaProviderMock(configuration: .init()), + analyticsService: ServiceLocator.shared.analytics, + userIndicatorController: ServiceLocator.shared.userIndicatorController, + notificationSettingsProxy: notificationSettingsProxyMock, + attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings) + + let deferred = deferFulfillment(context.$viewState) { state in + state.knockRequestsCount == 2 && + !state.canSeeKnockingRequests && + state.dmRecipient != nil && + state.canInviteUsers + } + + try await deferred.fulfill() + } } diff --git a/UnitTests/Sources/RoomFlowCoordinatorTests.swift b/UnitTests/Sources/RoomFlowCoordinatorTests.swift index 4ec720826e..a96e5a5af9 100644 --- a/UnitTests/Sources/RoomFlowCoordinatorTests.swift +++ b/UnitTests/Sources/RoomFlowCoordinatorTests.swift @@ -322,7 +322,7 @@ class RoomFlowCoordinatorTests: XCTestCase { topic: nil, avatarURL: nil, memberCount: 0, - isHistoryWorldReadable: false, + isHistoryWorldReadable: nil, isJoined: false, isInvited: true, isPublic: false, diff --git a/UnitTests/Sources/RoomRolesAndPermissionsScreenViewModelTests.swift b/UnitTests/Sources/RoomRolesAndPermissionsScreenViewModelTests.swift index c37c4c63c9..3500b78f12 100644 --- a/UnitTests/Sources/RoomRolesAndPermissionsScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomRolesAndPermissionsScreenViewModelTests.swift @@ -49,7 +49,7 @@ class RoomRolesAndPermissionsScreenViewModelTests: XCTestCase { context.send(viewAction: .editOwnUserRole) XCTAssertNotNil(context.alertInfo) - context.alertInfo?.verticalButtons?.first(where: { $0.title.localizedStandardContains("moderator") })?.action?() + context.alertInfo?.verticalButtons?.first { $0.title.localizedStandardContains("moderator") }?.action?() try await Task.sleep(for: .milliseconds(100)) @@ -64,7 +64,7 @@ class RoomRolesAndPermissionsScreenViewModelTests: XCTestCase { context.send(viewAction: .editOwnUserRole) XCTAssertNotNil(context.alertInfo) - context.alertInfo?.verticalButtons?.first(where: { $0.title.localizedStandardContains("member") })?.action?() + context.alertInfo?.verticalButtons?.first { $0.title.localizedStandardContains("member") }?.action?() try await Task.sleep(for: .milliseconds(100)) diff --git a/UnitTests/Sources/RoomScreenViewModelTests.swift b/UnitTests/Sources/RoomScreenViewModelTests.swift index 306abca905..cf078fff98 100644 --- a/UnitTests/Sources/RoomScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomScreenViewModelTests.swift @@ -239,4 +239,116 @@ class RoomScreenViewModelTests: XCTestCase { // Then the call button should remain visible shown. XCTAssertTrue(viewModel.state.shouldShowCallButton) } + + // MARK: - Knock Requests + + func testKnockRequestBanner() async throws { + ServiceLocator.shared.settings.knockingEnabled = true + let roomProxyMock = JoinedRoomProxyMock(.init(knockRequestsState: .loaded([KnockRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org", displayName: "Alice", reason: "Hello World!")), + // This one should be filtered + KnockRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org", isSeen: true))]), + joinRule: .knock)) + let viewModel = RoomScreenViewModel(clientProxy: ClientProxyMock(), + roomProxy: roomProxyMock, + initialSelectedPinnedEventID: nil, + mediaProvider: MediaProviderMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics, + userIndicatorController: ServiceLocator.shared.userIndicatorController) + self.viewModel = viewModel + + var deferred = deferFulfillment(viewModel.context.$viewState) { state in + state.shouldSeeKnockRequests && + state.unseenKnockRequests == [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: "Hello World!", eventID: "1")] + } + try await deferred.fulfill() + + let deferredAction = deferFulfillment(viewModel.actions) { $0 == .displayKnockRequests } + viewModel.context.send(viewAction: .viewKnockRequests) + try await deferredAction.fulfill() + + deferred = deferFulfillment(viewModel.context.$viewState) { state in + state.handledEventIDs == ["1"] && + !state.shouldSeeKnockRequests + } + viewModel.context.send(viewAction: .acceptKnock(eventID: "1")) + try await deferred.fulfill() + } + + func testKnockRequestBannerMarkAsSeen() async throws { + ServiceLocator.shared.settings.knockingEnabled = true + let roomProxyMock = JoinedRoomProxyMock(.init(knockRequestsState: .loaded([KnockRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org", displayName: "Alice", reason: "Hello World!")), + // This one should be filtered + KnockRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org"))]), + joinRule: .knock)) + let viewModel = RoomScreenViewModel(clientProxy: ClientProxyMock(), + roomProxy: roomProxyMock, + initialSelectedPinnedEventID: nil, + mediaProvider: MediaProviderMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics, + userIndicatorController: ServiceLocator.shared.userIndicatorController) + self.viewModel = viewModel + + var deferred = deferFulfillment(viewModel.context.$viewState) { state in + state.shouldSeeKnockRequests && + state.unseenKnockRequests == [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: "Hello World!", eventID: "1"), + .init(displayName: nil, avatarURL: nil, userID: "@bob:matrix.org", reason: nil, eventID: "2")] + } + try await deferred.fulfill() + + deferred = deferFulfillment(viewModel.context.$viewState) { state in + state.handledEventIDs == ["1", "2"] && + !state.shouldSeeKnockRequests + } + viewModel.context.send(viewAction: .dismissKnockRequests) + try await deferred.fulfill() + } + + func testLoadingKnockRequests() async throws { + ServiceLocator.shared.settings.knockingEnabled = true + let roomProxyMock = JoinedRoomProxyMock(.init(knockRequestsState: .loading, + joinRule: .knock)) + let viewModel = RoomScreenViewModel(clientProxy: ClientProxyMock(), + roomProxy: roomProxyMock, + initialSelectedPinnedEventID: nil, + mediaProvider: MediaProviderMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics, + userIndicatorController: ServiceLocator.shared.userIndicatorController) + self.viewModel = viewModel + + // Loading state just does not appear at all + let deferred = deferFulfillment(viewModel.context.$viewState) { !$0.shouldSeeKnockRequests } + try await deferred.fulfill() + } + + func testKnockRequestsBannerDoesNotAppearIfUserHasNoPermission() async throws { + ServiceLocator.shared.settings.knockingEnabled = true + let roomProxyMock = JoinedRoomProxyMock(.init(knockRequestsState: .loaded([KnockRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org", displayName: "Alice", reason: "Hello World!"))]), + canUserInvite: false, + joinRule: .knock)) + let viewModel = RoomScreenViewModel(clientProxy: ClientProxyMock(), + roomProxy: roomProxyMock, + initialSelectedPinnedEventID: nil, + mediaProvider: MediaProviderMock(configuration: .init()), + ongoingCallRoomIDPublisher: .init(.init(nil)), + appMediator: AppMediatorMock.default, + appSettings: ServiceLocator.shared.settings, + analyticsService: ServiceLocator.shared.analytics, + userIndicatorController: ServiceLocator.shared.userIndicatorController) + self.viewModel = viewModel + + var deferred = deferFulfillment(viewModel.context.$viewState) { state in + state.unseenKnockRequests == [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: "Hello World!", eventID: "1")] && + !state.shouldSeeKnockRequests + } + try await deferred.fulfill() + } } diff --git a/UnitTests/Sources/RoomSummaryTests.swift b/UnitTests/Sources/RoomSummaryTests.swift index 2626351eb4..76978af22f 100644 --- a/UnitTests/Sources/RoomSummaryTests.swift +++ b/UnitTests/Sources/RoomSummaryTests.swift @@ -56,7 +56,7 @@ class RoomSummaryTests: XCTestCase { func makeSummary(isDirect: Bool, hasRoomAvatar: Bool) -> RoomSummary { RoomSummary(roomListItem: .init(noPointer: .init()), id: roomDetails.id, - joinRequestType: nil, + knockRequestType: nil, name: roomDetails.name, isDirect: isDirect, avatarURL: hasRoomAvatar ? roomDetails.avatarURL : nil, diff --git a/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift b/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift new file mode 100644 index 0000000000..15cf4c3d7f --- /dev/null +++ b/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift @@ -0,0 +1,19 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import XCTest + +@testable import ElementX + +@MainActor +class SecurityAndPrivacyScreenViewModelTests: XCTestCase { + var viewModel: SecurityAndPrivacyScreenViewModelProtocol! + + var context: SecurityAndPrivacyScreenViewModelType.Context { + viewModel.context + } +} diff --git a/UnitTests/Sources/TextBasedRoomTimelineTests.swift b/UnitTests/Sources/TextBasedRoomTimelineTests.swift index 66a6d0e337..36837da99c 100644 --- a/UnitTests/Sources/TextBasedRoomTimelineTests.swift +++ b/UnitTests/Sources/TextBasedRoomTimelineTests.swift @@ -10,7 +10,7 @@ import XCTest final class TextBasedRoomTimelineTests: XCTestCase { func testTextRoomTimelineItemWhitespaceEnd() { - let timestamp = "Now" + let timestamp = Calendar.current.startOfDay(for: .now).addingTimeInterval(60 * 60) // 1:00 am let timelineItem = TextRoomTimelineItem(id: .randomEvent, timestamp: timestamp, isOutgoing: true, @@ -19,11 +19,11 @@ final class TextBasedRoomTimelineTests: XCTestCase { isThreaded: false, sender: .init(id: UUID().uuidString), content: .init(body: "Test")) - XCTAssertEqual(timelineItem.additionalWhitespaces(), timestamp.count + 1) + XCTAssertEqual(timelineItem.additionalWhitespaces(), timestamp.formattedTime().count + 1) } func testTextRoomTimelineItemWhitespaceEndLonger() { - let timestamp = "10:00 AM" + let timestamp = Calendar.current.startOfDay(for: .now).addingTimeInterval(-60) // 11:59 pm let timelineItem = TextRoomTimelineItem(id: .randomEvent, timestamp: timestamp, isOutgoing: true, @@ -32,11 +32,11 @@ final class TextBasedRoomTimelineTests: XCTestCase { isThreaded: false, sender: .init(id: UUID().uuidString), content: .init(body: "Test")) - XCTAssertEqual(timelineItem.additionalWhitespaces(), timestamp.count + 1) + XCTAssertEqual(timelineItem.additionalWhitespaces(), timestamp.formattedTime().count + 1) } func testTextRoomTimelineItemWhitespaceEndWithEdit() { - let timestamp = "Now" + let timestamp = Date.mock var timelineItem = TextRoomTimelineItem(id: .randomEvent, timestamp: timestamp, isOutgoing: true, @@ -47,11 +47,11 @@ final class TextBasedRoomTimelineTests: XCTestCase { content: .init(body: "Test")) timelineItem.properties.isEdited = true let editedCount = L10n.commonEditedSuffix.count - XCTAssertEqual(timelineItem.additionalWhitespaces(), timestamp.count + editedCount + 2) + XCTAssertEqual(timelineItem.additionalWhitespaces(), timestamp.formattedTime().count + editedCount + 2) } func testTextRoomTimelineItemWhitespaceEndWithEditAndAlert() { - let timestamp = "Now" + let timestamp = Date.mock var timelineItem = TextRoomTimelineItem(id: .randomEvent, timestamp: timestamp, isOutgoing: true, @@ -63,6 +63,6 @@ final class TextBasedRoomTimelineTests: XCTestCase { timelineItem.properties.isEdited = true timelineItem.properties.deliveryStatus = .sendingFailed(.unknown) let editedCount = L10n.commonEditedSuffix.count - XCTAssertEqual(timelineItem.additionalWhitespaces(), timestamp.count + editedCount + 5) + XCTAssertEqual(timelineItem.additionalWhitespaces(), timestamp.formattedTime().count + editedCount + 5) } } diff --git a/UnitTests/Sources/TimelineMediaPreviewViewModelTests.swift b/UnitTests/Sources/TimelineMediaPreviewViewModelTests.swift new file mode 100644 index 0000000000..e96bf68927 --- /dev/null +++ b/UnitTests/Sources/TimelineMediaPreviewViewModelTests.swift @@ -0,0 +1,268 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +@testable import ElementX + +import Combine +import MatrixRustSDK +import SwiftUI +import XCTest + +@MainActor +class TimelineMediaPreviewViewModelTests: XCTestCase { + var viewModel: TimelineMediaPreviewViewModel! + var context: TimelineMediaPreviewViewModel.Context { viewModel.context } + var mediaProvider: MediaProviderMock! + var photoLibraryManager: PhotoLibraryManagerMock! + var timelineController: MockRoomTimelineController! + + func testLoadingItem() async throws { + // Given a fresh view model. + setupViewModel() + XCTAssertFalse(mediaProvider.loadFileFromSourceFilenameCalled) + XCTAssertEqual(context.viewState.currentItem, context.viewState.previewItems[0]) + XCTAssertNotNil(context.viewState.currentItemActions) + + // When the preview controller sets the current item. + try await loadInitialItem() + + // Then the view model should load the item and update its view state. + XCTAssertTrue(mediaProvider.loadFileFromSourceFilenameCalled) + XCTAssertEqual(context.viewState.currentItem, context.viewState.previewItems[0]) + XCTAssertNotNil(context.viewState.currentItemActions) + } + + func testLoadingItemFailure() async throws { + // Given a fresh view model. + setupViewModel() + XCTAssertFalse(mediaProvider.loadFileFromSourceFilenameCalled) + XCTAssertEqual(context.viewState.currentItem, context.viewState.previewItems[0]) + XCTAssertNil(context.viewState.currentItem.downloadError) + + // When the preview controller sets an item that fails to load. + mediaProvider.loadFileFromSourceFilenameClosure = { _, _ in .failure(.failedRetrievingFile) } + let failure = deferFailure(viewModel.state.fileLoadedPublisher, timeout: 1) { _ in true } + context.send(viewAction: .updateCurrentItem(context.viewState.previewItems[0])) + try await failure.fulfill() + + // Then the view model should load the item and update its view state. + XCTAssertTrue(mediaProvider.loadFileFromSourceFilenameCalled) + XCTAssertEqual(context.viewState.currentItem, context.viewState.previewItems[0]) + XCTAssertNotNil(context.viewState.currentItem.downloadError) + } + + func testSwipingBetweenItems() async throws { + // Given a view model with a loaded item. + try await testLoadingItem() + + // When swiping to another item. + let deferred = deferFulfillment(viewModel.state.fileLoadedPublisher) { _ in true } + context.send(viewAction: .updateCurrentItem(context.viewState.previewItems[1])) + try await deferred.fulfill() + + // Then the view model should load the item and update its view state. + XCTAssertEqual(mediaProvider.loadFileFromSourceFilenameCallsCount, 2) + XCTAssertEqual(context.viewState.currentItem, context.viewState.previewItems[1]) + + // When swiping back to the first item. + let failure = deferFailure(viewModel.state.fileLoadedPublisher, timeout: 1) { _ in true } + context.send(viewAction: .updateCurrentItem(context.viewState.previewItems[0])) + try await failure.fulfill() + + // Then the view model should not need to load the item, but should still update its view state. + XCTAssertEqual(mediaProvider.loadFileFromSourceFilenameCallsCount, 2) + XCTAssertEqual(context.viewState.currentItem, context.viewState.previewItems[0]) + } + + func testViewInRoomTimeline() async throws { + // Given a view model with a loaded item. + try await testLoadingItem() + + // When choosing to view the current item in the timeline. + let item = context.viewState.currentItem + let deferred = deferFulfillment(viewModel.actions) { $0 == .viewInRoomTimeline(item.id) } + context.send(viewAction: .menuAction(.viewInRoomTimeline, item: item)) + + // Then the action should be sent upwards to make this happen. + try await deferred.fulfill() + } + + func testRedactConfirmation() async throws { + // Given a view model with a loaded item. + try await testLoadingItem() + XCTAssertNil(context.redactConfirmationItem) + XCTAssertFalse(timelineController.redactCalled) + + // When choosing to show the item details. + context.send(viewAction: .showCurrentItemDetails) + + // Then the details sheet should be presented. + guard let item = context.mediaDetailsItem else { + XCTFail("The default of the current item should be presented") + return + } + XCTAssertEqual(context.mediaDetailsItem, context.viewState.currentItem) + + // When choosing to redact the item. + context.send(viewAction: .menuAction(.redact, item: item)) + + // Then the confirmation sheet should be presented. + XCTAssertEqual(context.redactConfirmationItem, item) + XCTAssertFalse(timelineController.redactCalled) + + // When confirming the redaction. + let deferred = deferFulfillment(viewModel.actions) { $0 == .dismiss } + context.send(viewAction: .redactConfirmation(item: item)) + + // Then the item should be redacted and the view should be dismissed. + try await deferred.fulfill() + XCTAssertTrue(timelineController.redactCalled) + } + + func testSaveImage() async throws { + // Given a view model with a loaded image. + try await testLoadingItem() + XCTAssertEqual(viewModel.state.currentItem.contentType, "JPEG image") + + // When choosing to save the image. + let item = context.viewState.currentItem + context.send(viewAction: .saveCurrentItem) + try await Task.sleep(for: .seconds(0.5)) + + // Then the image should be saved as a photo to the user's photo library. + XCTAssertTrue(photoLibraryManager.addResourceAtCalled) + XCTAssertEqual(photoLibraryManager.addResourceAtReceivedArguments?.type, .photo) + XCTAssertEqual(photoLibraryManager.addResourceAtReceivedArguments?.url, item.fileHandle?.url) + } + + func testSaveImageWithoutAuthorization() async throws { + // Given a view model with a loaded image where the user has denied access to the photo library. + setupViewModel(photoLibraryAuthorizationDenied: true) + try await loadInitialItem() + XCTAssertEqual(viewModel.state.currentItem.contentType, "JPEG image") + + // When choosing to save the image. + let deferred = deferFulfillment(context.$viewState) { $0.bindings.alertInfo != nil } + context.send(viewAction: .saveCurrentItem) + try await deferred.fulfill() + + // Then the user should be prompted to allow access. + XCTAssertTrue(photoLibraryManager.addResourceAtCalled) + XCTAssertEqual(context.alertInfo?.id, .authorizationRequired) + } + + func testSaveVideo() async throws { + // Given a view model with a loaded video. + setupViewModel(initialItemIndex: 1) + try await loadInitialItem() + XCTAssertEqual(viewModel.state.currentItem.contentType, "MPEG-4 movie") + + // When choosing to save the video. + let item = context.viewState.currentItem + context.send(viewAction: .saveCurrentItem) + try await Task.sleep(for: .seconds(0.5)) + + // Then the video should be saved as a video in the user's photo library. + XCTAssertTrue(photoLibraryManager.addResourceAtCalled) + XCTAssertEqual(photoLibraryManager.addResourceAtReceivedArguments?.type, .video) + XCTAssertEqual(photoLibraryManager.addResourceAtReceivedArguments?.url, item.fileHandle?.url) + } + + func testSaveFile() async throws { + // Given a view model with a loaded file. + setupViewModel(initialItemIndex: 2) + try await loadInitialItem() + XCTAssertEqual(viewModel.state.currentItem.contentType, "PDF document") + + // When choosing to save the file. + let item = context.viewState.currentItem + context.send(viewAction: .saveCurrentItem) + try await Task.sleep(for: .seconds(0.5)) + + // Then the binding should be set for the user to export the file to their specified location. + XCTAssertFalse(photoLibraryManager.addResourceAtCalled) + XCTAssertNotNil(context.fileToExport) + XCTAssertEqual(context.fileToExport?.url, item.fileHandle?.url) + } + + func testDismiss() async throws { + // Given a view model with a loaded item. + try await testLoadingItem() + + // When requesting to dismiss the view. + let deferred = deferFulfillment(viewModel.actions) { $0 == .dismiss } + context.send(viewAction: .dismiss) + + // Then the action should be sent upwards to make this happen. + try await deferred.fulfill() + } + + // MARK: - Helpers + + private func loadInitialItem() async throws { + let deferred = deferFulfillment(viewModel.state.fileLoadedPublisher) { _ in true } + context.send(viewAction: .updateCurrentItem(context.viewState.previewItems[context.viewState.initialItemIndex])) + try await deferred.fulfill() + } + + @Namespace private var testNamespace + + private func setupViewModel(initialItemIndex: Int = 0, photoLibraryAuthorizationDenied: Bool = false) { + timelineController = MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen)) + timelineController.timelineItems = items + + mediaProvider = MediaProviderMock(configuration: .init()) + photoLibraryManager = PhotoLibraryManagerMock(.init(authorizationDenied: photoLibraryAuthorizationDenied)) + + viewModel = TimelineMediaPreviewViewModel(context: .init(item: items[initialItemIndex], + viewModel: TimelineViewModel.mock(timelineKind: .media(.mediaFilesScreen), + timelineController: timelineController), + namespace: testNamespace), + mediaProvider: mediaProvider, + photoLibraryManager: photoLibraryManager, + userIndicatorController: UserIndicatorControllerMock(), + appMediator: AppMediatorMock()) + } + + private let items: [EventBasedMessageTimelineItemProtocol] = [ + ImageRoomTimelineItem(id: .randomEvent, + timestamp: .mock, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: "", displayName: "Sally Sanderson"), + content: .init(filename: "Amazing image.jpeg", + caption: "A caption goes right here.", + imageInfo: .mockImage, + thumbnailInfo: .mockThumbnail, + contentType: .jpeg)), + VideoRoomTimelineItem(id: .randomEvent, + timestamp: .mock, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: ""), + content: .init(filename: "Super video.mp4", + videoInfo: .mockVideo, + thumbnailInfo: .mockThumbnail, + contentType: .mpeg4Movie)), + FileRoomTimelineItem(id: .randomEvent, + timestamp: .mock, + isOutgoing: false, + isEditable: false, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: ""), + content: .init(filename: "Important file.pdf", + source: try? .init(url: .mockMXCFile, mimeType: "document/pdf"), + fileSize: 2453, + thumbnailSource: nil, + contentType: .pdf)) + ] +} diff --git a/UnitTests/Sources/TimelineViewModelTests.swift b/UnitTests/Sources/TimelineViewModelTests.swift index fb89dc6f3a..addbccca5b 100644 --- a/UnitTests/Sources/TimelineViewModelTests.swift +++ b/UnitTests/Sources/TimelineViewModelTests.swift @@ -45,9 +45,9 @@ class TimelineViewModelTests: XCTestCase { let viewModel = makeViewModel(timelineController: timelineController) // Then the messages should be grouped together. - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .middle, "Nothing should prevent the middle message from being grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .last, "Nothing should prevent the last message from being grouped.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[1].groupStyle, .middle, "Nothing should prevent the middle message from being grouped.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[2].groupStyle, .last, "Nothing should prevent the last message from being grouped.") } func testMessageGroupingMultipleSenders() { @@ -73,12 +73,12 @@ class TimelineViewModelTests: XCTestCase { let viewModel = makeViewModel(timelineController: timelineController) // Then the messages should be grouped by sender. - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .single, "A message should not be grouped when the sender changes.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .single, "A message should not be grouped when the sender changes.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .first, "A group should start with a new sender if there are more messages from that sender.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[3].groupStyle, .last, "A group should be ended when the sender changes in the next message.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[4].groupStyle, .first, "A group should start with a new sender if there are more messages from that sender.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[5].groupStyle, .last, "A group should be ended when the sender changes in the next message.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[0].groupStyle, .single, "A message should not be grouped when the sender changes.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[1].groupStyle, .single, "A message should not be grouped when the sender changes.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[2].groupStyle, .first, "A group should start with a new sender if there are more messages from that sender.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[3].groupStyle, .last, "A group should be ended when the sender changes in the next message.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[4].groupStyle, .first, "A group should start with a new sender if there are more messages from that sender.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[5].groupStyle, .last, "A group should be ended when the sender changes in the next message.") } func testMessageGroupingWithLeadingReactions() { @@ -99,9 +99,9 @@ class TimelineViewModelTests: XCTestCase { let viewModel = makeViewModel(timelineController: timelineController) // Then the first message should not be grouped but the other two should. - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .single, "When the first message has reactions it should not be grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .first, "A new group should be made when the preceding message has reactions.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .last, "Nothing should prevent the last message from being grouped.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[0].groupStyle, .single, "When the first message has reactions it should not be grouped.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[1].groupStyle, .first, "A new group should be made when the preceding message has reactions.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[2].groupStyle, .last, "Nothing should prevent the last message from being grouped.") } func testMessageGroupingWithInnerReactions() { @@ -122,9 +122,9 @@ class TimelineViewModelTests: XCTestCase { let viewModel = makeViewModel(timelineController: timelineController) // Then the first and second messages should be grouped and the last one should not. - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .last, "When the message has reactions, the group should end here.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .single, "The last message should not be grouped when the preceding message has reactions.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[1].groupStyle, .last, "When the message has reactions, the group should end here.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[2].groupStyle, .single, "The last message should not be grouped when the preceding message has reactions.") } func testMessageGroupingWithTrailingReactions() { @@ -145,9 +145,9 @@ class TimelineViewModelTests: XCTestCase { let viewModel = makeViewModel(timelineController: timelineController) // Then the messages should be grouped together. - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[1].groupStyle, .middle, "Nothing should prevent the second message from being grouped.") - XCTAssertEqual(viewModel.state.timelineViewState.itemViewStates[2].groupStyle, .last, "Reactions on the last message should not prevent it from being grouped.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[0].groupStyle, .first, "Nothing should prevent the first message from being grouped.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[1].groupStyle, .middle, "Nothing should prevent the second message from being grouped.") + XCTAssertEqual(viewModel.state.timelineState.itemViewStates[2].groupStyle, .last, "Reactions on the last message should not prevent it from being grouped.") } // MARK: - Focussing @@ -162,18 +162,18 @@ class TimelineViewModelTests: XCTestCase { let viewModel = makeViewModel(timelineController: timelineController) XCTAssertEqual(timelineController.focusOnEventCallCount, 0) - XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEvent) + XCTAssertTrue(viewModel.context.viewState.timelineState.isLive) + XCTAssertNil(viewModel.context.viewState.timelineState.focussedEvent) // When focussing on an item that isn't loaded. - let deferred = deferFulfillment(viewModel.context.$viewState) { !$0.timelineViewState.isLive } + let deferred = deferFulfillment(viewModel.context.$viewState) { !$0.timelineState.isLive } await viewModel.focusOnEvent(eventID: "t4") try await deferred.fulfill() // Then a new timeline should be loaded and the room focussed on that event. XCTAssertEqual(timelineController.focusOnEventCallCount, 1) - XCTAssertFalse(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t4", appearance: .immediate)) + XCTAssertFalse(viewModel.context.viewState.timelineState.isLive) + XCTAssertEqual(viewModel.context.viewState.timelineState.focussedEvent, .init(eventID: "t4", appearance: .immediate)) } func testFocusLoadedItem() async throws { @@ -186,18 +186,18 @@ class TimelineViewModelTests: XCTestCase { let viewModel = makeViewModel(timelineController: timelineController) XCTAssertEqual(timelineController.focusOnEventCallCount, 0) - XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEvent) + XCTAssertTrue(viewModel.context.viewState.timelineState.isLive) + XCTAssertNil(viewModel.context.viewState.timelineState.focussedEvent) // When focussing on a loaded item. - let deferred = deferFailure(viewModel.context.$viewState, timeout: 1) { !$0.timelineViewState.isLive } + let deferred = deferFailure(viewModel.context.$viewState, timeout: 1) { !$0.timelineState.isLive } await viewModel.focusOnEvent(eventID: "t1") try await deferred.fulfill() // Then the timeline should remain live and the item should be focussed. XCTAssertEqual(timelineController.focusOnEventCallCount, 0) - XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t1", appearance: .animated)) + XCTAssertTrue(viewModel.context.viewState.timelineState.isLive) + XCTAssertEqual(viewModel.context.viewState.timelineState.focussedEvent, .init(eventID: "t1", appearance: .animated)) } func testFocusLive() async throws { @@ -210,30 +210,30 @@ class TimelineViewModelTests: XCTestCase { let viewModel = makeViewModel(timelineController: timelineController) - var deferred = deferFulfillment(viewModel.context.$viewState) { !$0.timelineViewState.isLive } + var deferred = deferFulfillment(viewModel.context.$viewState) { !$0.timelineState.isLive } await viewModel.focusOnEvent(eventID: "t4") try await deferred.fulfill() XCTAssertEqual(timelineController.focusLiveCallCount, 0) - XCTAssertFalse(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t4", appearance: .immediate)) + XCTAssertFalse(viewModel.context.viewState.timelineState.isLive) + XCTAssertEqual(viewModel.context.viewState.timelineState.focussedEvent, .init(eventID: "t4", appearance: .immediate)) // When switching back to a live timeline. - deferred = deferFulfillment(viewModel.context.$viewState) { $0.timelineViewState.isLive } + deferred = deferFulfillment(viewModel.context.$viewState) { $0.timelineState.isLive } viewModel.context.send(viewAction: .focusLive) try await deferred.fulfill() // Then the timeline should switch back to being live and the event focus should be removed. XCTAssertEqual(timelineController.focusLiveCallCount, 1) - XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive) - XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEvent) + XCTAssertTrue(viewModel.context.viewState.timelineState.isLive) + XCTAssertNil(viewModel.context.viewState.timelineState.focussedEvent) } func testInitialFocusViewState() async throws { let timelineController = MockRoomTimelineController() let viewModel = makeViewModel(focussedEventID: "t10", timelineController: timelineController) - XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEvent, .init(eventID: "t10", appearance: .immediate)) + XCTAssertEqual(viewModel.context.viewState.timelineState.focussedEvent, .init(eventID: "t10", appearance: .immediate)) } // MARK: - Read Receipts @@ -428,7 +428,7 @@ private extension TextRoomTimelineItem { init(text: String, sender: String, addReactions: Bool = false, addReadReceipts: [ReadReceipt] = []) { let reactions = addReactions ? [AggregatedReaction(accountOwnerID: "bob", key: "🦄", senders: [ReactionSender(id: sender, timestamp: Date())])] : [] self.init(id: .randomEvent, - timestamp: "10:47 am", + timestamp: .mock, isOutgoing: sender == "bob", isEditable: sender == "bob", canBeRepliedTo: true, @@ -441,14 +441,14 @@ private extension TextRoomTimelineItem { private extension SeparatorRoomTimelineItem { init(uniqueID: TimelineUniqueId) { - self.init(id: .virtual(uniqueID: uniqueID), text: "") + self.init(id: .virtual(uniqueID: uniqueID), timestamp: .mock) } } private extension TextRoomTimelineItem { init(eventID: String) { self.init(id: .event(uniqueID: .init(id: UUID().uuidString), eventOrTransactionID: .eventId(eventId: eventID)), - timestamp: "", + timestamp: .mock, isOutgoing: false, isEditable: false, canBeRepliedTo: true, diff --git a/UnitTests/Sources/VoiceMessageMediaManagerTests.swift b/UnitTests/Sources/VoiceMessageMediaManagerTests.swift index b9dba42870..92f4b0844f 100644 --- a/UnitTests/Sources/VoiceMessageMediaManagerTests.swift +++ b/UnitTests/Sources/VoiceMessageMediaManagerTests.swift @@ -22,6 +22,8 @@ class VoiceMessageMediaManagerTests: XCTestCase { override func setUp() async throws { voiceMessageCache = VoiceMessageCacheMock() mediaProvider = MediaProviderMock(configuration: .init()) + mediaProvider.loadFileFromSourceFilenameClosure = nil + mediaProvider.loadFileFromSourceFilenameReturnValue = .failure(.failedRetrievingFile) voiceMessageMediaManager = VoiceMessageMediaManager(mediaProvider: mediaProvider, voiceMessageCache: voiceMessageCache) } diff --git a/project.yml b/project.yml index 7660990072..afd60d79d4 100644 --- a/project.yml +++ b/project.yml @@ -41,7 +41,7 @@ settings: APP_GROUP_IDENTIFIER: group.$(BASE_APP_GROUP_IDENTIFIER) APP_NAME: ElementX KEYCHAIN_ACCESS_GROUP_IDENTIFIER: "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)" - MARKETING_VERSION: 1.9.8 + MARKETING_VERSION: 1.9.10 CURRENT_PROJECT_VERSION: 1 SUPPORTS_MACCATALYST: false @@ -61,11 +61,11 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.77 + exactVersion: 1.0.83 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios - revision: 901f3f2fc150db82cf8a2c4da53914b31f681b56 + revision: 9325643cb4d22150881c5bf79e1e6e3c5a87ea89 # path: ../compound-ios AnalyticsEvents: url: https://github.com/matrix-org/matrix-analytics-events diff --git a/renovate.json b/renovate.json index 5e5a3eafcd..ae25c1deb1 100644 --- a/renovate.json +++ b/renovate.json @@ -1,7 +1,8 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:recommended" + "config:recommended", + ":semanticCommitsDisabled" ], "labels" : [ "pr-misc"