From 4f8565c3b4a3bfeaac603c34447db588cfce9d1a Mon Sep 17 00:00:00 2001 From: Element CI Date: Thu, 7 Nov 2024 07:29:17 -0800 Subject: [PATCH 01/74] Prepare next release --- CHANGES.md | 57 ++++++++++++++++++++++++++++++ ElementX.xcodeproj/project.pbxproj | 4 +-- project.yml | 2 +- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2987f6851c..9c3b6148d2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,60 @@ +## Changes in 1.9.4 (2024-11-07) + +### What's Changed + +✨ Features +* Hook reaction pickers into the system's recently used keyboard emojis by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3453 +* Incoming session verification support by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3428 +* Enable the Optimised Media Uploads feature. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3467 + +🙌 Improvements +* Enable identity pinning violation notifications unconditionally by @andybalaam in https://github.com/element-hq/element-x-ios/pull/3457 +* Tweak the flow for changing a recovery key. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3452 +* Replace individual RoomProxy properties with a stored RoomInfo. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3445 +* Use an https callback for OIDC once again. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3461 +* Tweak the flow for setting up a recovery key. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3463 +* Tweak the flow for disabling key storage. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3464 +* Directly show Recovery Key and Encryption Reset screens from the home screen banner. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3482 + +🐛 Bugfixes +* Fix the order of the frequently used emojis when showing them in the full reaction picker by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3455 +* Stop the sync loop after each background app refresh. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3481 +* Fix the Setup Recovery flow from the home screen banner. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3483 +* Fix race condition when setting up session verification controller subscriptions by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3486 +* Fix a couple of race conditions when observing room info updates for calls. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3487 +* Syncing fixes by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3488 +* Start syncing when receiving a background VoIP call for the cases in which the app was suspended but not terminated by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3491 +* Update SDK 1.0.65 by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3494 + +🗣 Translations +* Update translations and some snapshots. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3459 +* Translations update by @RiotRobot in https://github.com/element-hq/element-x-ios/pull/3477 + +🧱 Build +* remove iOS 16 support by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3443 +* min macos support by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3451 +* Revert "min macos support" by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3458 + +📄 Documentation +* Update the README. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3480 + +🚧 In development 🚧 +* Knocked Preview implementation by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3426 +* Switch optimised video uploads to use 720p by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3462 + +Others +* Update verify identity button title. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3466 +* Update the strings for out of sync Key Storage. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3468 +* Update SDK 1.0.63 by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3479 +* Encryption Flow Coordinators. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3471 +* Update SDK 1.0.64 by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3490 +* Fastlane fails resetting the right simulator, use `device` instead of `destination`. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3493 + +### New Contributors +* @andybalaam made their first contribution in https://github.com/element-hq/element-x-ios/pull/3457 + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.9.3...1.9.4 + ## Changes in 1.9.3 (2024-10-24) ### What's Changed diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 715b05cf70..a1c706042a 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -7497,7 +7497,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 17.6; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; MACOSX_DEPLOYMENT_TARGET = 14.6; - MARKETING_VERSION = 1.9.4; + MARKETING_VERSION = 1.9.5; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCTION_APP_NAME = Element; @@ -7574,7 +7574,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 17.6; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; MACOSX_DEPLOYMENT_TARGET = 14.6; - MARKETING_VERSION = 1.9.4; + MARKETING_VERSION = 1.9.5; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; diff --git a/project.yml b/project.yml index 4c0b181f7b..dd1dead262 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.4 + MARKETING_VERSION: 1.9.5 CURRENT_PROJECT_VERSION: 1 SUPPORTS_MACCATALYST: false From 4e880f1924ca368b47b9b87264da3c44e60c8095 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Fri, 8 Nov 2024 08:36:15 +0000 Subject: [PATCH 02/74] Fix incorrect analytics mapping for UTDs. (#3497) * Fix incorrect analytics mapping for UTDs. * Upgrade GitHub workflows to use macOS 15. --- .github/workflows/danger.yml | 2 +- .github/workflows/pr-build.yml | 2 +- .github/workflows/translations-pr.yml | 2 +- .github/workflows/unit_tests.yml | 2 +- .github/workflows/unit_tests_enterprise.yml | 2 +- .../Sources/FlowCoordinators/UserSessionFlowCoordinator.swift | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index dabb5e4080..f4e9f148c2 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -7,7 +7,7 @@ on: jobs: build: name: Danger - runs-on: macos-14 + runs-on: macos-15 steps: - name: Checkout diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index b23b449aa6..eecda979ac 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -11,7 +11,7 @@ jobs: if: contains(github.event.pull_request.labels.*.name, 'Trigger-PR-Build') name: Release - runs-on: macos-14 + runs-on: macos-15 concurrency: # Only allow a single run of this workflow on each branch, automatically cancelling older runs. diff --git a/.github/workflows/translations-pr.yml b/.github/workflows/translations-pr.yml index 2c4ca11abb..5a5003fdf7 100644 --- a/.github/workflows/translations-pr.yml +++ b/.github/workflows/translations-pr.yml @@ -7,7 +7,7 @@ on: jobs: open-translations-pr: - runs-on: macos-14 + runs-on: macos-15 # Skip in forks if: github.repository == 'element-hq/element-x-ios' steps: diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 63fa5e54ed..81be7193e4 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -11,7 +11,7 @@ on: jobs: tests: name: Tests - runs-on: macos-14 + runs-on: macos-15 concurrency: # Only allow a single run of this workflow on each branch, automatically cancelling older runs. diff --git a/.github/workflows/unit_tests_enterprise.yml b/.github/workflows/unit_tests_enterprise.yml index 5bc8baac36..02545643dd 100644 --- a/.github/workflows/unit_tests_enterprise.yml +++ b/.github/workflows/unit_tests_enterprise.yml @@ -11,7 +11,7 @@ on: jobs: tests: name: Tests (Enterprise) - runs-on: macos-14 + runs-on: macos-15 # Skip in forks if: github.repository == 'element-hq/element-x-ios' diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index b824715d32..ff62ac4e2b 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -368,7 +368,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { switch info.cause { case .unknown: - analytics.trackError(context: nil, domain: .E2EE, name: .UnknownError, timeToDecryptMillis: timeToDecryptMs) + analytics.trackError(context: nil, domain: .E2EE, name: .OlmKeysNotSentError, timeToDecryptMillis: timeToDecryptMs) case .unknownDevice: analytics.trackError(context: nil, domain: .E2EE, name: .ExpectedSentByInsecureDevice, timeToDecryptMillis: timeToDecryptMs) case .unsignedDevice: From c42ef40aa4a2ac7e8b4edee2bc7f17a5d0dccad4 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 7 Nov 2024 16:57:17 +0200 Subject: [PATCH 03/74] #3372 - Stop setting up CallKit sessions when joining calls - comes following the discussions on https://developer.apple.com/forums//thread/767949?answerId=812951022#812951022 - this removes the lock screen controls entirely and lets the rest of the app behave normally --- .../ElementCall/ElementCallService.swift | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/ElementX/Sources/Services/ElementCall/ElementCallService.swift b/ElementX/Sources/Services/ElementCall/ElementCallService.swift index 1ecf1dfa20..9dffddc981 100644 --- a/ElementX/Sources/Services/ElementCall/ElementCallService.swift +++ b/ElementX/Sources/Services/ElementCall/ElementCallService.swift @@ -99,26 +99,18 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe incomingCallID = nil ongoingCallID = callID - let handle = CXHandle(type: .generic, value: roomDisplayName) - let startCallAction = CXStartCallAction(call: callID.callKitID, handle: handle) - startCallAction.isVideo = true + // Don't bother starting another CallKit session as it won't work properly + // https://developer.apple.com/forums//thread/767949?answerId=812951022#812951022 - do { - try await callController.request(CXTransaction(action: startCallAction)) - } catch { - MXLog.error("Failed requesting start call action with error: \(error)") - } + // let handle = CXHandle(type: .generic, value: roomDisplayName) + // let startCallAction = CXStartCallAction(call: callID.callKitID, handle: handle) + // startCallAction.isVideo = true - do { - // Have ElementCall default to the speaker so that the lock button doesn't end the call. - // Could also use `overrideOutputAudioPort` but the documentation is clear about it: - // `Sessions using PlayAndRecord category that always want to prefer the built-in - // speaker output over the receiver, should use AVAudioSessionCategoryOptionDefaultToSpeaker instead.`. - try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .videoChat, options: [.defaultToSpeaker]) - try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation) - } catch { - MXLog.error("Failed setting up audio session with error: \(error)") - } + // do { + // try await callController.request(CXTransaction(action: startCallAction)) + // } catch { + // MXLog.error("Failed requesting start call action with error: \(error)") + // } } func tearDownCallSession() { @@ -222,6 +214,8 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe // Reporting the call as ended imediately after answering it works around that // as EC gets access to media again and EX builds the right UI in `setupCallSession` // + // https://developer.apple.com/forums//thread/767949?answerId=812951022#812951022 + // // https://github.com/element-hq/element-x-ios/issues/3041 // https://forums.developer.apple.com/forums/thread/685268 // https://stackoverflow.com/questions/71483732/webrtc-running-from-wkwebview-avaudiosession-development-roadblock From c567901ec55ec3e57930f3833d314dc58a23c72b Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Fri, 8 Nov 2024 12:18:37 +0000 Subject: [PATCH 04/74] Update compound. (#3498) --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 6 +++--- project.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index a1c706042a..fe0c6e3102 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -7978,7 +7978,7 @@ repositoryURL = "https://github.com/element-hq/compound-ios"; requirement = { kind = revision; - revision = e3f9665621872f60d3652579c3f0dc7bf806e72c; + revision = 950a8884e269194e6030cbddabebbb116cdfe02a; }; }; 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 4cd886738e..57400ca50d 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" : "976db67b849775799b4153e7894d61e90fc96888", - "version" : "1.9.0" + "revision" : "f9510e9d309b5aeefe9a7ef6b8c073c84337d4e9", + "version" : "1.9.1" } }, { @@ -15,7 +15,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/compound-ios", "state" : { - "revision" : "e3f9665621872f60d3652579c3f0dc7bf806e72c" + "revision" : "950a8884e269194e6030cbddabebbb116cdfe02a" } }, { diff --git a/project.yml b/project.yml index dd1dead262..5eb74d64fa 100644 --- a/project.yml +++ b/project.yml @@ -64,7 +64,7 @@ packages: # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios - revision: e3f9665621872f60d3652579c3f0dc7bf806e72c + revision: 950a8884e269194e6030cbddabebbb116cdfe02a # path: ../compound-ios AnalyticsEvents: url: https://github.com/matrix-org/matrix-analytics-events From e7d4ea0d35f1ea5fb156c636639ebffe73eca58b Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:49:20 +0100 Subject: [PATCH 05/74] Add alias to public room creation (#3450) * added the address section * updated code and strings * syncing name and address * improved code * added a way to reset the state * better documentation * update strings * handling the alias * alias error state * update strings * error handling * improved the error handling * new preview tests, even if they do not work well * improved tests * unit tests * pr comments and using the correct value * fix * pr comments * to improve safety and control of the FF * fixed a test * updated tests * update SDK --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../en.lproj/Localizable.strings | 12 +- ElementX/Sources/Generated/Strings.swift | 24 +-- ElementX/Sources/Mocks/ClientProxyMock.swift | 8 +- .../Mocks/Generated/GeneratedMocks.swift | 118 +++++++++++--- .../Screens/CreateRoom/CreateRoomModels.swift | 25 ++- .../CreateRoom/CreateRoomViewModel.swift | 147 ++++++++++++++++-- .../CreateRoom/View/CreateRoomScreen.swift | 120 ++++++++++++-- .../View/SecureBackupRecoveryKeyScreen.swift | 4 +- .../Sources/Services/Client/ClientProxy.swift | 40 ++++- .../Services/Client/ClientProxyProtocol.swift | 12 +- .../CreateRoom/CreateRoomFlowParameters.swift | 1 + ...n-GB.Create-Public-Room-existing-alias.png | 3 + ...en-GB.Create-Public-Room-invalid-alias.png | 3 + ...eateRoom-iPad-en-GB.Create-Public-Room.png | 4 +- ...m-iPad-en-GB.Create-Room-without-users.png | 4 +- ...test_createRoom-iPad-en-GB.Create-Room.png | 4 +- ...eudo.Create-Public-Room-existing-alias.png | 3 + ...seudo.Create-Public-Room-invalid-alias.png | 3 + ...ateRoom-iPad-pseudo.Create-Public-Room.png | 4 +- ...-iPad-pseudo.Create-Room-without-users.png | 4 +- ...est_createRoom-iPad-pseudo.Create-Room.png | 4 +- ...n-GB.Create-Public-Room-existing-alias.png | 3 + ...en-GB.Create-Public-Room-invalid-alias.png | 3 + ...oom-iPhone-16-en-GB.Create-Public-Room.png | 4 +- ...one-16-en-GB.Create-Room-without-users.png | 4 +- ...createRoom-iPhone-16-en-GB.Create-Room.png | 4 +- ...eudo.Create-Public-Room-existing-alias.png | 3 + ...seudo.Create-Public-Room-invalid-alias.png | 3 + ...om-iPhone-16-pseudo.Create-Public-Room.png | 4 +- ...ne-16-pseudo.Create-Room-without-users.png | 4 +- ...reateRoom-iPhone-16-pseudo.Create-Room.png | 4 +- ...kupRecoveryKeyScreen-iPad-en-GB.Set-up.png | 4 +- ...upRecoveryKeyScreen-iPad-pseudo.Set-up.png | 4 +- ...coveryKeyScreen-iPhone-16-en-GB.Set-up.png | 4 +- ...overyKeyScreen-iPhone-16-pseudo.Set-up.png | 4 +- .../Sources/CreateRoomViewModelTests.swift | 100 +++++++++++- project.yml | 2 +- 39 files changed, 592 insertions(+), 115 deletions(-) create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-invalid-alias.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-existing-alias.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-invalid-alias.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index fe0c6e3102..24ab4952ad 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -7858,7 +7858,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.65; + version = 1.0.66; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 57400ca50d..0d3eb39468 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "399cc70987856c73e24b8888ac1ecc0eecf1716b", - "version" : "1.0.65" + "revision" : "902979581ff4f35e54a83cd7c5c340745d6f0d0e", + "version" : "1.0.66" } }, { diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 4200cde50f..23b47f1e3c 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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."; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 2c89b62e8c..f807da0708 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -1093,16 +1093,6 @@ internal enum L10n { internal static var screenCreatePollQuestionHint: String { return L10n.tr("Localizable", "screen_create_poll_question_hint") } /// Create Poll internal static var screenCreatePollTitle: String { return L10n.tr("Localizable", "screen_create_poll_title") } - /// Anyone can join this room - internal static var screenCreateRoomAccessSectionAnyoneOptionDescription: String { return L10n.tr("Localizable", "screen_create_room_access_section_anyone_option_description") } - /// Anyone - internal static var screenCreateRoomAccessSectionAnyoneOptionTitle: String { return L10n.tr("Localizable", "screen_create_room_access_section_anyone_option_title") } - /// Room Access - internal static var screenCreateRoomAccessSectionHeader: String { return L10n.tr("Localizable", "screen_create_room_access_section_header") } - /// Anyone can ask to join the room but an administrator or a moderator will have to accept the request - internal static var screenCreateRoomAccessSectionKnockingOptionDescription: String { return L10n.tr("Localizable", "screen_create_room_access_section_knocking_option_description") } - /// Ask to join - internal static var screenCreateRoomAccessSectionKnockingOptionTitle: String { return L10n.tr("Localizable", "screen_create_room_access_section_knocking_option_title") } /// New room internal static var screenCreateRoomActionCreateRoom: String { return L10n.tr("Localizable", "screen_create_room_action_create_room") } /// Invite people @@ -1118,6 +1108,20 @@ internal enum L10n { internal static var screenCreateRoomPublicOptionDescription: String { return L10n.tr("Localizable", "screen_create_room_public_option_description") } /// Public room internal static var screenCreateRoomPublicOptionTitle: String { return L10n.tr("Localizable", "screen_create_room_public_option_title") } + /// Anyone can join this room + internal static var screenCreateRoomRoomAccessSectionAnyoneOptionDescription: String { return L10n.tr("Localizable", "screen_create_room_room_access_section_anyone_option_description") } + /// Anyone + internal static var screenCreateRoomRoomAccessSectionAnyoneOptionTitle: String { return L10n.tr("Localizable", "screen_create_room_room_access_section_anyone_option_title") } + /// Room Access + internal static var screenCreateRoomRoomAccessSectionHeader: String { return L10n.tr("Localizable", "screen_create_room_room_access_section_header") } + /// Anyone can ask to join the room but an administrator or a moderator will have to accept the request + internal static var screenCreateRoomRoomAccessSectionKnockingOptionDescription: String { return L10n.tr("Localizable", "screen_create_room_room_access_section_knocking_option_description") } + /// Ask to join + internal static var screenCreateRoomRoomAccessSectionKnockingOptionTitle: String { return L10n.tr("Localizable", "screen_create_room_room_access_section_knocking_option_title") } + /// Some characters are not allowed. Only letters, digits and the following symbols are supported ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _ + internal static var screenCreateRoomRoomAddressInvalidSymbolsErrorDescription: String { return L10n.tr("Localizable", "screen_create_room_room_address_invalid_symbols_error_description") } + /// This room address already exists, please try editing the room address field or change the room name + internal static var screenCreateRoomRoomAddressNotAvailableErrorDescription: String { return L10n.tr("Localizable", "screen_create_room_room_address_not_available_error_description") } /// In order for this room to be visible in the public room directory, you will need a room address. internal static var screenCreateRoomRoomAddressSectionFooter: String { return L10n.tr("Localizable", "screen_create_room_room_address_section_footer") } /// Room address diff --git a/ElementX/Sources/Mocks/ClientProxyMock.swift b/ElementX/Sources/Mocks/ClientProxyMock.swift index b5b52018bd..9a21f91205 100644 --- a/ElementX/Sources/Mocks/ClientProxyMock.swift +++ b/ElementX/Sources/Mocks/ClientProxyMock.swift @@ -9,6 +9,8 @@ import Combine import Foundation struct ClientProxyMockConfiguration { + var homeserver = "" + var userIDServerName: String? var userID: String = RoomMemberProxyMock.mockMe.userID var deviceID: String? var roomSummaryProvider: RoomSummaryProviderProtocol? = RoomSummaryProviderMock(.init()) @@ -28,7 +30,8 @@ extension ClientProxyMock { userID = configuration.userID deviceID = configuration.deviceID - homeserver = "" + homeserver = configuration.homeserver + userIDServerName = configuration.userIDServerName roomSummaryProvider = configuration.roomSummaryProvider alternateRoomSummaryProvider = RoomSummaryProviderMock(.init()) @@ -52,13 +55,14 @@ extension ClientProxyMock { canDeactivateAccount = false directRoomForUserIDReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) createDirectRoomWithExpectedRoomNameReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) - createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) + createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) uploadMediaReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) loadUserDisplayNameReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) setUserDisplayNameReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) loadUserAvatarURLReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) setUserAvatarMediaReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) removeUserAvatarReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) + isAliasAvailableReturnValue = .success(true) logoutReturnValue = nil searchUsersSearchTermLimitReturnValue = .success(.init(results: [], limited: false)) profileForReturnValue = .success(.init(userID: "@a:b.com", displayName: "Some user")) diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index c7524379ca..51c386fda5 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -2628,15 +2628,15 @@ class ClientProxyMock: ClientProxyProtocol { } //MARK: - createRoom - var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLUnderlyingCallsCount = 0 - var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLCallsCount: Int { + var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartUnderlyingCallsCount = 0 + var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartCallsCount: Int { get { if Thread.isMainThread { - return createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLUnderlyingCallsCount + return createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLUnderlyingCallsCount + returnValue = createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartUnderlyingCallsCount } return returnValue! @@ -2644,29 +2644,29 @@ class ClientProxyMock: ClientProxyProtocol { } set { if Thread.isMainThread { - createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLUnderlyingCallsCount = newValue + createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLUnderlyingCallsCount = newValue + createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartUnderlyingCallsCount = newValue } } } } - var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLCalled: Bool { - return createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLCallsCount > 0 + var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartCalled: Bool { + return createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartCallsCount > 0 } - var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLReceivedArguments: (name: String, topic: String?, isRoomPrivate: Bool, isKnockingOnly: Bool, userIDs: [String], avatarURL: URL?)? - var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLReceivedInvocations: [(name: String, topic: String?, isRoomPrivate: Bool, isKnockingOnly: Bool, userIDs: [String], avatarURL: URL?)] = [] + var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartReceivedArguments: (name: String, topic: String?, isRoomPrivate: Bool, isKnockingOnly: Bool, userIDs: [String], avatarURL: URL?, aliasLocalPart: String?)? + var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartReceivedInvocations: [(name: String, topic: String?, isRoomPrivate: Bool, isKnockingOnly: Bool, userIDs: [String], avatarURL: URL?, aliasLocalPart: String?)] = [] - var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLUnderlyingReturnValue: Result! - var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLReturnValue: Result! { + var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartUnderlyingReturnValue: Result! + var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartReturnValue: Result! { get { if Thread.isMainThread { - return createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLUnderlyingReturnValue + return createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLUnderlyingReturnValue + returnValue = createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartUnderlyingReturnValue } return returnValue! @@ -2674,26 +2674,26 @@ class ClientProxyMock: ClientProxyProtocol { } set { if Thread.isMainThread { - createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLUnderlyingReturnValue = newValue + createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLUnderlyingReturnValue = newValue + createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartUnderlyingReturnValue = newValue } } } } - var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLClosure: ((String, String?, Bool, Bool, [String], URL?) async -> Result)? + var createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartClosure: ((String, String?, Bool, Bool, [String], URL?, String?) async -> Result)? - func createRoom(name: String, topic: String?, isRoomPrivate: Bool, isKnockingOnly: Bool, userIDs: [String], avatarURL: URL?) async -> Result { - createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLCallsCount += 1 - createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLReceivedArguments = (name: name, topic: topic, isRoomPrivate: isRoomPrivate, isKnockingOnly: isKnockingOnly, userIDs: userIDs, avatarURL: avatarURL) + func createRoom(name: String, topic: String?, isRoomPrivate: Bool, isKnockingOnly: Bool, userIDs: [String], avatarURL: URL?, aliasLocalPart: String?) async -> Result { + createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartCallsCount += 1 + createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartReceivedArguments = (name: name, topic: topic, isRoomPrivate: isRoomPrivate, isKnockingOnly: isKnockingOnly, userIDs: userIDs, avatarURL: avatarURL, aliasLocalPart: aliasLocalPart) DispatchQueue.main.async { - self.createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLReceivedInvocations.append((name: name, topic: topic, isRoomPrivate: isRoomPrivate, isKnockingOnly: isKnockingOnly, userIDs: userIDs, avatarURL: avatarURL)) + self.createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartReceivedInvocations.append((name: name, topic: topic, isRoomPrivate: isRoomPrivate, isKnockingOnly: isKnockingOnly, userIDs: userIDs, avatarURL: avatarURL, aliasLocalPart: aliasLocalPart)) } - if let createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLClosure = createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLClosure { - return await createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLClosure(name, topic, isRoomPrivate, isKnockingOnly, userIDs, avatarURL) + if let createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartClosure = createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartClosure { + return await createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartClosure(name, topic, isRoomPrivate, isKnockingOnly, userIDs, avatarURL, aliasLocalPart) } else { - return createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLReturnValue + return createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartReturnValue } } //MARK: - joinRoom @@ -3973,6 +3973,76 @@ class ClientProxyMock: ClientProxyProtocol { return resolveRoomAliasReturnValue } } + //MARK: - isAliasAvailable + + var isAliasAvailableUnderlyingCallsCount = 0 + var isAliasAvailableCallsCount: Int { + get { + if Thread.isMainThread { + return isAliasAvailableUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = isAliasAvailableUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + isAliasAvailableUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + isAliasAvailableUnderlyingCallsCount = newValue + } + } + } + } + var isAliasAvailableCalled: Bool { + return isAliasAvailableCallsCount > 0 + } + var isAliasAvailableReceivedAlias: String? + var isAliasAvailableReceivedInvocations: [String] = [] + + var isAliasAvailableUnderlyingReturnValue: Result! + var isAliasAvailableReturnValue: Result! { + get { + if Thread.isMainThread { + return isAliasAvailableUnderlyingReturnValue + } else { + var returnValue: Result? = nil + DispatchQueue.main.sync { + returnValue = isAliasAvailableUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + isAliasAvailableUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + isAliasAvailableUnderlyingReturnValue = newValue + } + } + } + } + var isAliasAvailableClosure: ((String) async -> Result)? + + func isAliasAvailable(_ alias: String) async -> Result { + isAliasAvailableCallsCount += 1 + isAliasAvailableReceivedAlias = alias + DispatchQueue.main.async { + self.isAliasAvailableReceivedInvocations.append(alias) + } + if let isAliasAvailableClosure = isAliasAvailableClosure { + return await isAliasAvailableClosure(alias) + } else { + return isAliasAvailableReturnValue + } + } //MARK: - getElementWellKnown var getElementWellKnownUnderlyingCallsCount = 0 diff --git a/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift b/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift index 44cefd052c..d225589bec 100644 --- a/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift +++ b/ElementX/Sources/Screens/CreateRoom/CreateRoomModels.swift @@ -25,20 +25,32 @@ enum CreateRoomViewModelAction { } struct CreateRoomViewState: BindableState { + var roomName: String + let serverName: String let isKnockingFeatureEnabled: Bool var selectedUsers: [UserProfileProxy] + var aliasLocalPart: String var bindings: CreateRoomViewStateBindings var avatarURL: URL? var canCreateRoom: Bool { - !bindings.roomName.isEmpty + !roomName.isEmpty && aliasErrors.isEmpty + } + + var aliasErrors: Set = [] + var aliasErrorDescription: String? { + if aliasErrors.contains(.alreadyExists) { + return L10n.screenCreateRoomRoomAddressNotAvailableErrorDescription + } else if aliasErrors.contains(.invalidSymbols) { + return L10n.screenCreateRoomRoomAddressInvalidSymbolsErrorDescription + } + return nil } } struct CreateRoomViewStateBindings { - var roomName: String var roomTopic: String var isRoomPrivate: Bool - var isKnockingOnly = false + var isKnockingOnly: Bool var showAttachmentConfirmationDialog = false /// Information describing the currently displayed alert. @@ -51,4 +63,11 @@ enum CreateRoomViewAction { case displayCameraPicker case displayMediaPicker case removeImage + case updateRoomName(String) + case updateAliasLocalPart(String) +} + +enum CreateRoomAliasErrorState { + case alreadyExists + case invalidSymbols } diff --git a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift index da70c7afb2..31e40fd5d6 100644 --- a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift +++ b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift @@ -6,6 +6,7 @@ // import Combine +import MatrixRustSDK import SwiftUI typealias CreateRoomViewModelType = StateStoreViewModel @@ -15,6 +16,8 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol private var createRoomParameters: CreateRoomFlowParameters private let analytics: AnalyticsService private let userIndicatorController: UserIndicatorControllerProtocol + private var syncNameAndAlias = true + @CancellableTask private var checkAliasAvailabilityTask: Task? private var actionsSubject: PassthroughSubject = .init() @@ -35,9 +38,17 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol self.analytics = analytics self.userIndicatorController = userIndicatorController - let bindings = CreateRoomViewStateBindings(roomName: parameters.name, roomTopic: parameters.topic, isRoomPrivate: parameters.isRoomPrivate) + let bindings = CreateRoomViewStateBindings(roomTopic: parameters.topic, + isRoomPrivate: parameters.isRoomPrivate, + isKnockingOnly: appSettings.knockingEnabled ? parameters.isKnockingOnly : false) - super.init(initialViewState: CreateRoomViewState(isKnockingFeatureEnabled: appSettings.knockingEnabled, selectedUsers: selectedUsers.value, bindings: bindings), mediaProvider: userSession.mediaProvider) + super.init(initialViewState: CreateRoomViewState(roomName: parameters.name, + serverName: userSession.clientProxy.userIDServerName ?? "", + isKnockingFeatureEnabled: appSettings.knockingEnabled, + selectedUsers: selectedUsers.value, + aliasLocalPart: parameters.aliasLocalPart ?? roomAliasNameFromRoomDisplayName(roomName: parameters.name), + bindings: bindings), + mediaProvider: userSession.mediaProvider) createRoomParameters .map(\.avatarImageMedia) @@ -80,31 +91,111 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol actionsSubject.send(.displayMediaPicker) case .removeImage: actionsSubject.send(.removeImage) + case .updateAliasLocalPart(let aliasLocalPart): + state.aliasLocalPart = aliasLocalPart + // If this has been called this means that the user wants a custom address not necessarily reflecting the name + // So we disable the two from syncing. + syncNameAndAlias = false + case .updateRoomName(let name): + // Reset the syncing if the name is fully cancelled + if name.isEmpty { + syncNameAndAlias = true + } + state.roomName = name + if syncNameAndAlias { + state.aliasLocalPart = roomAliasNameFromRoomDisplayName(roomName: name) + } } } // MARK: - Private private func setupBindings() { + // Reset the state related to public rooms if the user choses the room to be empty + context.$viewState + .dropFirst() + .map(\.bindings.isRoomPrivate) + .removeDuplicates() + .filter { $0 } + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in + guard let self else { return } + state.bindings.isKnockingOnly = false + state.aliasErrors = [] + state.aliasLocalPart = roomAliasNameFromRoomDisplayName(roomName: state.roomName) + syncNameAndAlias = true + } + .store(in: &cancellables) + context.$viewState - .map(\.bindings) .throttle(for: 0.5, scheduler: DispatchQueue.main, latest: true) .removeDuplicates { old, new in - old.roomName == new.roomName && old.roomTopic == new.roomTopic && old.isRoomPrivate == new.isRoomPrivate + old.roomName == new.roomName && + old.bindings.roomTopic == new.bindings.roomTopic && + old.bindings.isRoomPrivate == new.bindings.isRoomPrivate && + old.bindings.isKnockingOnly == new.bindings.isKnockingOnly && + old.aliasLocalPart == new.aliasLocalPart } - .sink { [weak self] bindings in + .sink { [weak self] state in guard let self else { return } - updateParameters(bindings: bindings) + updateParameters(state: state) actionsSubject.send(.updateDetails(createRoomParameters)) } .store(in: &cancellables) + + context.$viewState + .map(\.aliasLocalPart) + .removeDuplicates() + .debounce(for: 1, scheduler: DispatchQueue.main) + .sink { [weak self] aliasLocalPart in + guard let self else { + return + } + + guard state.isKnockingFeatureEnabled, + !state.bindings.isRoomPrivate, + let canonicalAlias = canonicalAlias(aliasLocalPart: aliasLocalPart) else { + // While is empty or private room we don't change or display the error + return + } + + if !isRoomAliasFormatValid(alias: canonicalAlias) { + state.aliasErrors.insert(.invalidSymbols) + // If the alias is invalid we don't need to check for availability + state.aliasErrors.remove(.alreadyExists) + checkAliasAvailabilityTask = nil + return + } + + state.aliasErrors.remove(.invalidSymbols) + + checkAliasAvailabilityTask = Task { [weak self] in + guard let self else { + return + } + + if case .success(false) = await self.userSession.clientProxy.isAliasAvailable(canonicalAlias) { + guard !Task.isCancelled else { return } + state.aliasErrors.insert(.alreadyExists) + } else { + guard !Task.isCancelled else { return } + state.aliasErrors.remove(.alreadyExists) + } + } + } + .store(in: &cancellables) } - private func updateParameters(bindings: CreateRoomViewStateBindings) { - createRoomParameters.name = bindings.roomName - createRoomParameters.topic = bindings.roomTopic - createRoomParameters.isRoomPrivate = bindings.isRoomPrivate - createRoomParameters.isKnockingOnly = bindings.isKnockingOnly + private func updateParameters(state: CreateRoomViewState) { + createRoomParameters.name = state.roomName + createRoomParameters.topic = state.bindings.roomTopic + createRoomParameters.isRoomPrivate = state.bindings.isRoomPrivate + createRoomParameters.isKnockingOnly = state.bindings.isKnockingOnly + if state.isKnockingFeatureEnabled, !state.aliasLocalPart.isEmpty { + createRoomParameters.aliasLocalPart = state.aliasLocalPart + } else { + createRoomParameters.aliasLocalPart = nil + } } private func createRoom() async { @@ -114,7 +205,28 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol showLoadingIndicator() // Since the parameters are throttled, we need to make sure that the latest values are used - updateParameters(bindings: state.bindings) + updateParameters(state: state) + + // Better to double check the errors also when trying to create the room + if state.isKnockingFeatureEnabled, !createRoomParameters.isRoomPrivate { + guard let canonicalAlias = canonicalAlias(aliasLocalPart: createRoomParameters.aliasLocalPart), + isRoomAliasFormatValid(alias: canonicalAlias) else { + state.aliasErrors = [.invalidSymbols] + return + } + + switch await userSession.clientProxy.isAliasAvailable(canonicalAlias) { + case .success(true): + break + case .success(false): + state.aliasErrors = [.alreadyExists] + return + case .failure: + state.bindings.alertInfo = AlertInfo(id: .unknown) + return + } + } + let avatarURL: URL? if let media = createRoomParameters.avatarImageMedia { switch await userSession.clientProxy.uploadMedia(media) { @@ -147,7 +259,8 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol // As of right now we don't want to make private rooms with the knock rule isKnockingOnly: createRoomParameters.isRoomPrivate ? false : createRoomParameters.isKnockingOnly, userIDs: state.selectedUsers.map(\.userID), - avatarURL: avatarURL) { + avatarURL: avatarURL, + aliasLocalPart: createRoomParameters.isRoomPrivate ? nil : createRoomParameters.aliasLocalPart) { case .success(let roomId): analytics.trackCreatedRoom(isDM: false) actionsSubject.send(.openRoom(withIdentifier: roomId)) @@ -158,6 +271,14 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol } } + func canonicalAlias(aliasLocalPart: String?) -> String? { + guard let aliasLocalPart, + !aliasLocalPart.isEmpty else { + return nil + } + return "#\(aliasLocalPart):\(state.serverName)" + } + // MARK: Loading indicator private static let loadingIndicatorIdentifier = "\(CreateRoomViewModel.self)-Loading" diff --git a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift index 726cf99f0e..be52464a9f 100644 --- a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift +++ b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift @@ -16,7 +16,23 @@ struct CreateRoomScreen: View { case name case topic } - + + private var aliasBinding: Binding { + .init(get: { + context.viewState.aliasLocalPart + }, set: { + context.send(viewAction: .updateAliasLocalPart($0)) + }) + } + + private var roomNameBinding: Binding { + .init(get: { + context.viewState.roomName + }, set: { + context.send(viewAction: .updateRoomName($0)) + }) + } + var body: some View { Form { roomSection @@ -25,6 +41,7 @@ struct CreateRoomScreen: View { if context.viewState.isKnockingFeatureEnabled, !context.isRoomPrivate { roomAccessSection + roomAliasSection } } .compoundList() @@ -48,7 +65,7 @@ struct CreateRoomScreen: View { .compoundListSectionHeader() TextField(L10n.screenCreateRoomRoomNameLabel, - text: $context.roomName, + text: roomNameBinding, prompt: Text(L10n.commonRoomNamePlaceholder).foregroundColor(.compound.textPlaceholder), axis: .horizontal) .focused($focus, equals: .name) @@ -150,22 +167,62 @@ struct CreateRoomScreen: View { iconAlignment: .top), kind: .selection(isSelected: !context.isRoomPrivate) { context.isRoomPrivate = false }) } header: { - Text(L10n.commonSecurity.uppercased()) + Text(L10n.screenCreateRoomRoomVisibilitySectionTitle) .compoundListSectionHeader() } } private var roomAccessSection: some View { Section { - ListRow(label: .plain(title: L10n.screenCreateRoomAccessSectionAnyoneOptionTitle, - description: L10n.screenCreateRoomAccessSectionAnyoneOptionDescription), + ListRow(label: .plain(title: L10n.screenCreateRoomRoomAccessSectionAnyoneOptionTitle, + description: L10n.screenCreateRoomRoomAccessSectionAnyoneOptionDescription), kind: .selection(isSelected: !context.isKnockingOnly) { context.isKnockingOnly = false }) - ListRow(label: .plain(title: L10n.screenCreateRoomAccessSectionKnockingOptionTitle, - description: L10n.screenCreateRoomAccessSectionKnockingOptionDescription), + ListRow(label: .plain(title: L10n.screenCreateRoomRoomAccessSectionKnockingOptionTitle, + description: L10n.screenCreateRoomRoomAccessSectionKnockingOptionDescription), kind: .selection(isSelected: context.isKnockingOnly) { context.isKnockingOnly = true }) } header: { - Text(L10n.screenCreateRoomAccessSectionHeader.uppercased()) + Text(L10n.screenCreateRoomRoomAccessSectionHeader) + .compoundListSectionHeader() + } + } + + private var roomAliasSection: some View { + Section { + ListRow(kind: .custom { + HStack(spacing: 0) { + Text("#") + .font(.compound.bodyLG) + .foregroundStyle(.compound.textSecondary) + + TextField("", text: aliasBinding) + .autocapitalization(.none) + .textCase(.lowercase) + .tint(.compound.iconAccentTertiary) + .font(.compound.bodyLG) + .foregroundStyle(.compound.textPrimary) + .padding(.horizontal, 8) + Text(":\(context.viewState.serverName)") + .font(.compound.bodyLG) + .foregroundStyle(.compound.textSecondary) + } + .padding(ListRowPadding.textFieldInsets) + .environment(\.layoutDirection, .leftToRight) + .errorBackground(!context.viewState.aliasErrors.isEmpty) + }) + } header: { + Text(L10n.screenCreateRoomRoomAddressSectionTitle) .compoundListSectionHeader() + } footer: { + VStack(alignment: .leading, spacing: 12) { + if let errorDescription = context.viewState.aliasErrorDescription { + Label(errorDescription, icon: \.error, iconSize: .xSmall, relativeTo: .compound.bodySM) + .foregroundStyle(.compound.textCriticalPrimary) + .font(.compound.bodySM) + } + Text(L10n.screenCreateRoomRoomAddressSectionFooter) + .compoundListSectionFooter() + .font(.compound.bodySM) + } } } @@ -180,6 +237,15 @@ struct CreateRoomScreen: View { } } +private extension View { + func errorBackground(_ shouldDisplay: Bool) -> some View { + listRowBackground(shouldDisplay ? AnyView(RoundedRectangle(cornerRadius: 10) + .inset(by: 1) + .fill(.compound.bgCriticalSubtleHovered) + .stroke(Color.compound.borderCriticalPrimary)) : AnyView(Color.compound.bgCanvasDefaultLevel1)) + } +} + // MARK: - Previews struct CreateRoom_Previews: PreviewProvider, TestablePreview { @@ -208,7 +274,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview { }() static let publicRoomViewModel = { - let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com")))) + let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "example.org", userID: "@userid:example.com")))) let parameters = CreateRoomFlowParameters(isRoomPrivate: false) let selectedUsers: [UserProfileProxy] = [.mockAlice, .mockBob, .mockCharlie] ServiceLocator.shared.settings.knockingEnabled = true @@ -220,6 +286,32 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview { appSettings: ServiceLocator.shared.settings) }() + static let publicRoomInvalidAliasViewModel = { + let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "example.org", userID: "@userid:example.com")))) + let parameters = CreateRoomFlowParameters(isRoomPrivate: false, aliasLocalPart: "#:") + ServiceLocator.shared.settings.knockingEnabled = true + return CreateRoomViewModel(userSession: userSession, + createRoomParameters: .init(parameters), + selectedUsers: .init([]), + analytics: ServiceLocator.shared.analytics, + userIndicatorController: UserIndicatorControllerMock(), + appSettings: ServiceLocator.shared.settings) + }() + + static let publicRoomExistingAliasViewModel = { + let clientProxy = ClientProxyMock(.init(userIDServerName: "example.org", userID: "@userid:example.com")) + clientProxy.isAliasAvailableReturnValue = .success(false) + let userSession = UserSessionMock(.init(clientProxy: clientProxy)) + let parameters = CreateRoomFlowParameters(isRoomPrivate: false, aliasLocalPart: "existing") + ServiceLocator.shared.settings.knockingEnabled = true + return CreateRoomViewModel(userSession: userSession, + createRoomParameters: .init(parameters), + selectedUsers: .init([]), + analytics: ServiceLocator.shared.analytics, + userIndicatorController: UserIndicatorControllerMock(), + appSettings: ServiceLocator.shared.settings) + }() + static var previews: some View { NavigationStack { CreateRoomScreen(context: viewModel.context) @@ -233,5 +325,15 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview { CreateRoomScreen(context: publicRoomViewModel.context) } .previewDisplayName("Create Public Room") + NavigationStack { + CreateRoomScreen(context: publicRoomInvalidAliasViewModel.context) + } + .snapshotPreferences(delay: 1.5) + .previewDisplayName("Create Public Room, invalid alias") + NavigationStack { + CreateRoomScreen(context: publicRoomExistingAliasViewModel.context) + } + .snapshotPreferences(delay: 1.5) + .previewDisplayName("Create Public Room, existing alias") } } diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift index acd39bd180..51314243eb 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift @@ -239,13 +239,13 @@ struct SecureBackupRecoveryKeyScreen_Previews: PreviewProvider, TestablePreview SecureBackupRecoveryKeyScreen(context: generatingViewModel.context) } .previewDisplayName("Generating") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) NavigationStack { SecureBackupRecoveryKeyScreen(context: setupViewModel.context) } .previewDisplayName("Set up") - .snapshot(delay: 0.25) + .snapshotPreferences(delay: 0.25) NavigationStack { SecureBackupRecoveryKeyScreen(context: incompleteViewModel.context) diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 801ce4e8cb..8516ab0211 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -67,6 +67,22 @@ class ClientProxy: ClientProxyProtocol { "org.matrix.msc3401.call.member": Int32(0) ]) } + + private static var knockingRoomCreationPowerLevelOverrides: PowerLevels { + .init(usersDefault: nil, + eventsDefault: nil, + stateDefault: nil, + ban: nil, + kick: nil, + redact: nil, + invite: Int32(50), + notifications: nil, + users: [:], + events: [ + "m.call.member": Int32(0), + "org.matrix.msc3401.call.member": Int32(0) + ]) + } private var loadCachedAvatarURLTask: Task? private let userAvatarURLSubject = CurrentValueSubject(nil) @@ -377,9 +393,14 @@ class ClientProxy: ClientProxyProtocol { } // swiftlint:disable:next function_parameter_count - func createRoom(name: String, topic: String?, isRoomPrivate: Bool, isKnockingOnly: Bool, userIDs: [String], avatarURL: URL?) async -> Result { + func createRoom(name: String, + topic: String?, + isRoomPrivate: Bool, + isKnockingOnly: Bool, + userIDs: [String], + avatarURL: URL?, + aliasLocalPart: String?) async -> Result { do { - // TODO: Revisit once the SDK supports the knocking API let parameters = CreateRoomParameters(name: name, topic: topic, isEncrypted: isRoomPrivate, @@ -388,7 +409,9 @@ class ClientProxy: ClientProxyProtocol { preset: isRoomPrivate ? .privateChat : .publicChat, invite: userIDs, avatar: avatarURL?.absoluteString, - powerLevelContentOverride: Self.roomCreationPowerLevelOverrides) + powerLevelContentOverride: isKnockingOnly ? Self.knockingRoomCreationPowerLevelOverrides : Self.roomCreationPowerLevelOverrides, + // This is an FFI naming mistake, what is required is the `aliasLocalPart` not the whole alias + canonicalAlias: aliasLocalPart) let roomID = try await client.createRoom(request: parameters) await waitForRoomToSync(roomID: roomID) @@ -626,6 +649,7 @@ class ClientProxy: ClientProxyProtocol { func resolveRoomAlias(_ alias: String) async -> Result { do { guard let resolvedAlias = try await client.resolveRoomAlias(roomAlias: alias) else { + MXLog.error("Failed resolving room alias, is nil") return .failure(.failedResolvingRoomAlias) } @@ -641,6 +665,16 @@ class ClientProxy: ClientProxyProtocol { } } + func isAliasAvailable(_ alias: String) async -> Result { + do { + let result = try await client.isRoomAliasAvailable(alias: alias) + return .success(result) + } catch { + MXLog.error("Failed checking if alias: \(alias) is available with error: \(error)") + return .failure(.sdkError(error)) + } + } + func getElementWellKnown() async -> Result { await client.getElementWellKnown().map(ElementWellKnown.init) } diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index 85bd4f7adf..0feae1793e 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -88,7 +88,7 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { var deviceID: String? { get } var homeserver: String { get } - + var slidingSyncVersion: SlidingSyncVersion { get } var availableSlidingSyncVersions: [SlidingSyncVersion] { get async } @@ -133,7 +133,13 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { func createDirectRoom(with userID: String, expectedRoomName: String?) async -> Result // swiftlint:disable:next function_parameter_count - func createRoom(name: String, topic: String?, isRoomPrivate: Bool, isKnockingOnly: Bool, userIDs: [String], avatarURL: URL?) async -> Result + func createRoom(name: String, + topic: String?, + isRoomPrivate: Bool, + isKnockingOnly: Bool, + userIDs: [String], + avatarURL: URL?, + aliasLocalPart: String?) async -> Result func joinRoom(_ roomID: String, via: [String]) async -> Result @@ -173,6 +179,8 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { func resolveRoomAlias(_ alias: String) async -> Result + func isAliasAvailable(_ alias: String) async -> Result + func getElementWellKnown() async -> Result // MARK: - Ignored users diff --git a/ElementX/Sources/Services/CreateRoom/CreateRoomFlowParameters.swift b/ElementX/Sources/Services/CreateRoom/CreateRoomFlowParameters.swift index d2e03d96dd..736e99c4b3 100644 --- a/ElementX/Sources/Services/CreateRoom/CreateRoomFlowParameters.swift +++ b/ElementX/Sources/Services/CreateRoom/CreateRoomFlowParameters.swift @@ -14,4 +14,5 @@ struct CreateRoomFlowParameters { var isRoomPrivate = true var isKnockingOnly = false var avatarImageMedia: MediaInfo? + var aliasLocalPart: String? } diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png new file mode 100644 index 0000000000..a048c452d3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9650c6b430799996d02b0d34cf9d8657c94a5b5627dde3cb74755b5020619cf6 +size 202009 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-invalid-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-invalid-alias.png new file mode 100644 index 0000000000..8ce2cc596c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-invalid-alias.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7563d6820945006a48db647fed692d4458338d63669ea4c344052f5a63a4a2ee +size 204578 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room.png index dd7544c1ee..93564aa4d5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3a984e4fc4d1aade45c5e8b98dcba2f1ecc0e50965e2ca64ad6faad777de26c -size 172668 +oid sha256:6f630b2ae196d0f8d9b98b68482863ea78aa84eb5e9b82e78d77430ec81dc007 +size 194309 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png index 57d2a78428..107a06bd65 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49a518ac1fe0ffd8719d757b5c5f2decde92b237937f68df15a239c228cf24b8 -size 144080 +oid sha256:860a4367f4ab161be805df36b2723829e023db753c45f9f49ecc126f6a2cc128 +size 145345 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png index 6c198b387e..c06ac05586 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:467d13af04d60db15fb1586df63b7589a59ae6f2cb4c7482b79cc0c56d7af0ce -size 143822 +oid sha256:b0a28cc070627724c44111ee0736006650e1453d85be6038783073d911f3d909 +size 144730 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-existing-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-existing-alias.png new file mode 100644 index 0000000000..35ad913994 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-existing-alias.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f255ed8f26b1f9efd108b7b0422262185f45152495727578822fb0691bfe08a9 +size 228341 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-invalid-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-invalid-alias.png new file mode 100644 index 0000000000..8b49055f95 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-invalid-alias.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b42242042ad3adf3b953a29ff58792511076930892a7bda4d813b3e3218f39e0 +size 226407 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room.png index 2bb300bfb9..e383e0a7ce 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f493e2b0a85be6d277f7138a11f0f02510b04df3fc22a8c76391fbc3444abd0 -size 208736 +oid sha256:a6f47df77fca87c83e7668b95a500c5b7d0a0640d694a7b92c58365573d0abd6 +size 224351 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png index d4accf96e4..8ca3e931d6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c03a493641d0f7c21680bec4ccea98428f210d642011feb3d61988aa09af2612 -size 168502 +oid sha256:b9311de66c92307e15ac5d62c025c953d20ce42e946eaaab30604f754ce6d395 +size 171925 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png index 927c1e3d61..800e0982e7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b8555d5ddea49cf85fc2fc9cb8981f9453f30152f8befc4d596358a7c79f63d -size 169943 +oid sha256:662701144b88061103f80d08c078a28ca918e768e4907e4100fd56941098acfa +size 173078 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png new file mode 100644 index 0000000000..5c280a5838 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:acf39359c47be4101e19fe3d0bfcedb7f0a262b418f3ab3f90da38c9ad3b88f0 +size 130131 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png new file mode 100644 index 0000000000..5d536e0a57 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66610bab01ad7ed399d8c4f72fd8d04990eafbf911c8b666c3ca21beba88a58b +size 128602 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png index 53af40f6dd..8f0fea0f9b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f54b4053b937e1fc6cee22dfff905bead3ccfbd45bf6607fb8492c74dda15fd -size 118717 +oid sha256:311d57b9b2cc2ad3b459c5817e6dd605740abef4559b571492de22a81b160285 +size 126941 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png index 9280f48615..3e986cdcbb 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:133221a0b8d4b9aed307a19043b323ca99c3cf639b2097c3713209c6c69c70e5 -size 94718 +oid sha256:d637d85d789f0d3d8756719f0b277a23b07730a21d46fe599afdb4b1143ce814 +size 95980 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png index 9699119670..215efe85a6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c99bf8cd5ba59b6343a3e61af3f2b45ebbe3cab0dda38ef6aa45750b7c13558 -size 94927 +oid sha256:c89527ca06fb7a7b03cb6bb2feda23cd9325e98378eecc364f537c29d6878b08 +size 96262 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png new file mode 100644 index 0000000000..96122c7846 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d191b67a8b246e26c7567427f09cd7562fc88402b06a150212a74eb55fb58831 +size 164266 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png new file mode 100644 index 0000000000..96122c7846 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d191b67a8b246e26c7567427f09cd7562fc88402b06a150212a74eb55fb58831 +size 164266 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png index cfb427967f..96122c7846 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2155e204f2bf31a62cc09e3656e77fa58ee327a1ba37de0a307ba7e4fdd9a836 -size 162088 +oid sha256:d191b67a8b246e26c7567427f09cd7562fc88402b06a150212a74eb55fb58831 +size 164266 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png index 6848b26ade..ebeef4fda4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:608dbe5519a764e6a9dd8c1d909b5d53ec969d34a03251cdedaabdc1508d661a -size 124622 +oid sha256:61ca01f8203d3c668ca2183f46d2954a32284624c8b7caaffd37124e2d454997 +size 126803 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png index 20411e7c1c..89c4aae8fa 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f5dd8e86929e05e9a30b27fe8895668246da009696ac614f8f4fbf4bf78d0d8 -size 125070 +oid sha256:ab43faa0b020b9628d10999a93d9c70e90e007eb788ce9a14eaca5330b9c5843 +size 127313 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Set-up.png index ebbd6a69f3..02ab29e321 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Set-up.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-en-GB.Set-up.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b4eb7771b9156b75c3812751b1219ba337e4d9b1b465dedd09e7784b1f009e9 -size 120296 +oid sha256:02851bc8304737c8eee1ea76ddee133ec47feb49e0471b8e6c1213696851e6e4 +size 140058 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Set-up.png index 37f1a320a7..83bba7ef50 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Set-up.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPad-pseudo.Set-up.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e80a71b9eaeb41bd700cf22e98b0290c06e6786cdffea72c0973549b4ba5bd43 -size 141940 +oid sha256:b694da58f6895e51248e8368a2baf1f7b9c4eef3119533ea2eca3c13407412d5 +size 171446 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Set-up.png index 8d002a493b..49cd7a983f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Set-up.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-en-GB.Set-up.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:872d515fe6aae36c12d21a3e6757abcddf9e03e51e6421324505a528b5946376 -size 74557 +oid sha256:bb8bc4cd519ee62becb550537da7bf15566b178330101c21c839d9d93bbd34ed +size 95875 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Set-up.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Set-up.png index 09ee043125..7c5fb0f79c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Set-up.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen-iPhone-16-pseudo.Set-up.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88b07c92a3f9763eb361918da508af0e140bce7241ebbc92c38f3ac38cc9394d -size 100293 +oid sha256:8db80a8ad96649272dac60a2a95aade580a6b5b09cbb79c49e81d210d41b4f0c +size 121490 diff --git a/UnitTests/Sources/CreateRoomViewModelTests.swift b/UnitTests/Sources/CreateRoomViewModelTests.swift index b145dfbfd9..110d788468 100644 --- a/UnitTests/Sources/CreateRoomViewModelTests.swift +++ b/UnitTests/Sources/CreateRoomViewModelTests.swift @@ -25,7 +25,7 @@ class CreateRoomScreenViewModelTests: XCTestCase { override func setUpWithError() throws { cancellables.removeAll() - clientProxy = ClientProxyMock(.init(userID: "@a:b.com")) + clientProxy = ClientProxyMock(.init(userIDServerName: "matrix.org", userID: "@a:b.com")) userSession = UserSessionMock(.init(clientProxy: clientProxy)) let parameters = CreateRoomFlowParameters() usersSubject.send([.mockAlice, .mockBob, .mockCharlie]) @@ -68,21 +68,25 @@ class CreateRoomScreenViewModelTests: XCTestCase { func testCreateRoomRequirements() { XCTAssertFalse(context.viewState.canCreateRoom) - context.roomName = "A" + context.send(viewAction: .updateRoomName("A")) XCTAssertTrue(context.viewState.canCreateRoom) } func testCreateKnockingRoom() async { - context.roomName = "A" + context.send(viewAction: .updateRoomName("A")) context.roomTopic = "B" context.isRoomPrivate = false + // When setting the room as private we always reset the knocking state to the default value of false + // so we need to wait a main actor cycle to ensure the view state is updated + await Task.yield() context.isKnockingOnly = true XCTAssertTrue(context.viewState.canCreateRoom) let expectation = expectation(description: "Wait for the room to be created") - clientProxy.createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLClosure = { _, _, isPrivate, isKnockingOnly, _, _ in + clientProxy.createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartClosure = { _, _, isPrivate, isKnockingOnly, _, _, localAliasPart in XCTAssertTrue(isKnockingOnly) XCTAssertFalse(isPrivate) + XCTAssertEqual(localAliasPart, "a") defer { expectation.fulfill() } return .success("") } @@ -90,14 +94,67 @@ class CreateRoomScreenViewModelTests: XCTestCase { await fulfillment(of: [expectation]) } + func testCreatePublicRoomFailsForInvalidAlias() async throws { + context.send(viewAction: .updateRoomName("A")) + context.roomTopic = "B" + context.isRoomPrivate = false + // When setting the room as private we always reset the alias + // so we need to wait a main actor cycle to ensure the view state is updated + await Task.yield() + + // we wait for the debounce to show the error + let deferred = deferFulfillment(context.$viewState) { viewState in + viewState.aliasErrors.contains(.invalidSymbols) && !viewState.canCreateRoom + } + context.send(viewAction: .updateAliasLocalPart("#:")) + try await deferred.fulfill() + + // We also want to force the room creation in case the user may tap the button before the debounce + // blocked it + context.send(viewAction: .createRoom) + await Task.yield() + XCTAssertFalse(clientProxy.createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartCalled) + } + + func testCreatePublicRoomFailsForExistingAlias() async throws { + clientProxy.isAliasAvailableReturnValue = .success(false) + context.send(viewAction: .updateRoomName("A")) + context.roomTopic = "B" + context.isRoomPrivate = false + // When setting the room as private we always reset the alias + // so we need to wait a main actor cycle to ensure the view state is updated + await Task.yield() + + // we wait for the debounce to show the error + let deferred = deferFulfillment(context.$viewState) { viewState in + viewState.aliasErrors.contains(.alreadyExists) && !viewState.canCreateRoom + } + context.send(viewAction: .updateAliasLocalPart("abc")) + try await deferred.fulfill() + + // We also want to force the room creation in case the user may tap the button before the debounce + // blocked it + let expectation = expectation(description: "Wait for the alias to be checked again") + clientProxy.isAliasAvailableClosure = { _ in + defer { + expectation.fulfill() + } + return .success(false) + } + context.send(viewAction: .createRoom) + await fulfillment(of: [expectation]) + XCTAssertEqual(clientProxy.isAliasAvailableCallsCount, 2) + XCTAssertFalse(clientProxy.createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartCalled) + } + func testCreatePrivateRoomCantHaveKnockRule() async { - context.roomName = "A" + context.send(viewAction: .updateRoomName("A")) context.roomTopic = "B" context.isRoomPrivate = true context.isKnockingOnly = true context.send(viewAction: .createRoom) let expectation = expectation(description: "Wait for the room to be created") - clientProxy.createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLClosure = { _, _, isPrivate, isKnockingOnly, _, _ in + clientProxy.createRoomNameTopicIsRoomPrivateIsKnockingOnlyUserIDsAvatarURLAliasLocalPartClosure = { _, _, isPrivate, isKnockingOnly, _, _, _ in XCTAssertFalse(isKnockingOnly) XCTAssertTrue(isPrivate) expectation.fulfill() @@ -105,4 +162,35 @@ class CreateRoomScreenViewModelTests: XCTestCase { } await fulfillment(of: [expectation]) } + + func testNameAndAddressSync() async { + context.isRoomPrivate = true + await Task.yield() + context.send(viewAction: .updateRoomName("abc")) + XCTAssertEqual(context.viewState.aliasLocalPart, "abc") + XCTAssertEqual(context.viewState.roomName, "abc") + context.send(viewAction: .updateRoomName("DEF")) + XCTAssertEqual(context.viewState.roomName, "DEF") + XCTAssertEqual(context.viewState.aliasLocalPart, "def") + context.send(viewAction: .updateRoomName("a b c")) + XCTAssertEqual(context.viewState.aliasLocalPart, "a-b-c") + XCTAssertEqual(context.viewState.roomName, "a b c") + context.send(viewAction: .updateAliasLocalPart("hello-world")) + // This removes the sync + XCTAssertEqual(context.viewState.aliasLocalPart, "hello-world") + XCTAssertEqual(context.viewState.roomName, "a b c") + + context.send(viewAction: .updateRoomName("Hello Matrix!")) + XCTAssertEqual(context.viewState.aliasLocalPart, "hello-world") + XCTAssertEqual(context.viewState.roomName, "Hello Matrix!") + + // Deleting the whole name will restore the sync + context.send(viewAction: .updateRoomName("")) + XCTAssertEqual(context.viewState.aliasLocalPart, "") + XCTAssertEqual(context.viewState.roomName, "") + + context.send(viewAction: .updateRoomName("Hello# Matrix!")) + XCTAssertEqual(context.viewState.aliasLocalPart, "hello-matrix!") + XCTAssertEqual(context.viewState.roomName, "Hello# Matrix!") + } } diff --git a/project.yml b/project.yml index 5eb74d64fa..649c0bf736 100644 --- a/project.yml +++ b/project.yml @@ -60,7 +60,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.65 + exactVersion: 1.0.66 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From c9aeebca2d7e8276e54b48e2c0f0fd55b52eec50 Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Fri, 8 Nov 2024 17:55:32 +0100 Subject: [PATCH 06/74] Fix for creating a knocking room (#3499) * fix for join rule override in knocking rooms. * improved some copies --- .../Localizations/en.lproj/Localizable.strings | 8 ++++++-- ElementX/Sources/Generated/Strings.swift | 12 ++++++++++-- ElementX/Sources/Services/Client/ClientProxy.swift | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 23b47f1e3c..3b8b01bc05 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -849,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "They don’t match"; "screen_session_verification_they_match" = "They match"; +"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_waiting_to_accept_subtitle" = "Accept the request to start the verification process in your other session to continue."; "screen_session_verification_waiting_to_accept_title" = "Waiting to accept request"; "screen_share_location_title" = "Share location"; @@ -913,8 +917,8 @@ "state_event_room_invite_you" = "%1$@ invited you"; "state_event_room_join" = "%1$@ joined the room"; "state_event_room_join_by_you" = "You joined the room"; -"state_event_room_knock" = "%1$@ requested to join"; -"state_event_room_knock_accepted" = "%1$@ allowed %2$@ to join"; +"state_event_room_knock" = "%1$@ is requesting to join"; +"state_event_room_knock_accepted" = "%1$@ granted access to %2$@"; "state_event_room_knock_accepted_by_you" = "You allowed %1$@ to join"; "state_event_room_knock_by_you" = "You requested to join"; "state_event_room_knock_denied" = "%1$@ rejected %2$@'s request to join"; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index f807da0708..fa25268816 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -2082,6 +2082,14 @@ internal enum L10n { internal static var screenSessionVerificationTheyDontMatch: String { return L10n.tr("Localizable", "screen_session_verification_they_dont_match") } /// They match internal static var screenSessionVerificationTheyMatch: String { return L10n.tr("Localizable", "screen_session_verification_they_match") } + /// Make sure you have the app open in the other device before starting verification from here. + internal static var screenSessionVerificationUseAnotherDeviceSubtitle: String { return L10n.tr("Localizable", "screen_session_verification_use_another_device_subtitle") } + /// Open the app on another verified device + internal static var screenSessionVerificationUseAnotherDeviceTitle: String { return L10n.tr("Localizable", "screen_session_verification_use_another_device_title") } + /// You should see a popup on the other device. Start the verification from there now. + internal static var screenSessionVerificationWaitingAnotherDeviceSubtitle: String { return L10n.tr("Localizable", "screen_session_verification_waiting_another_device_subtitle") } + /// Start verification on the other device + internal static var screenSessionVerificationWaitingAnotherDeviceTitle: String { return L10n.tr("Localizable", "screen_session_verification_waiting_another_device_title") } /// Accept the request to start the verification process in your other session to continue. internal static var screenSessionVerificationWaitingToAcceptSubtitle: String { return L10n.tr("Localizable", "screen_session_verification_waiting_to_accept_subtitle") } /// Waiting to accept request @@ -2278,11 +2286,11 @@ internal enum L10n { } /// You joined the room internal static var stateEventRoomJoinByYou: String { return L10n.tr("Localizable", "state_event_room_join_by_you") } - /// %1$@ requested to join + /// %1$@ is requesting to join internal static func stateEventRoomKnock(_ p1: Any) -> String { return L10n.tr("Localizable", "state_event_room_knock", String(describing: p1)) } - /// %1$@ allowed %2$@ to join + /// %1$@ granted access to %2$@ internal static func stateEventRoomKnockAccepted(_ p1: Any, _ p2: Any) -> String { return L10n.tr("Localizable", "state_event_room_knock_accepted", String(describing: p1), String(describing: p2)) } diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 8516ab0211..edf8200206 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -410,6 +410,7 @@ class ClientProxy: ClientProxyProtocol { invite: userIDs, avatar: avatarURL?.absoluteString, powerLevelContentOverride: isKnockingOnly ? Self.knockingRoomCreationPowerLevelOverrides : Self.roomCreationPowerLevelOverrides, + joinRuleOverride: isKnockingOnly ? .knock : nil, // This is an FFI naming mistake, what is required is the `aliasLocalPart` not the whole alias canonicalAlias: aliasLocalPart) let roomID = try await client.createRoom(request: parameters) From 814eff28ddffc421b08838464d4f7ae7221b792e Mon Sep 17 00:00:00 2001 From: Velin92 <34335419+Velin92@users.noreply.github.com> Date: Mon, 11 Nov 2024 00:01:49 +0000 Subject: [PATCH 07/74] Translations update --- .../be.lproj/Localizable.strings | 16 +- .../bg.lproj/Localizable.strings | 16 +- .../cs.lproj/Localizable.strings | 36 +- .../de.lproj/Localizable.strings | 16 +- .../el.lproj/Localizable.strings | 16 +- .../es.lproj/Localizable.strings | 16 +- .../et.lproj/Localizable.strings | 18 +- .../fa.lproj/Localizable.strings | 20 +- .../fa.lproj/Localizable.stringsdict | 326 ++++++++++++++++++ .../fr.lproj/Localizable.strings | 42 ++- .../hu.lproj/Localizable.strings | 16 +- .../id.lproj/Localizable.strings | 16 +- .../it.lproj/Localizable.strings | 16 +- .../ka.lproj/Localizable.strings | 16 +- .../nl.lproj/Localizable.strings | 16 +- .../pl.lproj/Localizable.strings | 16 +- .../pt-BR.lproj/Localizable.strings | 16 +- .../pt.lproj/Localizable.strings | 30 +- .../ro.lproj/Localizable.strings | 16 +- .../ru.lproj/Localizable.strings | 18 +- .../sk.lproj/Localizable.strings | 16 +- .../sv.lproj/Localizable.strings | 16 +- .../uk.lproj/Localizable.strings | 16 +- .../uz.lproj/Localizable.strings | 16 +- .../zh-Hans.lproj/Localizable.strings | 16 +- .../zh-Hant-TW.lproj/Localizable.strings | 20 +- 26 files changed, 637 insertions(+), 161 deletions(-) create mode 100644 ElementX/Resources/Localizations/fa.lproj/Localizable.stringsdict diff --git a/ElementX/Resources/Localizations/be.lproj/Localizable.strings b/ElementX/Resources/Localizations/be.lproj/Localizable.strings index 5e496bb337..e5e67403c0 100644 --- a/ElementX/Resources/Localizations/be.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/be.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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) і правільны адрас."; +"screen_create_room_room_access_section_anyone_option_description" = "Anyone can join this room"; +"screen_create_room_room_access_section_anyone_option_title" = "Хто заўгодна"; +"screen_create_room_room_access_section_header" = "Доступ у пакой"; +"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" = "Папрасіце далучыцца"; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Хто заўгодна"; -"screen_create_room_access_section_header" = "Доступ у пакой"; -"screen_create_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_access_section_knocking_option_title" = "Папрасіце далучыцца"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "Яны не супадаюць"; "screen_session_verification_they_match" = "Яны супадаюць"; +"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_waiting_to_accept_subtitle" = "Для працягу працы прыміце запыт на запуск працэсу праверкі ў іншым сеансе."; "screen_session_verification_waiting_to_accept_title" = "Чаканне прыняцця запыту"; "screen_share_location_title" = "Падзяліцца месцазнаходжаннем"; diff --git a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings index 8e7a783ffe..617936ad38 100644 --- a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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."; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "Те не съвпадат"; "screen_session_verification_they_match" = "Те съвпадат"; +"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_waiting_to_accept_subtitle" = "Приемете заявката, за да започнете процеса на потвърждаване в другата си сесия, за да продължите."; "screen_session_verification_waiting_to_accept_title" = "В очакване на приемане на заявка"; "screen_share_location_title" = "Споделяне на местоположение"; diff --git a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings index bc72b44767..b621c33010 100644 --- a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings @@ -246,10 +246,10 @@ "common.you" = "Vy"; "common_unable_to_decrypt_insecure_device" = "Šifrováno nezabezpečeným zařízením"; "common_unable_to_decrypt_verification_violation" = "Ověřená identita odesílatele se změnila"; -"confirm_recovery_key_banner_message" = "Vaše záloha chatu není aktuálně synchronizována. Abyste si zachovali přístup k záloze chatu, musíte potvrdit klíč pro obnovení."; -"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" = "Potvrďte klíč pro obnovení"; +"confirm_recovery_key_banner_message" = "Potvrďte klíč pro obnovení, abyste zachovali přístup k úložišti klíčů a historii zpráv."; +"confirm_recovery_key_banner_primary_button_title" = "Zadejte klíč pro obnovení"; +"confirm_recovery_key_banner_secondary_button_title" = "Zapomněli jste klíč pro obnovení?"; +"confirm_recovery_key_banner_title" = "Vaše úložiště klíčů není synchronizováno"; "crash_detection_dialog_content" = "%1$@ havaroval při posledním použití. Chcete se s námi podělit o zprávu o selhání?"; "crypto_identity_change_pin_violation" = "Zdá se, že se identita %1$@ změnila. %2$@"; "crypto_identity_change_pin_violation_new" = "Zdá se, že identita %1$@ %2$@ se změnila. %3$@"; @@ -344,18 +344,20 @@ "rich_text_editor_unindent" = "Zrušit odsazení"; "rich_text_editor_url_placeholder" = "Odkaz"; "rich_text_editor_a11y_add_attachment" = "Přidat přílohu"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Volitelný titulek..."; "screen_advanced_settings_element_call_base_url" = "Vlastní URL pro Element Call"; "screen_advanced_settings_element_call_base_url_description" = "Nastavte vlastní URL pro Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "Neplatné URL, ujistěte se, že jste uvedli protokol (http/https) a správnou adresu."; +"screen_create_room_room_access_section_anyone_option_description" = "Do této místnosti může vstoupit kdokoli"; +"screen_create_room_room_access_section_anyone_option_title" = "Kdokoliv"; +"screen_create_room_room_access_section_header" = "Přístup do místnosti"; +"screen_create_room_room_access_section_knocking_option_description" = "Kdokoli může požádat o vstup do místnosti, ale správce nebo moderátor bude muset žádost přijmout"; +"screen_create_room_room_access_section_knocking_option_title" = "Požádat o připojení"; +"screen_create_room_room_address_invalid_symbols_error_description" = "Některé znaky nejsou povoleny. Podporovány jsou pouze písmena, číslice a následující symboly ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Tato adresa místnosti již existuje, zkuste prosím upravit pole adresy místnosti nebo změnit název místnosti"; "screen_create_room_room_address_section_footer" = "Aby byla tato místnost viditelná v adresáři veřejných místností, budete potřebovat adresu místnosti."; "screen_create_room_room_address_section_title" = "Adresa místnosti"; "screen_create_room_room_visibility_section_title" = "Viditelnost místnosti"; -"screen_create_room_access_section_anyone_option_description" = "Do této místnosti může vstoupit kdokoli"; -"screen_create_room_access_section_anyone_option_title" = "Kdokoliv"; -"screen_create_room_access_section_header" = "Přístup do místnosti"; -"screen_create_room_access_section_knocking_option_description" = "Kdokoli může požádat o vstup do místnosti, ale správce nebo moderátor bude muset žádost přijmout"; -"screen_create_room_access_section_knocking_option_title" = "Požádat o připojení"; "screen_join_room_cancel_knock_action" = "Zrušit žádost"; "screen_join_room_cancel_knock_alert_confirmation" = "Ano, zrušit"; "screen_join_room_cancel_knock_alert_description" = "Opravdu chcete zrušit svou žádost o vstup do této místnosti?"; @@ -392,8 +394,8 @@ "screen_account_provider_signup_title" = "Chystáte se vytvořit účet na %@"; "screen_advanced_settings_developer_mode" = "Vývojářský režim"; "screen_advanced_settings_developer_mode_description" = "Povolením získáte přístup k funkcím a funkcím pro vývojáře."; -"screen_advanced_settings_media_compression_description" = "Optimalizovat pro nahrávání"; -"screen_advanced_settings_media_compression_title" = "Média"; +"screen_advanced_settings_media_compression_description" = "Rychlejší nahrávání fotografií a videí a snížení spotřeby dat"; +"screen_advanced_settings_media_compression_title" = "Optimalizace kvality médií"; "screen_advanced_settings_rich_text_editor_description" = "Vypněte editor formátovaného textu pro ruční zadání Markdown."; "screen_advanced_settings_send_read_receipts" = "Potvrzení o přečtení"; "screen_advanced_settings_send_read_receipts_description" = "Pokud je vypnuto, potvrzení o přečtení se nikomu neodesílají. Stále budete dostávat potvrzení o přečtení od ostatních uživatelů."; @@ -467,7 +469,7 @@ "screen_chat_backup_key_storage_toggle_title" = "Povolit ukládání klíčů"; "screen_chat_backup_recovery_action_change" = "Změnit klíč pro obnovení"; "screen_chat_backup_recovery_action_change_description" = "Obnovte svou kryptografickou identitu a historii zpráv pomocí klíče pro obnovení, pokud jste ztratili všechna stávající zařízení."; -"screen_chat_backup_recovery_action_confirm_description" = "Vaše záloha chatu není aktuálně synchronizována."; +"screen_chat_backup_recovery_action_confirm_description" = "Vaše úložiště klíčů je momentálně nesynchronizované."; "screen_chat_backup_recovery_action_setup_description" = "Získejte přístup ke svým zašifrovaným zprávám, pokud ztratíte všechna zařízení nebo jste všude odhlášeni z %1$@."; "screen_create_account_title" = "Vytvořit účet"; "screen_create_new_recovery_key_list_item_1" = "Otevřít %1$@ na stolním počítači"; @@ -642,7 +644,7 @@ "screen_recovery_key_change_title" = "Změnit klíč pro obnovení?"; "screen_recovery_key_confirm_create_new_recovery_key" = "Vytvořit nový klíč pro obnovení"; "screen_recovery_key_confirm_description" = "Ujistěte se, že tuto obrazovku nikdo nevidí!"; -"screen_recovery_key_confirm_error_content" = "Zkuste prosím znovu potvrdit přístup k záloze chatu."; +"screen_recovery_key_confirm_error_content" = "Zkuste prosím znovu potvrdit přístup k úložišti klíčů."; "screen_recovery_key_confirm_error_title" = "Nesprávný klíč pro obnovení"; "screen_recovery_key_confirm_key_description" = "Pokud máte bezpečnostní klíč nebo bezpečnostní frázi, bude to fungovat také."; "screen_recovery_key_confirm_key_placeholder" = "Zadejte..."; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Požadováno ověření"; "screen_session_verification_they_dont_match" = "Neshodují se"; "screen_session_verification_they_match" = "Shodují se"; +"screen_session_verification_use_another_device_subtitle" = "Před zahájením ověřování se ujistěte, že máte aplikaci otevřenou na druhém zařízení."; +"screen_session_verification_use_another_device_title" = "Otevřete aplikaci na jiném ověřeném zařízení"; +"screen_session_verification_waiting_another_device_subtitle" = "Na druhém zařízení byste měli vidět vyskakovací okno. Začněte s ověrením tam."; +"screen_session_verification_waiting_another_device_title" = "Spusťte ověření na druhém zařízení"; "screen_session_verification_waiting_to_accept_subtitle" = "Pro pokračování přijměte požadavek na zahájení ověření v jiné relaci."; "screen_session_verification_waiting_to_accept_title" = "Čekání na přijetí žádosti"; "screen_share_location_title" = "Sdílet polohu"; @@ -1033,7 +1039,7 @@ "screen_notification_settings_mentions_section_title" = "Zmínky"; "screen_qr_code_login_invalid_scan_state_retry_button" = "Zkusit znovu"; "screen_recovery_key_change_generate_key_description" = "Toto s nikým nesdílejte!"; -"screen_recovery_key_confirm_title" = "Enter your recovery key"; +"screen_recovery_key_confirm_title" = "Zadejte klíč pro obnovení"; "screen_report_content_block_user" = "Zablokovat uživatele"; "screen_reset_encryption_password_placeholder" = "Zadejte..."; "screen_room_attachment_source_camera_photo" = "Vyfotit"; diff --git a/ElementX/Resources/Localizations/de.lproj/Localizable.strings b/ElementX/Resources/Localizations/de.lproj/Localizable.strings index 0ba57e7b95..6e4634d9c6 100644 --- a/ElementX/Resources/Localizations/de.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/de.lproj/Localizable.strings @@ -348,14 +348,16 @@ "screen_advanced_settings_element_call_base_url" = "Benutzerdefinierte Element-Aufruf-Basis-URL"; "screen_advanced_settings_element_call_base_url_description" = "Lege eine eigene Basis-URL für Element Call fest."; "screen_advanced_settings_element_call_base_url_validation_error" = "Ungültige URL, bitte stelle sicher, dass du das Protokoll (http/https) und die richtige Adresse angibst."; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "Sie stimmen nicht überein"; "screen_session_verification_they_match" = "Sie stimmen überein"; +"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_waiting_to_accept_subtitle" = "Akzeptiere die Anfrage, um den Verifizierungsprozess in deiner anderen Session zu starten, um fortzufahren."; "screen_session_verification_waiting_to_accept_title" = "Warten auf die Annahme der Anfrage"; "screen_share_location_title" = "Standort teilen"; diff --git a/ElementX/Resources/Localizations/el.lproj/Localizable.strings b/ElementX/Resources/Localizations/el.lproj/Localizable.strings index 9c73cfbee0..bb6265fffc 100644 --- a/ElementX/Resources/Localizations/el.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/el.lproj/Localizable.strings @@ -348,14 +348,16 @@ "screen_advanced_settings_element_call_base_url" = "Προσαρμοσμένο URL βάσης κλήσεων Element"; "screen_advanced_settings_element_call_base_url_description" = "Όρισε μια προσαρμοσμένη διεύθυνση βάσης URL για κλήση Element."; "screen_advanced_settings_element_call_base_url_validation_error" = "Μη έγκυρη διεύθυνση URL, βεβαιώσου ότι έχεις συμπεριλάβει το πρωτόκολλο (http/https) και τη σωστή διεύθυνση."; +"screen_create_room_room_access_section_anyone_option_description" = "Οποιοσδήποτε μπορεί να συμμετάσχει σε αυτό το δωμάτιο"; +"screen_create_room_room_access_section_anyone_option_title" = "Οποιοσδήποτε"; +"screen_create_room_room_access_section_header" = "Πρόσβαση Δωματίου"; +"screen_create_room_room_access_section_knocking_option_description" = "Οποιοσδήποτε μπορεί να ζητήσει να συμμετάσχει στο δωμάτιο, αλλά ένας διαχειριστής ή συντονιστής θα πρέπει να αποδεχθεί το αίτημα"; +"screen_create_room_room_access_section_knocking_option_title" = "Αίτημα συμμετοχής"; +"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_create_room_access_section_anyone_option_description" = "Οποιοσδήποτε μπορεί να συμμετάσχει σε αυτό το δωμάτιο"; -"screen_create_room_access_section_anyone_option_title" = "Οποιοσδήποτε"; -"screen_create_room_access_section_header" = "Πρόσβαση Δωματίου"; -"screen_create_room_access_section_knocking_option_description" = "Οποιοσδήποτε μπορεί να ζητήσει να συμμετάσχει στο δωμάτιο, αλλά ένας διαχειριστής ή συντονιστής θα πρέπει να αποδεχθεί το αίτημα"; -"screen_create_room_access_section_knocking_option_title" = "Αίτημα συμμετοχής"; "screen_join_room_cancel_knock_action" = "Ακύρωση αιτήματος"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Ζητήθηκε επαλήθευση"; "screen_session_verification_they_dont_match" = "Δεν ταιριάζουν"; "screen_session_verification_they_match" = "Ταιριάζουν"; +"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_waiting_to_accept_subtitle" = "Αποδέξου το αίτημα για να ξεκινήσεις τη διαδικασία επαλήθευσης στην άλλη συνεδρία σου για να συνεχίσεις."; "screen_session_verification_waiting_to_accept_title" = "Αναμονή για αποδοχή αιτήματος"; "screen_share_location_title" = "Κοινή χρήση τοποθεσίας"; diff --git a/ElementX/Resources/Localizations/es.lproj/Localizable.strings b/ElementX/Resources/Localizations/es.lproj/Localizable.strings index ccbcbd2cdb..bfffc8d937 100644 --- a/ElementX/Resources/Localizations/es.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/es.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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."; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "No coinciden"; "screen_session_verification_they_match" = "Coinciden"; +"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_waiting_to_accept_subtitle" = "Acepta la solicitud para iniciar el proceso de verificación en tu otra sesión para continuar."; "screen_session_verification_waiting_to_accept_title" = "A la espera de aceptar la solicitud"; "screen_share_location_title" = "Compartir ubicación"; diff --git a/ElementX/Resources/Localizations/et.lproj/Localizable.strings b/ElementX/Resources/Localizations/et.lproj/Localizable.strings index abf2da5bbd..99d2763205 100644 --- a/ElementX/Resources/Localizations/et.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/et.lproj/Localizable.strings @@ -348,14 +348,16 @@ "screen_advanced_settings_element_call_base_url" = "Element Calli kohandatud teenuseaadress"; "screen_advanced_settings_element_call_base_url_description" = "Seadista kohandatud teenuseaadress Element Calli jaoks."; "screen_advanced_settings_element_call_base_url_validation_error" = "Vigane url. Palun vaata, et url algaks protokolliga (http/https) ning aadress ise oleks ka õige."; +"screen_create_room_room_access_section_anyone_option_description" = "Kõik võivad selle jututoaga liituda"; +"screen_create_room_room_access_section_anyone_option_title" = "Kõik"; +"screen_create_room_room_access_section_header" = "Ligipääs jututoale"; +"screen_create_room_room_access_section_knocking_option_description" = "Kõik võivad paluda selle jututoaga liitumist, kuid peakasutaja või moderaator peavad selle kinnitama"; +"screen_create_room_room_access_section_knocking_option_title" = "Küsi võimalust liitumiseks"; +"screen_create_room_room_address_invalid_symbols_error_description" = "Mõned tähemärgid pole lubatud. Kasuta vaid tähti, numbreid ja neid kirjavahemärke ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Selline jututoa aadress on juba olemas. Palun proovi muuta kas aadressi või jututoa nime"; "screen_create_room_room_address_section_footer" = "Selleks, et see jututuba oleks nähtav jututubade avalikus kataloogis, sa vajad jututoa aadressi."; "screen_create_room_room_address_section_title" = "Jututoa aadress"; "screen_create_room_room_visibility_section_title" = "Jututoa nähtavus"; -"screen_create_room_access_section_anyone_option_description" = "Kõik võivad selle jututoaga liituda"; -"screen_create_room_access_section_anyone_option_title" = "Kõik"; -"screen_create_room_access_section_header" = "Ligipääs jututoale"; -"screen_create_room_access_section_knocking_option_description" = "Kõik võivad paluda selle jututoaga liitumist, kuid peakasutaja või moderaator peavad selle kinnitama"; -"screen_create_room_access_section_knocking_option_title" = "Küsi võimalust liitumiseks"; "screen_join_room_cancel_knock_action" = "Tühista liitumispalve"; "screen_join_room_cancel_knock_alert_confirmation" = "Jah, tühista"; "screen_join_room_cancel_knock_alert_description" = "Kas sa oled kindel, et soovid tühistada oma palve jututoaga liitumiseks?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verifitseerimispäring"; "screen_session_verification_they_dont_match" = "Nad ei klapi omavahel"; "screen_session_verification_they_match" = "Nad klapivad omavahel"; +"screen_session_verification_use_another_device_subtitle" = "Enne kui alustad siin verifitseerimist, palun ava rakendus teises seadmes."; +"screen_session_verification_use_another_device_title" = "Ava rakendus teises verifitseeritud seadmes"; +"screen_session_verification_waiting_another_device_subtitle" = "Sa peaksid teises seadmes nägema hüpikakent. Palun alusta sealt verifitseerimist."; +"screen_session_verification_waiting_another_device_title" = "Alusta verifitseerimist teises seadmes"; "screen_session_verification_waiting_to_accept_subtitle" = "Jätkamaks nõustu verifitseerimisprotsessi alustamisega oma teises sessioonis."; "screen_session_verification_waiting_to_accept_title" = "Ootame nõustumist verifitseerimispäringuga"; "screen_share_location_title" = "Jaga asukohta"; @@ -911,7 +917,7 @@ "state_event_room_invite_you" = "%1$@ saatis sulle kutse"; "state_event_room_join" = "%1$@ liitus jututoaga"; "state_event_room_join_by_you" = "Sina liitusid jututoaga"; -"state_event_room_knock" = "%1$@ palus liitumist"; +"state_event_room_knock" = "%1$@ palus võimalust liituda"; "state_event_room_knock_accepted" = "%1$@ lubas kasutajal %2$@ liituda"; "state_event_room_knock_accepted_by_you" = "Sina lubasid kasutajal %1$@ liituda!"; "state_event_room_knock_by_you" = "Sina palusid liitumist"; diff --git a/ElementX/Resources/Localizations/fa.lproj/Localizable.strings b/ElementX/Resources/Localizations/fa.lproj/Localizable.strings index e8cce2aae0..0dec8b1557 100644 --- a/ElementX/Resources/Localizations/fa.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fa.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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."; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "مطابق نیستند"; "screen_session_verification_they_match" = "مطابقند"; +"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_waiting_to_accept_subtitle" = "Accept the request to start the verification process in your other session to continue."; "screen_session_verification_waiting_to_accept_title" = "منظر پذیرش درخواست"; "screen_share_location_title" = "هم‌رسانی موقعیت"; @@ -911,8 +917,8 @@ "state_event_room_invite_you" = "%1$@ دعوتتان کرد"; "state_event_room_join" = "%1$@ به اتاق پیوست"; "state_event_room_join_by_you" = "به اتاق پیوستید"; -"state_event_room_knock" = "%1$@ درخواست پیوستن کرد"; -"state_event_room_knock_accepted" = "%1$@ گذاشت %2$@ بپیوندد"; +"state_event_room_knock" = "%1$@ درخواست پیوستن دارد"; +"state_event_room_knock_accepted" = "%1$@ به %2$@ دسترسی داد"; "state_event_room_knock_accepted_by_you" = "گذاشتید %1$@ بپیوندد"; "state_event_room_knock_by_you" = "درخواست پیوستن کردید"; "state_event_room_knock_denied" = "درخواست پیوستن %2$@ به دست %1$@ لغو شد"; diff --git a/ElementX/Resources/Localizations/fa.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/fa.lproj/Localizable.stringsdict new file mode 100644 index 0000000000..3babb9bf3a --- /dev/null +++ b/ElementX/Resources/Localizations/fa.lproj/Localizable.stringsdict @@ -0,0 +1,326 @@ + + + + + a11y_digits_entered + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d digit entered + other + %1$d digits entered + + + a11y_read_receipts_multiple_with_others + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + Read by %1$@ and %2$d other + other + Read by %1$@ and %2$d others + + + common_member_count + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d عضو + other + %1$d عضو + + + common_poll_votes_count + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d vote + other + %d votes + + + notification_compat_summary_line_for_room + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@: %2$d message + other + %1$@: %2$d messages + + + notification_compat_summary_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d notification + other + %d notifications + + + notification_invitations + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d invitation + other + %d invitations + + + notification_new_messages_for_room + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d new message + other + %d new messages + + + notification_unread_notified_messages + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d unread notified message + other + %d unread notified messages + + + notification_unread_notified_messages_in_room_rooms + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d room + other + %d rooms + + + screen_app_lock_subtitle + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + You have %1$d attempt to unlock + other + You have %1$d attempts to unlock + + + screen_app_lock_subtitle_wrong_pin + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + Wrong PIN. You have %1$d more chance + other + Wrong PIN. You have %1$d more chances + + + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d Pinned message + other + %1$d Pinned messages + + + screen_room_member_list_header_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d person + other + %1$d people + + + screen_room_timeline_state_changes + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d room change + other + %1$d room changes + + + screen_room_typing_many_members + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@, %2$@ and %3$d other + other + %1$@, %2$@ and %3$d others + + + screen_room_typing_many_members_second_component_ios + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d other + other + %d others + + + screen_room_typing_notification + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ is typing + other + %1$@ are typing + + + troubleshoot_notifications_test_detect_push_provider_success + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + Found %1$d push provider: %2$@ + other + Found %1$d push providers: %2$@ + + + troubleshoot_notifications_test_unified_push_success + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d distributor found: %2$@. + other + %1$d distributors found: %2$@. + + + + \ No newline at end of file diff --git a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings index 5fe2924ebb..7cb63f2178 100644 --- a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings @@ -233,7 +233,7 @@ "common_verification_failed" = "Échec de la vérification"; "common_verified" = "Vérifié(e)"; "common_verify_device" = "Vérifier la session"; -"common_verify_identity" = "Verify identity"; +"common_verify_identity" = "Vérifier l'identité"; "common_video" = "Vidéo"; "common_voice_message" = "Message vocal"; "common_waiting" = "En attente..."; @@ -246,10 +246,10 @@ "common.you" = "Vous"; "common_unable_to_decrypt_insecure_device" = "Envoyé depuis un appareil non sécurisé"; "common_unable_to_decrypt_verification_violation" = "L'identité vérifiée de l'expéditeur a changé"; -"confirm_recovery_key_banner_message" = "La sauvegarde des conversations est désynchronisée. Vous devez confirmer la clé de récupération pour accéder à votre historique."; -"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" = "Confirmer votre clé de récupération"; +"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_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$@"; "crypto_identity_change_pin_violation_new" = "L'identité de %1$@ %2$@ semble avoir changé. %3$@"; @@ -344,18 +344,20 @@ "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" = "Optional caption…"; +"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."; +"screen_create_room_room_access_section_anyone_option_description" = "Tout le monde peut rejoindre ce salon"; +"screen_create_room_room_access_section_anyone_option_title" = "Tout le monde"; +"screen_create_room_room_access_section_header" = "Accès au salon"; +"screen_create_room_room_access_section_knocking_option_description" = "Tout le monde peut demander à rejoindre le salon, mais un administrateur ou un modérateur devra accepter la demande"; +"screen_create_room_room_access_section_knocking_option_title" = "Demander à rejoindre"; +"screen_create_room_room_address_invalid_symbols_error_description" = "Certains caractères ne sont pas autorisés. Seuls les lettres, les chiffres et les symboles suivants sont utilisables ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Cette adresse de salon existe déjà, veuillez essayer de modifier le champ d'adresse de salon ou de modifier le nom du salon"; "screen_create_room_room_address_section_footer" = "Pour que ce salon soit visible dans le répertoire des salons publics, vous aurez besoin d'une adresse de salon."; "screen_create_room_room_address_section_title" = "Adresse du salon"; "screen_create_room_room_visibility_section_title" = "Visibilité du salon"; -"screen_create_room_access_section_anyone_option_description" = "Tout le monde peut rejoindre ce salon"; -"screen_create_room_access_section_anyone_option_title" = "Tout le monde"; -"screen_create_room_access_section_header" = "Accès au salon"; -"screen_create_room_access_section_knocking_option_description" = "Tout le monde peut demander à rejoindre le salon, mais un administrateur ou un modérateur devra accepter la demande"; -"screen_create_room_access_section_knocking_option_title" = "Demander à rejoindre"; "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?"; @@ -392,8 +394,8 @@ "screen_account_provider_signup_title" = "Vous êtes sur le point de créer un compte sur %@"; "screen_advanced_settings_developer_mode" = "Mode développeur"; "screen_advanced_settings_developer_mode_description" = "Activer pour pouvoir accéder aux fonctionnalités destinées aux développeurs."; -"screen_advanced_settings_media_compression_description" = "Optimisé pour le téléchargement"; -"screen_advanced_settings_media_compression_title" = "Media"; +"screen_advanced_settings_media_compression_description" = "Téléchargez des photos et des vidéos plus rapidement et réduisez la consommation de données"; +"screen_advanced_settings_media_compression_title" = "Optimisez la qualité des médias"; "screen_advanced_settings_rich_text_editor_description" = "Désactivez l’éditeur de texte enrichi pour saisir manuellement du Markdown."; "screen_advanced_settings_send_read_receipts" = "Accusés de lecture"; "screen_advanced_settings_send_read_receipts_description" = "En cas de désactivation, vos accusés de lecture ne seront pas envoyés aux autres membres. Vous verrez toujours les accusés des autres membres."; @@ -462,12 +464,12 @@ "screen_chat_backup_key_backup_action_enable" = "Activer la sauvegarde"; "screen_chat_backup_key_backup_description" = "Stockez votre identité cryptographique et vos clés de message en toute sécurité sur le serveur. Cela vous permettra de consulter l'historique de vos messages sur tous les nouveaux appareils. %1$@."; "screen_chat_backup_key_backup_title" = "Stockage des clés"; -"screen_chat_backup_key_storage_disabled_error" = "Key storage must be turned on to set up recovery."; +"screen_chat_backup_key_storage_disabled_error" = "Le stockage des clés doit être activé pour configurer la restauration."; "screen_chat_backup_key_storage_toggle_description" = "Télécharger les clés depuis cet appareil"; "screen_chat_backup_key_storage_toggle_title" = "Autoriser le stockage des clés"; "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" = "La sauvegarde des discussions est désynchronisée."; +"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_create_account_title" = "Créer un compte"; "screen_create_new_recovery_key_list_item_1" = "Ouvrez %1$@ sur un ordinateur"; @@ -642,7 +644,7 @@ "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_error_content" = "Veuillez réessayer afin de pouvoir accéder à vos anciens messages."; +"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…"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Vérification demandée"; "screen_session_verification_they_dont_match" = "Ils ne correspondent pas"; "screen_session_verification_they_match" = "Ils correspondent"; +"screen_session_verification_use_another_device_subtitle" = "Assurez-vous que l'application est ouverte sur un autre appareil avant de commencer la vérification."; +"screen_session_verification_use_another_device_title" = "Ouvrez l'application sur un autre appareil vérifié"; +"screen_session_verification_waiting_another_device_subtitle" = "Vous devriez voir une alerte sur l'autre appareil. Démarrez la vérification à partir de là dès maintenant."; +"screen_session_verification_waiting_another_device_title" = "Démarrer la vérification sur l’autre appareil"; "screen_session_verification_waiting_to_accept_subtitle" = "Pour continuer, acceptez la demande de lancement de la procédure de vérification dans votre autre session."; "screen_session_verification_waiting_to_accept_title" = "En attente d’acceptation de la demande"; "screen_share_location_title" = "Partage de position"; @@ -911,7 +917,7 @@ "state_event_room_invite_you" = "%1$@ vous a invité(e)"; "state_event_room_join" = "%1$@ a rejoint le salon"; "state_event_room_join_by_you" = "Vous avez rejoint le salon"; -"state_event_room_knock" = "%1$@ a demandé à rejoindre"; +"state_event_room_knock" = "%1$@ demande à rejoindre le salon"; "state_event_room_knock_accepted" = "%1$@ a autorisé %2$@ à rejoindre"; "state_event_room_knock_accepted_by_you" = "Vous avez autorisé %1$@ à joindre le salon"; "state_event_room_knock_by_you" = "Vous avez demandé à rejoindre"; @@ -1033,7 +1039,7 @@ "screen_notification_settings_mentions_section_title" = "Mentions"; "screen_qr_code_login_invalid_scan_state_retry_button" = "Essayer à nouveau"; "screen_recovery_key_change_generate_key_description" = "Ne partagez cela avec personne !"; -"screen_recovery_key_confirm_title" = "Enter your recovery key"; +"screen_recovery_key_confirm_title" = "Saisissez votre clé de récupération"; "screen_report_content_block_user" = "Bloquer l’utilisateur"; "screen_reset_encryption_password_placeholder" = "Saisissez la clé ici…"; "screen_room_attachment_source_camera_photo" = "Prendre une photo"; diff --git a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings index 829d85237a..15f239bb9c 100644 --- a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings @@ -348,14 +348,16 @@ "screen_advanced_settings_element_call_base_url" = "Egyéni Element Call alapwebcím"; "screen_advanced_settings_element_call_base_url_description" = "Egyéni alapwebcím beállítása az Element Callhoz."; "screen_advanced_settings_element_call_base_url_validation_error" = "Érvénytelen webcím, győződjön meg arról, hogy szerepel-e benne a protokoll (http/https), és hogy helyes-e a cím."; +"screen_create_room_room_access_section_anyone_option_description" = "Bárki csatlakozhat ehhez a szobához"; +"screen_create_room_room_access_section_anyone_option_title" = "Bárki"; +"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_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"; -"screen_create_room_access_section_anyone_option_description" = "Bárki csatlakozhat ehhez a szobához"; -"screen_create_room_access_section_anyone_option_title" = "Bárki"; -"screen_create_room_access_section_header" = "Szobahozzáférés"; -"screen_create_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_access_section_knocking_option_title" = "Csatlakozás kérése"; "screen_join_room_cancel_knock_action" = "Kérés visszavonása"; "screen_join_room_cancel_knock_alert_confirmation" = "Igen, visszavonás"; "screen_join_room_cancel_knock_alert_description" = "Biztos, hogy visszavonja a szobához való csatlakozási kérését?"; @@ -847,6 +849,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_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"; diff --git a/ElementX/Resources/Localizations/id.lproj/Localizable.strings b/ElementX/Resources/Localizations/id.lproj/Localizable.strings index b217ee3984..5a5bde12f6 100644 --- a/ElementX/Resources/Localizations/id.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/id.lproj/Localizable.strings @@ -348,14 +348,16 @@ "screen_advanced_settings_element_call_base_url" = "URL dasar Element Call khusus"; "screen_advanced_settings_element_call_base_url_description" = "Tetapkan URL dasar khusus untuk Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "URL tidak valid, pastikan Anda menyertakan protokol (http/https) dan alamat yang benar."; +"screen_create_room_room_access_section_anyone_option_description" = "Siapa pun dapat bergabung dengan ruangan ini"; +"screen_create_room_room_access_section_anyone_option_title" = "Siapa pun"; +"screen_create_room_room_access_section_header" = "Akses Ruangan"; +"screen_create_room_room_access_section_knocking_option_description" = "Siapa pun dapat meminta untuk bergabung dengan ruangan tetapi administrator atau moderator harus menerima permintaan tersebut"; +"screen_create_room_room_access_section_knocking_option_title" = "Minta untuk bergabung"; +"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" = "Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan."; "screen_create_room_room_address_section_title" = "Alamat ruangan"; "screen_create_room_room_visibility_section_title" = "Keterlihatan ruangan"; -"screen_create_room_access_section_anyone_option_description" = "Siapa pun dapat bergabung dengan ruangan ini"; -"screen_create_room_access_section_anyone_option_title" = "Siapa pun"; -"screen_create_room_access_section_header" = "Akses Ruangan"; -"screen_create_room_access_section_knocking_option_description" = "Siapa pun dapat meminta untuk bergabung dengan ruangan tetapi administrator atau moderator harus menerima permintaan tersebut"; -"screen_create_room_access_section_knocking_option_title" = "Minta untuk bergabung"; "screen_join_room_cancel_knock_action" = "Batalkan permintaan"; "screen_join_room_cancel_knock_alert_confirmation" = "Ya, batalkan"; "screen_join_room_cancel_knock_alert_description" = "Apakah Anda yakin ingin membatalkan permintaan Anda untuk bergabung dengan ruangan ini?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verifikasi diminta"; "screen_session_verification_they_dont_match" = "Mereka tidak cocok"; "screen_session_verification_they_match" = "Mereka cocok"; +"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_waiting_to_accept_subtitle" = "Terima permintaan untuk memulai proses verifikasi di sesi Anda yang lain untuk melanjutkan."; "screen_session_verification_waiting_to_accept_title" = "Menunggu untuk menerima permintaan"; "screen_share_location_title" = "Bagikan lokasi"; diff --git a/ElementX/Resources/Localizations/it.lproj/Localizable.strings b/ElementX/Resources/Localizations/it.lproj/Localizable.strings index ef7bddaf9f..4f3d038ed2 100644 --- a/ElementX/Resources/Localizations/it.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/it.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "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_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"; diff --git a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings index 33314f91c3..4fda4d6093 100644 --- a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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) და სწორი მისამართი."; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "ისინი არ ემთხვევიან ერთმანეთს"; "screen_session_verification_they_match" = "ისინი ემთხვევიან ერთმანეთს"; +"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_waiting_to_accept_subtitle" = "მიიღეთ დადასტურების მოთხოვნა თქვენს სხვა სესიაში ამ პროცესის გასაგრძელებლად."; "screen_session_verification_waiting_to_accept_title" = "მოთხოვნის მიღებას ველოდებით"; "screen_share_location_title" = "მდებარეობის გაზიარება"; diff --git a/ElementX/Resources/Localizations/nl.lproj/Localizable.strings b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings index a149e82a7b..db0bf30ad1 100644 --- a/ElementX/Resources/Localizations/nl.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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."; +"screen_create_room_room_access_section_anyone_option_description" = "Iedereen kan toetreden tot deze kamer"; +"screen_create_room_room_access_section_anyone_option_title" = "Iedereen"; +"screen_create_room_room_access_section_header" = "Toegang tot de kamer"; +"screen_create_room_room_access_section_knocking_option_description" = "Iedereen kan vragen om toe te treden tot de kamer, maar een beheerder of moderator moet het verzoek accepteren"; +"screen_create_room_room_access_section_knocking_option_title" = "Vraag om toe te treden"; +"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_create_room_access_section_anyone_option_description" = "Iedereen kan toetreden tot deze kamer"; -"screen_create_room_access_section_anyone_option_title" = "Iedereen"; -"screen_create_room_access_section_header" = "Toegang tot de kamer"; -"screen_create_room_access_section_knocking_option_description" = "Iedereen kan vragen om toe te treden tot de kamer, maar een beheerder of moderator moet het verzoek accepteren"; -"screen_create_room_access_section_knocking_option_title" = "Vraag om toe te treden"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "Ze komen niet overeen"; "screen_session_verification_they_match" = "Ze komen overeen"; +"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_waiting_to_accept_subtitle" = "Accepteer het verzoek tot verificatie in je andere sessie om door te gaan."; "screen_session_verification_waiting_to_accept_title" = "Wachten om verzoek te accepteren"; "screen_share_location_title" = "Locatie delen"; diff --git a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings index 56841a16e6..6d8ec5744e 100644 --- a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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."; +"screen_create_room_room_access_section_anyone_option_description" = "Każdy może dołączyć do tego pokoju"; +"screen_create_room_room_access_section_anyone_option_title" = "Wszyscy"; +"screen_create_room_room_access_section_header" = "Dostęp do pokoju"; +"screen_create_room_room_access_section_knocking_option_description" = "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić prośbę"; +"screen_create_room_room_access_section_knocking_option_title" = "Poproś o dołączenie"; +"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" = "Aby ten pokój był widoczny w katalogu pomieszczeń publicznych, będziesz potrzebował adres pokoju."; "screen_create_room_room_address_section_title" = "Adres pokoju"; "screen_create_room_room_visibility_section_title" = "Widoczność pomieszczenia"; -"screen_create_room_access_section_anyone_option_description" = "Każdy może dołączyć do tego pokoju"; -"screen_create_room_access_section_anyone_option_title" = "Wszyscy"; -"screen_create_room_access_section_header" = "Dostęp do pokoju"; -"screen_create_room_access_section_knocking_option_description" = "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić prośbę"; -"screen_create_room_access_section_knocking_option_title" = "Poproś o dołączenie"; "screen_join_room_cancel_knock_action" = "Anuluj prośbę"; "screen_join_room_cancel_knock_alert_confirmation" = "Tak, anuluj"; "screen_join_room_cancel_knock_alert_description" = "Czy na pewno chcesz anulować prośbę o dołączenie do tego pokoju?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Zażądano weryfikacji"; "screen_session_verification_they_dont_match" = "Nie pasują do siebie"; "screen_session_verification_they_match" = "Pasują do siebie"; +"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_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_share_location_title" = "Udostępnij lokalizację"; diff --git a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings index 659c5bf139..decda9de4c 100644 --- a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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" = "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"; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "Eles não combinam"; "screen_session_verification_they_match" = "Eles combinam"; +"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_waiting_to_accept_subtitle" = "Aceite a solicitação para iniciar o processo de verificação em sua outra sessão para continuar."; "screen_session_verification_waiting_to_accept_title" = "Aguardando para aceitar a solicitação"; "screen_share_location_title" = "Compartilhar localização"; diff --git a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings index b4a06c13f7..445ea610ca 100644 --- a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings @@ -115,7 +115,7 @@ "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."; "banner_migrate_to_native_sliding_sync_title" = "Atualização disponível"; -"banner_set_up_recovery_content" = "Gere uma nova chave de recuperação que pode ser usada para restaurar seu histórico de mensagens criptografadas caso você perca o acesso aos seus dispositivos."; +"banner_set_up_recovery_content" = "Recupera a tua identidade criptográfica e o histórico de mensagens com uma chave de recuperação se tiveres perdido todos os teus dispositivos existentes."; "banner_set_up_recovery_title" = "Configurar a recuperação"; "common_about" = "Sobre"; "common_acceptable_use_policy" = "Política de utilização aceitável"; @@ -243,7 +243,7 @@ "common.open_source_licenses" = "Licenças de código aberto"; "common.pinned" = "Afixado"; "common.send_to" = "Enviar para"; -"common.you" = "Você"; +"common.you" = "Tu"; "common_unable_to_decrypt_insecure_device" = "Enviado de um dispositivo inseguro"; "common_unable_to_decrypt_verification_violation" = "A identidade verificada do remetente foi alterada"; "confirm_recovery_key_banner_message" = "Confirma a tua chave de recuperação para manteres o acesso ao teu armazenamento de chaves e ao histórico de mensagens."; @@ -348,14 +348,16 @@ "screen_advanced_settings_element_call_base_url" = "URL base para Element Call personalizado"; "screen_advanced_settings_element_call_base_url_description" = "Define um URL base para a Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "URL inválido, certifica-te de que incluis o protocolo (http/https) e o endereço correto."; +"screen_create_room_room_access_section_anyone_option_description" = "Qualquer pessoa pode entrar nesta sala"; +"screen_create_room_room_access_section_anyone_option_title" = "Qualquer pessoa"; +"screen_create_room_room_access_section_header" = "Acesso à sala"; +"screen_create_room_room_access_section_knocking_option_description" = "Qualquer pessoa pode pedir para entrar na sala, mas um administrador ou um moderador terá de aceitar o pedido"; +"screen_create_room_room_access_section_knocking_option_title" = "Pedir para participar"; +"screen_create_room_room_address_invalid_symbols_error_description" = "Alguns caracteres não são permitidos. Apenas letras, dígitos e os seguintes símbolos são suportados! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Este endereço de sala já existe, tente editar o campo de endereço da sala ou altere o nome da sala"; "screen_create_room_room_address_section_footer" = "Para que esta sala seja visível no diretório público de salas, precisas de um endereço de sala."; "screen_create_room_room_address_section_title" = "Endereço da sala"; "screen_create_room_room_visibility_section_title" = "Visibilidade da sala"; -"screen_create_room_access_section_anyone_option_description" = "Qualquer pessoa pode entrar nesta sala"; -"screen_create_room_access_section_anyone_option_title" = "Qualquer pessoa"; -"screen_create_room_access_section_header" = "Acesso à sala"; -"screen_create_room_access_section_knocking_option_description" = "Qualquer pessoa pode pedir para entrar na sala, mas um administrador ou um moderador terá de aceitar o pedido"; -"screen_create_room_access_section_knocking_option_title" = "Pedir para participar"; "screen_join_room_cancel_knock_action" = "Cancelar pedido"; "screen_join_room_cancel_knock_alert_confirmation" = "Sim, cancelar"; "screen_join_room_cancel_knock_alert_description" = "Tens a certeza de que queres cancelar o teu pedido de entrada nesta sala?"; @@ -367,12 +369,12 @@ "screen_pinned_timeline_empty_state_headline" = "Fixa mensagens importantes para que possam ser facilmente descobertas"; "screen_reset_encryption_password_error" = "Um erro desconhecido aconteceu. Verifique se a senha da sua conta está correta e tente novamente."; "screen_resolve_send_failure_changed_identity_primary_button_title" = "Retirar verificação e enviar"; -"screen_resolve_send_failure_changed_identity_subtitle" = "Você pode retirar sua verificação e enviar esta mensagem de qualquer maneira, ou você pode cancelar por enquanto e tentar novamente mais tarde depois de verificar novamente %1$@."; +"screen_resolve_send_failure_changed_identity_subtitle" = "Podes retirar a tua verificação e enviar esta mensagem na mesma, ou podes cancelar por agora e tentar novamente mais tarde depois de reverificares %1$@."; "screen_resolve_send_failure_changed_identity_title" = "A sua mensagem não foi enviada porque a identidade verificada de %1$@ foi alterada"; "screen_resolve_send_failure_unsigned_device_primary_button_title" = "Enviar mensagem mesmo assim"; -"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ está usando um ou mais dispositivos não verificados. Você pode enviar a mensagem de qualquer maneira, ou você pode cancelar por enquanto e tentar novamente mais tarde depois que %2$@ tiver verificado todos os seus dispositivos."; +"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ está a utilizar um ou mais dispositivos não verificados. Podes enviar a mensagem na mesma, ou podes cancelar por agora e tentar novamente mais tarde, depois de %2$@ ter verificado todos os seus dispositivos."; "screen_resolve_send_failure_unsigned_device_title" = "A sua mensagem não foi enviada porque %1$@ não verificou todos os dispositivos"; -"screen_resolve_send_failure_you_unsigned_device_subtitle" = "Um ou mais dos seus dispositivos não são verificados. Você pode enviar a mensagem de qualquer maneira, ou você pode cancelar por enquanto e tentar novamente mais tarde depois de ter verificado todos os seus dispositivos."; +"screen_resolve_send_failure_you_unsigned_device_subtitle" = "Um ou mais dos teus dispositivos não foram verificados. Podes enviar a mensagem na mesma, ou podes cancelar por agora e tentar novamente mais tarde, depois de teres verificado todos os teus dispositivos."; "screen_resolve_send_failure_you_unsigned_device_title" = "A sua mensagem não foi enviada porque não verificou um ou mais dos seus dispositivos"; "screen_room_mentions_at_room_subtitle" = "Notificar toda a sala"; "screen_room_pinned_banner_indicator" = "%1$@ de %2$@"; @@ -501,7 +503,7 @@ "screen_deactivate_account_list_item_1_bold_part" = "Desativar permanentemente"; "screen_deactivate_account_list_item_2" = "Removê-lo de todas as salas de chat."; "screen_deactivate_account_list_item_3" = "Exclua as informações da sua conta do nosso servidor de identidade."; -"screen_deactivate_account_list_item_4" = "Suas mensagens ainda estarão visíveis para usuários registrados, mas não estarão disponíveis para usuários novos ou não registrados se você optar por excluí-las."; +"screen_deactivate_account_list_item_4" = "As tuas mensagens continuarão a ser visíveis para os utilizadores registados, mas não estarão disponíveis para os utilizadores novos ou não registados se optares por as apagar."; "screen_deactivate_account_title" = "Desativar conta"; "screen_edit_poll_delete_confirmation" = "Tens a certeza que queres apagar esta sondagem?"; "screen_edit_profile_display_name" = "Pseudónimo"; @@ -669,7 +671,7 @@ "screen_reset_encryption_confirmation_alert_title" = "Tens a certeza que pretendes repor a tua cifra?"; "screen_reset_encryption_password_subtitle" = "Confirma que pretendes realmente repor a tua cifra."; "screen_reset_encryption_password_title" = "Insere a tua palavra-passe para continuares"; -"screen_reset_identity_confirmation_subtitle" = "Está prestes a aceder à sua conta %1$@ para repor a sua identidade. Depois, você será levado de volta ao aplicativo."; +"screen_reset_identity_confirmation_subtitle" = "Estás prestes a aceder à tua conta %1$@ para redefinir a tua identidade. Depois disso, serás levado de volta à aplicação."; "screen_reset_identity_confirmation_title" = "Não consegue confirmar? Aceda à sua conta para repor a sua identidade."; "screen_room_alias_resolver_resolve_alias_failure" = "Não foi possível encontrar esse endereço de sala"; "screen_room_attachment_source_camera" = "Câmara"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verificação solicitada"; "screen_session_verification_they_dont_match" = "Não correspondem"; "screen_session_verification_they_match" = "Correspondem"; +"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_waiting_to_accept_subtitle" = "Para continuar, aceita o pedido de verificação na tua outra sessão."; "screen_session_verification_waiting_to_accept_title" = "À aguardar a aceitação do pedido"; "screen_share_location_title" = "Partilhar localização"; diff --git a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings index fdaff848fe..b226a59516 100644 --- a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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ă."; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "Nu se potrivesc"; "screen_session_verification_they_match" = "Se potrivesc"; +"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_waiting_to_accept_subtitle" = "Acceptați solicitarea de a începe procesul de verificare în cealaltă sesiune pentru a continua."; "screen_session_verification_waiting_to_accept_title" = "Se așteptă acceptarea cererii"; "screen_share_location_title" = "Partajați locația"; diff --git a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings index c4b1205b07..9bc2f1d815 100644 --- a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings @@ -348,14 +348,16 @@ "screen_advanced_settings_element_call_base_url" = "Базовый URL сервера звонков Element"; "screen_advanced_settings_element_call_base_url_description" = "Задайте свой сервер Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "Адрес указан неверно, удостоверьтесь, что вы указали протокол (http/https) и правильный адрес."; +"screen_create_room_room_access_section_anyone_option_description" = "Любой желающий может присоединиться к этой комнате"; +"screen_create_room_room_access_section_anyone_option_title" = "Любой"; +"screen_create_room_room_access_section_header" = "Доступ в комнату"; +"screen_create_room_room_access_section_knocking_option_description" = "Любой желающий может подать заявку на присоединение к комнате, но администратор или модератор должен будет принять запрос."; +"screen_create_room_room_access_section_knocking_option_title" = "Попросить присоединиться"; +"screen_create_room_room_address_invalid_symbols_error_description" = "Некоторые символы не допускаются. Поддерживаются только буквы, цифры и следующие символы! $ & '() * +/; =? @ [] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Такой адрес комнаты уже существует, попробуйте отредактировать поле адреса комнаты или изменить название комнаты"; "screen_create_room_room_address_section_footer" = "Чтобы эта комната была видна в каталоге общедоступных, вам необходим ее адрес"; "screen_create_room_room_address_section_title" = "Адрес комнаты"; "screen_create_room_room_visibility_section_title" = "Видимость комнаты"; -"screen_create_room_access_section_anyone_option_description" = "Любой желающий может присоединиться к этой комнате"; -"screen_create_room_access_section_anyone_option_title" = "Любой"; -"screen_create_room_access_section_header" = "Доступ в комнату"; -"screen_create_room_access_section_knocking_option_description" = "Любой желающий может подать заявку на присоединение к комнате, но администратор или модератор должен будет принять запрос."; -"screen_create_room_access_section_knocking_option_title" = "Попросить присоединиться"; "screen_join_room_cancel_knock_action" = "Отменить запрос"; "screen_join_room_cancel_knock_alert_confirmation" = "Да, отменить"; "screen_join_room_cancel_knock_alert_description" = "Вы действительно хотите отменить заявку на вступление в эту комнату?"; @@ -498,7 +500,7 @@ "screen_deactivate_account_description" = "Отключение вашей учетной записи %1$@ и означает следующее:"; "screen_deactivate_account_description_bold_part" = "необратимо"; "screen_deactivate_account_list_item_1" = "Ваша учётная запись будет %1$@ (вы не сможете войти в неё снова, и ваш ID не может быть использован повторно)."; -"screen_deactivate_account_list_item_1_bold_part" = "Отключить навсегда"; +"screen_deactivate_account_list_item_1_bold_part" = "отключена навсегда"; "screen_deactivate_account_list_item_2" = "Вы будете удалены из всех чатов."; "screen_deactivate_account_list_item_3" = "Данные вашей учётной записи будут удалены с нашего сервера идентификации."; "screen_deactivate_account_list_item_4" = "Ваши сообщения по-прежнему будут видны зарегистрированным пользователям, но не будут доступны новым или незарегистрированным пользователям, если вы решите удалить их."; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Запрошено подтверждение"; "screen_session_verification_they_dont_match" = "Они не совпадают"; "screen_session_verification_they_match" = "Они совпадают"; +"screen_session_verification_use_another_device_subtitle" = "Прежде чем начать проверку, убедитесь, что приложение открыто на другом устройстве."; +"screen_session_verification_use_another_device_title" = "Откройте приложение на другом проверенном устройстве"; +"screen_session_verification_waiting_another_device_subtitle" = "Вы должны увидеть всплывающее окно на другом устройстве. Начните проверку оттуда прямо сейчас."; +"screen_session_verification_waiting_another_device_title" = "Начать проверку на другом устройстве"; "screen_session_verification_waiting_to_accept_subtitle" = "Чтобы продолжить, примите запрос на запуск процесса подтверждения в другом сеансе."; "screen_session_verification_waiting_to_accept_title" = "Ожидание принятия запроса"; "screen_share_location_title" = "Поделиться местоположением"; diff --git a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings index 1008f9615c..3fd39dc069 100644 --- a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings @@ -348,14 +348,16 @@ "screen_advanced_settings_element_call_base_url" = "Vlastná Element Call základná URL adresa"; "screen_advanced_settings_element_call_base_url_description" = "Nastaviť vlastnú základnú URL adresu pre Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "Neplatná adresa URL, uistite sa, že ste uviedli protokol (http/https) a správnu adresu."; +"screen_create_room_room_access_section_anyone_option_description" = "Do tejto miestnosti sa môže pripojiť ktokoľvek"; +"screen_create_room_room_access_section_anyone_option_title" = "Ktokoľvek"; +"screen_create_room_room_access_section_header" = "Prístup do miestnosti"; +"screen_create_room_room_access_section_knocking_option_description" = "Ktokoľvek môže požiadať o pripojenie sa k miestnosti, ale administrátor alebo moderátor bude musieť žiadosť schváliť"; +"screen_create_room_room_access_section_knocking_option_title" = "Požiadať o pripojenie"; +"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" = "Aby bola táto miestnosť viditeľná v adresári verejných miestností, budete potrebovať adresu miestnosti."; "screen_create_room_room_address_section_title" = "Adresa miestnosti"; "screen_create_room_room_visibility_section_title" = "Viditeľnosť miestnosti"; -"screen_create_room_access_section_anyone_option_description" = "Do tejto miestnosti sa môže pripojiť ktokoľvek"; -"screen_create_room_access_section_anyone_option_title" = "Ktokoľvek"; -"screen_create_room_access_section_header" = "Prístup do miestnosti"; -"screen_create_room_access_section_knocking_option_description" = "Ktokoľvek môže požiadať o pripojenie sa k miestnosti, ale administrátor alebo moderátor bude musieť žiadosť schváliť"; -"screen_create_room_access_section_knocking_option_title" = "Požiadať o pripojenie"; "screen_join_room_cancel_knock_action" = "Zrušiť žiadosť"; "screen_join_room_cancel_knock_alert_confirmation" = "Áno, zrušiť"; "screen_join_room_cancel_knock_alert_description" = "Ste si istí, že chcete zrušiť svoju žiadosť o vstup do tejto miestnosti?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Vyžadované overenie"; "screen_session_verification_they_dont_match" = "Nezhodujú sa"; "screen_session_verification_they_match" = "Zhodujú sa"; +"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_waiting_to_accept_subtitle" = "Ak chcete pokračovať, prijmite žiadosť o spustenie procesu overenia vo vašej druhej relácii."; "screen_session_verification_waiting_to_accept_title" = "Čaká sa na prijatie žiadosti"; "screen_share_location_title" = "Zdieľať polohu"; diff --git a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings index 579f9bff91..f6fa8b9f5b 100644 --- a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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."; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "De matchar inte"; "screen_session_verification_they_match" = "De matchar"; +"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_waiting_to_accept_subtitle" = "Godkänn begäran om att starta verifieringsprocessen på din andra session för att fortsätta."; "screen_session_verification_waiting_to_accept_title" = "Väntar på att acceptera begäran"; "screen_share_location_title" = "Dela plats"; diff --git a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings index 6e5b02cfdd..09cd368c3e 100644 --- a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings @@ -348,14 +348,16 @@ "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" = "Неправильна URL-адреса, будь ласка, переконайтеся, що ви вказали протокол (http/https) та правильну адресу."; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "Вони не збігаються"; "screen_session_verification_they_match" = "Вони збігаються"; +"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_waiting_to_accept_subtitle" = "Щоб продовжити, прийміть запит на початок процесу перевірки в іншому сеансі."; "screen_session_verification_waiting_to_accept_title" = "Очікування на прийняття запиту"; "screen_share_location_title" = "Поділитися розташуванням"; diff --git a/ElementX/Resources/Localizations/uz.lproj/Localizable.strings b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings index a6242a13c4..04cb4691a0 100644 --- a/ElementX/Resources/Localizations/uz.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings @@ -348,14 +348,16 @@ "screen_advanced_settings_element_call_base_url" = "Maxsus element qo‘ng‘iroqlar bazasi URL manzili"; "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."; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "Ular mos kelmaydi"; "screen_session_verification_they_match" = "Ular mos keladi"; +"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_waiting_to_accept_subtitle" = "Davom etish uchun boshqa seansda tekshirish jarayonini boshlash soʻrovini qabul qiling."; "screen_session_verification_waiting_to_accept_title" = "Soʻrovni qabul qilish kutilmoqda"; "screen_share_location_title" = "Joylashuvni ulashish"; diff --git a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings index 82305720b9..7454457022 100644 --- a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings @@ -348,14 +348,16 @@ "screen_advanced_settings_element_call_base_url" = "自定义 Element Call URL"; "screen_advanced_settings_element_call_base_url_description" = "为 Element 通话设置根 URL。"; "screen_advanced_settings_element_call_base_url_validation_error" = "URL 无效,请确保包含协议(http/https)和正确的地址。"; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "不匹配"; "screen_session_verification_they_match" = "匹配"; +"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_waiting_to_accept_subtitle" = "请在其他会话中接受验证请求。"; "screen_session_verification_waiting_to_accept_title" = "等待接受请求"; "screen_share_location_title" = "分享位置"; diff --git a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings index ebb04ae153..315ae5eefc 100644 --- a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings @@ -130,7 +130,7 @@ "common_chat_backup" = "聊天室備份"; "common_copyright" = "著作權"; "common_creating_room" = "正在建立聊天室..."; -"common_current_user_left_room" = "離開聊天室"; +"common_current_user_left_room" = "已離開聊天室"; "common_dark" = "深色"; "common_decryption_error" = "解密錯誤"; "common_developer_options" = "開發者選項"; @@ -294,7 +294,7 @@ "full_screen_intent_banner_title" = "提升您的通話體驗"; "invite_friends_rich_title" = "🔐️ Join me on %1$@"; "invite_friends_text" = "嘿,來 %1$@ 和我聊天:%2$@"; -"leave_conversation_alert_subtitle" = "Are you sure that you want to leave this conversation? This conversation is not public and you won't be able to rejoin without an invite."; +"leave_conversation_alert_subtitle" = "您確定要離開對話嗎?此對話不是公開的,如果沒有收到邀請,您無法重新加入。"; "leave_room_alert_empty_subtitle" = "您確定要離開聊天室嗎?這裡只有您一個人。如果您離開了,包含您在內的所有人都無法再進入此聊天室。"; "leave_room_alert_private_subtitle" = "您確定要離開聊天室嗎?此聊天室不是公開的,如果沒有收到邀請,您無法重新加入。"; "leave_room_alert_subtitle" = "您確定要離開聊天室嗎?"; @@ -348,14 +348,16 @@ "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."; +"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_create_room_access_section_anyone_option_description" = "Anyone can join this room"; -"screen_create_room_access_section_anyone_option_title" = "Anyone"; -"screen_create_room_access_section_header" = "Room Access"; -"screen_create_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_access_section_knocking_option_title" = "Ask to join"; "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?"; @@ -847,6 +849,10 @@ "screen_session_verification_request_title" = "Verification requested"; "screen_session_verification_they_dont_match" = "不一樣"; "screen_session_verification_they_match" = "一樣"; +"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_waiting_to_accept_subtitle" = "準備開始驗證,請到您的其他工作階段接受請求。"; "screen_session_verification_waiting_to_accept_title" = "等待接受請求"; "screen_share_location_title" = "分享位置"; From b9409e5310fbb95b7d525950688d4f00258896cc Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 7 Nov 2024 16:20:52 +0200 Subject: [PATCH 08/74] Tweak the session verification icons and copy. --- .../SessionVerificationScreenModels.swift | 39 ++++++++++--------- .../View/SessionVerificationScreen.swift | 13 ++----- ...ication-iPad-en-GB.Accepting-Challenge.png | 4 +- ...d-en-GB.Accepting-Verification-Request.png | 4 +- ...ssionVerification-iPad-en-GB.Cancelled.png | 4 +- ...ication-iPad-en-GB.Declining-Challenge.png | 4 +- ...ification-iPad-en-GB.Initial-Initiator.png | 4 +- ...ification-iPad-en-GB.Initial-Responder.png | 4 +- ...rification-iPad-en-GB.Request-Accepted.png | 4 +- ...ion-iPad-en-GB.Requesting-Verification.png | 4 +- ...on-iPad-en-GB.SAS-Verification-started.png | 4 +- ...ification-iPad-en-GB.Showing-Challenge.png | 4 +- ...n-iPad-en-GB.Starting-SAS-Verification.png | 4 +- ...essionVerification-iPad-en-GB.Verified.png | 4 +- ...cation-iPad-pseudo.Accepting-Challenge.png | 4 +- ...-pseudo.Accepting-Verification-Request.png | 4 +- ...sionVerification-iPad-pseudo.Cancelled.png | 4 +- ...cation-iPad-pseudo.Declining-Challenge.png | 4 +- ...fication-iPad-pseudo.Initial-Initiator.png | 4 +- ...fication-iPad-pseudo.Initial-Responder.png | 4 +- ...ification-iPad-pseudo.Request-Accepted.png | 4 +- ...on-iPad-pseudo.Requesting-Verification.png | 4 +- ...n-iPad-pseudo.SAS-Verification-started.png | 4 +- ...fication-iPad-pseudo.Showing-Challenge.png | 4 +- ...-iPad-pseudo.Starting-SAS-Verification.png | 4 +- ...ssionVerification-iPad-pseudo.Verified.png | 4 +- ...on-iPhone-16-en-GB.Accepting-Challenge.png | 4 +- ...6-en-GB.Accepting-Verification-Request.png | 4 +- ...Verification-iPhone-16-en-GB.Cancelled.png | 4 +- ...on-iPhone-16-en-GB.Declining-Challenge.png | 4 +- ...tion-iPhone-16-en-GB.Initial-Initiator.png | 4 +- ...tion-iPhone-16-en-GB.Initial-Responder.png | 4 +- ...ation-iPhone-16-en-GB.Request-Accepted.png | 4 +- ...Phone-16-en-GB.Requesting-Verification.png | 4 +- ...hone-16-en-GB.SAS-Verification-started.png | 4 +- ...tion-iPhone-16-en-GB.Showing-Challenge.png | 4 +- ...one-16-en-GB.Starting-SAS-Verification.png | 4 +- ...nVerification-iPhone-16-en-GB.Verified.png | 4 +- ...n-iPhone-16-pseudo.Accepting-Challenge.png | 4 +- ...-pseudo.Accepting-Verification-Request.png | 4 +- ...erification-iPhone-16-pseudo.Cancelled.png | 4 +- ...n-iPhone-16-pseudo.Declining-Challenge.png | 4 +- ...ion-iPhone-16-pseudo.Initial-Initiator.png | 4 +- ...ion-iPhone-16-pseudo.Initial-Responder.png | 4 +- ...tion-iPhone-16-pseudo.Request-Accepted.png | 4 +- ...hone-16-pseudo.Requesting-Verification.png | 4 +- ...one-16-pseudo.SAS-Verification-started.png | 4 +- ...ion-iPhone-16-pseudo.Showing-Challenge.png | 4 +- ...ne-16-pseudo.Starting-SAS-Verification.png | 4 +- ...Verification-iPhone-16-pseudo.Verified.png | 4 +- 50 files changed, 120 insertions(+), 124 deletions(-) diff --git a/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/SessionVerificationScreenModels.swift b/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/SessionVerificationScreenModels.swift index ec7d72b44f..12424e3dce 100644 --- a/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/SessionVerificationScreenModels.swift +++ b/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/SessionVerificationScreenModels.swift @@ -5,7 +5,8 @@ // Please see LICENSE in the repository root for full details. // -import Foundation +import Compound +import SwiftUI enum SessionVerificationScreenViewModelAction { case finished @@ -26,32 +27,32 @@ struct SessionVerificationScreenViewState: BindableState { let flow: SessionVerificationScreenFlow var verificationState: SessionVerificationScreenStateMachine.State - var headerImageName: String { + var headerIcon: (keyPath: KeyPath, style: BigIcon.Style) { switch verificationState { case .initial: - return "lock" + return (\.devices, .defaultSolid) case .acceptingVerificationRequest: - return "hourglass" + return (\.devices, .defaultSolid) case .requestingVerification: - return "hourglass" + return (\.devices, .defaultSolid) case .verificationRequestAccepted: - return "face.smiling" + return (\.reaction, .defaultSolid) case .startingSasVerification: - return "hourglass" + return (\.devices, .defaultSolid) case .sasVerificationStarted: - return "hourglass" + return (\.devices, .defaultSolid) case .cancelling: - return "hourglass" + return (\.lockSolid, .defaultSolid) + case .showingChallenge: + return (\.reaction, .defaultSolid) case .acceptingChallenge: - return "hourglass" + return (\.reaction, .defaultSolid) case .decliningChallenge: - return "hourglass" - case .showingChallenge: - return "face.smiling" + return (\.reaction, .defaultSolid) case .verified: - return "checkmark.shield" + return (\.checkCircleSolid, .successSolid) case .cancelled: - return "exclamationmark.shield" + return (\.infoSolid, .alertSolid) } } @@ -60,12 +61,12 @@ struct SessionVerificationScreenViewState: BindableState { case .initial: switch flow { case .initiator: - return L10n.screenSessionVerificationOpenExistingSessionTitle + return L10n.screenSessionVerificationUseAnotherDeviceTitle case .responder: return L10n.screenSessionVerificationRequestTitle } case .acceptingVerificationRequest: - return L10n.screenSessionVerificationRequestTitle + return L10n.screenSessionVerificationWaitingAnotherDeviceTitle case .requestingVerification: return L10n.screenSessionVerificationWaitingToAcceptTitle case .verificationRequestAccepted: @@ -98,12 +99,12 @@ struct SessionVerificationScreenViewState: BindableState { case .initial: switch flow { case .initiator: - return L10n.screenSessionVerificationOpenExistingSessionSubtitle + return L10n.screenSessionVerificationUseAnotherDeviceSubtitle case .responder: return L10n.screenSessionVerificationRequestSubtitle } case .acceptingVerificationRequest: - return L10n.screenSessionVerificationRequestSubtitle + return L10n.screenSessionVerificationWaitingAnotherDeviceSubtitle case .requestingVerification: return L10n.screenSessionVerificationWaitingToAcceptSubtitle case .verificationRequestAccepted: diff --git a/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationScreen.swift b/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationScreen.swift index dfb5a1f577..0dda4ee0c5 100644 --- a/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationScreen.swift +++ b/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationScreen.swift @@ -31,15 +31,10 @@ struct SessionVerificationScreen: View { @ViewBuilder private var screenHeader: some View { VStack(spacing: 0) { - if context.viewState.verificationState == .initial { - BigIcon(icon: \.lockSolid) - .padding(.bottom, 16) - } else { - Image(systemName: context.viewState.headerImageName) - .bigIcon() - .padding(.bottom, 16) - } - + BigIcon(icon: context.viewState.headerIcon.keyPath, + style: context.viewState.headerIcon.style) + .padding(.bottom, 16) + Text(context.viewState.title ?? "") .font(.compound.headingMDBold) .multilineTextAlignment(.center) diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Accepting-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Accepting-Challenge.png index 58c12218f7..76a5c2482c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Accepting-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Accepting-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:78da542fab77c7138034ee29b3985d0b6198cb79600ec22679a9aa8cf6b7de7b -size 161895 +oid sha256:093952c8bbb20d47d49770aba04081684d057a5b5f149055e90e78677a2a59ec +size 162220 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Accepting-Verification-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Accepting-Verification-Request.png index e1b75aa3fb..eed613f242 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Accepting-Verification-Request.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Accepting-Verification-Request.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1e631e093fcbae1de84ecf012e2dad0feace858d4825f839adc9feae8d497ef -size 96902 +oid sha256:d34314c93b65050cf9a196b831aea3255d836a4f064602757924c10725e6a50d +size 98778 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Cancelled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Cancelled.png index e9017e415a..68e7521ef2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Cancelled.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Cancelled.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e2aacff101d124325e3966e44c22fa02ef1a307c23a723d6622d4ee64412c21 -size 95267 +oid sha256:ebb7355183ca0262339abe03c1fb3254f1cdc4ac2745070eaf48f508d4c4e036 +size 93905 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Declining-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Declining-Challenge.png index 58c12218f7..76a5c2482c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Declining-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Declining-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:78da542fab77c7138034ee29b3985d0b6198cb79600ec22679a9aa8cf6b7de7b -size 161895 +oid sha256:093952c8bbb20d47d49770aba04081684d057a5b5f149055e90e78677a2a59ec +size 162220 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial-Initiator.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial-Initiator.png index bd2dd65ff4..80de0e358e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial-Initiator.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial-Initiator.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7da5f266ee5cfcf31a53a3edd37e6077e9cc5266bdc02009eb69743d69c98d83 -size 95443 +oid sha256:b6dbcd72f3590b7479092b3424eb4fa1cde31d145fc64674fea45952b466676e +size 100849 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial-Responder.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial-Responder.png index 5eda7c579a..cc8608a2a0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial-Responder.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Initial-Responder.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de6d5e5d95b4fee23d4b0a7fb771752ac426c6bf81499b9c6e3a357a10d2c2f8 -size 125144 +oid sha256:544b7532106675cab7af24c26b8e4fec538f3db9d954dbb01d43c165e9404f94 +size 124983 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Request-Accepted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Request-Accepted.png index 8fd5a7453b..d2a5379de7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Request-Accepted.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Request-Accepted.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c17fe42adcc844769eebfef93482366a692ed8e8d7cd1bd098106e4435e25e92 -size 92605 +oid sha256:20e5b35491a6c586a4724dbffc5f90f119953663005eb8e7eb614c32540fa04f +size 91690 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Requesting-Verification.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Requesting-Verification.png index 8eed329f39..1a6ce56341 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Requesting-Verification.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Requesting-Verification.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6b0a9b619f1dc6f02399aa4976c3dc19796d987e2a41ed37e5c2a449c85c11d -size 98780 +oid sha256:0ec30edbbc01c05deafe947f7c3f334fc4482aff926adf68d7a9d2e71bf3bc7d +size 97729 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.SAS-Verification-started.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.SAS-Verification-started.png index 93aa6d0e38..5cb6a712ca 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.SAS-Verification-started.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.SAS-Verification-started.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:356ec08a1adbca9186d746bb84c3597ec1f7e324bcc975186b9233ee3d3813d5 -size 72478 +oid sha256:84dab505b5ded1fba821d93c460239fc3b8ba156b3f261f9391c36227c65062d +size 71434 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Showing-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Showing-Challenge.png index 1728de5221..be15c8d547 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Showing-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Showing-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8741e91150e57869e2f8d94a13360e57b4d243e9054711d2335a514e5d9029b -size 165427 +oid sha256:552fd0224f27cade91fe607c87648c2aab28c46fcfe5f7ee0a065689e768af17 +size 164748 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Starting-SAS-Verification.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Starting-SAS-Verification.png index 93aa6d0e38..5cb6a712ca 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Starting-SAS-Verification.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Starting-SAS-Verification.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:356ec08a1adbca9186d746bb84c3597ec1f7e324bcc975186b9233ee3d3813d5 -size 72478 +oid sha256:84dab505b5ded1fba821d93c460239fc3b8ba156b3f261f9391c36227c65062d +size 71434 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Verified.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Verified.png index b069b75c29..f940645f0d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Verified.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-en-GB.Verified.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:635a1ce925fbb458b9fe414d6621f78d42d1c00c8ac55c9136b7aa4bbe5315b5 -size 94303 +oid sha256:fc01d5d81d68e878a344b3989a78cdfbd1f6b34f4785eab85255564133bc88b9 +size 93000 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Accepting-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Accepting-Challenge.png index 0dbc6de5cd..a367afd2a0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Accepting-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Accepting-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28e89a7b00f5b07cc1ebef0034a38d2bfebdce8d8e924c20252877d8f4643d44 -size 180153 +oid sha256:e196922c62442c910c38dc097bb2a0b7529079a0aa002bfeec3a673925f6dcc4 +size 180582 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Accepting-Verification-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Accepting-Verification-Request.png index a372662b16..e424bf4f05 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Accepting-Verification-Request.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Accepting-Verification-Request.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55e04390c635595b18a60905e2ebffef065d27a88023484cd1a25e9a683ea378 -size 108580 +oid sha256:5ae01c6fc18e49c952ad0202540abbdd959bb01264e6c682b835a93c3254a21f +size 118334 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Cancelled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Cancelled.png index 877166a2c8..36e542d63c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Cancelled.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Cancelled.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c313669307a1f85aef0d367a1284685eee2ed0f07b4b0fcedfa3728f27b869f -size 108998 +oid sha256:e1717005a937f2599fbf77cb20af768dac84ec548b4fa06fbbc36ced53152cf5 +size 107553 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Declining-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Declining-Challenge.png index 0dbc6de5cd..a367afd2a0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Declining-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Declining-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28e89a7b00f5b07cc1ebef0034a38d2bfebdce8d8e924c20252877d8f4643d44 -size 180153 +oid sha256:e196922c62442c910c38dc097bb2a0b7529079a0aa002bfeec3a673925f6dcc4 +size 180582 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial-Initiator.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial-Initiator.png index 42fc1b2e3e..c4ba53f7e1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial-Initiator.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial-Initiator.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2145bd9b612e25b80915d4d5a125026bdb800f505c4fbb7908438da715e79fa5 -size 106608 +oid sha256:28d003928602f6669539a1ddc6a467a29171dc97b46bdc455ed2da34179feb6d +size 121565 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial-Responder.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial-Responder.png index 7f1fd82499..2ff0104a65 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial-Responder.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Initial-Responder.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bad67fb36d792965b12fe728fae7c9664d4b8031c554117162fadd4b74502045 -size 146678 +oid sha256:9ba093b11028e7ff672fc7fdfa3d0df629fa463893e2e7191e6a022100b5fff8 +size 146508 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Request-Accepted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Request-Accepted.png index f5cb9c384a..3bcd94b772 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Request-Accepted.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Request-Accepted.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34e080a55f1ba530db20813f64a561439ef668094fb83742ea94f25984385069 -size 102546 +oid sha256:7797d60ba9745e8b2e372988a329aa95663751ccd2d1e94710d9161e42d22078 +size 101777 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Requesting-Verification.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Requesting-Verification.png index afa704e8d8..9bcbd667f8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Requesting-Verification.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Requesting-Verification.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa39a6dc77a211f757f20bdfa63ef04bfd79dd3d3b69a5bb8e3d9fc454a18e06 -size 111330 +oid sha256:d0eff524cd9d12cd7bf2a8e8984b2629a202a1d876cec64e9e80204e6a0aef13 +size 110488 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.SAS-Verification-started.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.SAS-Verification-started.png index f577b869db..66f6d92157 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.SAS-Verification-started.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.SAS-Verification-started.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21a964833655bb12bbbb2ae486961cad6f3046bd3c2c6a2127c99821b14e0dcd -size 72175 +oid sha256:2547e9244d4b77e2f9f14a76e6953de43854b2714a747081cc96b07619fb5263 +size 71096 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Showing-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Showing-Challenge.png index 426bb9d736..317c09f8d9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Showing-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Showing-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f25fc8b1b70ac00f2eb1cf5b6e55c4c3b5e509b3ed2e03458c99c36fa5abb30d -size 184353 +oid sha256:06e13d43f8de2d1c6571bff27260a5e4998e74c163b95536bfcaa63dd8d0e09d +size 183174 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Starting-SAS-Verification.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Starting-SAS-Verification.png index f577b869db..66f6d92157 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Starting-SAS-Verification.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Starting-SAS-Verification.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21a964833655bb12bbbb2ae486961cad6f3046bd3c2c6a2127c99821b14e0dcd -size 72175 +oid sha256:2547e9244d4b77e2f9f14a76e6953de43854b2714a747081cc96b07619fb5263 +size 71096 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Verified.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Verified.png index 1acb67e6e9..93c199f7f8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Verified.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPad-pseudo.Verified.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c148a7440eb8cba1f937f385949dd60b2aeec5f5e61725d768c524599d27a5e -size 110794 +oid sha256:e0046de699cf2116f045f2c3962f2a1321b1fcd4052daae58f5fd0f63c381f96 +size 109433 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Accepting-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Accepting-Challenge.png index 99147967f7..8d97b62bb2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Accepting-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Accepting-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d039980194a63eb87c15b4179b6132cb98cd4b9c069a90483cc2761d771c7c6 -size 112841 +oid sha256:c103377195f66d616a0494c3a8875e57267ce2b4e40c3f4b8ec8decd4a86f6f7 +size 113100 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Accepting-Verification-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Accepting-Verification-Request.png index 19feb7d545..f25c8dca20 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Accepting-Verification-Request.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Accepting-Verification-Request.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8df3040ac64296541ce088a3c89d173874981fb413ec12168d4e6c976364c4a -size 54304 +oid sha256:59787c26b565686c7df1be3abd74df657b8b1dd57045ba322991492d19a03073 +size 58033 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Cancelled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Cancelled.png index ac0a568b0f..3f518cf490 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Cancelled.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Cancelled.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3eee192ba2ba7f7a04dc6b30ebd453ff037fd93cbdbc5f7385749f598718d2c -size 52650 +oid sha256:0ca50f8fef275d6de9455d7e9bb54e09ae3f3f3118ac99f07d89b19d40e97d53 +size 51690 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Declining-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Declining-Challenge.png index 99147967f7..8d97b62bb2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Declining-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Declining-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d039980194a63eb87c15b4179b6132cb98cd4b9c069a90483cc2761d771c7c6 -size 112841 +oid sha256:c103377195f66d616a0494c3a8875e57267ce2b4e40c3f4b8ec8decd4a86f6f7 +size 113100 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Initial-Initiator.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Initial-Initiator.png index f30541b374..2a412e956d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Initial-Initiator.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Initial-Initiator.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b6f32135cf4cfcbd8fd2414e45c88eff842789c4f5a72128ba76e969c0c25ed -size 53430 +oid sha256:0a7497a191de63a335dc9c202f329774a9fc19e58f03a8229366a5988f251b30 +size 57944 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Initial-Responder.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Initial-Responder.png index e8d110ad6d..ed2d0104c0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Initial-Responder.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Initial-Responder.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b4ab3956d6cdaab31410c633ad87f68b95992ed7f2f1fdcfe47d264833d925a -size 76508 +oid sha256:80978072d73aeb5da1e0770e43c90d4b520e9033869a0bdef0e7d2f18726cf5b +size 76338 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Request-Accepted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Request-Accepted.png index 2784a60391..42e19b541b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Request-Accepted.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Request-Accepted.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc443e3c292fc373eeabd6c6194e62b30bdb3aaf62be51c4c6a00f24eecd2701 -size 50313 +oid sha256:24ca5f4be0cb99d102fafeb8fa48ca45abb46ec0463641b4382c4f2cd6c08a31 +size 49827 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Requesting-Verification.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Requesting-Verification.png index f69522ee80..955b7bb47a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Requesting-Verification.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Requesting-Verification.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c24f2aeb174dbaad526a45ea0aadc4a88e96af5acee0395dce735437f33fed37 -size 56314 +oid sha256:fae4c9c5121b82e082366b1d7ae71276831a7d40df94d138329c3c134769bc5a +size 55510 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.SAS-Verification-started.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.SAS-Verification-started.png index c19a7629e7..e775767ef4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.SAS-Verification-started.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.SAS-Verification-started.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6f9ffc43e63a49254324af496f8aadda255e84f5ec97aae0f1a05542c8c1a5b -size 32123 +oid sha256:1e16a425e3fb0c4946932d50e94fa103dee23bc4366f68c66d813fb790242174 +size 31094 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Showing-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Showing-Challenge.png index fd6ea1a9c9..1bc59311dc 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Showing-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Showing-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0c95e9f0f51109b8fef6f771a8fe27bcd33eac2e244eefbcad2f223c8228fc2 -size 115566 +oid sha256:f300ea23a0ec87222c5126d1849c6790e2b3f34e98b49a266a990866862d453c +size 115248 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Starting-SAS-Verification.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Starting-SAS-Verification.png index c19a7629e7..e775767ef4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Starting-SAS-Verification.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Starting-SAS-Verification.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6f9ffc43e63a49254324af496f8aadda255e84f5ec97aae0f1a05542c8c1a5b -size 32123 +oid sha256:1e16a425e3fb0c4946932d50e94fa103dee23bc4366f68c66d813fb790242174 +size 31094 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Verified.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Verified.png index 7afd9890d0..29bfed2278 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Verified.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-en-GB.Verified.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9fff8ecc6a113ae1e4ede8a1e599972f47e80bd057b22145f361e8927354d59 -size 51657 +oid sha256:00819f8614a1ad24c40a10052132b25cdb5202459d94bc10485c903a6348dd84 +size 50419 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Accepting-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Accepting-Challenge.png index bec410d878..5898b89e2a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Accepting-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Accepting-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:251fc57d77b23ca84e5b659dfb3cf51effba91e496566447dd5d5956f19eb81a -size 134250 +oid sha256:560c79a382fc2e7154e764b49eeb443d771fd28c47d3a77f04d705c45d4064a0 +size 134554 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Accepting-Verification-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Accepting-Verification-Request.png index 20dc47e8d0..1ddebe56e5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Accepting-Verification-Request.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Accepting-Verification-Request.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:61faed09ca05772707dc737fe7c9fbe7c59ddd5852b607f7df13a43071d1e82c -size 74935 +oid sha256:1e7835d5c27384b6fef3f9d6fc675f4d960124d1bc525857222955b61a389a4b +size 82012 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Cancelled.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Cancelled.png index 4746b79354..467bd83788 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Cancelled.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Cancelled.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4cb1087bf68fc7dc34b5c26653ee7ddf3859f2f1de22df1513c1d7b944d68feb -size 71714 +oid sha256:f0c91675d682e16d63f46de2470009d7f1de83e327a91b49d59fd9f363d98d6c +size 70566 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Declining-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Declining-Challenge.png index bec410d878..5898b89e2a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Declining-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Declining-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:251fc57d77b23ca84e5b659dfb3cf51effba91e496566447dd5d5956f19eb81a -size 134250 +oid sha256:560c79a382fc2e7154e764b49eeb443d771fd28c47d3a77f04d705c45d4064a0 +size 134554 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Initial-Initiator.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Initial-Initiator.png index 66aab7502c..d226434fab 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Initial-Initiator.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Initial-Initiator.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:897ebea0b95135d24dbaf686e4fb6d39bd45057adc514ada77508fddd9a4c985 -size 70591 +oid sha256:08ecdf5643eef846297fc94ceb7051c3df4fdeb4f012bf9cdd9ab509a4f51b33 +size 81918 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Initial-Responder.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Initial-Responder.png index 9f49db15d9..2fa7e07cb9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Initial-Responder.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Initial-Responder.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a7ffbb91030a6ba3d0e064bd6cbaaa0f109915cc4f04ceced27b0185b6a541f -size 101933 +oid sha256:74f3e11279a27cae1ee631f1ecd9a1caad06413afbc96ca5449250c37b9c0b8e +size 101758 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Request-Accepted.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Request-Accepted.png index f8f6077cc1..89d79c8ebf 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Request-Accepted.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Request-Accepted.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dfc36dd990bf345a9fa23bd388414745f4724bf342586d120c65efafca228e35 -size 60837 +oid sha256:60a6a9afa852e0bedbea1290a5b15a0de6692ed2f98b549ab7806a263c253f49 +size 60139 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Requesting-Verification.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Requesting-Verification.png index d3e5135cbe..e8231f291c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Requesting-Verification.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Requesting-Verification.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c40c972bb56a40bbb70725248eee5ff642e9cced47e1b794128f1c2468309a84 -size 79541 +oid sha256:82ce8b845e4da08a1128dbbd2b5329dded3db3b66889c19ef040e74deb0438a1 +size 78555 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.SAS-Verification-started.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.SAS-Verification-started.png index 2d563d6a18..da443905af 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.SAS-Verification-started.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.SAS-Verification-started.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1cd1abe33be884130a8475ada0aab30cadd3ce7b1262e316bd0b4552aacead14 -size 33085 +oid sha256:c4436735155f7c4fc8e89c4e1763870ce160d02bf33ed0be7de8f1a7290469d8 +size 32044 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Showing-Challenge.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Showing-Challenge.png index fb252261b3..017ce34901 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Showing-Challenge.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Showing-Challenge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91e8118f1315c91e4c4968fd6662253f0da5785dbf54a1c32aeb1b91a1785de9 -size 134584 +oid sha256:2fb9b38b661e439fad8e4180f0e4d8881ccbfe3bf7f9aa9ecb0261c6e8781cb0 +size 133881 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Starting-SAS-Verification.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Starting-SAS-Verification.png index 2d563d6a18..da443905af 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Starting-SAS-Verification.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Starting-SAS-Verification.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1cd1abe33be884130a8475ada0aab30cadd3ce7b1262e316bd0b4552aacead14 -size 33085 +oid sha256:c4436735155f7c4fc8e89c4e1763870ce160d02bf33ed0be7de8f1a7290469d8 +size 32044 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Verified.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Verified.png index ff6e9cb0ad..9db9c407c8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Verified.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sessionVerification-iPhone-16-pseudo.Verified.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1590c8d73b8f24da7bc06e741b024bf6c4013670cc9f95fadd931157929591c -size 71663 +oid sha256:3bdff6ad83674283dcfabb0076ba73d8f7ac4491325d0e6b1490b0d16400c11a +size 70573 From 468afd8e878a2e8eda136ac4d036dd5bb40e4e2c Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Mon, 11 Nov 2024 10:32:58 +0000 Subject: [PATCH 09/74] Make stopSync more aware of background usage. (#3501) --- .../Sources/Application/AppCoordinator.swift | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 1a97ac8718..d86e6ca0a8 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -561,7 +561,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg showLoadingIndicator() - stopSync() + stopSync(isBackgroundTask: false) userSessionFlowCoordinator?.stop() guard !isSoft else { @@ -748,7 +748,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg navigationRootCoordinator.setRootCoordinator(PlaceholderScreenCoordinator()) - stopSync() + stopSync(isBackgroundTask: false) userSessionFlowCoordinator?.stop() let userID = userSession.clientProxy.userID @@ -848,7 +848,11 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg // MARK: - Application State - private func stopSync() { + private func stopSync(isBackgroundTask: Bool) { + if isBackgroundTask, UIApplication.shared.applicationState == .active { + // Attempt to stop the background task sync loop cleanly, only if the app not already running + return + } userSession?.clientProxy.stopSync() clientProxyObserver = nil } @@ -911,7 +915,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg @objc private func applicationWillTerminate() { - stopSync() + stopSync(isBackgroundTask: false) } @objc @@ -930,7 +934,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg backgroundTask = appMediator.beginBackgroundTask { [weak self] in guard let self else { return } - stopSync() + stopSync(isBackgroundTask: true) if let backgroundTask { appMediator.endBackgroundTask(backgroundTask) @@ -988,10 +992,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg scheduleBackgroundAppRefresh() task.expirationHandler = { [weak self] in - if UIApplication.shared.applicationState != .active { - // Attempt to stop the sync loop cleanly, only if the app not already running - self?.stopSync() - } + self?.stopSync(isBackgroundTask: true) MXLog.info("Background app refresh task expired") task.setTaskCompleted(success: true) @@ -1015,7 +1016,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg // Make sure we stop the sync loop, otherwise the ongoing request is immediately // handled the next time the app refreshes, which can trigger timeout failures. - stopSync() + stopSync(isBackgroundTask: true) backgroundRefreshSyncObserver?.cancel() task.setTaskCompleted(success: true) From 096bdbb15108f910621d9383416bd038091fa515 Mon Sep 17 00:00:00 2001 From: Element CI Date: Mon, 11 Nov 2024 04:02:37 -0800 Subject: [PATCH 10/74] Prepare next release --- CHANGES.md | 23 +++++++++++++++++++++++ ElementX.xcodeproj/project.pbxproj | 6 ++++-- project.yml | 2 +- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9c3b6148d2..ef61cce70d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,26 @@ +## Changes in 1.9.5 (2024-11-11) + +### What's Changed + +🐛 Bugfixes +* Stop setting up CallKit sessions when joining calls by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3496 +* Fix for creating a knocking room by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3499 +* Make stopSync more aware of background usage. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3501 + +🗣 Translations +* Translations update by @RiotRobot in https://github.com/element-hq/element-x-ios/pull/3500 + +🚧 In development 🚧 +* Add alias to public room creation by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3450 + +Others +* Fix incorrect analytics mapping for UTDs. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3497 +* Update compound. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3498 +* Tweak the session verification icons and copy. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3495 + + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.9.4...1.9.5 + ## Changes in 1.9.4 (2024-11-07) ### What's Changed diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 24ab4952ad..da4d2c323c 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -1549,6 +1549,7 @@ 47F29139BC2A804CE5E0757E /* MediaUploadPreviewScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModel.swift; sourceTree = ""; }; 4853C923A1AF43711D025EAF /* TextRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineView.swift; sourceTree = ""; }; 48A5C34C4E4268EF65D171EF /* RoomChangeRolesScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenModels.swift; sourceTree = ""; }; + 48CE6BF18E542B32FA52CE06 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = fa; path = fa.lproj/Localizable.stringsdict; sourceTree = ""; }; 48FEFF746DB341CDB18D7AAA /* RoomRolesAndPermissionsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsScreenViewModelTests.swift; sourceTree = ""; }; 490BEADEFB2D6B7C9F618AE8 /* AppLockTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockTimer.swift; sourceTree = ""; }; 49193CB0C248D621A96FB2AA /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/Localizable.strings; sourceTree = ""; }; @@ -7214,6 +7215,7 @@ 13802897C7AFA360EA74C0B0 /* en */, AACE9B8E1A4AE79A7E2914F6 /* es */, 4F5F0662483ED69791D63B16 /* et */, + 48CE6BF18E542B32FA52CE06 /* fa */, 653610CB5F9776EAAAB98155 /* fr */, C95ADE8D9527523572532219 /* hu */, 475D47D0BFE961B02BAC5D49 /* id */, @@ -7497,7 +7499,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 17.6; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; MACOSX_DEPLOYMENT_TARGET = 14.6; - MARKETING_VERSION = 1.9.5; + MARKETING_VERSION = 1.9.6; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCTION_APP_NAME = Element; @@ -7574,7 +7576,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 17.6; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; MACOSX_DEPLOYMENT_TARGET = 14.6; - MARKETING_VERSION = 1.9.5; + MARKETING_VERSION = 1.9.6; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; diff --git a/project.yml b/project.yml index 649c0bf736..9c04fccc87 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.5 + MARKETING_VERSION: 1.9.6 CURRENT_PROJECT_VERSION: 1 SUPPORTS_MACCATALYST: false From a0c99e88ce585d4041cdd7f20e00770b4c83f9f9 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:48:19 +0000 Subject: [PATCH 11/74] Regenerate thumbnails to see if it helps with phantom avatar switching. (#3503) --- ElementX/Sources/Other/Extensions/UNNotificationContent.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ElementX/Sources/Other/Extensions/UNNotificationContent.swift b/ElementX/Sources/Other/Extensions/UNNotificationContent.swift index 2fa224d5a6..cc77eb22df 100644 --- a/ElementX/Sources/Other/Extensions/UNNotificationContent.swift +++ b/ElementX/Sources/Other/Extensions/UNNotificationContent.swift @@ -184,7 +184,7 @@ extension UNMutableNotificationContent { private func getPlaceholderAvatarImageData(name: String, id: String) async -> Data? { // The version value is used in case the design of the placeholder is updated to force a replacement let shouldFlipAvatar = shouldFlipAvatar() - let prefix = "notification_placeholder\(shouldFlipAvatar ? "V8F" : "V8")" + let prefix = "notification_placeholder\(shouldFlipAvatar ? "V9F" : "V9")" let fileName = "\(prefix)_\(name)_\(id).png" if let data = try? Data(contentsOf: URL.temporaryDirectory.appendingPathComponent(fileName)) { MXLog.info("Found existing notification icon placeholder") From 77ade52718f919b8bbc01e6cf414fdbb5b420e66 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:45:06 +0000 Subject: [PATCH 12/74] Update the strings for unsupported calls. (#3502) --- .../Localizations/en.lproj/Localizable.strings | 2 ++ ElementX/Sources/Generated/Strings.swift | 4 ++++ .../CallInviteRoomTimelineView.swift | 15 +++++++++------ .../Room/RoomSummary/RoomEventStringBuilder.swift | 2 +- NSE/Sources/NotificationContentBuilder.swift | 2 +- ...st_callInviteRoomTimelineView-iPad-en-GB.1.png | 4 ++-- ...t_callInviteRoomTimelineView-iPad-pseudo.1.png | 4 ++-- ...llInviteRoomTimelineView-iPhone-16-en-GB.1.png | 4 ++-- ...lInviteRoomTimelineView-iPhone-16-pseudo.1.png | 4 ++-- 9 files changed, 25 insertions(+), 16 deletions(-) diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 3b8b01bc05..2633939413 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -226,6 +226,7 @@ "common_unable_to_invite_title" = "Unable to send invite(s)"; "common_unlock" = "Unlock"; "common_unmute" = "Unmute"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Unsupported event"; "common_username" = "Username"; "common_verification_cancelled" = "Verification cancelled"; @@ -789,6 +790,7 @@ "screen_room_timeline_add_reaction" = "Add emoji"; "screen_room_timeline_beginning_of_room" = "This is the beginning of %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "This is the beginning of this conversation."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use to the new Element X app."; "screen_room_timeline_less_reactions" = "Show less"; "screen_room_timeline_message_copied" = "Message copied"; "screen_room_timeline_no_permission_to_post" = "You do not have permission to post to this room"; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index fa25268816..1bb831c6b8 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -512,6 +512,8 @@ internal enum L10n { internal static var commonUnlock: String { return L10n.tr("Localizable", "common_unlock") } /// Unmute internal static var commonUnmute: String { return L10n.tr("Localizable", "common_unmute") } + /// Unsupported call + internal static var commonUnsupportedCall: String { return L10n.tr("Localizable", "common_unsupported_call") } /// Unsupported event internal static var commonUnsupportedEvent: String { return L10n.tr("Localizable", "common_unsupported_event") } /// Username @@ -1926,6 +1928,8 @@ internal enum L10n { } /// This is the beginning of this conversation. internal static var screenRoomTimelineBeginningOfRoomNoName: String { return L10n.tr("Localizable", "screen_room_timeline_beginning_of_room_no_name") } + /// Unsupported call. Ask if the caller can use to the new Element X app. + internal static var screenRoomTimelineLegacyCall: String { return L10n.tr("Localizable", "screen_room_timeline_legacy_call") } /// Show less internal static var screenRoomTimelineLessReactions: String { return L10n.tr("Localizable", "screen_room_timeline_less_reactions") } /// Message copied diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallInviteRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallInviteRoomTimelineView.swift index 3beab6197c..05d57448c8 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallInviteRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallInviteRoomTimelineView.swift @@ -13,12 +13,15 @@ struct CallInviteRoomTimelineView: View { let timelineItem: CallInviteRoomTimelineItem var body: some View { - Label(title: { Text(L10n.commonCallInvite) }, - icon: { CompoundIcon(\.voiceCall, size: .medium, relativeTo: .compound.bodyMD) }) - .font(.compound.bodyMD) - .foregroundColor(.compound.textSecondary) - .frame(maxWidth: .infinity, alignment: .center) - .padding() + Label { + Text(L10n.screenRoomTimelineLegacyCall) + } icon: { + CompoundIcon(\.voiceCall, size: .medium, relativeTo: .compound.bodyMD) + } + .font(.compound.bodyMD) + .foregroundColor(.compound.textSecondary) + .frame(maxWidth: .infinity, alignment: .center) + .padding() } } diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift index a5948fc4e7..1e3222a29d 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift @@ -73,7 +73,7 @@ struct RoomEventStringBuilder { } return prefix(L10n.commonPollSummary(question), with: displayName) case .callInvite: - return prefix(L10n.commonCallInvite, with: displayName) + return prefix(L10n.commonUnsupportedCall, with: displayName) case .callNotify: return prefix(L10n.commonCallStarted, with: displayName) } diff --git a/NSE/Sources/NotificationContentBuilder.swift b/NSE/Sources/NotificationContentBuilder.swift index f767a9538d..383098d176 100644 --- a/NSE/Sources/NotificationContentBuilder.swift +++ b/NSE/Sources/NotificationContentBuilder.swift @@ -131,7 +131,7 @@ struct NotificationContentBuilder { private func processCallInviteEvent(notificationItem: NotificationItemProxyProtocol, mediaProvider: MediaProviderProtocol?) async throws -> UNMutableNotificationContent { let notification = try await processCommonRoomMessage(notificationItem: notificationItem, mediaProvider: mediaProvider) - notification.body = L10n.commonCallInvite + notification.body = L10n.commonUnsupportedCall return notification } diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png index 8f0b1331f5..b81a7696c9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73e3426c1023e8174271fb1e163b85033ab1ea531881ed2a5a9f3db24ebd5598 -size 73834 +oid sha256:83c70644604dc70c886dea41fc3935e9d8d7bed388e0d57619bbdfe026c3b0c5 +size 78127 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png index eeefc7e2d8..a667d1bf06 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b9c353ac087285f4b2a7ac41f032f891cccef0cc76e1ea11c562223abdfb122 -size 77179 +oid sha256:d22830f81bb98725d9e25e49814b3263269ffd6f59a0af60fe19d55e13ab1448 +size 84129 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-en-GB.1.png index 2e62a1a941..a3aa4dbc25 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f9fc5b3400d6f5ee581d283f2e38dc0a9502f66f8d912a0158c8856eee650f9 -size 33067 +oid sha256:3f9beb2df735de7ad5d2c3c187b236672813db91a987992b13e2a344c663e3cf +size 38721 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-pseudo.1.png index 59252b40da..abb75a6173 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a08fabc8d61ef8ea8ae9e161b5c560e30eac85097823dc5077d1f32e65975cfb -size 37845 +oid sha256:7210cfeed3af08712b88d2f845118d284adf441f11f5cf03b84ea7b3d02d6205 +size 47915 From 2b153306dd769fb448911c6ff14a5801c966229b Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Tue, 12 Nov 2024 12:24:08 +0000 Subject: [PATCH 13/74] Update the project to use Xcode 16.1 (#3505) --- PreviewTests/Sources/PreviewTests.swift | 2 +- .../test_bugReport-iPhone-16-en-GB.1.png | 4 ++-- .../test_bugReport-iPhone-16-en-GB.2.png | 4 ++-- .../test_bugReport-iPhone-16-pseudo.1.png | 4 ++-- .../test_bugReport-iPhone-16-pseudo.2.png | 4 ++-- ...n-GB.Create-Public-Room-existing-alias.png | 4 ++-- ...en-GB.Create-Public-Room-invalid-alias.png | 4 ++-- ...oom-iPhone-16-en-GB.Create-Public-Room.png | 4 ++-- ...one-16-en-GB.Create-Room-without-users.png | 4 ++-- ...createRoom-iPhone-16-en-GB.Create-Room.png | 4 ++-- ...eudo.Create-Public-Room-existing-alias.png | 4 ++-- ...seudo.Create-Public-Room-invalid-alias.png | 4 ++-- ...om-iPhone-16-pseudo.Create-Public-Room.png | 4 ++-- ...ne-16-pseudo.Create-Room-without-users.png | 4 ++-- ...reateRoom-iPhone-16-pseudo.Create-Room.png | 4 ++-- ...cationSettingsScreen-iPhone-16-en-GB.1.png | 4 ++-- ...ationSettingsScreen-iPhone-16-pseudo.1.png | 4 ++-- ...st_pollFormScreen-iPhone-16-en-GB.Edit.png | 4 ++-- ...est_pollFormScreen-iPhone-16-en-GB.New.png | 4 ++-- ...t_pollFormScreen-iPhone-16-pseudo.Edit.png | 4 ++-- ...st_pollFormScreen-iPhone-16-pseudo.New.png | 4 ++-- ..._reportContentScreen-iPhone-16-en-GB.1.png | 4 ++-- ...reportContentScreen-iPhone-16-pseudo.1.png | 4 ++-- ...ilsEditScreen-iPhone-16-en-GB.Editable.png | 4 ++-- ...lsEditScreen-iPhone-16-pseudo.Editable.png | 4 ++-- .../MediaUploadingPreprocessorTests.swift | 2 +- fastlane/Fastfile | 22 +++++++++---------- 27 files changed, 61 insertions(+), 61 deletions(-) diff --git a/PreviewTests/Sources/PreviewTests.swift b/PreviewTests/Sources/PreviewTests.swift index 5fd769481a..5558714caf 100644 --- a/PreviewTests/Sources/PreviewTests.swift +++ b/PreviewTests/Sources/PreviewTests.swift @@ -15,7 +15,7 @@ import XCTest class PreviewTests: XCTestCase { private let deviceConfig: ViewImageConfig = .iPhoneX private let simulatorDevice: String? = "iPhone14,6" // iPhone SE 3rd Generation - private let requiredOSVersion = (major: 18, minor: 0) + private let requiredOSVersion = (major: 18, minor: 1) private let snapshotDevices = ["iPhone 16", "iPad"] private var recordMode: SnapshotTestingConfiguration.Record = .missing diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.1.png index b40a04a39c..3ccb34510e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4ca48111eef3faa437cab02d2f9b77f7ea0e0db7044ce356c242ae03da51719 -size 112787 +oid sha256:6f25c322c0d96697ebbfe37cc8f41968437e85b87f97e748cdea491488f8cb75 +size 112639 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.2.png index eb98ce3b89..e499cdfb02 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.2.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:119511075ab801b223b83f1101c2fb3da1c9ab11dcee8d193b668b46ee52cb4f -size 157198 +oid sha256:5e63f79d033afa74e531694a0c12494e35338d6ec8ae79af4994329b1cfa9760 +size 157066 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.1.png index f7c6a26c2c..e5ab66f18f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e898c781a857620e338ab3a84ece132c831a4b19351ee5f70109d4e137bf71a7 -size 166289 +oid sha256:dbfaf0931f09c371773b709625af2043bb071466f2747a0b103bfeac35ccb418 +size 165823 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.2.png index 7cbcb5a18d..1dd2e71f1f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.2.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9734dd90fa64366676961ca677e8d176ad36ba308f9e6939a209368a117f2d70 -size 192993 +oid sha256:b423001dd6139ac4c68427bb5eab3200af160c65f445eb9eca4028d4cba653ee +size 192079 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png index 5c280a5838..0c9b80f2e0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:acf39359c47be4101e19fe3d0bfcedb7f0a262b418f3ab3f90da38c9ad3b88f0 -size 130131 +oid sha256:2eae9a04d15e762cf6b176bb3bd5821b89bdb211699117afb808861bddd78a22 +size 129989 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png index 5d536e0a57..1fa9061ceb 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66610bab01ad7ed399d8c4f72fd8d04990eafbf911c8b666c3ca21beba88a58b -size 128602 +oid sha256:6888c9b3c1a7040d71398aeb79c1a4573dd5596eee4c914ab58b2aca3954de0e +size 128543 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png index 8f0fea0f9b..e716343e71 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:311d57b9b2cc2ad3b459c5817e6dd605740abef4559b571492de22a81b160285 -size 126941 +oid sha256:899d2b2ed4da2bf70ada0e6fd4321aef6b962f6da3a35eeeed7f6b56b7d6fe59 +size 126876 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png index 3e986cdcbb..b45b2e80ef 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d637d85d789f0d3d8756719f0b277a23b07730a21d46fe599afdb4b1143ce814 -size 95980 +oid sha256:edf83c0605163d2207d25c80a1a4114f80c7a132655da7c4f2e02fb278e1aeda +size 95990 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png index 215efe85a6..0749b3e7a3 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c89527ca06fb7a7b03cb6bb2feda23cd9325e98378eecc364f537c29d6878b08 -size 96262 +oid sha256:90b9741e61b00917ccfbd419f34af981eb9f944a30e15620ec269d70dafa66a8 +size 96294 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png index 96122c7846..580ea9f7d9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d191b67a8b246e26c7567427f09cd7562fc88402b06a150212a74eb55fb58831 -size 164266 +oid sha256:80d33358e3425fc1997f4e88d60b49b0a239302e9addc2e82c104e06fc6e4827 +size 163893 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png index 96122c7846..580ea9f7d9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d191b67a8b246e26c7567427f09cd7562fc88402b06a150212a74eb55fb58831 -size 164266 +oid sha256:80d33358e3425fc1997f4e88d60b49b0a239302e9addc2e82c104e06fc6e4827 +size 163893 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png index 96122c7846..580ea9f7d9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d191b67a8b246e26c7567427f09cd7562fc88402b06a150212a74eb55fb58831 -size 164266 +oid sha256:80d33358e3425fc1997f4e88d60b49b0a239302e9addc2e82c104e06fc6e4827 +size 163893 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png index ebeef4fda4..8d1c9f7cc7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:61ca01f8203d3c668ca2183f46d2954a32284624c8b7caaffd37124e2d454997 -size 126803 +oid sha256:02db1a440a19b94afd8d5d8876b83d003459c76c95c8c76ebd2a351fb8177b94 +size 126452 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png index 89c4aae8fa..4ee0a1009a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab43faa0b020b9628d10999a93d9c70e90e007eb788ce9a14eaca5330b9c5843 -size 127313 +oid sha256:a4c2d75263491ba4ab1153d3281a14d752b22381c4f49bf853b8e0f68f6b324e +size 126969 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-en-GB.1.png index 6159caa6ad..531dc815dd 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:773528462e21578b18913b3696f8614d8679645fb62c92f2344b5852ba9638a3 -size 92329 +oid sha256:c21c3ea27ac9839bbc7f8833610e0a51a6e6760880c0d1317e772bf2912d46d1 +size 92027 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-pseudo.1.png index 4fc0a1cc0f..44bcb716ed 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_notificationSettingsScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f31ea41a2793dcc67ae3dfd3c54014bd9bc15352fe0e2c8742cf62435be45ed -size 126574 +oid sha256:ba7519925fc4afbb5c19415e94520b143fe011574e05f1c8a53d6b6a74b9f63f +size 126013 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.Edit.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.Edit.png index 408cef51f5..2bf48287ad 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.Edit.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.Edit.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08afa1f613cec282b2e33635cd9c3f27b261551f3e3fca8abb7f246da3b872bd -size 73311 +oid sha256:b02e2157743d2e768218051d54e0974ef5c39b934fa4634d43718e8b4ceaec01 +size 73302 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.New.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.New.png index 1a66842d58..7c2aae7658 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.New.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.New.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:443329bbf5362a9a96ac46b96b6888a324550501a9f23e073f2319ac40501c0d -size 71836 +oid sha256:9be456bd194cff211021f905cd730221cf906e236b0b8879962a38e1d43e4598 +size 71615 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.Edit.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.Edit.png index ff5e858af7..93b3b650b5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.Edit.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.Edit.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26559d5ff08ce908efae27b352af8aabeca49f4a8b78f5f43582def38b27cf6e -size 83493 +oid sha256:e6d890e96d22309d0195951f7675948fafc92457e368d48f6a3fd921c1774587 +size 83468 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.New.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.New.png index 1a7a5ce208..e794b6aeb5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.New.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.New.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ba37435702fee3ee5e125ed3300efe64c878c49dedf853371de7dabf8b30332 -size 88037 +oid sha256:42b87fe104dff813561d71281324db46beeb6ff13983e392e63ae50234758705 +size 87830 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-en-GB.1.png index 0264bbf24c..0b1a9cae13 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d740cb882db2bb28a58d230ddbecb05e5137ed90599b548d0c738a41c0328627 -size 76955 +oid sha256:5dcdb831ac0280b214032b69541fb2477d7b7fe424ba8f736a4653ecffa15ecf +size 76949 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-pseudo.1.png index c6a952c1e4..ccb0217769 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4d7c5eb70787cf15781d04f624de54f40214f069f02ae148006c34a492c333ac -size 108915 +oid sha256:10e930e4812753de6c21166119c60c770a4319eb143884eef1f095ccac661110 +size 108956 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Editable.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Editable.png index 2c10803442..f8efbb1f06 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Editable.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Editable.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aab4eda3890d79da42a2945387ea8f7ff046643d5e8e0b1d17275814ad284183 -size 57794 +oid sha256:8056bc13948e460652ba7b76ac908f6490d1ce107724dd595ca53df5d4b02acd +size 57469 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Editable.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Editable.png index 035d621a30..10963df605 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Editable.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Editable.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:651a9dae5da28d6b42de24f1f9154c8f5bad7c0bc88f3fd924a489d6f6ba9bc2 -size 67616 +oid sha256:8743bd26c5c538b1e3419d5e32845c88dae8090d29eda408e6c979c3807f8ffe +size 67433 diff --git a/UnitTests/Sources/MediaUploadingPreprocessorTests.swift b/UnitTests/Sources/MediaUploadingPreprocessorTests.swift index 93ae732697..245935a585 100644 --- a/UnitTests/Sources/MediaUploadingPreprocessorTests.swift +++ b/UnitTests/Sources/MediaUploadingPreprocessorTests.swift @@ -336,7 +336,7 @@ final class MediaUploadingPreprocessorTests: XCTestCase { // Check resulting image info XCTAssertEqual(imageInfo.mimetype, "image/heic") XCTAssertEqual(imageInfo.blurhash, "KGD]3ns:T00$kWxFXmt6xv") - XCTAssertEqual(imageInfo.size ?? 0, 1_857_833, accuracy: 100) + XCTAssertEqual(imageInfo.size ?? 0, 1_850_479, accuracy: 100) XCTAssertEqual(imageInfo.width, 3024) XCTAssertEqual(imageInfo.height, 4032) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 9e336b42d7..c27dc3e3cb 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -7,7 +7,7 @@ if File.exist?(enterprise) end before_all do - xcversion(version: "16.0") + xcversion(version: "16.1") ENV["FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT"] = "180" ENV["FASTLANE_XCODE_LIST_TIMEOUT"] = "180" @@ -84,7 +84,7 @@ lane :unit_tests do |options| run_tests( scheme: "UnitTests", - device: "iPhone 16 (18.0)", + device: "iPhone 16 (18.1)", ensure_devices_found: true, result_bundle: true, number_of_retries: 3, @@ -94,7 +94,7 @@ lane :unit_tests do |options| if !options[:skip_previews] run_tests( scheme: "PreviewTests", - device: "iPhone SE (3rd generation) (18.0)", + device: "iPhone SE (3rd generation) (18.1)", ensure_devices_found: true, result_bundle: true, number_of_retries: 3, @@ -107,15 +107,15 @@ end lane :ui_tests do |options| create_simulator_if_necessary( - name: "iPhone 16 (18.0)", + name: "iPhone 16 (18.1)", type: "com.apple.CoreSimulator.SimDeviceType.iPhone-16", - runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-0" + runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-1" ) create_simulator_if_necessary( - name: "iPad (10th generation) (18.0)", + name: "iPad (10th generation) (18.1)", type: "com.apple.CoreSimulator.SimDeviceType.iPad-10th-generation", - runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-0" + runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-1" ) if options[:test_name] @@ -128,7 +128,7 @@ lane :ui_tests do |options| run_tests( scheme: "UITests", - devices: ["iPhone 16 (18.0)", "iPad (10th generation) (18.0)"], + devices: ["iPhone 16 (18.1)", "iPad (10th generation) (18.1)"], ensure_devices_found: true, prelaunch_simulator: true, result_bundle: true, @@ -143,16 +143,16 @@ lane :integration_tests do clear_derived_data() create_simulator_if_necessary( - name: "iPhone 16 Pro (18.0)", + name: "iPhone 16 Pro (18.1)", type: "com.apple.CoreSimulator.SimDeviceType.iPhone-16-Pro", - runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-0" + runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-1" ) reset_simulator = ENV.key?('CI') run_tests( scheme: "IntegrationTests", - device: "iPhone 16 Pro (18.0)", + device: "iPhone 16 Pro (18.1)", ensure_devices_found: true, result_bundle: true, reset_simulator: reset_simulator From f7aeb3ee955161b33c8ee4ba4844498982030eec Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Tue, 12 Nov 2024 14:00:51 +0100 Subject: [PATCH 14/74] Stacked Avatars View (#3504) * stacked avatars * fix tests * remove comment --- ElementX.xcodeproj/project.pbxproj | 4 ++ ElementX/Sources/Other/AvatarSize.swift | 3 + .../SwiftUI/Views/StackedAvatarsView.swift | 66 +++++++++++++++++++ .../TimelineReadReceiptsView.swift | 29 ++++---- .../Sources/GeneratedPreviewTests.swift | 6 ++ .../test_roomScreen-iPad-en-GB.1.png | 4 +- .../test_roomScreen-iPad-pseudo.1.png | 4 +- .../test_roomScreen-iPhone-16-en-GB.1.png | 4 +- .../test_roomScreen-iPhone-16-pseudo.1.png | 4 +- .../test_stackedAvatarsView-iPad-en-GB.1.png | 3 + .../test_stackedAvatarsView-iPad-pseudo.1.png | 3 + ...t_stackedAvatarsView-iPhone-16-en-GB.1.png | 3 + ..._stackedAvatarsView-iPhone-16-pseudo.1.png | 3 + ...tylerView-iPad-en-GB.Mock-Timeline-RTL.png | 4 +- ...ledStylerView-iPad-en-GB.Mock-Timeline.png | 4 +- ...ylerView-iPad-pseudo.Mock-Timeline-RTL.png | 4 +- ...edStylerView-iPad-pseudo.Mock-Timeline.png | 4 +- ...View-iPhone-16-en-GB.Mock-Timeline-RTL.png | 4 +- ...ylerView-iPhone-16-en-GB.Mock-Timeline.png | 4 +- ...iew-iPhone-16-pseudo.Mock-Timeline-RTL.png | 4 +- ...lerView-iPhone-16-pseudo.Mock-Timeline.png | 4 +- ..._timelineReadReceiptsView-iPad-en-GB.1.png | 4 +- ...timelineReadReceiptsView-iPad-pseudo.1.png | 4 +- ...lineReadReceiptsView-iPhone-16-en-GB.1.png | 4 +- ...ineReadReceiptsView-iPhone-16-pseudo.1.png | 4 +- .../test_timelineView-iPad-en-GB.1.png | 4 +- .../test_timelineView-iPad-pseudo.1.png | 4 +- .../test_timelineView-iPhone-16-en-GB.1.png | 4 +- .../test_timelineView-iPhone-16-pseudo.1.png | 4 +- 29 files changed, 144 insertions(+), 56 deletions(-) create mode 100644 ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPad-en-GB.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPad-pseudo.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPhone-16-en-GB.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPhone-16-pseudo.1.png diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index da4d2c323c..3c8d612e79 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -1012,6 +1012,7 @@ E0FB26262689F04D66A949D7 /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E227F34BE43B08E098796E /* TestablePreview.swift */; }; E14E469CD97550D0FC58F3CA /* CancellableTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE52983FAFB4E0998C00EE8A /* CancellableTask.swift */; }; E184FFAD32342D3D6E2F89AA /* PinnedEventsTimelineScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D53754227CEBD06358956D7 /* PinnedEventsTimelineScreenCoordinator.swift */; }; + E1C67E5D9E22135A8FEBBD60 /* StackedAvatarsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8558D41DD4B553A752C868A /* StackedAvatarsView.swift */; }; E1DF24D085572A55C9758A2D /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; }; E21FE4C5B614F311C0955859 /* UserProfileProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C454AE59914B551A6D02C0 /* UserProfileProxy.swift */; }; E27C4D1A1F8BB77CA790B403 /* InviteUsersScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A861DA5932B128FE1DCB5CE2 /* InviteUsersScreenCoordinator.swift */; }; @@ -1946,6 +1947,7 @@ A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModelProtocol.swift; sourceTree = ""; }; A7E37072597F67C4DD8CC2DB /* ComposerDraftServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerDraftServiceProtocol.swift; sourceTree = ""; }; A84D413BF49F0E980F010A6B /* LogViewerScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenCoordinator.swift; sourceTree = ""; }; + A8558D41DD4B553A752C868A /* StackedAvatarsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackedAvatarsView.swift; sourceTree = ""; }; A861DA5932B128FE1DCB5CE2 /* InviteUsersScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenCoordinator.swift; sourceTree = ""; }; A8DF55467ED4CE76B7AE9A33 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/InfoPlist.strings; sourceTree = ""; }; A9873374E72AA53260AE90A2 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = ""; }; @@ -2989,6 +2991,7 @@ 7EB58E4E8D6D634C246AD5C2 /* RoomInviterLabel.swift */, 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */, AEB5FF7A09B79B0C6B528F7C /* SFNumberedListView.swift */, + A8558D41DD4B553A752C868A /* StackedAvatarsView.swift */, E10DA51DBC8C7E1460DBCCBD /* UserProfileListRow.swift */, AD529C89924EE32CE307F36F /* VisualListItem.swift */, ); @@ -6952,6 +6955,7 @@ F37629BAA5E8F50AAF2A131D /* SoftLogoutScreenViewModel.swift in Sources */, CF4044A8EED5C41BC0ED6ABE /* SoftLogoutScreenViewModelProtocol.swift in Sources */, DF004A5B2EABBD0574D06A04 /* SplashScreenCoordinator.swift in Sources */, + E1C67E5D9E22135A8FEBBD60 /* StackedAvatarsView.swift in Sources */, 3DAF325D8AE461F7CDB282BD /* StartChatScreen.swift in Sources */, 6CD61FAF03E8986523C2ABB8 /* StartChatScreenCoordinator.swift in Sources */, C051475DFF4C8EBDDF4DC8E4 /* StartChatScreenModels.swift in Sources */, diff --git a/ElementX/Sources/Other/AvatarSize.swift b/ElementX/Sources/Other/AvatarSize.swift index aa1b477b1c..4aec55c4c1 100644 --- a/ElementX/Sources/Other/AvatarSize.swift +++ b/ElementX/Sources/Other/AvatarSize.swift @@ -46,6 +46,7 @@ enum UserAvatarSizeOnScreen { case editUserDetails case suggestions case blockedUsers + case knockingUsers var value: CGFloat { switch self { @@ -75,6 +76,8 @@ enum UserAvatarSizeOnScreen { return 96 case .dmDetails: return 75 + case .knockingUsers: + return 28 } } } diff --git a/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift b/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift new file mode 100644 index 0000000000..b4cf190fef --- /dev/null +++ b/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift @@ -0,0 +1,66 @@ +// +// 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 StackedAvatarInfo { + let url: URL? + let name: String? + let contentID: String +} + +struct StackedAvatarsView: View { + let overlap: CGFloat + let lineWidth: CGFloat + var shouldStackFromLast = false + let avatars: [StackedAvatarInfo] + let avatarSize: AvatarSize + let mediaProvider: MediaProviderProtocol? + + var body: some View { + HStack(spacing: -overlap) { + ForEach(0.. displayNumber { Text("+\(remaining)") .font(.compound.bodySM) diff --git a/PreviewTests/Sources/GeneratedPreviewTests.swift b/PreviewTests/Sources/GeneratedPreviewTests.swift index c42a3a3024..492fbd85f9 100644 --- a/PreviewTests/Sources/GeneratedPreviewTests.swift +++ b/PreviewTests/Sources/GeneratedPreviewTests.swift @@ -785,6 +785,12 @@ extension PreviewTests { } } + func test_stackedAvatarsView() { + for preview in StackedAvatarsView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_startChatScreen() { for preview in StartChatScreen_Previews._allPreviews { assertSnapshots(matching: preview) 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 16e7cc7bbc..ff3b7d7e6d 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:dbba95d7bded549e3b54dd8468f44f338f75df9dc2d384c800ca69d240c526bb -size 295572 +oid sha256:033f43d5be47abd91cd5f36b93a8b32b0f9800e7a8a947e0c2cd4debd8b4c694 +size 295633 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 74310722a3..65b5872de5 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:0d28a596ca48a0cd680be7014adef2f2aac11aaf1592676da57b942bd3329708 -size 297527 +oid sha256:bc959ac1d5a22da8ca928d891e9f0a649dfa28b1cdfa7a91b0a74d2189cc38a3 +size 297711 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 e044e0e64d..bd01dd63c7 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:fbfaf40b0602964736bbe6dc41beea21d1733c8ec0b84c82e0c547596c4032f0 -size 180515 +oid sha256:26de643c28b47f7fd0631c0c754d979c43fc51bc274e863fdb6acaf0ed299960 +size 180507 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 f8a53763cf..10b37a11f3 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:9c928084fecfee3ff804ebc41d17b3433fe7dea94f7c0c82ef7c40175203061f -size 178534 +oid sha256:58ae4f390371ef48aca7b5faeb4c75ba7bdfad4294797fd422c0d102036ee4a8 +size 178571 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPad-en-GB.1.png new file mode 100644 index 0000000000..774ff3f4ca --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f2cccb8af5d3b2f9caaa29584364834f3c58685da13e7b0ed9c305b9aed08954 +size 76364 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPad-pseudo.1.png new file mode 100644 index 0000000000..774ff3f4ca --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f2cccb8af5d3b2f9caaa29584364834f3c58685da13e7b0ed9c305b9aed08954 +size 76364 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..cbd7c80e16 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ccd3bb00ea04f0482ad6fe087b3421eff7273d5ffe659b13d26b079486f22ce +size 35126 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..cbd7c80e16 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_stackedAvatarsView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ccd3bb00ea04f0482ad6fe087b3421eff7273d5ffe659b13d26b079486f22ce +size 35126 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 54f4895512..7b7cf7d2f3 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:17403a44b5f71ef51b12a2392d3c8eed2b30cd4ddeb25188c29e738f8ed3c3fc -size 285676 +oid sha256:7222cb8f9b8d5f35d70b7c9d6498825271f2f4701328789f29ce4434060df93b +size 285869 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 1e57c3f8e0..dff6e61c8c 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:2f576e2c44ecda928a8afdbd29bf9c79631517d9c42d6b8a16b1dcdbac1885a9 -size 284180 +oid sha256:5c52b5f33ef60a009368a4f69841c64596c4cd3c0597206f7c6e77159b3182b9 +size 284251 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 f2545df7ae..c9a94af864 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:fc726f43094e192a9f367c0ece419d581de5d43bab53275eaa73ae25969e65ab -size 287326 +oid sha256:72f66b7d7cf29690fe5cbf3c7a624462369735231ffdab3d196c31eb285c1a3c +size 287531 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 e9f3a9cb70..cfb579b34c 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:982eb9dd6ed5fe3c4c13811ae463b80f1b571fec18953d98d641d367cd705db0 -size 285493 +oid sha256:7c65adc9249fe0e725160eed2ad5854e7b719b7d3c5fad3b5501b9259db582c2 +size 285667 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 33f9d4b5d6..ef759681c5 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:1a39ebd070935b96d697dc0c70244962a8d55c6c9ce3e958808c35f8ed009506 -size 190461 +oid sha256:dd5ce3f8ce6de79110a64880e7d65132bd4eeb689562e65dda79b9fe39ef8148 +size 190473 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 bbd1e7fb93..a284470ca0 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:e4278c55045120935c02fe570409295a0eb0b984a103e5fd09d314bb2f4e09a6 -size 188620 +oid sha256:2edda65eb2b77d65105f17dada5fbe8be1f7610cce462e967ffe1513fdd878b0 +size 188590 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 651a6d750a..60f0aa2585 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:1eb05117714fb7853917a32dba87565ed0ad83b3097ca01703581dc0ec8e7b7a -size 188275 +oid sha256:989002cd49c3455efc5d1f3982cf5b8efbe9527d6bef80464e01ac11452fe1c6 +size 188265 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 d9a42bff3f..c67b5b9bc4 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:a421129a41149ca0c3be3981ef169ddcbce8b0c57a0b94ea43a3fea2dc4202f8 -size 186287 +oid sha256:c0bce781f1031c33a6f2161d11f572ded92262d9e394bb82b4fdbfed15a9c41b +size 186270 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-en-GB.1.png index 1316b0ac85..c5270a494b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd4120e82a247929c0b20e95e5e75889853c5aeb1ca529a4928657159781e1ba -size 74341 +oid sha256:3832d15395990ba70d725f952594ba8525ae4d6e34b0c94a3518c1498c629ad7 +size 74883 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-pseudo.1.png index e8692c0bf2..6361f6d3bb 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d037477f4b7663cfbe5067f1782261da930f7ded80f39d44dc6ad64ada84b15 -size 74917 +oid sha256:d4bf1c97977129580a538593b9a418855a7293040b0f98c4c86eaf52f89922b3 +size 75388 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-en-GB.1.png index 4c4e7faa2e..8d75cb1e82 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b649638070c638275198e207be41db38c0ddae908bab0da10f2bd69d2c8054d -size 33967 +oid sha256:1f8e0493510c102234ef73712d603f484bdee6db7393eb3ba9e4a890787fdb51 +size 34021 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-pseudo.1.png index c8740c3e25..b9ef5f58cf 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineReadReceiptsView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74ddd0f05b73833113d6814c5c2afe86e5429bbdb01a4e82d09f075208df4362 -size 34383 +oid sha256:40f28da9c6ca03946b234d0b9f33b30c69d03628b3e8f1d0ced8f06e36fc050a +size 34494 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 16e7cc7bbc..ff3b7d7e6d 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:dbba95d7bded549e3b54dd8468f44f338f75df9dc2d384c800ca69d240c526bb -size 295572 +oid sha256:033f43d5be47abd91cd5f36b93a8b32b0f9800e7a8a947e0c2cd4debd8b4c694 +size 295633 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 74310722a3..65b5872de5 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:0d28a596ca48a0cd680be7014adef2f2aac11aaf1592676da57b942bd3329708 -size 297527 +oid sha256:bc959ac1d5a22da8ca928d891e9f0a649dfa28b1cdfa7a91b0a74d2189cc38a3 +size 297711 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 e044e0e64d..bd01dd63c7 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:fbfaf40b0602964736bbe6dc41beea21d1733c8ec0b84c82e0c547596c4032f0 -size 180515 +oid sha256:26de643c28b47f7fd0631c0c754d979c43fc51bc274e863fdb6acaf0ed299960 +size 180507 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 f8a53763cf..10b37a11f3 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:9c928084fecfee3ff804ebc41d17b3433fe7dea94f7c0c82ef7c40175203061f -size 178534 +oid sha256:58ae4f390371ef48aca7b5faeb4c75ba7bdfad4294797fd422c0d102036ee4a8 +size 178571 From 3a600a94d577cf099e250031b135296f6f2ec6e4 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Tue, 12 Nov 2024 14:13:28 +0200 Subject: [PATCH 15/74] Fix #1947 - Check expected files are still present before restoring a session. --- .../Sources/Services/UserSession/SessionDirectories.swift | 8 ++++++++ .../Sources/Services/UserSession/UserSessionStore.swift | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/ElementX/Sources/Services/UserSession/SessionDirectories.swift b/ElementX/Sources/Services/UserSession/SessionDirectories.swift index 8a93aed129..29b1b076b3 100644 --- a/ElementX/Sources/Services/UserSession/SessionDirectories.swift +++ b/ElementX/Sources/Services/UserSession/SessionDirectories.swift @@ -51,6 +51,14 @@ struct SessionDirectories: Hashable, Codable { } } + /// Check that mission critical files (the crypto db) are still in the right place when restoring a session + /// iOS might decide to move the app with its user defaults and keychain but without + /// some of the files stored in the shared container e.g. after a device transfer, offloading etc. + /// If that happens we should fail the session restoration. + func isNonTransientUserDataValid() -> Bool { + FileManager.default.fileExists(atPath: dataPath.appending("/matrix-sdk-crypto.sqlite3")) + } + private func deleteFiles(at url: URL, with prefix: String) throws { let sessionDirectoryContents = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil) for url in sessionDirectoryContents where url.lastPathComponent.hasPrefix(prefix) { diff --git a/ElementX/Sources/Services/UserSession/UserSessionStore.swift b/ElementX/Sources/Services/UserSession/UserSessionStore.swift index 310475032a..1f4ca5e5b5 100644 --- a/ElementX/Sources/Services/UserSession/UserSessionStore.swift +++ b/ElementX/Sources/Services/UserSession/UserSessionStore.swift @@ -118,6 +118,11 @@ class UserSessionStore: UserSessionStoreProtocol { MXLog.info("Restoring client with encrypted store.") } + guard credentials.restorationToken.sessionDirectories.isNonTransientUserDataValid() else { + MXLog.error("Failed restoring login, missing non-transient user data") + return .failure(.failedRestoringLogin) + } + let homeserverURL = credentials.restorationToken.session.homeserverUrl let builder = ClientBuilder From b122b02beebddd7ce5c96a1553aeb9ec6d075da0 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 13 Nov 2024 14:02:47 +0200 Subject: [PATCH 16/74] Share extension (#3506) * Setup simple share extension * Switch the app url scheme to be the full bundle identifier * Setup a share extension that show a SwiftUI view, uses rust tracing and redirects to the hosting aplication * Move media as json through the custom scheme into the main app and deep link into the media upload preview screen * Fix message forwarding and global search screen room summary provider filtering. * Tweak the message forwarding and global search screen designs. * Add a room selection screen to use after receiving a share request from the share extension * Fix share extension entitlements * Share the temporary directory between the main app and the extensions; rename the caches one. * Remove the no longer needed notification avatar flipping fix. * Extract the placeholder avatar image generator from the NSE * Nest `AvatarSize` within the new `Avatars` enum * Donate an `INSendMessageIntent` to the system every time we send a message so they appear as share suggestions * Support suggestions in the share extension itself * Improve sharing animations and fix presentation when room already on the stack * Clear all routes when sharing without a preselected room. * Fix broken unit tests * Various initial tweaks following code review. * Correctly clean up and dismiss the share extension for all paths. * Move the share extension path to a constants enum * Rename UserSessionFlowCoordinator specific share extension states and events * Add UserSession and Room flow coordinator share route tests * Tweak the share extension logic. --- ElementX.xcodeproj/project.pbxproj | 284 +++++++++++++++++- .../xcschemes/ShareExtension.xcscheme | 98 ++++++ .../Sources/Application/AppCoordinator.swift | 6 + .../Application/Navigation/AppRoutes.swift | 29 +- .../EncryptionSettingsFlowCoordinator.swift | 2 +- .../OnboardingFlowCoordinator.swift | 4 +- .../PinnedEventsTimelineFlowCoordinator.swift | 4 +- .../RoomFlowCoordinator.swift | 123 +++++--- .../UserSessionFlowCoordinator.swift | 67 +++++ ...erSessionFlowCoordinatorStateMachine.swift | 12 +- .../Mocks/Generated/GeneratedMocks.swift | 96 +++--- .../RoomTimelineControllerFactoryMock.swift | 2 +- .../Other/{AvatarSize.swift => Avatars.swift} | 73 +++-- .../Other/Extensions/FileManager.swift | 2 +- .../Extensions/UNNotificationContent.swift | 67 +---- ElementX/Sources/Other/Extensions/URL.swift | 17 +- .../Other/Logging/ExtensionLogger.swift | 6 +- .../SwiftUI/Views/AvatarHeaderView.swift | 8 +- .../SwiftUI/Views/LoadableAvatarImage.swift | 4 +- .../Views/OverridableAvatarImage.swift | 4 +- .../Other/SwiftUI/Views/RoomAvatarImage.swift | 2 +- .../SwiftUI/Views/StackedAvatarsView.swift | 2 +- .../GlobalSearchScreenModels.swift | 4 +- .../GlobalSearchScreenViewModel.swift | 10 +- .../View/GlobalSearchScreenCell.swift | 8 +- .../MessageForwardingScreenModels.swift | 4 +- .../MessageForwardingScreenViewModel.swift | 13 +- .../View/MessageForwardingScreen.swift | 4 +- .../RoomSelectionScreenCoordinator.swift | 52 ++++ .../RoomSelectionScreenModels.swift | 39 +++ .../RoomSelectionScreenViewModel.swift | 105 +++++++ ...RoomSelectionScreenViewModelProtocol.swift | 14 + .../View/RoomSelectionScreen.swift | 104 +++++++ .../Sources/Services/Client/ClientProxy.swift | 2 +- .../Room/RoomSummary/RoomSummary.swift | 14 + .../RoomTimelineController.swift | 58 ++++ .../RoomTimelineControllerFactory.swift | 8 +- ...oomTimelineControllerFactoryProtocol.swift | 6 +- .../UserSession/SessionDirectories.swift | 6 +- .../ShareExtension/ShareExtensionModels.swift | 21 ++ .../UITests/UITestsAppCoordinator.swift | 1 + ElementX/SupportingFiles/Info.plist | 2 +- ElementX/SupportingFiles/target.yml | 3 +- .../NotificationServiceExtension.swift | 6 +- NSE/SupportingFiles/target.yml | 2 +- .../Sources/GeneratedPreviewTests.swift | 6 + .../test_globalSearchScreen-iPad-en-GB.1.png | 4 +- .../test_globalSearchScreen-iPad-pseudo.1.png | 4 +- ...t_globalSearchScreen-iPhone-16-en-GB.1.png | 4 +- ..._globalSearchScreen-iPhone-16-pseudo.1.png | 4 +- ...t_messageForwardingScreen-iPad-en-GB.1.png | 4 +- ..._messageForwardingScreen-iPad-pseudo.1.png | 4 +- ...sageForwardingScreen-iPhone-16-en-GB.1.png | 4 +- ...ageForwardingScreen-iPhone-16-pseudo.1.png | 4 +- .../test_roomSelectionScreen-iPad-en-GB.1.png | 3 + ...test_roomSelectionScreen-iPad-pseudo.1.png | 3 + ..._roomSelectionScreen-iPhone-16-en-GB.1.png | 3 + ...roomSelectionScreen-iPhone-16-pseudo.1.png | 3 + .../ShareExtensionViewController.swift | 141 +++++++++ .../Sources/View/ShareExtensionView.swift | 23 ++ ShareExtension/SupportingFiles/Info.plist | 55 ++++ .../ShareExtension.entitlements | 10 + ShareExtension/SupportingFiles/target.yml | 85 ++++++ .../MediaProvider/MediaProviderTests.swift | 18 +- UnitTests/Sources/RestorationTokenTests.swift | 6 +- .../Sources/RoomFlowCoordinatorTests.swift | 25 ++ .../Sources/SessionDirectoriesTests.swift | 4 +- .../UserSessionFlowCoordinatorTests.swift | 39 ++- project.yml | 1 + 69 files changed, 1583 insertions(+), 272 deletions(-) create mode 100644 ElementX.xcodeproj/xcshareddata/xcschemes/ShareExtension.xcscheme rename ElementX/Sources/Other/{AvatarSize.swift => Avatars.swift} (55%) rename NSE/Sources/Other/NSELogger.swift => ElementX/Sources/Other/Logging/ExtensionLogger.swift (93%) create mode 100644 ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenCoordinator.swift create mode 100644 ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenModels.swift create mode 100644 ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenViewModel.swift create mode 100644 ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenViewModelProtocol.swift create mode 100644 ElementX/Sources/Screens/RoomSelectionScreen/View/RoomSelectionScreen.swift create mode 100644 ElementX/Sources/ShareExtension/ShareExtensionModels.swift create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-en-GB.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-pseudo.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-en-GB.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-pseudo.1.png create mode 100644 ShareExtension/Sources/ShareExtensionViewController.swift create mode 100644 ShareExtension/Sources/View/ShareExtensionView.swift create mode 100644 ShareExtension/SupportingFiles/Info.plist create mode 100644 ShareExtension/SupportingFiles/ShareExtension.entitlements create mode 100644 ShareExtension/SupportingFiles/target.yml diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 3c8d612e79..6f4f71e3f0 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ /* Begin PBXBuildFile section */ 0033481EE363E4914295F188 /* LocalizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C070FD43DC6BF4E50217965A /* LocalizationTests.swift */; }; + 00C3023B6DF55024D8876B76 /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 3D8BEEFCA07BEA43F4F4BF77 /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 01681E8B20AD6F0D237F2DC1 /* IdentityConfirmedScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C6624240FFD32B7F0834229 /* IdentityConfirmedScreenViewModel.swift */; }; 0180C44B997EDA8D21F883AC /* RoomNotificationSettingsCustomSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B746EFA112532A7B701FB914 /* RoomNotificationSettingsCustomSectionView.swift */; }; 01B63F1A04A276B39AC17014 /* CallInviteRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9A3D3CFA199FA7897364547 /* CallInviteRoomTimelineItem.swift */; }; @@ -31,6 +32,7 @@ 02D8DF8EB7537EB4E9019DDB /* EventBasedTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 218AB05B4E3889731959C5F1 /* EventBasedTimelineItemProtocol.swift */; }; 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 */; }; 03CDCA6243F89B194E3FAD17 /* EncryptionAuthenticity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955336CBD5ED73C792D1F580 /* EncryptionAuthenticity.swift */; }; 0437765FF480249486893CC7 /* ScreenTrackerViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 196004E7695FBA292A7944AF /* ScreenTrackerViewModifier.swift */; }; 044DD8F80231BC30570F7965 /* UserDiscoveryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65AAD845E53B0C8B5E0812C2 /* UserDiscoveryService.swift */; }; @@ -39,7 +41,10 @@ 059173B3C77056C406906B6D /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = D4DA544B2520BFA65D6DB4BB /* target.yml */; }; 05BAB510CBC2ED35C154ADD0 /* AnalyticsPromptScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFD012C3A9F5EF276DDD4AA /* AnalyticsPromptScreenViewModelProtocol.swift */; }; 05EC896A4B9AF4A56670C0BB /* SessionVerificationUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4777F0142E330A75C46FE4 /* SessionVerificationUITests.swift */; }; + 05FF0CD80EDAB3A7C0D4700A /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; }; + 0638CBDE3098B1C3F23AFCFA /* MXLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111B698739E3410E2CDB7144 /* MXLog.swift */; }; 066A1E9B94723EE9F3038044 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.swift */; }; + 069358C2C825A19DE6CB127E /* TracingConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED003DF1B7CF40E7073A2280 /* TracingConfiguration.swift */; }; 06B31F84CE52A7A7C271267C /* SecureBackupRecoveryKeyScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0FF08D0BD7D0B4B6877AB7D /* SecureBackupRecoveryKeyScreenViewModelTests.swift */; }; 06B55882911B4BF5B14E9851 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 227AC5D71A4CE43512062243 /* URL.swift */; }; 06D3942496E9E0E655F14D21 /* NotificationManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */; }; @@ -109,6 +114,7 @@ 1555A7643D85187D4851040C /* TemplateScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4549FCB53F43DB0B278374BC /* TemplateScreen.swift */; }; 1583E2D766E4485FF91662FC /* PermalinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA3EB5B1848CF4F64E63C6B7 /* PermalinkTests.swift */; }; 15913A5B07118C1268A840E4 /* RoomSummaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 046C0D3F53B0B5EF0A1F5BEA /* RoomSummaryTests.swift */; }; + 1621BF6316FFFEF5AE067C77 /* Avatars.swift in Sources */ = {isa = PBXBuildFile; fileRef = C142248014E08E885E323E56 /* Avatars.swift */; }; 1653275750CE11F5CE94DDFD /* ReadReceiptsSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8063E65441E771200108C558 /* ReadReceiptsSummaryView.swift */; }; 167D00CAA13FAFB822298021 /* MediaProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */; }; 16CBD087038DE3815CDA512C /* PollMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D38391154120264910D19528 /* PollMock.swift */; }; @@ -119,12 +125,14 @@ 17BC15DA08A52587466698C5 /* RoomMessageEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */; }; 18867F4F1C8991EEC56EA932 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; }; 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 */; }; 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 */; }; 19DF5600A7F547B22DD7872A /* CompletionSuggestionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A12D3D8138F1B71AFA7C858 /* CompletionSuggestionService.swift */; }; 19FE025AE9BA2959B6589B0D /* RoomMemberDetailsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC575D1895FA62591451A93 /* RoomMemberDetailsScreen.swift */; }; + 1A3783005E6945F8583AF997 /* NSItemProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72EFC8C634469F9262659C7 /* NSItemProvider.swift */; }; 1A3B073568D1DC8F76F1F3A0 /* UserProfileScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23EE69982BBA18C6D51AD08E /* UserProfileScreen.swift */; }; 1A70A2199394B5EC660934A5 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = A678E40E917620059695F067 /* MatrixRustSDK */; }; 1A83DD22F3E6F76B13B6E2F9 /* VideoRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C8616254EE40CA8BA5E9BC2 /* VideoRoomTimelineItemContent.swift */; }; @@ -176,12 +184,14 @@ 25C4C1100B6EA79F5CC7CBB5 /* AppLockSetupPINScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 989D7380D9C86B3A10D30B13 /* AppLockSetupPINScreenViewModelTests.swift */; }; 260FFC1475EE94F641C3F3F9 /* PollFormScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A40F1985065500F0E7F61A27 /* PollFormScreenViewModelProtocol.swift */; }; 261261778DEFAEFC042B875E /* JoinedRoomProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07C6B0B087FE6601C3F77816 /* JoinedRoomProxy.swift */; }; + 26252AA9AED64010788F4C26 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A3E8741D199CD1A37F4CBF /* UIView.swift */; }; 2689D22EF1D10D22B0A4DAEA /* NotificationContentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7BB243B26D54EF1A0C422C0 /* NotificationContentBuilder.swift */; }; 273AB64B9A26B61C51858867 /* AsyncSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = A73A07BAEDD74C48795A996A /* AsyncSequence.swift */; }; 274CE3C986841D15FD530BF5 /* ShimmerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97CE98208321C4D66E363612 /* ShimmerModifier.swift */; }; 275EDE8849A2AC1D9309ED7C /* TemplateScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43456E73F8A2D52B69B9FB9 /* TemplateScreenViewModel.swift */; }; 2797C9D9BA642370F1C85D78 /* Untranslated.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = F75DF9500D69A3AAF8339E69 /* Untranslated.stringsdict */; }; 27F015B0D5436633B5B3C8C3 /* SecureBackupRecoveryKeyScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7061BE2C0BF427C38AEDEF5E /* SecureBackupRecoveryKeyScreenViewModel.swift */; }; + 27FEF0F40750465195C9D6D6 /* RoomSelectionScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B9D191A81FFB0C72CE73E77 /* RoomSelectionScreenModels.swift */; }; 2814E7075BF3A5C0CCBC9F90 /* RoomDirectorySearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AF32E4136FD6F159D86C2C /* RoomDirectorySearchView.swift */; }; 281BED345D59A9A6A99E9D98 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; }; 282A5F3375DDC774AE09B0C3 /* TracingConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */; }; @@ -214,6 +224,7 @@ 2E8C6672D0EE7D5B1BEDB8E2 /* ServerConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */; }; 2F09DF0CB213CAE86A3E3B67 /* EventTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B10423B9102086A2D9BFCBA /* EventTimelineItem.swift */; }; 2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086B997409328F091EBA43CE /* RoomScreenUITests.swift */; }; + 2F2906AE9BC3D0E79A6F98F8 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; }; 2F6207CB5C4715FE313B1E95 /* TimelineViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6509708F54FC883604DFDC95 /* TimelineViewModelTests.swift */; }; 2F623DA1122140A987B34D08 /* NotificationSettingsEditScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA7BB497B2F539C17E88F6B7 /* NotificationSettingsEditScreenViewModelProtocol.swift */; }; 2F94054F50E312AF30BE07F3 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B21E611DADDEF00307E7AC /* String.swift */; }; @@ -243,6 +254,7 @@ 355B11D08CE0CEF97A813236 /* AppRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A9E3FBE8A66B5A17AD7F74 /* AppRoutes.swift */; }; 3582056513A384F110EC8274 /* MediaPlayerProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7A2C4A3A74F0D2FFE9356A /* MediaPlayerProviderTests.swift */; }; 35E975CFDA60E05362A7CF79 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 1222DB76B917EB8A55365BA5 /* target.yml */; }; + 36206F74DDEBF9BEAF6A6A1F /* ExtensionLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41A8571A8A071FB41778C016 /* ExtensionLogger.swift */; }; 366D5BFE52CB79E804C7D095 /* CallScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD9547E47C58930E2CE8306 /* CallScreenViewModelTests.swift */; }; 36926D795D6D19177C7812F8 /* EncryptionResetPasswordScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6935A55AB3B0C94BC566DD6 /* EncryptionResetPasswordScreenCoordinator.swift */; }; 369BF960E52BBEE61F8A5BD1 /* BlockedUsersScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */; }; @@ -264,6 +276,7 @@ 3982C505960006B341CFD0C6 /* UserDetailsEditScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27D0EA07BD545CC9F234DB8D /* UserDetailsEditScreenModels.swift */; }; 3982E60F9C126437D5E488A3 /* PillContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A6314FDC51DA25712D9A81 /* PillContextTests.swift */; }; 39A987B3E41B976D1DF944C6 /* CallScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */; }; + 39DFC4B9EB6A8757210BDEC6 /* RoomSelectionScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DD2A058F3566FEEBA1D11B3 /* RoomSelectionScreenViewModelProtocol.swift */; }; 3A08584ECDD4A4541DBF21F8 /* EmojiLoaderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 201305507D7DFD16E544563A /* EmojiLoaderProtocol.swift */; }; 3A164187907DA43B7858F9EC /* CompletionSuggestionServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5EA0312A6262484AA393AC9 /* CompletionSuggestionServiceTests.swift */; }; 3A64A93A651A3CB8774ADE8E /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = BA93CD75CCE486660C9040BD /* Collections */; }; @@ -360,6 +373,7 @@ 4DAEE2468669848B6C9F55B4 /* TimelineReadReceiptsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33035418BB35754232985871 /* TimelineReadReceiptsView.swift */; }; 4DEEFB73181C3B023DB42686 /* NetworkMonitorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1575947B7A6FE08C57FE5EE4 /* NetworkMonitorProtocol.swift */; }; 4E0D9E09B52CEC4C0E6211A8 /* MediaPickerScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F49FB9EE2913234F06CE68 /* MediaPickerScreenCoordinator.swift */; }; + 4E22086585CB3B35FEEFBBB9 /* UserPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35FA991289149D31F4286747 /* UserPreference.swift */; }; 4E36A66E0EDA74BF3A036FD0 /* RoomChangeRolesScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAD8C633AA57948B34EDCF7 /* RoomChangeRolesScreenViewModelProtocol.swift */; }; 4E8A2A2CFEB212F14E49E1A1 /* AppLockSetupSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5484457C81B325660901B161 /* AppLockSetupSettingsScreen.swift */; }; 4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */; }; @@ -386,11 +400,11 @@ 53C1E7F6A7D6409D89F36ED7 /* AggregatedReactionMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69CB8242D69B7E4D0B32E18D /* AggregatedReactionMock.swift */; }; 53DEF39F0C4DE02E3FC56D91 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 800631D7250B7F93195035F1 /* KeychainAccess */; }; 53F1196F9C69512306A2693F /* TextRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C19F54A0C4FC9AB7ABD583 /* TextRoomTimelineItemContent.swift */; }; - 5455147CAC63F71E48F7D699 /* NSELogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3D455BC2423D911A62ACFB2 /* NSELogger.swift */; }; 54AE8860D668AFD96E7E177B /* UITestsScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */; }; 54C774874BED4A8FAD1F22FE /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.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 */; }; 562EFB9AB62B38830D9AA778 /* TimelineMediaFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */; }; @@ -409,6 +423,8 @@ 5992EF10AA157EBD97D88910 /* AudioRecorderState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6569593FA36B22259E806A67 /* AudioRecorderState.swift */; }; 59C41313AED7566C3AC51163 /* RoomSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A953B6C0C431DBF4DD00B4 /* RoomSummary.swift */; }; 59F940FCBE6BC343AECEF75E /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E2245243369B99216C7D84E /* ImageCache.swift */; }; + 5AA81A4E2D40A32A9E7F71F2 /* ShareExtensionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C3ADF21BE301D0DA48F2A7E /* ShareExtensionView.swift */; }; + 5AC5CD6D893073EE4D9A277E /* ShareExtensionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D27299A36536DBF91AE8FA6 /* ShareExtensionViewController.swift */; }; 5AE6404C4FD4848ACCFF9EDC /* SecureBackupLogoutConfirmationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1573D28C8A9FB6399D0EEFB /* SecureBackupLogoutConfirmationScreenCoordinator.swift */; }; 5B6E5AD224509E6C0B520D6E /* RoomMemberDetailsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DDF49CEBC0DFC59C308335F /* RoomMemberDetailsScreenViewModelProtocol.swift */; }; 5B7D24A318AFF75AD611A026 /* RoomDirectorySearchScreenScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE6BFF453838CF6C3982C5A3 /* RoomDirectorySearchScreenScreenViewModelTests.swift */; }; @@ -421,6 +437,7 @@ 5D53AE9342A4C06B704247ED /* MediaLoaderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A02406480C351B8C6E0682C /* MediaLoaderProtocol.swift */; }; 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 */; }; 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 */; }; @@ -463,6 +480,8 @@ 66357ECB73B1290E5490A012 /* WebRegistrationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F418426410F3823F3EB0828 /* WebRegistrationScreenViewModelProtocol.swift */; }; 663E198678778F7426A9B27D /* Collection.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FAFE1C2149E6AC8156ED2B /* Collection.swift */; }; 6681D6D3ADF69EBD2625F29A /* KnockedRoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E8F4D7D61B80EBD5CB92F8A /* KnockedRoomProxyMock.swift */; }; + 66832DE7B5C2E861045265DC /* RoomSelectionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D879DC5515B1D42577F96C94 /* RoomSelectionScreen.swift */; }; + 66E9202BED03B5BB00E812A1 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 227AC5D71A4CE43512062243 /* URL.swift */; }; 67160204A8D362BB7D4AD259 /* Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693E16574C6F7F9FA1015A8C /* Search.swift */; }; 6786C4B0936AC84D993B20BF /* NotificationSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5F06F2F09B2EDD067DC2174 /* NotificationSettingsScreen.swift */; }; 6793E75E3EBE48EBB8F857AF /* ProcessInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077B01C13BBA2996272C5FB5 /* ProcessInfo.swift */; }; @@ -561,6 +580,7 @@ 7A642EE5F1ADC5D520F21924 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */; }; 7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */; }; 7A8B264506D3DDABC01B4EEB /* AppMediator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53AC78E49A297AC1D72A7CF /* AppMediator.swift */; }; + 7AED78DC086695E93F0647D2 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.swift */; }; 7B1605C6FFD4D195F264A684 /* RoomPollsHistoryScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40233F2989AD49906BB310D /* RoomPollsHistoryScreenViewModelTests.swift */; }; 7B3A59786DB2F741A1743ED0 /* PinnedEventsTimelineScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 510E89B989477E5EE8E503C0 /* PinnedEventsTimelineScreenViewModelProtocol.swift */; }; 7B5DAB915357BE596529BF25 /* MapTilerStaticMapProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */; }; @@ -630,6 +650,7 @@ 88CBF1595E39CE697928DE48 /* SFNumberedListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEB5FF7A09B79B0C6B528F7C /* SFNumberedListView.swift */; }; 88F348E2CB14FF71CBBB665D /* AudioRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7475C5AE20BA896930907EA8 /* AudioRoomTimelineItemContent.swift */; }; 890F0D453FE388756479AC97 /* AnalyticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C687844F60BFF532D49A994C /* AnalyticsTests.swift */; }; + 89198AE2649DD77673D5793B /* ExtensionLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41A8571A8A071FB41778C016 /* ExtensionLogger.swift */; }; 8944548A684F1C837CEC47F4 /* RoomMembersListScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D0946F77B696176E062D037 /* RoomMembersListScreenModels.swift */; }; 89658A44C9FC19B58FD1C226 /* ServerConfirmationScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F08776C48FFB47CACF64ED10 /* ServerConfirmationScreenViewModelTests.swift */; }; 899359A4D1147601F6C4E364 /* PillConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB8D34E94AB07128DB73D6C7 /* PillConstants.swift */; }; @@ -656,6 +677,7 @@ 8D3E1FADD78E72504DE0E402 /* UserAgentBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */; }; 8D71E5E53F372202379BECCE /* BugReportScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 303FCADE77DF1F3670C086ED /* BugReportScreenViewModel.swift */; }; 8DC176CC5ABA24138EB443DD /* RoomMemberDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55679AF67545EF8087E47BE /* RoomMemberDetails.swift */; }; + 8DCA1F05C3BA6ED826F1599D /* RoomSelectionScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83B4E3F1265581683E4997B8 /* RoomSelectionScreenViewModel.swift */; }; 8DCD9CC5361FF22A5B2C20F1 /* AppLockSetupSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D9FCE4D1E3A81AC1CC5CB91 /* AppLockSetupSettingsScreenCoordinator.swift */; }; 8DDC6F28C797D8685F2F8E32 /* AnalyticsConsentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57B6B383F1FD04CC0E7B60C6 /* AnalyticsConsentState.swift */; }; 8E650379587C31D7912ED67B /* UNNotification+Creator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC0AEA686E425F86F6BA0404 /* UNNotification+Creator.swift */; }; @@ -694,7 +716,6 @@ 9603EEF6DE980BB1D15D4707 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A3E8741D199CD1A37F4CBF /* UIView.swift */; }; 962A4F8AD6312804E2C6BB6E /* PhotoLibraryPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A232D9156D225BD9FD1D0C43 /* PhotoLibraryPicker.swift */; }; 964B9D2EC38C488C360CE0C9 /* HomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B902EA6CD3296B0E10EE432B /* HomeScreen.swift */; }; - 968A5B890004526AB58A217C /* AvatarSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E24B88AD3D1599E8CB1376E0 /* AvatarSize.swift */; }; 9696ECAFB4F0C079C5C2A526 /* AppLockSetupPINScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FAF8C2226A57B9AB7446B31 /* AppLockSetupPINScreenCoordinator.swift */; }; 96B3606E30F824095B1DD022 /* NetworkMonitorMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DA1E8F287680C8ED25EDBAC /* NetworkMonitorMock.swift */; }; 97189E495F0E47805D1868DB /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 527578916BD388A09F5A8036 /* DTCoreText */; }; @@ -848,6 +869,7 @@ B818580464CFB5400A3EF6AE /* TimelineModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 029D5701F80A9AF7167BB4D0 /* TimelineModels.swift */; }; B879446FD8E65A711EF8F9F7 /* AdvancedSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B63B69F9A2BC74DD40DC75C8 /* AdvancedSettingsScreenViewModel.swift */; }; B89990DD875B0B603D4D4332 /* NotificationItemProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B927CF5EF7FCCDA5EDC474B /* NotificationItemProxyProtocol.swift */; }; + B8EC8A544162B0A41B9AB339 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC3F82523D6F48B926D6AF68 /* AppSettings.swift */; }; B93D7CE520088AD53FA6D53C /* SettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B663BE498BB39EADC24025D /* SettingsScreenModels.swift */; }; B93FA0DA1504B301CAEE141B /* NotificationSettingsProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6F5D66F158A6662F953733E /* NotificationSettingsProxy.swift */; }; B94368839BDB69172E28E245 /* MXLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111B698739E3410E2CDB7144 /* MXLog.swift */; }; @@ -870,9 +892,11 @@ BDA68E8D95B2B24B28825B8B /* LoginScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C368CAB3063EF275357ECD4 /* LoginScreenViewModel.swift */; }; BDC4EB54CC3036730475CB8B /* QRCodeLoginScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25E7E9B7FEAB6169D960C206 /* QRCodeLoginScreenViewModelTests.swift */; }; 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 */; }; 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 */; }; C051475DFF4C8EBDDF4DC8E4 /* StartChatScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B99E13633862847D8B7E2815 /* StartChatScreenModels.swift */; }; C08AAE7563E0722C9383F51C /* RoomMembersListScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B8E176484A89BAC389D4076 /* RoomMembersListScreen.swift */; }; C0B97FFEC0083F3A36609E61 /* TimelineItemMacContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = A243A6E6207297123E60DE48 /* TimelineItemMacContextMenu.swift */; }; @@ -983,11 +1007,12 @@ D6DE764B17FB4A9A12C33BF4 /* MessageComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1DF3FFFE5ED2B8133F43A7 /* MessageComposer.swift */; }; D7CDBAE82782BD0529DECB5F /* AttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BD6ED18E2EB61E28C340AD /* AttributedString.swift */; }; D8459AAD6969B1431ECBE990 /* UnsupportedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9E535B3388755B65C34CD10 /* UnsupportedRoomTimelineView.swift */; }; - D876EC0FED3B6D46C806912A /* AvatarSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E24B88AD3D1599E8CB1376E0 /* AvatarSize.swift */; }; D8CFA0EE46376F9FF04EEE45 /* TextRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4853C923A1AF43711D025EAF /* TextRoomTimelineView.swift */; }; + D8F1462EA00AFC939FF9ACCA /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 203D1ACC20287F8986C959D3 /* target.yml */; }; D98B5EE8C4F5A2CE84687AE8 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; }; D9F80CE61BF8FF627FDB0543 /* LoadableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352359663A0E52BA20761EE /* LoadableImage.swift */; }; DA7E867F5EAFF8E20B2EE3B6 /* SecureBackupScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3D16709ADD4F4BCC710B1E /* SecureBackupScreenModels.swift */; }; + DAF63A9CF9932CA8F6830F11 /* ShareExtensionModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAC01A97A43BE07B9E94E43 /* ShareExtensionModels.swift */; }; DB079D1929B5A5F52D207C83 /* RoomDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466C71A0FED9BFF287613C82 /* RoomDetailsScreenModels.swift */; }; DB65401349C143DFF883E2B0 /* AnalyticsPromptScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C8EC6EA7EDFCE46710DA306 /* AnalyticsPromptScreenViewModel.swift */; }; DBC8D1DBFE9F9CA7662BC8AA /* RoomPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 974AEAF3FE0C577A6C04AD6E /* RoomPermissions.swift */; }; @@ -1097,8 +1122,10 @@ F12F6BED7B6D7EE4BEE55039 /* PlainMentionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AE78FA0011E07920AE83135 /* PlainMentionBuilder.swift */; }; F18CA61A58C77C84F551B8E7 /* GeneratedMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57916A1578D8043BB0795441 /* GeneratedMocks.swift */; }; F253AAB4C8F06208173C9C4A /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; + F255083E18CDBFDF7E640FB1 /* Avatars.swift in Sources */ = {isa = PBXBuildFile; fileRef = C142248014E08E885E323E56 /* Avatars.swift */; }; F2D5C0E1351DA7BD16867629 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD4823EAB4B4E8BAB4F6B8C /* TimelineStyle.swift */; }; F37629BAA5E8F50AAF2A131D /* SoftLogoutScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB7BAD55A4E2B8E5828CD64C /* SoftLogoutScreenViewModel.swift */; }; + F38D32C1B0232AAFE6A0822C /* ExtensionLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41A8571A8A071FB41778C016 /* ExtensionLogger.swift */; }; F3E2D3F7ACDED65A4E5CD8DE /* RoomMembersListScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECF79FB25E2D4BD6F50CE7C9 /* RoomMembersListScreenViewModel.swift */; }; F3ECA377FF77E81A4F1FA062 /* TimelineItemSendInfoLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753B4C6C0EDDCBF0708DC384 /* TimelineItemSendInfoLabel.swift */; }; F3F38062C6CA21CF403C5C90 /* AudioConverterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2757B1BE23DF8AA239937243 /* AudioConverterProtocol.swift */; }; @@ -1112,6 +1139,7 @@ F5D2270B5021D521C0D22E11 /* FlowCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.swift */; }; F656F92A63D3DC1978D79427 /* Algorithms in Frameworks */ = {isa = PBXBuildFile; productRef = 290FDEDA4D764B9F7EBE55A9 /* Algorithms */; }; 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 */; }; F697284B9B5F2C00CFEA3B12 /* EmojiDetectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E93D91DE3288010390DEE /* EmojiDetectionTests.swift */; }; F6DFA23885980118AD7359C5 /* NotificationSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2389732B0E115A999A069083 /* NotificationSettingsScreenCoordinator.swift */; }; @@ -1149,6 +1177,7 @@ FD4C21F8DA1E273DE94FCD1A /* NotificationItemProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B927CF5EF7FCCDA5EDC474B /* NotificationItemProxyProtocol.swift */; }; FD762761C5D0C30E6255C3D8 /* ServerConfirmationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */; }; FDD5B4B616D9FF4DE3E9A418 /* QRCodeScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92DB574F954CC2B40F7BE892 /* QRCodeScannerView.swift */; }; + FDE47D4686BA0F86BB584633 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = CAA3B9DF998B397C9EE64E8B /* Collections */; }; 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 */; }; @@ -1173,6 +1202,13 @@ remoteGlobalIDString = C0FAEB81CFD9776CD78CE489; remoteInfo = ElementX; }; + 52A426E590105174D83B9532 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = AC22997D58D612146053154D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 19F0C845D67E9BEA4BE7133E; + remoteInfo = ShareExtension; + }; 6848AF4480814C5F810FB7EB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = AC22997D58D612146053154D /* Project object */; @@ -1204,6 +1240,7 @@ dstSubfolderSpec = 13; files = ( EB88DBD77221E2CFE463018C /* NSE.appex in Embed Foundation Extensions */, + 00C3023B6DF55024D8876B76 /* ShareExtension.appex in Embed Foundation Extensions */, ); name = "Embed Foundation Extensions"; runOnlyForDeploymentPostprocessing = 0; @@ -1334,6 +1371,7 @@ 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenModels.swift; sourceTree = ""; }; 1B8E176484A89BAC389D4076 /* RoomMembersListScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreen.swift; sourceTree = ""; }; 1B927CF5EF7FCCDA5EDC474B /* NotificationItemProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxyProtocol.swift; sourceTree = ""; }; + 1B9D191A81FFB0C72CE73E77 /* RoomSelectionScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSelectionScreenModels.swift; sourceTree = ""; }; 1BA5A62DA4B543827FF82354 /* LAContextMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LAContextMock.swift; sourceTree = ""; }; 1C21A715237F2B6D6E80998C /* SecureBackupControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupControllerProtocol.swift; sourceTree = ""; }; 1C25B6EBEB414431187D73B7 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = ""; }; @@ -1348,6 +1386,7 @@ 1D9F148717D74F73BE724434 /* LongPressWithFeedback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongPressWithFeedback.swift; sourceTree = ""; }; 1DA7E93C2E148B96EF6A8500 /* TimelineItemAccessibilityModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemAccessibilityModifier.swift; sourceTree = ""; }; 1DB2FC2AA9A07EE792DF65CF /* NotificationPermissionsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenModels.swift; sourceTree = ""; }; + 1DD2A058F3566FEEBA1D11B3 /* RoomSelectionScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSelectionScreenViewModelProtocol.swift; sourceTree = ""; }; 1DE7969EBCAF078813E18EA1 /* RoomRolesAndPermissionsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsScreenModels.swift; sourceTree = ""; }; 1DF8F7A3AD83D04C08D75E01 /* RoomDetailsEditScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenViewModelProtocol.swift; sourceTree = ""; }; 1DFE0E493FB55E5A62E7852A /* ProposedViewSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProposedViewSize.swift; sourceTree = ""; }; @@ -1358,6 +1397,7 @@ 1FAF8C2226A57B9AB7446B31 /* AppLockSetupPINScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenCoordinator.swift; sourceTree = ""; }; 1FD51B4D5173F7FC886F5360 /* NoticeRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItemContent.swift; 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 = ""; }; @@ -1484,15 +1524,18 @@ 3BDCCD2F6B405C14B9BCE94E /* JoinRoomScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenCoordinator.swift; sourceTree = ""; }; 3BF8E5D4C95974B96A18C80E /* EncryptionSettingsUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionSettingsUITests.swift; sourceTree = ""; }; 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 = ""; }; + 3D27299A36536DBF91AE8FA6 /* ShareExtensionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionViewController.swift; sourceTree = ""; }; 3D487C1185D658F8B15B8F55 /* SettingsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModelTests.swift; sourceTree = ""; }; 3D4DD336905C72F95EAF34B7 /* ElementX-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ElementX-Bridging-Header.h"; sourceTree = ""; }; 3D65BCC659FD9087E49B3C25 /* AppAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAppearance.swift; sourceTree = ""; }; 3D75941CBD7D336F831924EC /* ReadReceiptCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadReceiptCell.swift; sourceTree = ""; }; + 3D8BEEFCA07BEA43F4F4BF77 /* ShareExtension.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 3D9B45D584D232CB9E5C7734 /* RoomChangeRolesScreenSelectedItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenSelectedItem.swift; sourceTree = ""; }; 3D9FCE4D1E3A81AC1CC5CB91 /* AppLockSetupSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreenCoordinator.swift; sourceTree = ""; }; 3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreenModels.swift; sourceTree = ""; }; @@ -1512,6 +1555,7 @@ 4137900E28201C314C835C11 /* RoomScreenFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenFooterView.swift; sourceTree = ""; }; 4176C3E20C772DE8D182863C /* LegalInformationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreen.swift; sourceTree = ""; }; 419957D7B1C983D7B3B93678 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/InfoPlist.strings"; sourceTree = ""; }; + 41A8571A8A071FB41778C016 /* ExtensionLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionLogger.swift; sourceTree = ""; }; 41BB37D96C3EA18F3CE8675D /* RoomDirectorySearchScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreenModels.swift; sourceTree = ""; }; 41D041A857614A9AE13C7795 /* RoomChangePermissionsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModelTests.swift; sourceTree = ""; }; 421E716C521F96D24ECE69B3 /* NoticeRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItem.swift; sourceTree = ""; }; @@ -1581,6 +1625,7 @@ 4FDD775CFD72DD2D3C8A8390 /* NotificationSettingsProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxyProtocol.swift; sourceTree = ""; }; 502F986D57158674172C58E3 /* AppLockSetupSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreenModels.swift; sourceTree = ""; }; 505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelTests.swift; sourceTree = ""; }; + 505ADA084C0B38A0C4AD2574 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 5098DA7799946A61E34A2373 /* FileRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineItem.swift; sourceTree = ""; }; 50D685B4DB38BB5BD87C956A /* AuthenticationStartScreenBackgroundImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenBackgroundImage.swift; sourceTree = ""; }; 50E31AB0E77BB70E2BC77463 /* MatrixUserShareLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixUserShareLink.swift; sourceTree = ""; }; @@ -1788,6 +1833,7 @@ 8319173DD66C07F45DC48848 /* IdentityConfirmedScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreenViewModelProtocol.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 = ""; }; 84311D707B09854D67F78BBF /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = ""; }; 845DDBDE5A0887E73D38B826 /* InviteUsersViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersViewModelTests.swift; sourceTree = ""; }; 848F69921527D31CAACB93AF /* SecureBackupLogoutConfirmationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenViewModelTests.swift; sourceTree = ""; }; @@ -2034,6 +2080,7 @@ B81B6170DB690013CEB646F4 /* MapLibreModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLibreModels.swift; sourceTree = ""; }; B8516302ACCA94A0E680AB3B /* VoiceMessageButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageButton.swift; sourceTree = ""; }; B858A61F2A570DFB8DE570A7 /* AggregratedReaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AggregratedReaction.swift; sourceTree = ""; }; + B88CE0A058727BC68EEEC6B6 /* ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtension.entitlements; sourceTree = ""; }; B8A3B7637DDBD6AA97AC2545 /* CameraPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraPicker.swift; sourceTree = ""; }; B8F28602AC7AC881AED37EBA /* NavigationCoordinators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationCoordinators.swift; sourceTree = ""; }; B902EA6CD3296B0E10EE432B /* HomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreen.swift; sourceTree = ""; }; @@ -2068,6 +2115,7 @@ C0900BBF0A5D5D775E917C70 /* EventBasedMessageTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBasedMessageTimelineItemProtocol.swift; sourceTree = ""; }; C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenEmptyStateView.swift; sourceTree = ""; }; C0FF08D0BD7D0B4B6877AB7D /* SecureBackupRecoveryKeyScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenViewModelTests.swift; sourceTree = ""; }; + C142248014E08E885E323E56 /* Avatars.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Avatars.swift; sourceTree = ""; }; C14D83B2B7CD5501A0089EFC /* LayoutDirection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutDirection.swift; sourceTree = ""; }; C1511766C534367700C8DD75 /* RoomNotificationModeProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationModeProxy.swift; sourceTree = ""; }; C15E0017717EAE3A1D02D005 /* StaticLocationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLocationScreenCoordinator.swift; sourceTree = ""; }; @@ -2150,7 +2198,6 @@ D33116993D54FADC0C721C1F /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; D38391154120264910D19528 /* PollMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollMock.swift; sourceTree = ""; }; D39D7F513A36C9C1951DB44C /* AnalyticsSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreen.swift; sourceTree = ""; }; - D3D455BC2423D911A62ACFB2 /* NSELogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSELogger.swift; sourceTree = ""; }; D3F219838588C62198E726E3 /* LABiometryType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LABiometryType.swift; sourceTree = ""; }; D3F275432954C8C6B1B7D966 /* AppLockSetupPINScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreen.swift; sourceTree = ""; }; D45C9EAA86423D7D3126DE4F /* VoiceMessageRecorderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorderProtocol.swift; sourceTree = ""; }; @@ -2173,6 +2220,7 @@ D79BB714D28C9F588DD69353 /* SecureBackupScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenViewModelProtocol.swift; sourceTree = ""; }; D7BB243B26D54EF1A0C422C0 /* NotificationContentBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationContentBuilder.swift; sourceTree = ""; }; D7BEB970F500BFB248443FA1 /* BloomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BloomView.swift; sourceTree = ""; }; + D879DC5515B1D42577F96C94 /* RoomSelectionScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSelectionScreen.swift; sourceTree = ""; }; D8E60332509665C00179ACF6 /* MessageForwardingScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenViewModel.swift; sourceTree = ""; }; D8F5F9E02B1AB5350B1815E7 /* TimelineStartRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStartRoomTimelineItem.swift; sourceTree = ""; }; D8FC33C3F6BF597E095CE9FA /* HomeScreenInviteCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenInviteCell.swift; sourceTree = ""; }; @@ -2187,6 +2235,7 @@ DC0AEA686E425F86F6BA0404 /* UNNotification+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNNotification+Creator.swift"; sourceTree = ""; }; DC10CCC8D68B863E20660DBC /* MessageForwardingScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenViewModelProtocol.swift; sourceTree = ""; }; DC528B3764E3CF7FCFEF40E7 /* PollInteractionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollInteractionHandler.swift; 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 = ""; }; DD97F9661ABF08CE002054A2 /* AppLockServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceTests.swift; sourceTree = ""; }; DE5127D6EA05B2E45D0A7D59 /* JoinRoomScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenViewModelTests.swift; sourceTree = ""; }; @@ -2205,7 +2254,6 @@ E1A5FEF17ED7E6176D922D4F /* RoomDetailsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreen.swift; sourceTree = ""; }; E1E0B4A34E69BD2132BEC521 /* MessageText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageText.swift; sourceTree = ""; }; E1ED17433ADC77287F8904F9 /* CallNotificationRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallNotificationRoomTimelineItem.swift; sourceTree = ""; }; - E24B88AD3D1599E8CB1376E0 /* AvatarSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarSize.swift; sourceTree = ""; }; E26C69EC1157D71CC61ADAE4 /* ScaledPaddingModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScaledPaddingModifier.swift; sourceTree = ""; }; E2B1CC9AA154F4D5435BF60A /* Comparable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comparable.swift; sourceTree = ""; }; E2F96CCBEAAA7F2185BFA354 /* ClientProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxyMock.swift; sourceTree = ""; }; @@ -2284,6 +2332,7 @@ F08776C48FFB47CACF64ED10 /* ServerConfirmationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModelTests.swift; sourceTree = ""; }; F0B9F5BC4C80543DE7228B9D /* MapTilerStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyle.swift; sourceTree = ""; }; F0E14FF533D25A0692F7CEB0 /* RoomPollsHistoryScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenViewModel.swift; sourceTree = ""; }; + F104596B0620CEFE5DFD31B1 /* RoomSelectionScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSelectionScreenCoordinator.swift; sourceTree = ""; }; F134D2D91DFF732FB75B2CB7 /* UserProfileScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileScreenViewModelProtocol.swift; sourceTree = ""; }; F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; @@ -2355,6 +2404,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 7E8EB7CD881C54161D4474E5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F66BBBE51B258BBB0B918C68 /* MatrixRustSDK in Frameworks */, + FDE47D4686BA0F86BB584633 /* Collections in Frameworks */, + 558F37B1A8F2C4CC9B1ACEDA /* Compound in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; BF59B36A7B2DB184B62826F6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -2495,6 +2554,7 @@ 06501F0E978B2D5C92771DC7 /* Logging */ = { isa = PBXGroup; children = ( + 41A8571A8A071FB41778C016 /* ExtensionLogger.swift */, 111B698739E3410E2CDB7144 /* MXLog.swift */, 542D4F49FABA056DEEEB3400 /* RustTracing.swift */, ED003DF1B7CF40E7073A2280 /* TracingConfiguration.swift */, @@ -2866,6 +2926,18 @@ path = View; sourceTree = ""; }; + 2E42D43DB6835A58D88B2F91 /* RoomSelectionScreen */ = { + isa = PBXGroup; + children = ( + F104596B0620CEFE5DFD31B1 /* RoomSelectionScreenCoordinator.swift */, + 1B9D191A81FFB0C72CE73E77 /* RoomSelectionScreenModels.swift */, + 83B4E3F1265581683E4997B8 /* RoomSelectionScreenViewModel.swift */, + 1DD2A058F3566FEEBA1D11B3 /* RoomSelectionScreenViewModelProtocol.swift */, + FF654D7FD6693839E3185FAD /* View */, + ); + path = RoomSelectionScreen; + sourceTree = ""; + }; 2ECFF6B05DAA37EB10DBF7E8 /* UITests */ = { isa = PBXGroup; children = ( @@ -3221,10 +3293,21 @@ 823ED0EC3F1B6CF47D284011 /* Tools */, B04B538A859CD012755DC19C /* NSE */, 1803CD2B96BF06009334BB61 /* PreviewTests */, + D0111119CDF3E28E6D7768E8 /* ShareExtension */, 681566846AF307E9BA4C72C6 /* Products */, ); sourceTree = ""; }; + 40D9A816C45E0278C29DF883 /* SupportingFiles */ = { + isa = PBXGroup; + children = ( + 505ADA084C0B38A0C4AD2574 /* Info.plist */, + B88CE0A058727BC68EEEC6B6 /* ShareExtension.entitlements */, + 203D1ACC20287F8986C959D3 /* target.yml */, + ); + path = SupportingFiles; + sourceTree = ""; + }; 40E6246F03D1FE377BC5D963 /* Room */ = { isa = PBXGroup; children = ( @@ -3518,11 +3601,18 @@ path = BugReportScreen; sourceTree = ""; }; + 557C534BD2052BFFD810CE3D /* ShareExtension */ = { + isa = PBXGroup; + children = ( + DCAC01A97A43BE07B9E94E43 /* ShareExtensionModels.swift */, + ); + path = ShareExtension; + sourceTree = ""; + }; 566F2B84465726112B830CF6 /* Other */ = { isa = PBXGroup; children = ( 4959CECEC984B3995616F427 /* DataProtectionManager.swift */, - D3D455BC2423D911A62ACFB2 /* NSELogger.swift */, EEAA2832D93EC7D2608703FB /* NSEUserSession.swift */, 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */, ); @@ -3698,6 +3788,7 @@ 9C7F7DE62D33C6A26CBFCD72 /* IntegrationTests.xctest */, 0D8F620C8B314840D8602E3F /* NSE.appex */, D95E8C0EFEC0C6F96EDAA71A /* PreviewTests.xctest */, + 3D8BEEFCA07BEA43F4F4BF77 /* ShareExtension.appex */, F506C6ADB1E1DA6638078E11 /* UITests.xctest */, AAC9344689121887B74877AF /* UnitTests.xctest */, ); @@ -4144,6 +4235,14 @@ path = Replies; sourceTree = ""; }; + 7FF02C3DED8CD9890375D9FF /* View */ = { + isa = PBXGroup; + children = ( + 3C3ADF21BE301D0DA48F2A7E /* ShareExtensionView.swift */, + ); + path = View; + sourceTree = ""; + }; 8039515BAA53B7C3275AC64A /* Client */ = { isa = PBXGroup; children = ( @@ -4908,7 +5007,7 @@ children = ( 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */, 3D65BCC659FD9087E49B3C25 /* AppAppearance.swift */, - E24B88AD3D1599E8CB1376E0 /* AvatarSize.swift */, + C142248014E08E885E323E56 /* Avatars.swift */, E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */, 9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */, AE52983FAFB4E0998C00EE8A /* CancellableTask.swift */, @@ -5105,6 +5204,15 @@ path = Layout; sourceTree = ""; }; + D0111119CDF3E28E6D7768E8 /* ShareExtension */ = { + isa = PBXGroup; + children = ( + F08E29610C82E4201463C4A5 /* Sources */, + 40D9A816C45E0278C29DF883 /* SupportingFiles */, + ); + path = ShareExtension; + sourceTree = ""; + }; D382E465AF067C1BF888BF8E /* View */ = { isa = PBXGroup; children = ( @@ -5295,6 +5403,7 @@ D57B3BC211BB74420C9138D7 /* RoomPollsHistoryScreen */, 7B890CCD20B037760BFDF957 /* RoomRolesAndPermissionsScreen */, 679E9837ECA8D6776079D16E /* RoomScreen */, + 2E42D43DB6835A58D88B2F91 /* RoomSelectionScreen */, 2565414373E6F68005966B8E /* SecureBackup */, 70B74A432C241E56A7ACE610 /* Settings */, EC4545C7E37E8294D3FE6800 /* StartChatScreen */, @@ -5334,6 +5443,7 @@ 22F9F1514B91803BB4B88894 /* AppHooks */, 337015ADFBA3AB96660DB3A6 /* Generated */, 31CE4DA53232AA534057F912 /* Mocks */, + 557C534BD2052BFFD810CE3D /* ShareExtension */, 4C826614718790C58C17117F /* UnitTests */, ); path = Sources; @@ -5426,6 +5536,15 @@ path = BlockedUsersScreen; sourceTree = ""; }; + F08E29610C82E4201463C4A5 /* Sources */ = { + isa = PBXGroup; + children = ( + 3D27299A36536DBF91AE8FA6 /* ShareExtensionViewController.swift */, + 7FF02C3DED8CD9890375D9FF /* View */, + ); + path = Sources; + sourceTree = ""; + }; F12966DF3DA87FEF21348D60 /* InviteUsersScreen */ = { isa = PBXGroup; children = ( @@ -5567,6 +5686,14 @@ path = View; sourceTree = ""; }; + FF654D7FD6693839E3185FAD /* View */ = { + isa = PBXGroup; + children = ( + D879DC5515B1D42577F96C94 /* RoomSelectionScreen.swift */, + ); + path = View; + sourceTree = ""; + }; FFD7C58CA6A7D6BBC2F584B5 /* JoinRoomScreen */ = { isa = PBXGroup; children = ( @@ -5616,6 +5743,28 @@ productReference = F506C6ADB1E1DA6638078E11 /* UITests.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; }; + 19F0C845D67E9BEA4BE7133E /* ShareExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = A60414DDC2A95B206C91D4A4 /* Build configuration list for PBXNativeTarget "ShareExtension" */; + buildPhases = ( + 8431C24C3AE0AA27308F4185 /* Sources */, + 087F14F27D0A6FDFB80392A1 /* Resources */, + 7E8EB7CD881C54161D4474E5 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ShareExtension; + packageProductDependencies = ( + C79D91A7F9F378CECEF64B5A /* MatrixRustSDK */, + CAA3B9DF998B397C9EE64E8B /* Collections */, + 3262F08E1C3483C22A7A319F /* Compound */, + ); + productName = ShareExtension; + productReference = 3D8BEEFCA07BEA43F4F4BF77 /* ShareExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; 32C23C8D224D46EFE62AFAD0 /* UnitTests */ = { isa = PBXNativeTarget; buildConfigurationList = 79663128986C62EFAC289176 /* Build configuration list for PBXNativeTarget "UnitTests" */; @@ -5672,6 +5821,7 @@ ); dependencies = ( 2C29670603B37E38705D5FF1 /* PBXTargetDependency */, + 58C473A5DEA945AACFEA8E9F /* PBXTargetDependency */, ); name = ElementX; packageProductDependencies = ( @@ -5774,6 +5924,9 @@ DevelopmentTeam = 7J4U792NQT; TestTargetID = C0FAEB81CFD9776CD78CE489; }; + 19F0C845D67E9BEA4BE7133E = { + DevelopmentTeam = "$(DEVELOPMENT_TEAM)"; + }; 32C23C8D224D46EFE62AFAD0 = { DevelopmentTeam = 7J4U792NQT; }; @@ -5862,6 +6015,7 @@ FEB53A5BC378C913769656D8 /* NSE */, F8E276FD6DC43EADB85241BC /* Periphery */, 7A17BE29BAC81ADBAC6349D9 /* PreviewTests */, + 19F0C845D67E9BEA4BE7133E /* ShareExtension */, 0E28CD62691FDBC63147D5E3 /* UITests */, 32C23C8D224D46EFE62AFAD0 /* UnitTests */, ); @@ -5869,6 +6023,14 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 087F14F27D0A6FDFB80392A1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D8F1462EA00AFC939FF9ACCA /* target.yml in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 215E1D91B98672C856F559D0 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -6071,7 +6233,7 @@ 484202C5D50983442D24D061 /* AttributedString.swift in Sources */, CDCA8A559E098503DDE29477 /* AttributedStringBuilder.swift in Sources */, BA43D782BE85C7F5F20C624A /* AttributedStringBuilderProtocol.swift in Sources */, - 968A5B890004526AB58A217C /* AvatarSize.swift in Sources */, + F255083E18CDBFDF7E640FB1 /* Avatars.swift in Sources */, 9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */, 238D561CA231339C6D4D06F3 /* ClientBuilder.swift in Sources */, 0BAF83521871E69D222EE8E4 /* ClientBuilderHook.swift in Sources */, @@ -6081,6 +6243,7 @@ 24A75F72EEB7561B82D726FD /* Date.swift in Sources */, 9F11B9F347F9E2D236799FB3 /* ElementCallServiceConstants.swift in Sources */, CFEC53440C572CEEABC4A6A0 /* ElementXAttributeScope.swift in Sources */, + 89198AE2649DD77673D5793B /* ExtensionLogger.swift in Sources */, A33784831AD880A670CAA9F9 /* FileManager.swift in Sources */, 59F940FCBE6BC343AECEF75E /* ImageCache.swift in Sources */, EBE13FAB4E29738AC41BD3E5 /* InfoPlistReader.swift in Sources */, @@ -6095,7 +6258,6 @@ 9DD5AA10E85137140FEA86A3 /* MediaProvider.swift in Sources */, 7A642EE5F1ADC5D520F21924 /* MediaProviderProtocol.swift in Sources */, E2DB696117BAEABAD5718023 /* MediaSourceProxy.swift in Sources */, - 5455147CAC63F71E48F7D699 /* NSELogger.swift in Sources */, 30CC4F796B27BE8B1DFDBF5A /* NSEUserSession.swift in Sources */, 1D5DC685CED904386C89B7DA /* NSRegularExpresion.swift in Sources */, 94F0B78928E952689ACDB271 /* NetworkMonitor.swift in Sources */, @@ -6267,6 +6429,30 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 8431C24C3AE0AA27308F4185 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B8EC8A544162B0A41B9AB339 /* AppSettings.swift in Sources */, + 2F2906AE9BC3D0E79A6F98F8 /* Bundle.swift in Sources */, + F38D32C1B0232AAFE6A0822C /* ExtensionLogger.swift in Sources */, + C022284E2774A5E1EF683B4D /* FileManager.swift in Sources */, + 05FF0CD80EDAB3A7C0D4700A /* InfoPlistReader.swift in Sources */, + 0638CBDE3098B1C3F23AFCFA /* MXLog.swift in Sources */, + 1A3783005E6945F8583AF997 /* NSItemProvider.swift in Sources */, + BE8E5985771DF9137C6CE89A /* ProcessInfo.swift in Sources */, + 7AED78DC086695E93F0647D2 /* RustTracing.swift in Sources */, + DAF63A9CF9932CA8F6830F11 /* ShareExtensionModels.swift in Sources */, + 5AA81A4E2D40A32A9E7F71F2 /* ShareExtensionView.swift in Sources */, + 5AC5CD6D893073EE4D9A277E /* ShareExtensionViewController.swift in Sources */, + 069358C2C825A19DE6CB127E /* TracingConfiguration.swift in Sources */, + 03BD83E8BDD23AE059802E0D /* UITestsScreenIdentifier.swift in Sources */, + 26252AA9AED64010788F4C26 /* UIView.swift in Sources */, + 66E9202BED03B5BB00E812A1 /* URL.swift in Sources */, + 4E22086585CB3B35FEEFBBB9 /* UserPreference.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 9797D588420FCBBC228A63C9 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -6371,7 +6557,7 @@ 874FEFB9D4A4AF447E0E086E /* AuthenticationStartScreenViewModelProtocol.swift in Sources */, 6146996D5C4DDD5DA816FC87 /* AuthenticationTextFieldStyle.swift in Sources */, 4AAA8606FBA290E23D15422E /* AvatarHeaderView.swift in Sources */, - D876EC0FED3B6D46C806912A /* AvatarSize.swift in Sources */, + 1621BF6316FFFEF5AE067C77 /* Avatars.swift in Sources */, 7A25D6926A2C01DB8D0D67A5 /* BadgeLabel.swift in Sources */, A4B0BAD62A12ED76BD611B79 /* BadgeView.swift in Sources */, FC0EEFF630F34899953BB950 /* BigIcon.swift in Sources */, @@ -6509,6 +6695,7 @@ 02D8DF8EB7537EB4E9019DDB /* EventBasedTimelineItemProtocol.swift in Sources */, 2F09DF0CB213CAE86A3E3B67 /* EventTimelineItem.swift in Sources */, 63E46D18B91D08E15FC04125 /* ExpiringTaskRunner.swift in Sources */, + 36206F74DDEBF9BEAF6A6A1F /* ExtensionLogger.swift in Sources */, 5F06AD3C66884CE793AE6119 /* FileManager.swift in Sources */, D33AC79A50DFC26D2498DD28 /* FileRoomTimelineItem.swift in Sources */, 37D789F24199B32E3FD1AA7B /* FileRoomTimelineItemContent.swift in Sources */, @@ -6860,6 +7047,11 @@ 352C439BE0F75E101EF11FB1 /* RoomScreenModels.swift in Sources */, 7BB31E67648CF32D2AB5E502 /* RoomScreenViewModel.swift in Sources */, 617624A97BDBB75ED3DD8156 /* RoomScreenViewModelProtocol.swift in Sources */, + 66832DE7B5C2E861045265DC /* RoomSelectionScreen.swift in Sources */, + 18FDE4ED6D83B0771452B43D /* RoomSelectionScreenCoordinator.swift in Sources */, + 27FEF0F40750465195C9D6D6 /* RoomSelectionScreenModels.swift in Sources */, + 8DCA1F05C3BA6ED826F1599D /* RoomSelectionScreenViewModel.swift in Sources */, + 39DFC4B9EB6A8757210BDEC6 /* RoomSelectionScreenViewModelProtocol.swift in Sources */, 6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */, 59C41313AED7566C3AC51163 /* RoomSummary.swift in Sources */, 983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */, @@ -6945,6 +7137,7 @@ B93D7CE520088AD53FA6D53C /* SettingsScreenModels.swift in Sources */, E0B6A569AC3E81D233B43D60 /* SettingsScreenViewModel.swift in Sources */, A009BDFB0A6816D4C392ADCB /* SettingsScreenViewModelProtocol.swift in Sources */, + 5D99F63CC88BB29383019FC6 /* ShareExtensionModels.swift in Sources */, 1C8BC70A18060677E295A846 /* ShareToMapsAppActivity.swift in Sources */, 274CE3C986841D15FD530BF5 /* ShimmerModifier.swift in Sources */, 77920AFA8091AC6B9F190C90 /* Signposter.swift in Sources */, @@ -7174,6 +7367,11 @@ target = C0FAEB81CFD9776CD78CE489 /* ElementX */; targetProxy = 6848AF4480814C5F810FB7EB /* PBXContainerItemProxy */; }; + 58C473A5DEA945AACFEA8E9F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 19F0C845D67E9BEA4BE7133E /* ShareExtension */; + targetProxy = 52A426E590105174D83B9532 /* PBXContainerItemProxy */; + }; 8E24DC048A099AAFEE13B4F5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = C0FAEB81CFD9776CD78CE489 /* ElementX */; @@ -7445,6 +7643,27 @@ }; name = Debug; }; + 7620CDAB1B38B30431DA8878 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = ShareExtension/SupportingFiles/ShareExtension.entitlements; + CURRENT_PROJECT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)"; + INFOPLIST_FILE = ShareExtension/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = "$(MARKETING_VERSION)"; + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.shareextension"; + PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; + PRODUCT_NAME = ShareExtension; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; 7A90A3EBE1ABAB9EAE0952F0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -7697,6 +7916,27 @@ }; name = Release; }; + E57C898C511BBC8215673DEF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = ShareExtension/SupportingFiles/ShareExtension.entitlements; + CURRENT_PROJECT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)"; + INFOPLIST_FILE = ShareExtension/SupportingFiles/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = "$(MARKETING_VERSION)"; + PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.shareextension"; + PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; + PRODUCT_NAME = ShareExtension; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; F0A74453D306F668178A859E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -7754,6 +7994,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + A60414DDC2A95B206C91D4A4 /* Build configuration list for PBXNativeTarget "ShareExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7620CDAB1B38B30431DA8878 /* Debug */, + E57C898C511BBC8215673DEF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; B15427F8699AD5A5FC75C17E /* Build configuration list for PBXNativeTarget "ElementX" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -8068,6 +8317,11 @@ package = EC6D0C817B1C21D9D096505A /* XCRemoteSwiftPackageReference "Version" */; productName = Version; }; + 3262F08E1C3483C22A7A319F /* Compound */ = { + isa = XCSwiftPackageProductDependency; + package = F71C70A4404CC6D9C4AF35F2 /* XCRemoteSwiftPackageReference "compound-ios" */; + productName = Compound; + }; 36B7FC232711031AA2B0D188 /* DTCoreText */ = { isa = XCSwiftPackageProductDependency; package = C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */; @@ -8253,11 +8507,21 @@ package = 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */; productName = MatrixRustSDK; }; + C79D91A7F9F378CECEF64B5A /* MatrixRustSDK */ = { + isa = XCSwiftPackageProductDependency; + package = 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */; + productName = MatrixRustSDK; + }; CA07D57389DACE18AEB6A5E2 /* WysiwygComposer */ = { isa = XCSwiftPackageProductDependency; package = EE40B0E16A55BD23ECBFFD22 /* XCRemoteSwiftPackageReference "matrix-rich-text-editor-swift" */; productName = WysiwygComposer; }; + CAA3B9DF998B397C9EE64E8B /* Collections */ = { + isa = XCSwiftPackageProductDependency; + package = F76A08D0EA29A07A54F4EB4D /* XCRemoteSwiftPackageReference "swift-collections" */; + productName = Collections; + }; CCE5BF78B125320CBF3BB834 /* PostHog */ = { isa = XCSwiftPackageProductDependency; package = 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */; diff --git a/ElementX.xcodeproj/xcshareddata/xcschemes/ShareExtension.xcscheme b/ElementX.xcodeproj/xcshareddata/xcschemes/ShareExtension.xcscheme new file mode 100644 index 0000000000..6bbbe2daaa --- /dev/null +++ b/ElementX.xcodeproj/xcshareddata/xcschemes/ShareExtension.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index d86e6ca0a8..5d4ad70d7e 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -235,6 +235,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg } else { handleAppRoute(.childEventOnRoomAlias(eventID: eventID, alias: alias)) } + case .share: + guard isExternalURL else { + MXLog.error("Received unexpected internal share route") + break + } + handleAppRoute(route) default: break } diff --git a/ElementX/Sources/Application/Navigation/AppRoutes.swift b/ElementX/Sources/Application/Navigation/AppRoutes.swift index d90b9282a5..842bb436b0 100644 --- a/ElementX/Sources/Application/Navigation/AppRoutes.swift +++ b/ElementX/Sources/Application/Navigation/AppRoutes.swift @@ -8,7 +8,7 @@ import Foundation import MatrixRustSDK -enum AppRoute: Equatable { +enum AppRoute: Equatable, Hashable { /// The app's home screen. case roomList /// A room, shown as the root of the stack (popping any child rooms). @@ -41,6 +41,8 @@ enum AppRoute: Equatable { case settings /// The setting screen for key backup. case chatBackupSettings + /// An external share request e.g. from the ShareExtension + case share(ShareExtensionPayload) } struct AppRouteURLParser { @@ -48,6 +50,7 @@ struct AppRouteURLParser { init(appSettings: AppSettings) { urlParsers = [ + AppGroupURLParser(), MatrixPermalinkParser(), ElementWebURLParser(domains: appSettings.elementWebHosts), ElementCallURLParser() @@ -73,6 +76,30 @@ protocol URLParser { func route(from url: URL) -> AppRoute? } +struct AppGroupURLParser: URLParser { + func route(from url: URL) -> AppRoute? { + guard let scheme = url.scheme, + scheme == InfoPlistReader.app.appScheme, + url.pathComponents.last == ShareExtensionConstants.urlPath else { + return nil + } + + guard let query = url.query(percentEncoded: false), + let queryData = query.data(using: .utf8) else { + MXLog.error("Failed processing share parameters") + return nil + } + + do { + let payload = try JSONDecoder().decode(ShareExtensionPayload.self, from: queryData) + return .share(payload) + } catch { + MXLog.error("Failed decoding share payload with error: \(error)") + return nil + } + } +} + /// The parser for Element Call links. This always returns a `.genericCallLink`. struct ElementCallURLParser: URLParser { private let knownHosts = ["call.element.io"] diff --git a/ElementX/Sources/FlowCoordinators/EncryptionSettingsFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/EncryptionSettingsFlowCoordinator.swift index af620ef40b..d8be441aca 100644 --- a/ElementX/Sources/FlowCoordinators/EncryptionSettingsFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/EncryptionSettingsFlowCoordinator.swift @@ -83,7 +83,7 @@ class EncryptionSettingsFlowCoordinator: FlowCoordinatorProtocol { case .roomList, .room, .roomAlias, .childRoom, .childRoomAlias, .roomDetails, .roomMemberDetails, .userProfile, .event, .eventOnRoomAlias, .childEvent, .childEventOnRoomAlias, - .call, .genericCallLink, .settings: + .call, .genericCallLink, .settings, .share: // These routes aren't in this flow so clear the entire stack. clearRoute(animated: animated) case .chatBackupSettings: diff --git a/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift index cea5f952c5..8fd08c9223 100644 --- a/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift @@ -293,9 +293,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { let coordinator = SecureBackupRecoveryKeyScreenCoordinator(parameters: parameters) coordinator.actions - .sink { [weak self] action in - guard let self else { return } - + .sink { action in switch action { case .complete: break // Moving to next state is Handled by the global session verification listener diff --git a/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift index f900329307..fcaf4fb7dc 100644 --- a/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/PinnedEventsTimelineFlowCoordinator.swift @@ -65,7 +65,9 @@ class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol { attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)) - guard let timelineController = await roomTimelineControllerFactory.buildRoomPinnedTimelineController(roomProxy: roomProxy, timelineItemFactory: timelineItemFactory) else { + guard let timelineController = await roomTimelineControllerFactory.buildRoomPinnedTimelineController(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 fd84208489..51163c8c43 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -34,6 +34,8 @@ enum RoomFlowCoordinatorEntryPoint: Hashable { case eventID(String) /// The flow will start by showing the room's details. case roomDetails + /// An external media share request + case share(ShareExtensionPayload) var isEventID: Bool { guard case .eventID = self else { return false } @@ -41,6 +43,32 @@ enum RoomFlowCoordinatorEntryPoint: Hashable { } } +struct FocusEvent: Hashable { + /// The event ID that the timeline should be focussed around + let eventID: String + /// if the focus is coming from the pinned timeline, this should also update the pin banner + let shouldSetPin: Bool +} + +private enum PinnedEventsTimelineSource: Hashable { + case room + case details(isRoot: Bool) +} + +private enum PresentationAction: Hashable { + case eventFocus(FocusEvent) + case share(ShareExtensionPayload) + + var focusedEvent: FocusEvent? { + switch self { + case .eventFocus(let focusEvent): + return focusEvent + default: + return nil + } + } +} + // swiftlint:disable:next type_body_length class RoomFlowCoordinator: FlowCoordinatorProtocol { private let roomID: String @@ -112,6 +140,7 @@ 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` ☠️") @@ -152,7 +181,12 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { stateMachine.tryEvent(.presentRoomMemberDetails(userID: userID), userInfo: EventUserInfo(animated: animated)) } case .event(let eventID, let roomID, let via): - Task { await handleRoomRoute(roomID: roomID, via: via, focussedEventID: eventID, animated: animated) } + Task { + await handleRoomRoute(roomID: roomID, + via: via, + presentationAction: .eventFocus(.init(eventID: eventID, shouldSetPin: false)), + animated: animated) + } case .childEvent(let eventID, let roomID, let via): if case .presentingChild = stateMachine.state, let childRoomFlowCoordinator { childRoomFlowCoordinator.handleAppRoute(appRoute, animated: animated) @@ -161,6 +195,21 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } else { roomScreenCoordinator?.focusOnEvent(.init(eventID: eventID, shouldSetPin: false)) } + case .share(let payload): + guard case let .mediaFile(roomID, _) = payload else { + return + } + + guard let roomID, roomID == self.roomID else { + fatalError("Navigation route doesn't belong to this room flow.") + } + + Task { + await handleRoomRoute(roomID: roomID, + via: [], + presentationAction: .share(payload), + animated: animated) + } case .roomAlias, .childRoomAlias, .eventOnRoomAlias, .childEventOnRoomAlias: break // These are converted to a room ID route one level above. case .roomList, .userProfile, .call, .genericCallLink, .settings, .chatBackupSettings: @@ -176,7 +225,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { actionsSubject.send(.presentCallScreen(roomProxy: roomProxy)) } - private func handleRoomRoute(roomID: String, via: [String], focussedEventID: String? = nil, animated: Bool) async { + private func handleRoomRoute(roomID: String, via: [String], presentationAction: PresentationAction? = nil, animated: Bool) async { guard roomID == self.roomID else { fatalError("Navigation route doesn't belong to this room flow.") } guard let room = await userSession.clientProxy.roomForIdentifier(roomID) else { @@ -187,8 +236,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { switch room { case .joined(let roomProxy): await storeAndSubscribeToRoomProxy(roomProxy) - let focussedEvent = focussedEventID.map { FocusEvent(eventID: $0, shouldSetPin: false) } - stateMachine.tryEvent(.presentRoom(focussedEvent: focussedEvent), userInfo: EventUserInfo(animated: animated)) + stateMachine.tryEvent(.presentRoom(presentationAction: presentationAction), userInfo: EventUserInfo(animated: animated)) default: stateMachine.tryEvent(.presentJoinRoomScreen(via: via), userInfo: EventUserInfo(animated: animated)) } @@ -376,9 +424,13 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { presentJoinRoomScreen(via: via, animated: true) case (_, .dismissJoinRoomScreen, .complete): dismissFlow(animated: animated) - - case (_, .presentRoom(let focussedEvent), .room): - Task { await self.presentRoom(fromState: context.fromState, focussedEvent: focussedEvent, animated: animated) } + + case (_, .presentRoom(let presentationAction), .room): + Task { + await self.presentRoom(fromState: context.fromState, + presentationAction: presentationAction, + animated: animated) + } case (_, .dismissFlow, .complete): dismissFlow(animated: animated) @@ -445,9 +497,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { break case (.mediaUploadPicker, .presentMediaUploadPreview, .mediaUploadPreview(let fileURL)): - presentMediaUploadPreviewScreen(for: fileURL) + presentMediaUploadPreviewScreen(for: fileURL, animated: animated) case (.room, .presentMediaUploadPreview, .mediaUploadPreview(let fileURL)): - presentMediaUploadPreviewScreen(for: fileURL) + presentMediaUploadPreviewScreen(for: fileURL, animated: animated) case (.mediaUploadPreview, .dismissMediaUploadPreview, .room): break @@ -542,7 +594,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { /// - fromState: The state that asked for the room presentation. /// - focussedEvent: An (optional) struct that contains the event ID that the timeline should be focussed around, and a boolean telling if such event should update the pinned events banner /// - animated: whether it should animate the transition - private func presentRoom(fromState: State, focussedEvent: FocusEvent?, animated: Bool) async { + private func presentRoom(fromState: State, presentationAction: PresentationAction?, animated: Bool) async { // If any sheets are presented dismiss them, rely on their dismissal callbacks to transition the state machine // through the correct states before presenting the room navigationStackCoordinator.setSheetCoordinator(nil) @@ -559,9 +611,13 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { default: // The room is already on the stack, no need to present it again - // Check if we need to focus on an event - if let focussedEvent { - roomScreenCoordinator?.focusOnEvent(focussedEvent) + switch presentationAction { + case .eventFocus(let focusedEvent): + roomScreenCoordinator?.focusOnEvent(focusedEvent) + case .share(.mediaFile(_, let mediaFile)): + stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: mediaFile.url)) + default: + break } return @@ -580,8 +636,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)) let timelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy, - initialFocussedEventID: focussedEvent?.eventID, - timelineItemFactory: timelineItemFactory) + initialFocussedEventID: presentationAction?.focusedEvent?.eventID, + timelineItemFactory: timelineItemFactory, + mediaProvider: userSession.mediaProvider) self.timelineController = timelineController analytics.trackViewRoom(isDM: roomProxy.infoPublisher.value.isDirect, isSpace: roomProxy.infoPublisher.value.isSpace) @@ -592,7 +649,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { let parameters = RoomScreenCoordinatorParameters(clientProxy: userSession.clientProxy, roomProxy: roomProxy, - focussedEvent: focussedEvent, + focussedEvent: presentationAction?.focusedEvent, timelineController: timelineController, mediaProvider: userSession.mediaProvider, mediaPlayerProvider: MediaPlayerProvider(), @@ -655,6 +712,13 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { self?.stateMachine.tryEvent(.dismissFlow) } } + + switch presentationAction { + case .share(.mediaFile(_, let mediaFile)): + stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: mediaFile.url), userInfo: EventUserInfo(animated: animated)) + default: + break + } } private func presentJoinRoomScreen(via: [String], animated: Bool) { @@ -679,7 +743,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { if case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) { await storeAndSubscribeToRoomProxy(roomProxy) - stateMachine.tryEvent(.presentRoom(focussedEvent: nil), userInfo: EventUserInfo(animated: animated)) + stateMachine.tryEvent(.presentRoom(presentationAction: nil), userInfo: EventUserInfo(animated: animated)) analytics.trackJoinedRoom(isDM: roomProxy.infoPublisher.value.isDirect, isSpace: roomProxy.infoPublisher.value.isSpace, @@ -894,7 +958,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } } - private func presentMediaUploadPreviewScreen(for url: URL) { + private func presentMediaUploadPreviewScreen(for url: URL, animated: Bool) { let stackCoordinator = NavigationStackCoordinator() let parameters = MediaUploadPreviewScreenCoordinatorParameters(userIndicatorController: userIndicatorController, @@ -918,7 +982,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { stackCoordinator.setRootCoordinator(mediaUploadPreviewScreenCoordinator) - navigationStackCoordinator.setSheetCoordinator(stackCoordinator) { [weak self] in + navigationStackCoordinator.setSheetCoordinator(stackCoordinator, animated: animated) { [weak self] in self?.stateMachine.tryEvent(.dismissMediaUploadPreview) } } @@ -1091,7 +1155,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { let roomTimelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy, initialFocussedEventID: nil, - timelineItemFactory: timelineItemFactory) + timelineItemFactory: timelineItemFactory, + mediaProvider: userSession.mediaProvider) let parameters = RoomPollsHistoryScreenCoordinatorParameters(pollInteractionHandler: PollInteractionHandler(analyticsService: analytics, roomProxy: roomProxy), roomTimelineController: roomTimelineController) @@ -1361,7 +1426,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room)) case .displayRoomScreenWithFocussedPin(let eventID): navigationStackCoordinator.setSheetCoordinator(nil) - stateMachine.tryEvent(.presentRoom(focussedEvent: .init(eventID: eventID, shouldSetPin: true))) + stateMachine.tryEvent(.presentRoom(presentationAction: .eventFocus(.init(eventID: eventID, shouldSetPin: true)))) } } .store(in: &cancellables) @@ -1427,6 +1492,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { coordinator.handleAppRoute(.event(eventID: eventID, roomID: roomID, via: via), animated: true) case .roomDetails: coordinator.handleAppRoute(.roomDetails(roomID: roomID), animated: true) + case .share(let payload): + coordinator.handleAppRoute(.share(payload), animated: true) } } } @@ -1483,7 +1550,7 @@ private extension RoomFlowCoordinator { case presentJoinRoomScreen(via: [String]) case dismissJoinRoomScreen - case presentRoom(focussedEvent: FocusEvent?) + case presentRoom(presentationAction: PresentationAction?) case dismissFlow case presentReportContent(itemID: TimelineItemIdentifier, senderID: String) @@ -1559,15 +1626,3 @@ private extension Result { } } } - -private enum PinnedEventsTimelineSource: Hashable { - case room - case details(isRoot: Bool) -} - -struct FocusEvent: Hashable { - /// The event ID that the timeline should be focussed around - let eventID: String - /// if the focus is coming from the pinned timeline, this should also update the pin banner - let shouldSetPin: Bool -} diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index ff62ac4e2b..d6ff185383 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -206,6 +206,18 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { presentCallScreen(genericCallLink: url) case .settings, .chatBackupSettings: settingsFlowCoordinator.handleAppRoute(appRoute, animated: animated) + case .share(let payload): + switch payload { + case .mediaFile(let roomID, _): + if let roomID { + stateMachine.processEvent(.selectRoom(roomID: roomID, + via: [], + entryPoint: .share(payload)), + userInfo: .init(animated: animated)) + } else { + stateMachine.processEvent(.showShareExtensionRoomList(sharePayload: payload), userInfo: .init(animated: animated)) + } + } } } @@ -243,6 +255,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { case .room: .room(roomID: roomID, via: via) case .roomDetails: .roomDetails(roomID: roomID) case .eventID(let eventID): .event(eventID: eventID, roomID: roomID, via: via) // ignored. + case .share(let payload): .share(payload) } roomFlowCoordinator.handleAppRoute(route, animated: animated) } else { @@ -296,6 +309,12 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { case (.userProfileScreen, .dismissedUserProfileScreen, .roomList): break + case (.roomList, .showShareExtensionRoomList, .shareExtensionRoomList(let sharePayload)): + clearRoute(animated: animated) + presentRoomSelectionScreen(sharePayload: sharePayload, animated: animated) + case (.shareExtensionRoomList, .dismissedShareExtensionRoomList, .roomList): + dismissRoomSelectionScreen() + default: fatalError("Unknown transition: \(context)") } @@ -583,6 +602,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { coordinator.handleAppRoute(.event(eventID: eventID, roomID: roomID, via: via), animated: animated) case .roomDetails: coordinator.handleAppRoute(.roomDetails(roomID: roomID), animated: animated) + case .share(let payload): + coordinator.handleAppRoute(.share(payload), animated: animated) } Task { @@ -894,6 +915,52 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { } } + // MARK: Sharing + + private func presentRoomSelectionScreen(sharePayload: ShareExtensionPayload, animated: Bool) { + guard let roomSummaryProvider = userSession.clientProxy.alternateRoomSummaryProvider else { + fatalError() + } + + let stackCoordinator = NavigationStackCoordinator() + + let coordinator = RoomSelectionScreenCoordinator(parameters: .init(clientProxy: userSession.clientProxy, + roomSummaryProvider: roomSummaryProvider, + mediaProvider: userSession.mediaProvider)) + + coordinator.actionsPublisher.sink { [weak self] action in + guard let self else { return } + + switch action { + case .dismiss: + navigationSplitCoordinator.setSheetCoordinator(nil) + case .confirm(let roomID): + let sharePayload = switch sharePayload { + case .mediaFile(_, let mediaFile): + ShareExtensionPayload.mediaFile(roomID: roomID, mediaFile: mediaFile) + } + + navigationSplitCoordinator.setSheetCoordinator(nil) + + stateMachine.processEvent(.selectRoom(roomID: roomID, + via: [], + entryPoint: .share(sharePayload)), + userInfo: .init(animated: animated)) + } + } + .store(in: &cancellables) + + stackCoordinator.setRootCoordinator(coordinator) + + navigationSplitCoordinator.setSheetCoordinator(stackCoordinator, animated: animated) { [weak self] in + self?.stateMachine.processEvent(.dismissedShareExtensionRoomList) + } + } + + private func dismissRoomSelectionScreen() { + navigationSplitCoordinator.setSheetCoordinator(nil) + } + // MARK: Toasts and loading indicators private static let loadingIndicatorIdentifier = "\(UserSessionFlowCoordinator.self)-Loading" diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift index 5fe2d18c6f..c07dc5adad 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinatorStateMachine.swift @@ -42,10 +42,12 @@ class UserSessionFlowCoordinatorStateMachine { /// Showing the user profile screen. This screen clears the navigation. case userProfileScreen + case shareExtensionRoomList(sharePayload: ShareExtensionPayload) + /// The selected room ID from the state if available. var selectedRoomID: String? { switch self { - case .initial, .userProfileScreen: + case .initial, .userProfileScreen, .shareExtensionRoomList: nil case .roomList(let selectedRoomID), .feedbackScreen(let selectedRoomID), @@ -116,6 +118,9 @@ class UserSessionFlowCoordinatorStateMachine { case showUserProfileScreen(userID: String) /// The user profile screen has been dismissed. case dismissedUserProfileScreen + + case showShareExtensionRoomList(sharePayload: ShareExtensionPayload) + case dismissedShareExtensionRoomList } private let stateMachine: StateMachine @@ -184,6 +189,11 @@ class UserSessionFlowCoordinatorStateMachine { case (.userProfileScreen, .dismissedUserProfileScreen): return .roomList(selectedRoomID: nil) + case (.roomList, .showShareExtensionRoomList(let sharePayload)): + return .shareExtensionRoomList(sharePayload: sharePayload) + case (.shareExtensionRoomList, .dismissedShareExtensionRoomList): + return .roomList(selectedRoomID: nil) + default: return nil } diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 51c386fda5..6dac05ec44 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -12939,15 +12939,15 @@ class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol { //MARK: - buildRoomTimelineController - var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryUnderlyingCallsCount = 0 - var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount: Int { + var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount = 0 + var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount: Int { get { if Thread.isMainThread { - return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryUnderlyingCallsCount + return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryUnderlyingCallsCount + returnValue = buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount } return returnValue! @@ -12955,29 +12955,29 @@ class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol { } set { if Thread.isMainThread { - buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryUnderlyingCallsCount = newValue + buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryUnderlyingCallsCount = newValue + buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue } } } } - var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCalled: Bool { - return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount > 0 + var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCalled: Bool { + return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount > 0 } - var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol)? - var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol)] = [] + var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)? + var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = [] - var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryUnderlyingReturnValue: RoomTimelineControllerProtocol! - var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReturnValue: RoomTimelineControllerProtocol! { + var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue: RoomTimelineControllerProtocol! + var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReturnValue: RoomTimelineControllerProtocol! { get { if Thread.isMainThread { - return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryUnderlyingReturnValue + return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue } else { var returnValue: RoomTimelineControllerProtocol? = nil DispatchQueue.main.sync { - returnValue = buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryUnderlyingReturnValue + returnValue = buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue } return returnValue! @@ -12985,39 +12985,39 @@ class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol { } set { if Thread.isMainThread { - buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryUnderlyingReturnValue = newValue + buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryUnderlyingReturnValue = newValue + buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue } } } } - var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryClosure: ((JoinedRoomProxyProtocol, String?, RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol)? + var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure: ((JoinedRoomProxyProtocol, String?, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) -> RoomTimelineControllerProtocol)? - func buildRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol { - buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount += 1 - buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments = (roomProxy: roomProxy, initialFocussedEventID: initialFocussedEventID, timelineItemFactory: timelineItemFactory) + func buildRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol { + buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount += 1 + buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments = (roomProxy: roomProxy, initialFocussedEventID: initialFocussedEventID, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider) DispatchQueue.main.async { - self.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedInvocations.append((roomProxy: roomProxy, initialFocussedEventID: initialFocussedEventID, timelineItemFactory: timelineItemFactory)) + self.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedInvocations.append((roomProxy: roomProxy, initialFocussedEventID: initialFocussedEventID, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)) } - if let buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryClosure = buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryClosure { - return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryClosure(roomProxy, initialFocussedEventID, timelineItemFactory) + if let buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure = buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure { + return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure(roomProxy, initialFocussedEventID, timelineItemFactory, mediaProvider) } else { - return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReturnValue + return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReturnValue } } //MARK: - buildRoomPinnedTimelineController - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingCallsCount = 0 - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryCallsCount: Int { + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = 0 + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount: Int { get { if Thread.isMainThread { - return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingCallsCount + return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingCallsCount + returnValue = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount } return returnValue! @@ -13025,29 +13025,29 @@ class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol { } set { if Thread.isMainThread { - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingCallsCount = newValue + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingCallsCount = newValue + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue } } } } - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryCalled: Bool { - return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryCallsCount > 0 + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCalled: Bool { + return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount > 0 } - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol)? - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol)] = [] + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)? + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = [] - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingReturnValue: RoomTimelineControllerProtocol? - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReturnValue: RoomTimelineControllerProtocol? { + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue: RoomTimelineControllerProtocol? + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue: RoomTimelineControllerProtocol? { get { if Thread.isMainThread { - return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingReturnValue + return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue } else { var returnValue: RoomTimelineControllerProtocol?? = nil DispatchQueue.main.sync { - returnValue = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingReturnValue + returnValue = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue } return returnValue! @@ -13055,26 +13055,26 @@ class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol { } set { if Thread.isMainThread { - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingReturnValue = newValue + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryUnderlyingReturnValue = newValue + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue } } } } - var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryClosure: ((JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol) async -> RoomTimelineControllerProtocol?)? + var buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure: ((JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) async -> RoomTimelineControllerProtocol?)? - func buildRoomPinnedTimelineController(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol) async -> RoomTimelineControllerProtocol? { - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryCallsCount += 1 - buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReceivedArguments = (roomProxy: roomProxy, timelineItemFactory: timelineItemFactory) + func buildRoomPinnedTimelineController(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol? { + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount += 1 + buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments = (roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider) DispatchQueue.main.async { - self.buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReceivedInvocations.append((roomProxy: roomProxy, timelineItemFactory: timelineItemFactory)) + self.buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations.append((roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)) } - if let buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryClosure = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryClosure { - return await buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryClosure(roomProxy, timelineItemFactory) + if let buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure = buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure { + return await buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure(roomProxy, timelineItemFactory, mediaProvider) } else { - return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryReturnValue + return buildRoomPinnedTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue } } } diff --git a/ElementX/Sources/Mocks/RoomTimelineControllerFactoryMock.swift b/ElementX/Sources/Mocks/RoomTimelineControllerFactoryMock.swift index 6dd55f8e35..8c99f36ec7 100644 --- a/ElementX/Sources/Mocks/RoomTimelineControllerFactoryMock.swift +++ b/ElementX/Sources/Mocks/RoomTimelineControllerFactoryMock.swift @@ -15,7 +15,7 @@ extension RoomTimelineControllerFactoryMock { convenience init(configuration: RoomTimelineControllerFactoryMockConfiguration) { self.init() - buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReturnValue = configuration.timelineController ?? { + buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReturnValue = configuration.timelineController ?? { let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk return timelineController diff --git a/ElementX/Sources/Other/AvatarSize.swift b/ElementX/Sources/Other/Avatars.swift similarity index 55% rename from ElementX/Sources/Other/AvatarSize.swift rename to ElementX/Sources/Other/Avatars.swift index 4aec55c4c1..fab60ce616 100644 --- a/ElementX/Sources/Other/AvatarSize.swift +++ b/ElementX/Sources/Other/Avatars.swift @@ -6,29 +6,55 @@ // import Foundation -import UIKit +import SwiftUI -enum AvatarSize { - case user(on: UserAvatarSizeOnScreen) - case room(on: RoomAvatarSizeOnScreen) - // custom - case custom(CGFloat) +enum Avatars { + enum Size { + case user(on: UserAvatarSizeOnScreen) + case room(on: RoomAvatarSizeOnScreen) + // custom + case custom(CGFloat) - /// Value in UIKit points - var value: CGFloat { - switch self { - case .user(let screen): - return screen.value - case .room(let screen): - return screen.value - case .custom(let val): - return val + /// Value in UIKit points + var value: CGFloat { + switch self { + case .user(let screen): + return screen.value + case .room(let screen): + return screen.value + case .custom(let val): + return val + } } - } - /// Value in pixels by using the scale of the main screen - var scaledValue: CGFloat { - value * UIScreen.main.scale + /// Value in pixels by using the scale of the main screen + var scaledValue: CGFloat { + value * UIScreen.main.scale + } + + var scaledSize: CGSize { + CGSize(width: scaledValue, height: scaledValue) + } + } + + @MainActor + static func generatePlaceholderAvatarImageData(name: String, id: String, size: CGSize) -> Data? { + let image = PlaceholderAvatarImage(name: name, contentID: id) + .clipShape(Circle()) + .frame(width: size.width, height: size.height) + + let renderer = ImageRenderer(content: image) + + // Specify the scale so the image is rendered correctly. We don't have access to the screen + // here so a hardcoded 3.0 will have to do + renderer.scale = 3.0 + + guard let image = renderer.uiImage else { + MXLog.info("Generating notification icon placeholder failed") + return nil + } + + return image.pngData() } } @@ -87,6 +113,7 @@ enum RoomAvatarSizeOnScreen { case home case messageForwarding case globalSearch + case roomSelection case details case notificationSettings case roomDirectorySearch @@ -104,6 +131,8 @@ enum RoomAvatarSizeOnScreen { return 36 case .globalSearch: return 36 + case .roomSelection: + return 36 case .home: return 52 case .details: @@ -113,9 +142,3 @@ enum RoomAvatarSizeOnScreen { } } } - -extension AvatarSize { - var scaledSize: CGSize { - CGSize(width: scaledValue, height: scaledValue) - } -} diff --git a/ElementX/Sources/Other/Extensions/FileManager.swift b/ElementX/Sources/Other/Extensions/FileManager.swift index 0709dec3a4..a969d63265 100644 --- a/ElementX/Sources/Other/Extensions/FileManager.swift +++ b/ElementX/Sources/Other/Extensions/FileManager.swift @@ -38,7 +38,7 @@ extension FileManager { @discardableResult func writeDataToTemporaryDirectory(data: Data, fileName: String) throws -> URL { - let newURL = URL.temporaryDirectory.appendingPathComponent(fileName) + let newURL = URL.appGroupTemporaryDirectory.appendingPathComponent(fileName) try data.write(to: newURL) diff --git a/ElementX/Sources/Other/Extensions/UNNotificationContent.swift b/ElementX/Sources/Other/Extensions/UNNotificationContent.swift index cc77eb22df..f9a45d8d77 100644 --- a/ElementX/Sources/Other/Extensions/UNNotificationContent.swift +++ b/ElementX/Sources/Other/Extensions/UNNotificationContent.swift @@ -183,37 +183,17 @@ extension UNMutableNotificationContent { @MainActor private func getPlaceholderAvatarImageData(name: String, id: String) async -> Data? { // The version value is used in case the design of the placeholder is updated to force a replacement - let shouldFlipAvatar = shouldFlipAvatar() - let prefix = "notification_placeholder\(shouldFlipAvatar ? "V9F" : "V9")" + let prefix = "notification_placeholderV9" + let fileName = "\(prefix)_\(name)_\(id).png" if let data = try? Data(contentsOf: URL.temporaryDirectory.appendingPathComponent(fileName)) { MXLog.info("Found existing notification icon placeholder") return data } - - MXLog.info("Generating notification icon placeholder") - let image = PlaceholderAvatarImage(name: name, - contentID: id) - .clipShape(Circle()) - .frame(width: 50, height: 50) - let renderer = ImageRenderer(content: image) - - // Specify the scale so the image is rendered correctly. We don't have access to the screen - // here so a hardcoded 3.0 will have to do - renderer.scale = 3.0 - - guard let image = renderer.uiImage else { - MXLog.info("Generating notification icon placeholder failed") - return nil - } - let data: Data? + MXLog.info("Generating notification icon placeholder") - if shouldFlipAvatar { - data = image.flippedVertically().pngData() - } else { - data = image.pngData() - } + let data = Avatars.generatePlaceholderAvatarImageData(name: name, id: id, size: .init(width: 50, height: 50)) if let data { do { @@ -224,44 +204,7 @@ extension UNMutableNotificationContent { return data } } - return data - } - - /// On simulators and macOS the image is rendered correctly - /// On devices before iOS 17 and iOS 17.2.0 it's rendered upside down and needs to be flipped - /// On all other versions it's rendered correctly and **doesn't** need to be flipped - private func shouldFlipAvatar() -> Bool { - #if targetEnvironment(simulator) - return false - #else - if ProcessInfo.processInfo.isiOSAppOnMac { - return false - } - - guard let version = Version(UIDevice.current.systemVersion) else { - return false - } - - if version < Version(17, 0, 0) { - return true - } - - if version == Version(17, 2, 0) { - return true - } - return false - #endif - } -} - -private extension UIImage { - func flippedVertically() -> UIImage { - let format = UIGraphicsImageRendererFormat() - format.scale = scale - return UIGraphicsImageRenderer(size: size, format: format).image { context in - context.cgContext.concatenate(CGAffineTransform(scaleX: 1, y: -1)) - self.draw(at: CGPoint(x: 0, y: -size.height)) - } + return data } } diff --git a/ElementX/Sources/Other/Extensions/URL.swift b/ElementX/Sources/Other/Extensions/URL.swift index 3506d46c5f..fc26b266b5 100644 --- a/ElementX/Sources/Other/Extensions/URL.swift +++ b/ElementX/Sources/Other/Extensions/URL.swift @@ -60,7 +60,7 @@ extension URL: @retroactive ExpressibleByStringLiteral { } /// The base directory where all application support data is stored. - static var cachesBaseDirectory: URL { + static var sessionCachesBaseDirectory: URL { let url = appGroupContainerDirectory .appendingPathComponent("Library", isDirectory: true) .appendingPathComponent("Caches", isDirectory: true) @@ -69,7 +69,20 @@ extension URL: @retroactive ExpressibleByStringLiteral { try? FileManager.default.createDirectoryIfNeeded(at: url) - // Caches are excluded from backups automatically anyway. + // Caches are excluded from backups automatically. + // https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html + + return url + } + + /// The app group temporary directory + static var appGroupTemporaryDirectory: URL { + let url = appGroupContainerDirectory + .appendingPathComponent("tmp", isDirectory: true) + + try? FileManager.default.createDirectoryIfNeeded(at: url) + + // Temporary files are excluded from backups automatically. // https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html return url diff --git a/NSE/Sources/Other/NSELogger.swift b/ElementX/Sources/Other/Logging/ExtensionLogger.swift similarity index 93% rename from NSE/Sources/Other/NSELogger.swift rename to ElementX/Sources/Other/Logging/ExtensionLogger.swift index 985038136a..3367d1c7ee 100644 --- a/NSE/Sources/Other/NSELogger.swift +++ b/ElementX/Sources/Other/Logging/ExtensionLogger.swift @@ -8,7 +8,7 @@ import Foundation import MatrixRustSDK -enum NSELogger { +enum ExtensionLogger { private static var isConfigured = false /// Memory formatter, uses exact 2 fraction digits and no grouping @@ -66,13 +66,13 @@ enum NSELogger { return "\(formattedStr) MB" } - static func configure(logLevel: TracingConfiguration.LogLevel) { + static func configure(currentTarget: String, logLevel: TracingConfiguration.LogLevel) { guard !isConfigured else { return } isConfigured = true - MXLog.configure(currentTarget: "nse", filePrefix: "nse", logLevel: logLevel) + MXLog.configure(currentTarget: currentTarget, filePrefix: currentTarget, logLevel: logLevel) } static func logMemory(with tag: String) { diff --git a/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift b/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift index 2717af4a82..f78421bf94 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift @@ -25,13 +25,13 @@ struct AvatarHeaderView: View { private let subtitle: String? private let badges: [Badge] - private let avatarSize: AvatarSize + private let avatarSize: Avatars.Size private let mediaProvider: MediaProviderProtocol? private var onAvatarTap: ((URL) -> Void)? @ViewBuilder private var footer: () -> Footer init(room: RoomDetails, - avatarSize: AvatarSize, + avatarSize: Avatars.Size, mediaProvider: MediaProviderProtocol? = nil, onAvatarTap: ((URL) -> Void)? = nil, @ViewBuilder footer: @escaping () -> Footer) { @@ -72,7 +72,7 @@ struct AvatarHeaderView: View { init(member: RoomMemberDetails, isVerified: Bool = false, - avatarSize: AvatarSize, + avatarSize: Avatars.Size, mediaProvider: MediaProviderProtocol? = nil, onAvatarTap: ((URL) -> Void)? = nil, @ViewBuilder footer: @escaping () -> Footer) { @@ -88,7 +88,7 @@ struct AvatarHeaderView: View { init(user: UserProfileProxy, isVerified: Bool, - avatarSize: AvatarSize, + avatarSize: Avatars.Size, mediaProvider: MediaProviderProtocol? = nil, onAvatarTap: ((URL) -> Void)? = nil, @ViewBuilder footer: @escaping () -> Footer) { diff --git a/ElementX/Sources/Other/SwiftUI/Views/LoadableAvatarImage.swift b/ElementX/Sources/Other/SwiftUI/Views/LoadableAvatarImage.swift index 7daf4655de..1c048bd114 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/LoadableAvatarImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/LoadableAvatarImage.swift @@ -11,7 +11,7 @@ struct LoadableAvatarImage: View { private let url: URL? private let name: String? private let contentID: String? - private let avatarSize: AvatarSize + private let avatarSize: Avatars.Size private let mediaProvider: MediaProviderProtocol? private let onTap: ((URL) -> Void)? @@ -19,7 +19,7 @@ struct LoadableAvatarImage: View { init(url: URL?, name: String?, contentID: String?, - avatarSize: AvatarSize, + avatarSize: Avatars.Size, mediaProvider: MediaProviderProtocol?, onTap: ((URL) -> Void)? = nil) { self.url = url diff --git a/ElementX/Sources/Other/SwiftUI/Views/OverridableAvatarImage.swift b/ElementX/Sources/Other/SwiftUI/Views/OverridableAvatarImage.swift index 68137fdad4..7594c5b375 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/OverridableAvatarImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/OverridableAvatarImage.swift @@ -12,12 +12,12 @@ struct OverridableAvatarImage: View { private let url: URL? private let name: String? private let contentID: String? - private let avatarSize: AvatarSize + private let avatarSize: Avatars.Size private let mediaProvider: MediaProviderProtocol? @ScaledMetric private var frameSize: CGFloat - init(overrideURL: URL?, url: URL?, name: String?, contentID: String?, avatarSize: AvatarSize, mediaProvider: MediaProviderProtocol?) { + init(overrideURL: URL?, url: URL?, name: String?, contentID: String?, avatarSize: Avatars.Size, mediaProvider: MediaProviderProtocol?) { self.overrideURL = overrideURL self.url = url self.name = name diff --git a/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift b/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift index 17cf55e783..f4b3d2bee1 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift @@ -22,7 +22,7 @@ enum RoomAvatar: Equatable { struct RoomAvatarImage: View { let avatar: RoomAvatar - let avatarSize: AvatarSize + let avatarSize: Avatars.Size let mediaProvider: MediaProviderProtocol? private(set) var onAvatarTap: ((URL) -> Void)? diff --git a/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift b/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift index b4cf190fef..b2ee66f1ce 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift @@ -18,7 +18,7 @@ struct StackedAvatarsView: View { let lineWidth: CGFloat var shouldStackFromLast = false let avatars: [StackedAvatarInfo] - let avatarSize: AvatarSize + let avatarSize: Avatars.Size let mediaProvider: MediaProviderProtocol? var body: some View { diff --git a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenModels.swift b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenModels.swift index 586a95647a..b6723a4b0a 100644 --- a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenModels.swift +++ b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenModels.swift @@ -30,7 +30,7 @@ enum GlobalSearchScreenViewAction { struct GlobalSearchRoom: Identifiable, Equatable { let id: String - let name: String - let alias: String? + let title: String + let description: String let avatar: RoomAvatar } diff --git a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModel.swift b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModel.swift index ed85554fe0..6ea45004a9 100644 --- a/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModel.swift +++ b/ElementX/Sources/Screens/GlobalSearchScreen/GlobalSearchScreenViewModel.swift @@ -36,7 +36,11 @@ class GlobalSearchScreenViewModel: GlobalSearchScreenViewModelType, GlobalSearch .map(\.bindings.searchQuery) .removeDuplicates() .sink { [weak self] searchQuery in - self?.roomSummaryProvider.setFilter(.search(query: searchQuery)) + if searchQuery.isEmpty { + self?.roomSummaryProvider.setFilter(.all(filters: [])) + } else { + self?.roomSummaryProvider.setFilter(.search(query: searchQuery)) + } } .store(in: &cancellables) @@ -66,8 +70,8 @@ class GlobalSearchScreenViewModel: GlobalSearchScreenViewModelType, GlobalSearch private func updateRooms(with summaries: [RoomSummary]) { state.rooms = summaries.compactMap { summary in GlobalSearchRoom(id: summary.id, - name: summary.name, - alias: summary.canonicalAlias, + title: summary.name, + description: summary.roomListDescription, avatar: summary.avatar) } } diff --git a/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift b/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift index 6a9225facd..354e1cef80 100644 --- a/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift +++ b/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift @@ -16,8 +16,8 @@ struct GlobalSearchScreenListRow: View { var body: some View { ZStack { // The list row swallows listRowBackgrounds for some reason - ListRow(label: .avatar(title: room.name, - description: room.alias ?? room.id, + ListRow(label: .avatar(title: room.title, + description: room.description, icon: avatar), kind: .label) } @@ -42,8 +42,8 @@ struct GlobalSearchScreenListRow_Previews: PreviewProvider, TestablePreview { static var previews: some View { List { GlobalSearchScreenListRow(room: .init(id: "123", - name: "Tech central", - alias: "The best place in the whole wide world", + title: "Tech central", + description: "The best place in the whole wide world", avatar: .room(id: "123", name: "Tech central", avatarURL: .picturesDirectory)), diff --git a/ElementX/Sources/Screens/MessageForwardingScreen/MessageForwardingScreenModels.swift b/ElementX/Sources/Screens/MessageForwardingScreen/MessageForwardingScreenModels.swift index 0a459a3f6e..cf0280f96d 100644 --- a/ElementX/Sources/Screens/MessageForwardingScreen/MessageForwardingScreenModels.swift +++ b/ElementX/Sources/Screens/MessageForwardingScreen/MessageForwardingScreenModels.swift @@ -33,8 +33,8 @@ enum MessageForwardingScreenViewAction { struct MessageForwardingRoom: Identifiable, Equatable { let id: String - let name: String - let alias: String? + let title: String + let description: String let avatar: RoomAvatar } diff --git a/ElementX/Sources/Screens/MessageForwardingScreen/MessageForwardingScreenViewModel.swift b/ElementX/Sources/Screens/MessageForwardingScreen/MessageForwardingScreenViewModel.swift index ef27e2a2ae..d9ed472c12 100644 --- a/ElementX/Sources/Screens/MessageForwardingScreen/MessageForwardingScreenViewModel.swift +++ b/ElementX/Sources/Screens/MessageForwardingScreen/MessageForwardingScreenViewModel.swift @@ -45,8 +45,11 @@ class MessageForwardingScreenViewModel: MessageForwardingScreenViewModelType, Me .map(\.bindings.searchQuery) .removeDuplicates() .sink { [weak self] searchQuery in - guard let self else { return } - self.roomSummaryProvider.setFilter(.search(query: searchQuery)) + if searchQuery.isEmpty { + self?.roomSummaryProvider.setFilter(.all(filters: [])) + } else { + self?.roomSummaryProvider.setFilter(.search(query: searchQuery)) + } } .store(in: &cancellables) @@ -79,8 +82,10 @@ class MessageForwardingScreenViewModel: MessageForwardingScreenViewModelType, Me continue } - let room = MessageForwardingRoom(id: summary.id, name: summary.name, alias: summary.canonicalAlias, avatar: summary.avatar) - rooms.append(room) + rooms.append(.init(id: summary.id, + title: summary.name, + description: summary.roomListDescription, + avatar: summary.avatar)) } state.rooms = rooms diff --git a/ElementX/Sources/Screens/MessageForwardingScreen/View/MessageForwardingScreen.swift b/ElementX/Sources/Screens/MessageForwardingScreen/View/MessageForwardingScreen.swift index 2801f66ef2..552c6c8be7 100644 --- a/ElementX/Sources/Screens/MessageForwardingScreen/View/MessageForwardingScreen.swift +++ b/ElementX/Sources/Screens/MessageForwardingScreen/View/MessageForwardingScreen.swift @@ -68,8 +68,8 @@ private struct MessageForwardingListRow: View { let context: MessageForwardingScreenViewModel.Context var body: some View { - ListRow(label: .avatar(title: room.name, - description: room.alias ?? room.id, + ListRow(label: .avatar(title: room.title, + description: room.description, icon: avatar), kind: .selection(isSelected: isSelected) { context.send(viewAction: .selectRoom(roomID: room.id)) diff --git a/ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenCoordinator.swift b/ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenCoordinator.swift new file mode 100644 index 0000000000..a89a8b4cc4 --- /dev/null +++ b/ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenCoordinator.swift @@ -0,0 +1,52 @@ +// +// 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 RoomSelectionScreenCoordinatorParameters { + let clientProxy: ClientProxyProtocol + let roomSummaryProvider: RoomSummaryProviderProtocol + let mediaProvider: MediaProviderProtocol +} + +enum RoomSelectionScreenCoordinatorAction { + case dismiss + case confirm(roomID: String) +} + +final class RoomSelectionScreenCoordinator: CoordinatorProtocol { + private var viewModel: RoomSelectionScreenViewModelProtocol + private let actionsSubject: PassthroughSubject = .init() + private var cancellables = Set() + + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(parameters: RoomSelectionScreenCoordinatorParameters) { + viewModel = RoomSelectionScreenViewModel(clientProxy: parameters.clientProxy, + roomSummaryProvider: parameters.roomSummaryProvider, + mediaProvider: parameters.mediaProvider) + } + + func start() { + viewModel.actionsPublisher.sink { [weak self] action in + switch action { + case .dismiss: + self?.actionsSubject.send(.dismiss) + case .confirm(let roomID): + self?.actionsSubject.send(.confirm(roomID: roomID)) + } + } + .store(in: &cancellables) + } + + func toPresentable() -> AnyView { + AnyView(RoomSelectionScreen(context: viewModel.context)) + } +} diff --git a/ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenModels.swift b/ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenModels.swift new file mode 100644 index 0000000000..1d066b994d --- /dev/null +++ b/ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenModels.swift @@ -0,0 +1,39 @@ +// +// 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 +import MatrixRustSDK + +enum RoomSelectionScreenViewModelAction { + case dismiss + case confirm(roomID: String) +} + +struct RoomSelectionScreenViewState: BindableState { + var rooms: [RoomSelectionRoom] = [] + var selectedRoomID: String? + var bindings = RoomSelectionScreenViewStateBindings() +} + +struct RoomSelectionScreenViewStateBindings { + var searchQuery = "" +} + +enum RoomSelectionScreenViewAction { + case cancel + case confirm + case selectRoom(roomID: String) + case reachedTop + case reachedBottom +} + +struct RoomSelectionRoom: Identifiable, Equatable { + let id: String + let title: String + let description: String + let avatar: RoomAvatar +} diff --git a/ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenViewModel.swift b/ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenViewModel.swift new file mode 100644 index 0000000000..3bad9ac694 --- /dev/null +++ b/ElementX/Sources/Screens/RoomSelectionScreen/RoomSelectionScreenViewModel.swift @@ -0,0 +1,105 @@ +// +// 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 RoomSelectionScreenViewModelType = StateStoreViewModel + +class RoomSelectionScreenViewModel: RoomSelectionScreenViewModelType, RoomSelectionScreenViewModelProtocol { + private let clientProxy: ClientProxyProtocol + private let roomSummaryProvider: RoomSummaryProviderProtocol + + private var actionsSubject: PassthroughSubject = .init() + + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(clientProxy: ClientProxyProtocol, + roomSummaryProvider: RoomSummaryProviderProtocol, + mediaProvider: MediaProviderProtocol) { + self.clientProxy = clientProxy + self.roomSummaryProvider = roomSummaryProvider + + super.init(initialViewState: RoomSelectionScreenViewState(), mediaProvider: mediaProvider) + + roomSummaryProvider.roomListPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in + self?.updateRooms() + } + .store(in: &cancellables) + + context.$viewState + .map(\.bindings.searchQuery) + .removeDuplicates() + .sink { [weak self] searchQuery in + if searchQuery.isEmpty { + self?.roomSummaryProvider.setFilter(.all(filters: [])) + } else { + self?.roomSummaryProvider.setFilter(.search(query: searchQuery)) + } + } + .store(in: &cancellables) + + updateRooms() + } + + override func process(viewAction: RoomSelectionScreenViewAction) { + switch viewAction { + case .cancel: + actionsSubject.send(.dismiss) + roomSummaryProvider.setFilter(.all(filters: [])) + case .confirm: + guard let selectedRoomID = state.selectedRoomID else { + return + } + + actionsSubject.send(.confirm(roomID: selectedRoomID)) + case .selectRoom(let roomID): + state.selectedRoomID = roomID + case .reachedTop: + updateVisibleRange(edge: .top) + case .reachedBottom: + updateVisibleRange(edge: .bottom) + } + } + + // MARK: - Private + + private func updateRooms() { + var rooms = [RoomSelectionRoom]() + + for summary in roomSummaryProvider.roomListPublisher.value { + rooms.append(.init(id: summary.id, + title: summary.name, + description: summary.roomListDescription, + avatar: summary.avatar)) + } + + state.rooms = rooms + } + + /// The actual range values don't matter as long as they contain the lower + /// or upper bounds. updateVisibleRange is a hybrid API that powers both + /// sliding sync visible range update and list paginations + /// For lists other than the home screen one we don't care about visible ranges, + /// we just need the respective bounds to be there to trigger a next page load or + /// a reset to just one page + private func updateVisibleRange(edge: UIRectEdge) { + switch edge { + case .top: + roomSummaryProvider.updateVisibleRange(0..<0) + case .bottom: + let roomCount = roomSummaryProvider.roomListPublisher.value.count + roomSummaryProvider.updateVisibleRange(roomCount.. { get } + var context: RoomSelectionScreenViewModelType.Context { get } +} diff --git a/ElementX/Sources/Screens/RoomSelectionScreen/View/RoomSelectionScreen.swift b/ElementX/Sources/Screens/RoomSelectionScreen/View/RoomSelectionScreen.swift new file mode 100644 index 0000000000..8a1ea9113d --- /dev/null +++ b/ElementX/Sources/Screens/RoomSelectionScreen/View/RoomSelectionScreen.swift @@ -0,0 +1,104 @@ +// +// 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 RoomSelectionScreen: View { + @ObservedObject var context: RoomSelectionScreenViewModel.Context + + var body: some View { + Form { + Section { + ForEach(context.viewState.rooms) { room in + RoomSelectionListRow(room: room, + isSelected: context.viewState.selectedRoomID == room.id, + context: context) + } + // Replace these with ScrollView's `scrollPosition` when dropping iOS 16. + } header: { + emptyRectangle + .onAppear { + context.send(viewAction: .reachedTop) + } + } footer: { + emptyRectangle + .onAppear { + context.send(viewAction: .reachedBottom) + } + } + } + .compoundList() + .navigationTitle(L10n.screenRoomlistMainSpaceTitle) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .cancellationAction) { + Button(L10n.actionCancel) { + context.send(viewAction: .cancel) + } + } + ToolbarItem(placement: .confirmationAction) { + Button(L10n.actionShare) { + context.send(viewAction: .confirm) + } + .disabled(context.viewState.selectedRoomID == nil) + } + } + .searchController(query: $context.searchQuery, showsCancelButton: false) + .compoundSearchField() + .disableAutocorrection(true) + } + + /// The greedy size of Rectangle can create an issue with the navigation bar when the search is highlighted, so is best to use a fixed frame instead of hidden() or EmptyView() + private var emptyRectangle: some View { + Rectangle() + .frame(width: 0, height: 0) + } +} + +private struct RoomSelectionListRow: View { + @Environment(\.dynamicTypeSize) var dynamicTypeSize + + let room: RoomSelectionRoom + let isSelected: Bool + let context: RoomSelectionScreenViewModel.Context + + var body: some View { + ListRow(label: .avatar(title: room.title, + description: room.description, + icon: avatar), + kind: .selection(isSelected: isSelected) { + context.send(viewAction: .selectRoom(roomID: room.id)) + }) + } + + @ViewBuilder @MainActor + var avatar: some View { + if dynamicTypeSize < .accessibility3 { + RoomAvatarImage(avatar: room.avatar, + avatarSize: .room(on: .roomSelection), + mediaProvider: context.mediaProvider) + .dynamicTypeSize(dynamicTypeSize < .accessibility1 ? dynamicTypeSize : .accessibility1) + .accessibilityHidden(true) + } + } +} + +// MARK: - Previews + +struct RoomSelectionScreen_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + let summaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))) + let viewModel = RoomSelectionScreenViewModel(clientProxy: ClientProxyMock(.init()), + roomSummaryProvider: summaryProvider, + mediaProvider: MediaProviderMock(configuration: .init())) + + NavigationStack { + RoomSelectionScreen(context: viewModel.context) + } + } +} diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index edf8200206..c8f948be3a 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -833,7 +833,7 @@ class ClientProxy: ClientProxyProtocol { alternateRoomSummaryProvider = RoomSummaryProvider(roomListService: roomListService, eventStringBuilder: eventStringBuilder, - name: "MessageForwarding", + name: "AlternateAllRooms", notificationSettings: notificationSettings, appSettings: appSettings) try await alternateRoomSummaryProvider?.setRoomList(roomListService.allRooms()) diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift index 429cba58ad..7b9b3a5ed7 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift @@ -69,6 +69,20 @@ extension RoomSummary: CustomStringConvertible { - notificationMode: \(notificationMode?.rawValue ?? "nil") """ } + + /// Used where summaries are shown in a list e.g. message forwarding, + /// global search, share destination list etc. + var roomListDescription: String { + if isDirect { + return canonicalAlias ?? "" + } + + if let alias = canonicalAlias { + return alias + } + + return heroes.compactMap(\.displayName).formatted(.list(type: .and)) + } } extension RoomSummary { diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift index 09681aa418..50ac8ef321 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift @@ -7,6 +7,7 @@ import Combine import Foundation +import IntentsUI import MatrixRustSDK import UIKit @@ -14,7 +15,9 @@ class RoomTimelineController: RoomTimelineControllerProtocol { private let roomProxy: JoinedRoomProxyProtocol private let liveTimelineProvider: RoomTimelineProviderProtocol private let timelineItemFactory: RoomTimelineItemFactoryProtocol + private let mediaProvider: MediaProviderProtocol private let appSettings: AppSettings + private let serialDispatchQueue: DispatchQueue let callbacks = PassthroughSubject() @@ -40,11 +43,14 @@ class RoomTimelineController: RoomTimelineControllerProtocol { timelineProxy: TimelineProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol, appSettings: AppSettings) { self.roomProxy = roomProxy liveTimelineProvider = timelineProxy.timelineProvider self.timelineItemFactory = timelineItemFactory + self.mediaProvider = mediaProvider self.appSettings = appSettings + serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomtimelineprovider", qos: .utility) activeTimeline = timelineProxy @@ -153,11 +159,63 @@ class RoomTimelineController: RoomTimelineControllerProtocol { intentionalMentions: intentionalMentions) { case .success: MXLog.info("Finished sending message") + await donateSendMessageIntent() case .failure(let error): MXLog.error("Failed sending message with error: \(error)") } } + private func donateSendMessageIntent() async { + guard let displayName = roomProxy.details.name ?? roomProxy.details.canonicalAlias, !displayName.isEmpty else { + MXLog.error("Failed donating send message intent, room missing name or alias.") + return + } + + let groupName = INSpeakableString(spokenPhrase: displayName) + + let sendMessageIntent = INSendMessageIntent(recipients: nil, + outgoingMessageType: .outgoingMessageText, + content: nil, + speakableGroupName: groupName, + conversationIdentifier: roomProxy.id, + serviceName: nil, + sender: nil, + attachments: nil) + + let avatarURL = switch roomProxy.details.avatar { + case .room(_, _, let avatarURL): + avatarURL + case .heroes(let userProfiles): + userProfiles.first?.avatarURL + } + + func addPlacehoder() { + if let imageData = Avatars.generatePlaceholderAvatarImageData(name: displayName, id: roomProxy.id, size: .init(width: 100, height: 100)) { + sendMessageIntent.setImage(INImage(imageData: imageData), forParameterNamed: \.speakableGroupName) + } + } + + if let avatarURL { + let mediaSource = MediaSourceProxy(url: avatarURL, mimeType: nil) + + if case let .success(avatarData) = await mediaProvider.loadThumbnailForSource(source: mediaSource, size: .init(width: 100, height: 100)) { + sendMessageIntent.setImage(INImage(imageData: avatarData), forParameterNamed: \.speakableGroupName) + } else { + addPlacehoder() + } + } else { + addPlacehoder() + } + + let interaction = INInteraction(intent: sendMessageIntent, response: nil) + + do { + try await interaction.donate() + } catch { + MXLog.error("Failed donating send message intent with error: \(error)") + } + } + func toggleReaction(_ reaction: String, to eventOrTransactionID: EventOrTransactionId) async { MXLog.info("Toggle reaction \(reaction) to \(eventOrTransactionID)") diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift index d090f7d90e..4e86953c25 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactory.swift @@ -10,16 +10,19 @@ import Foundation struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol { func buildRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, - timelineItemFactory: RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol { + timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol { RoomTimelineController(roomProxy: roomProxy, timelineProxy: roomProxy.timeline, initialFocussedEventID: initialFocussedEventID, timelineItemFactory: timelineItemFactory, + mediaProvider: mediaProvider, appSettings: ServiceLocator.shared.settings) } func buildRoomPinnedTimelineController(roomProxy: JoinedRoomProxyProtocol, - timelineItemFactory: RoomTimelineItemFactoryProtocol) async -> RoomTimelineControllerProtocol? { + timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol? { guard let pinnedEventsTimeline = await roomProxy.pinnedEventsTimeline else { return nil } @@ -27,6 +30,7 @@ struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol { timelineProxy: pinnedEventsTimeline, initialFocussedEventID: nil, timelineItemFactory: timelineItemFactory, + mediaProvider: mediaProvider, appSettings: ServiceLocator.shared.settings) } } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift index 71746fd849..0f1093c8f5 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerFactoryProtocol.swift @@ -11,9 +11,11 @@ import Foundation protocol RoomTimelineControllerFactoryProtocol { func buildRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, - timelineItemFactory: RoomTimelineItemFactoryProtocol) -> RoomTimelineControllerProtocol + timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol func buildRoomPinnedTimelineController(roomProxy: JoinedRoomProxyProtocol, - timelineItemFactory: RoomTimelineItemFactoryProtocol) async -> RoomTimelineControllerProtocol? + timelineItemFactory: RoomTimelineItemFactoryProtocol, + mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol? } // sourcery: AutoMockable diff --git a/ElementX/Sources/Services/UserSession/SessionDirectories.swift b/ElementX/Sources/Services/UserSession/SessionDirectories.swift index 29b1b076b3..ae768f30ea 100644 --- a/ElementX/Sources/Services/UserSession/SessionDirectories.swift +++ b/ElementX/Sources/Services/UserSession/SessionDirectories.swift @@ -72,19 +72,19 @@ extension SessionDirectories { init() { let sessionDirectoryName = UUID().uuidString dataDirectory = .sessionsBaseDirectory.appending(component: sessionDirectoryName) - cacheDirectory = .cachesBaseDirectory.appending(component: sessionDirectoryName) + cacheDirectory = .sessionCachesBaseDirectory.appending(component: sessionDirectoryName) } /// Creates the session directories for a user who signed in before the data directory was stored. init(userID: String) { dataDirectory = .legacySessionDirectory(for: userID) - cacheDirectory = .cachesBaseDirectory.appending(component: dataDirectory.lastPathComponent) + cacheDirectory = .sessionCachesBaseDirectory.appending(component: dataDirectory.lastPathComponent) } /// Creates the session directories for a user who has a single session directory stored without a separate caches directory. init(dataDirectory: URL) { self.dataDirectory = dataDirectory - cacheDirectory = .cachesBaseDirectory.appending(component: dataDirectory.lastPathComponent) + cacheDirectory = .sessionCachesBaseDirectory.appending(component: dataDirectory.lastPathComponent) } } diff --git a/ElementX/Sources/ShareExtension/ShareExtensionModels.swift b/ElementX/Sources/ShareExtension/ShareExtensionModels.swift new file mode 100644 index 0000000000..3324554c65 --- /dev/null +++ b/ElementX/Sources/ShareExtension/ShareExtensionModels.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 + +enum ShareExtensionConstants { + static let urlPath = "share" +} + +enum ShareExtensionPayload: Hashable, Codable { + case mediaFile(roomID: String?, mediaFile: ShareExtensionMediaFile) +} + +struct ShareExtensionMediaFile: Hashable, Codable { + let url: URL + let suggestedName: String? +} diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index 01bea2b808..73c4910754 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -684,6 +684,7 @@ class MockScreen: Identifiable { timelineItemFactory: RoomTimelineItemFactory(userID: "@alice:matrix.org", attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), stateEventStringBuilder: RoomStateEventStringBuilder(userID: "@alice:matrix.org")), + mediaProvider: MediaProviderMock(configuration: .init()), appSettings: ServiceLocator.shared.settings) let flowCoordinator = UserSessionFlowCoordinator(userSession: UserSessionMock(.init(clientProxy: clientProxy)), diff --git a/ElementX/SupportingFiles/Info.plist b/ElementX/SupportingFiles/Info.plist index fb51c555a9..39c81a8d9c 100644 --- a/ElementX/SupportingFiles/Info.plist +++ b/ElementX/SupportingFiles/Info.plist @@ -54,7 +54,7 @@ Application CFBundleURLSchemes - io.element + $(BASE_BUNDLE_IDENTIFIER) diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml index 33e3b1b850..e7b1587635 100644 --- a/ElementX/SupportingFiles/target.yml +++ b/ElementX/SupportingFiles/target.yml @@ -66,7 +66,7 @@ targets: CFBundleTypeRole: Editor, CFBundleURLName: "Application", CFBundleURLSchemes: [ - io.element + $(BASE_BUNDLE_IDENTIFIER) ] } ] @@ -189,6 +189,7 @@ targets: dependencies: - target: NSE + - target: ShareExtension # not used yet # - target: NCE - package: MatrixRustSDK diff --git a/NSE/Sources/NotificationServiceExtension.swift b/NSE/Sources/NotificationServiceExtension.swift index 3ea1ed8a6c..c55123454e 100644 --- a/NSE/Sources/NotificationServiceExtension.swift +++ b/NSE/Sources/NotificationServiceExtension.swift @@ -66,10 +66,10 @@ class NotificationServiceExtension: UNNotificationServiceExtension { handler = contentHandler modifiedContent = request.content.mutableCopy() as? UNMutableNotificationContent - NSELogger.configure(logLevel: settings.logLevel) + ExtensionLogger.configure(currentTarget: "nse", logLevel: settings.logLevel) MXLog.info("\(tag) #########################################") - NSELogger.logMemory(with: tag) + ExtensionLogger.logMemory(with: tag) MXLog.info("\(tag) Payload came: \(request.content.userInfo)") Self.serialQueue.sync { @@ -201,7 +201,7 @@ class NotificationServiceExtension: UNNotificationServiceExtension { deinit { cleanUp() - NSELogger.logMemory(with: tag) + ExtensionLogger.logMemory(with: tag) MXLog.info("\(tag) deinit") } diff --git a/NSE/SupportingFiles/target.yml b/NSE/SupportingFiles/target.yml index 417469aa13..dea122a13e 100644 --- a/NSE/SupportingFiles/target.yml +++ b/NSE/SupportingFiles/target.yml @@ -77,7 +77,7 @@ targets: - path: ../../ElementX/Sources/Application/AppSettings.swift - path: ../../ElementX/Sources/Generated/Assets.swift - path: ../../ElementX/Sources/Generated/Strings.swift - - path: ../../ElementX/Sources/Other/AvatarSize.swift + - path: ../../ElementX/Sources/Other/Avatars.swift - path: ../../ElementX/Sources/Other/CurrentValuePublisher.swift - path: ../../ElementX/Sources/Other/Extensions/AttributedString.swift - path: ../../ElementX/Sources/Other/Extensions/Bundle.swift diff --git a/PreviewTests/Sources/GeneratedPreviewTests.swift b/PreviewTests/Sources/GeneratedPreviewTests.swift index 492fbd85f9..926ad7802a 100644 --- a/PreviewTests/Sources/GeneratedPreviewTests.swift +++ b/PreviewTests/Sources/GeneratedPreviewTests.swift @@ -701,6 +701,12 @@ extension PreviewTests { } } + func test_roomSelectionScreen() { + for preview in RoomSelectionScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_sFNumberedListView() { for preview in SFNumberedListView_Previews._allPreviews { assertSnapshots(matching: preview) 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 784d368a36..f498e2c853 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:481969f82410ed28b3c259d53e88310fd5669d1c6041020c99c47a7a64fde666 -size 151180 +oid sha256:ec8339fcf606ac520989a6915da4f3a15a43d049e49c3e93524ad70bd8097778 +size 148064 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 fb1a5abde9..665b44f58c 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:ac9dc777f9bdaca948c7a5cf56aebb163ff80be491a124c78084b5d1309396af -size 151589 +oid sha256:aa3fb400d0af05b6c81181a040f3746c11fafe82703f7587ae9d98cdcce44386 +size 148467 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 f80889fefc..c585a86568 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:656ab8534b3b28a11a09b7ee3bd735de4f9173687006d8346093ec8fa70caf54 -size 88511 +oid sha256:ed42c3e99db34f3dedb33b5faaf768caee7d15d8d5dfb50fbed0f97da2b990f0 +size 85859 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 84e27fc201..a82c51c502 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:6dece45267d9514a73241f045de87eb76d7d87ccc236aed3d114ccfbe9507d74 -size 88837 +oid sha256:f33f9d8cc790b5a03c0da8423e948bc9faffa7580e587d509e13fb691a255eaf +size 86196 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 07c4385f19..a484a78c47 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:7001c732a5f38e3b8093488f80504a474c0b8f4f494e68793029f387047522e8 -size 152484 +oid sha256:1705df7384f16656d63d4efca503b4533cd3d67f54733855f284ddc49cdf973f +size 149086 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 b97167e9de..e2223527cd 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:4d213faa018f71016ebc6f31691ac3cbf97849e8a739937d9e351b92bef7877c -size 154392 +oid sha256:de6fe930505a8b4e9ab2b3052ebd1345118eaa64149381f28b3142447722d61a +size 151009 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 9bb41b57cf..8e24daa0ca 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:ee5ecf468c941282295014187f8fc03929c122f343465113496e20a8cca738d6 -size 101988 +oid sha256:96596029a45f8bc48da6f8cbd77f09eb65236ac111534d9dec7d45e0e083cf32 +size 99144 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 559fd39e1b..4c51e28475 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:53268d051594a0dd4250a79b5b3093a4f57f4104250c990e6bb276c751093b94 -size 101810 +oid sha256:dd2bd5da5c119e827b8b195971a34b645d5e47f577bf622e5856412c91d616e2 +size 98976 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 new file mode 100644 index 0000000000..640b8a5dd1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75e855ee7f0e97644797ed467953cd618fbc64a1ca185e6784cd24aa5cdef613 +size 146330 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..9d16fb4425 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7749e68e119cf015e5110e889ef29f283af3b7f4f71840bba60b7abdfbea787b +size 147778 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 new file mode 100644 index 0000000000..47ca6ba736 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f53f2f4cc267e92bab7d8bf4a1fdfd307609312cf7e623ae43a6a254971c1f6 +size 97028 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 new file mode 100644 index 0000000000..e839f735b8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomSelectionScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e76ee2d1d8b3dee92997af404d846a889e9ccea0862b848c8d2386d4489220b +size 98291 diff --git a/ShareExtension/Sources/ShareExtensionViewController.swift b/ShareExtension/Sources/ShareExtensionViewController.swift new file mode 100644 index 0000000000..e2060491cf --- /dev/null +++ b/ShareExtension/Sources/ShareExtensionViewController.swift @@ -0,0 +1,141 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import IntentsUI +import SwiftUI + +class ShareExtensionViewController: UIViewController { + private let appSettings: CommonSettingsProtocol = AppSettings() + private let hostingController = UIHostingController(rootView: ShareExtensionView()) + + override func viewDidLoad() { + super.viewDidLoad() + + addChild(hostingController) + view.addMatchedSubview(hostingController.view) + hostingController.didMove(toParent: self) + + MXLog.configure(currentTarget: "shareextension", filePrefix: "shareextension", logLevel: appSettings.logLevel) + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + Task { + if let payload = await prepareSharePayload() { + await self.openMainApp(payload: payload) + } + + self.dismiss() + } + } + + // MARK: - Private + + private func prepareSharePayload() async -> ShareExtensionPayload? { + guard let extensionItem = extensionContext?.inputItems.first as? NSExtensionItem, + let itemProvider = extensionItem.attachments?.first else { + return nil + } + + guard let contentType = itemProvider.preferredContentType, + let preferredExtension = contentType.preferredFilenameExtension else { + MXLog.error("Invalid NSItemProvider: \(itemProvider)") + return nil + } + + let roomID = (extensionContext?.intent as? INSendMessageIntent)?.conversationIdentifier + let providerSuggestedName = itemProvider.suggestedName + let providerDescription = itemProvider.description + + let shareData: Data? = await withCheckedContinuation { continuation in + _ = itemProvider.loadDataRepresentation(for: contentType) { data, error in + if let error { + MXLog.error("Failed processing NSItemProvider: \(providerDescription) with error: \(error)") + continuation.resume(returning: nil) + return + } + + guard let data else { + MXLog.error("Invalid NSItemProvider data: \(providerDescription)") + continuation.resume(returning: nil) + return + } + + continuation.resume(returning: data) + } + } + + guard let shareData else { + return nil + } + + do { + let url: URL + if let filename = providerSuggestedName { + let hasExtension = !(filename as NSString).pathExtension.isEmpty + let filename = hasExtension ? filename : "\(filename).\(preferredExtension)" + url = try FileManager.default.writeDataToTemporaryDirectory(data: shareData, fileName: filename) + } else { + let filename = "\(UUID().uuidString).\(preferredExtension)" + url = try FileManager.default.writeDataToTemporaryDirectory(data: shareData, fileName: filename) + } + + return .mediaFile(roomID: roomID, mediaFile: .init(url: url, suggestedName: providerSuggestedName)) + } catch { + MXLog.error("Failed storing NSItemProvider data \(providerDescription) with error: \(error)") + return nil + } + } + + private func openMainApp(payload: ShareExtensionPayload) async { + guard let payload = urlEncodeSharePayload(payload) else { + MXLog.error("Failed preparing share payload") + return + } + + guard let url = URL(string: "\(InfoPlistReader.main.baseBundleIdentifier):/\(ShareExtensionConstants.urlPath)?\(payload)") else { + MXLog.error("Failed retrieving main application scheme") + return + } + + await openURL(url) + } + + private func urlEncodeSharePayload(_ payload: ShareExtensionPayload) -> String? { + let data: Data + do { + data = try JSONEncoder().encode(payload) + } catch { + MXLog.error("Failed encoding share payload with error: \(error)") + return nil + } + + guard let jsonString = String(data: data, encoding: .utf8) else { + MXLog.error("Invalid payload data") + return nil + } + + return jsonString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) + } + + private func dismiss() { + extensionContext?.completeRequest(returningItems: [], completionHandler: nil) + } + + private func openURL(_ url: URL) async { + var responder: UIResponder? = self + while responder != nil { + if let application = responder as? UIApplication { + await application.open(url) + return + } + + responder = responder?.next + } + } +} diff --git a/ShareExtension/Sources/View/ShareExtensionView.swift b/ShareExtension/Sources/View/ShareExtensionView.swift new file mode 100644 index 0000000000..9329e3c1ec --- /dev/null +++ b/ShareExtension/Sources/View/ShareExtensionView.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 Compound +import SwiftUI + +struct ShareExtensionView: View { + var body: some View { + ZStack { + ProgressView() + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + .background(.compound.bgCanvasDefault) + } +} + +#Preview { + ShareExtensionView() +} diff --git a/ShareExtension/SupportingFiles/Info.plist b/ShareExtension/SupportingFiles/Info.plist new file mode 100644 index 0000000000..863d9f93c3 --- /dev/null +++ b/ShareExtension/SupportingFiles/Info.plist @@ -0,0 +1,55 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + $(PRODUCT_DISPLAY_NAME) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSExtension + + NSExtensionAttributes + + IntentsSupported + + INSendMessageIntent + + NSExtensionActivationRule + + NSExtensionActivationSupportsFileWithMaxCount + 1 + NSExtensionActivationSupportsImageWithMaxCount + 1 + NSExtensionActivationSupportsMovieWithMaxCount + 1 + + + NSExtensionPointIdentifier + com.apple.share-services + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).ShareExtensionViewController + + appGroupIdentifier + $(APP_GROUP_IDENTIFIER) + baseBundleIdentifier + $(BASE_BUNDLE_IDENTIFIER) + keychainAccessGroupIdentifier + $(KEYCHAIN_ACCESS_GROUP_IDENTIFIER) + productionAppName + $(PRODUCTION_APP_NAME) + + diff --git a/ShareExtension/SupportingFiles/ShareExtension.entitlements b/ShareExtension/SupportingFiles/ShareExtension.entitlements new file mode 100644 index 0000000000..8cb4a1a418 --- /dev/null +++ b/ShareExtension/SupportingFiles/ShareExtension.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.io.element + + + diff --git a/ShareExtension/SupportingFiles/target.yml b/ShareExtension/SupportingFiles/target.yml new file mode 100644 index 0000000000..469de107a8 --- /dev/null +++ b/ShareExtension/SupportingFiles/target.yml @@ -0,0 +1,85 @@ +name: ShareExtension + +schemes: + ShareExtension: + analyze: + config: Debug + archive: + config: Release + build: + targets: + ShareExtension: + - running + - testing + - profiling + - analyzing + - archiving + profile: + config: Release + run: + askForAppToLaunch: true + config: Debug + debugEnabled: false + disableMainThreadChecker: false + launchAutomaticallySubstyle: 2 + test: + config: Debug + disableMainThreadChecker: false + +targets: + ShareExtension: + type: app-extension + platform: iOS + + dependencies: + - package: MatrixRustSDK + - package: Collections + - package: Compound + + info: + path: ../SupportingFiles/Info.plist + properties: + CFBundleDisplayName: $(PRODUCT_DISPLAY_NAME) + CFBundleShortVersionString: $(MARKETING_VERSION) + CFBundleVersion: $(CURRENT_PROJECT_VERSION) + appGroupIdentifier: $(APP_GROUP_IDENTIFIER) + baseBundleIdentifier: $(BASE_BUNDLE_IDENTIFIER) + keychainAccessGroupIdentifier: $(KEYCHAIN_ACCESS_GROUP_IDENTIFIER) + productionAppName: $(PRODUCTION_APP_NAME) + NSExtension: + NSExtensionPointIdentifier: com.apple.share-services + NSExtensionPrincipalClass: $(PRODUCT_MODULE_NAME).ShareExtensionViewController + NSExtensionAttributes: + IntentsSupported: [ + INSendMessageIntent, + ] + NSExtensionActivationRule: + NSExtensionActivationSupportsFileWithMaxCount: 1 + NSExtensionActivationSupportsImageWithMaxCount: 1 + NSExtensionActivationSupportsMovieWithMaxCount: 1 + + settings: + base: + PRODUCT_NAME: ShareExtension + PRODUCT_DISPLAY_NAME: $(APP_DISPLAY_NAME) + PRODUCT_BUNDLE_IDENTIFIER: ${BASE_BUNDLE_IDENTIFIER}.shareextension + MARKETING_VERSION: $(MARKETING_VERSION) + CURRENT_PROJECT_VERSION: $(CURRENT_PROJECT_VERSION) + DEVELOPMENT_TEAM: $(DEVELOPMENT_TEAM) + CODE_SIGN_ENTITLEMENTS: ShareExtension/SupportingFiles/ShareExtension.entitlements + + sources: + - path: ../Sources + - path: ../SupportingFiles + - path: ../../ElementX/Sources/ShareExtension + - path: ../../ElementX/Sources/Application/AppSettings.swift + - path: ../../ElementX/Sources/Other/Extensions/Bundle.swift + - path: ../../ElementX/Sources/Other/Extensions/FileManager.swift + - path: ../../ElementX/Sources/Other/Extensions/NSItemProvider.swift + - path: ../../ElementX/Sources/Other/Extensions/ProcessInfo.swift + - path: ../../ElementX/Sources/Other/Extensions/UIView.swift + - path: ../../ElementX/Sources/Other/Extensions/URL.swift + - path: ../../ElementX/Sources/Other/InfoPlistReader.swift + - path: ../../ElementX/Sources/Other/Logging + - path: ../../ElementX/Sources/Other/UserPreference.swift + - path: ../../ElementX/Sources/UITests/UITestsScreenIdentifier.swift diff --git a/UnitTests/Sources/MediaProvider/MediaProviderTests.swift b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift index c33640482f..98712ba6c9 100644 --- a/UnitTests/Sources/MediaProvider/MediaProviderTests.swift +++ b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift @@ -73,12 +73,12 @@ final class MediaProviderTests: XCTestCase { } func test_whenImageFromSourceWithSourceNil_nilReturned() throws { - let image = mediaProvider.imageFromSource(nil, size: AvatarSize.room(on: .timeline).scaledSize) + let image = mediaProvider.imageFromSource(nil, size: Avatars.Size.room(on: .timeline).scaledSize) XCTAssertNil(image) } func test_whenImageFromSourceWithSourceNotNilAndImageCacheContainsImage_ImageIsReturned() throws { - let avatarSize = AvatarSize.room(on: .timeline) + let avatarSize = Avatars.Size.room(on: .timeline) let url = URL.picturesDirectory let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() @@ -90,12 +90,12 @@ final class MediaProviderTests: XCTestCase { func test_whenImageFromSourceWithSourceNotNilAndImageNotCached_nilReturned() throws { let image = mediaProvider.imageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), - size: AvatarSize.room(on: .timeline).scaledSize) + size: Avatars.Size.room(on: .timeline).scaledSize) XCTAssertNil(image) } func test_whenLoadImageFromSourceAndImageCacheContainsImage_successIsReturned() async throws { - let avatarSize = AvatarSize.room(on: .timeline) + let avatarSize = Avatars.Size.room(on: .timeline) let url = URL.picturesDirectory let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() @@ -106,7 +106,7 @@ final class MediaProviderTests: XCTestCase { } func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageSucceeds_successIsReturned() async throws { - let avatarSize = AvatarSize.room(on: .timeline) + let avatarSize = Avatars.Size.room(on: .timeline) let url = URL.picturesDirectory let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() @@ -117,7 +117,7 @@ final class MediaProviderTests: XCTestCase { } func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFails_imageThumbnailIsLoaded() async throws { - let avatarSize = AvatarSize.room(on: .timeline) + let avatarSize = Avatars.Size.room(on: .timeline) let expectedImage = try loadTestImage() mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = expectedImage.pngData() @@ -133,7 +133,7 @@ final class MediaProviderTests: XCTestCase { } func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFails_imageIsStored() async throws { - let avatarSize = AvatarSize.room(on: .timeline) + let avatarSize = Avatars.Size.room(on: .timeline) let url = URL.picturesDirectory let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let expectedImage = try loadTestImage() @@ -165,7 +165,7 @@ final class MediaProviderTests: XCTestCase { mediaLoader.loadMediaThumbnailForSourceWidthHeightThrowableError = MediaProviderTestsError.error let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), - size: AvatarSize.room(on: .timeline).scaledSize) + size: Avatars.Size.room(on: .timeline).scaledSize) switch result { case .success: XCTFail("Should fail") @@ -191,7 +191,7 @@ final class MediaProviderTests: XCTestCase { mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = Data() let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), - size: AvatarSize.room(on: .timeline).scaledSize) + size: Avatars.Size.room(on: .timeline).scaledSize) switch result { case .success: XCTFail("Should fail") diff --git a/UnitTests/Sources/RestorationTokenTests.swift b/UnitTests/Sources/RestorationTokenTests.swift index 404ae04ad3..72009d52ef 100644 --- a/UnitTests/Sources/RestorationTokenTests.swift +++ b/UnitTests/Sources/RestorationTokenTests.swift @@ -31,7 +31,7 @@ class RestorationTokenTests: XCTestCase { XCTAssertNil(decodedToken.pusherNotificationClientIdentifier, "There should not be a push notification client ID.") XCTAssertEqual(decodedToken.sessionDirectories.dataDirectory, .sessionsBaseDirectory.appending(component: "@user_example.com"), "The session directory should match the original location set by the Rust SDK from our base directory.") - XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, .cachesBaseDirectory.appending(component: "@user_example.com"), + XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, .sessionCachesBaseDirectory.appending(component: "@user_example.com"), "The cache directory should be derived from the session directory but in the caches directory.") } @@ -60,7 +60,7 @@ class RestorationTokenTests: XCTestCase { "The push notification client identifier should not be changed.") XCTAssertEqual(decodedToken.sessionDirectories.dataDirectory, originalToken.sessionDirectory, "The session directory should not be changed.") - XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, .cachesBaseDirectory.appending(component: sessionDirectoryName), + XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, .sessionCachesBaseDirectory.appending(component: sessionDirectoryName), "The cache directory should be derived from the session directory but in the caches directory.") } @@ -75,7 +75,7 @@ class RestorationTokenTests: XCTestCase { oidcData: "data-from-mas", slidingSyncVersion: .native), sessionDirectory: .sessionsBaseDirectory.appending(component: sessionDirectoryName), - cacheDirectory: .cachesBaseDirectory.appending(component: sessionDirectoryName), + cacheDirectory: .sessionCachesBaseDirectory.appending(component: sessionDirectoryName), passphrase: "passphrase", pusherNotificationClientIdentifier: "pusher-identifier") let data = try JSONEncoder().encode(originalToken) diff --git a/UnitTests/Sources/RoomFlowCoordinatorTests.swift b/UnitTests/Sources/RoomFlowCoordinatorTests.swift index 18e20f4524..6e2534b889 100644 --- a/UnitTests/Sources/RoomFlowCoordinatorTests.swift +++ b/UnitTests/Sources/RoomFlowCoordinatorTests.swift @@ -218,6 +218,31 @@ class RoomFlowCoordinatorTests: XCTestCase { XCTAssert(navigationStackCoordinator.stackCoordinators.first is RoomScreenCoordinator) } + func testShareRoute() async throws { + await setupRoomFlowCoordinator() + + try await process(route: .room(roomID: "1", via: [])) + XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) + XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) + + let sharePayload: ShareExtensionPayload = .mediaFile(roomID: "1", mediaFile: .init(url: .picturesDirectory, suggestedName: nil)) + try await process(route: .share(sharePayload)) + + XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) + XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) + + XCTAssertTrue((navigationStackCoordinator.sheetCoordinator as? NavigationStackCoordinator)?.rootCoordinator is MediaUploadPreviewScreenCoordinator) + + try await process(route: .childRoom(roomID: "2", via: [])) + XCTAssertNil(navigationStackCoordinator.sheetCoordinator) + XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 1) + + try await process(route: .share(sharePayload)) + + XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) + XCTAssertTrue((navigationStackCoordinator.sheetCoordinator as? NavigationStackCoordinator)?.rootCoordinator is MediaUploadPreviewScreenCoordinator) + } + // MARK: - Private private func process(route: AppRoute) async throws { diff --git a/UnitTests/Sources/SessionDirectoriesTests.swift b/UnitTests/Sources/SessionDirectoriesTests.swift index 62db895c7a..dfb934b648 100644 --- a/UnitTests/Sources/SessionDirectoriesTests.swift +++ b/UnitTests/Sources/SessionDirectoriesTests.swift @@ -21,7 +21,7 @@ class SessionDirectoriesTests: XCTestCase { // Then the directories should be generated in the correct location, using an escaped version of the user ID XCTAssertEqual(sessionDirectories.dataDirectory, .sessionsBaseDirectory.appending(component: "@user_matrix.org")) - XCTAssertEqual(sessionDirectories.cacheDirectory, .cachesBaseDirectory.appending(component: "@user_matrix.org")) + XCTAssertEqual(sessionDirectories.cacheDirectory, .sessionCachesBaseDirectory.appending(component: "@user_matrix.org")) } func testInitWithDataDirectory() { @@ -34,7 +34,7 @@ class SessionDirectoriesTests: XCTestCase { // Then the data directory should remain unchanged and the caches directory should be generated. XCTAssertEqual(sessionDirectories.dataDirectory, sessionDirectory) - XCTAssertEqual(sessionDirectories.cacheDirectory, .cachesBaseDirectory.appending(component: sessionDirectoryName)) + XCTAssertEqual(sessionDirectories.cacheDirectory, .sessionCachesBaseDirectory.appending(component: sessionDirectoryName)) } func testPathOutput() { diff --git a/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift b/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift index 83f79dfa92..30ed610786 100644 --- a/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift +++ b/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift @@ -211,8 +211,8 @@ class UserSessionFlowCoordinatorTests: XCTestCase { XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0) XCTAssertNotNil(detailCoordinator) - XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount, 1) - XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments?.initialFocussedEventID, "1") + XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 1) + XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "1") // A child event route should push a new room screen onto the stack and focus on the event. userSessionFlowCoordinator.handleAppRoute(.childEvent(eventID: "2", roomID: "2", via: []), animated: true) @@ -221,27 +221,50 @@ class UserSessionFlowCoordinatorTests: XCTestCase { XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 1) XCTAssertTrue(detailNavigationStack?.stackCoordinators.first is RoomScreenCoordinator) XCTAssertNotNil(detailCoordinator) - XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount, 2) - XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments?.initialFocussedEventID, "2") + XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 2) + XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "2") // A subsequent regular event route should clear the stack and set the new room as the root of the stack. try await process(route: .event(eventID: "3", roomID: "3", via: []), expectedState: .roomList(selectedRoomID: "3")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0) XCTAssertNotNil(detailCoordinator) - XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount, 3) - XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments?.initialFocussedEventID, "3") + XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 3) + XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "3") // A regular event route for the same room should set a new instance of the room as the root of the stack. try await process(route: .event(eventID: "4", roomID: "3", via: []), expectedState: .roomList(selectedRoomID: "3")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0) XCTAssertNotNil(detailCoordinator) - XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount, 4) - XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments?.initialFocussedEventID, "4", + XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 4) + XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "4", "A new timeline should be created for the same room ID, so that the screen isn't stale while loading.") } + func testShareRouteWithoutRoom() async throws { + try await process(route: .settings, expectedState: .settingsScreen(selectedRoomID: nil)) + XCTAssertTrue((splitCoordinator?.sheetCoordinator as? NavigationStackCoordinator)?.rootCoordinator is SettingsScreenCoordinator) + + let sharePayload: ShareExtensionPayload = .mediaFile(roomID: nil, mediaFile: .init(url: .picturesDirectory, suggestedName: nil)) + try await process(route: .share(sharePayload), + expectedState: .shareExtensionRoomList(sharePayload: sharePayload)) + + XCTAssertTrue((splitCoordinator?.sheetCoordinator as? NavigationStackCoordinator)?.rootCoordinator is RoomSelectionScreenCoordinator) + } + + func testShareRouteWithRoom() async throws { + try await process(route: .event(eventID: "1", roomID: "1", via: []), expectedState: .roomList(selectedRoomID: "1")) + XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) + + let sharePayload: ShareExtensionPayload = .mediaFile(roomID: "2", mediaFile: .init(url: .picturesDirectory, suggestedName: nil)) + try await process(route: .share(sharePayload), + expectedState: .roomList(selectedRoomID: "2")) + + XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) + XCTAssertTrue((splitCoordinator?.sheetCoordinator as? NavigationStackCoordinator)?.rootCoordinator is MediaUploadPreviewScreenCoordinator) + } + // MARK: - Private private func process(route: AppRoute, expectedState: UserSessionFlowCoordinatorStateMachine.State) async throws { diff --git a/project.yml b/project.yml index 9c04fccc87..4363aa49b4 100644 --- a/project.yml +++ b/project.yml @@ -53,6 +53,7 @@ include: - path: UITests/SupportingFiles/target.yml - path: IntegrationTests/SupportingFiles/target.yml - path: NSE/SupportingFiles/target.yml +- path: ShareExtension/SupportingFiles/target.yml # - path: NCE/SupportingFiles/target.yml (not used yet) # - path: MyAppVariant/override.yml From 03cb50e6e3427a124dcce1429d37059b0272ca58 Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:14:18 +0100 Subject: [PATCH 17/74] Knock requests banner (#3510) * need to add strings * preview tests * code improvements * fixed an error --- ElementX.xcodeproj/project.pbxproj | 46 ++--- .../en.lproj/Localizable.strings | 6 +- .../en.lproj/Localizable.stringsdict | 16 ++ ElementX/Sources/Generated/Strings.swift | 16 +- ElementX/Sources/Other/Avatars.swift | 7 +- .../SwiftUI/Views/StackedAvatarsView.swift | 4 +- .../View/KnockRequestsBannerView.swift | 191 ++++++++++++++++++ .../Sources/GeneratedPreviewTests.swift | 6 + ...allInviteRoomTimelineView-iPad-en-GB.1.png | 4 +- ...llInviteRoomTimelineView-iPad-pseudo.1.png | 4 +- ...viteRoomTimelineView-iPhone-16-en-GB.1.png | 4 +- ...iteRoomTimelineView-iPhone-16-pseudo.1.png | 4 +- ...annerView-iPad-en-GB.Multiple-Requests.png | 3 + ...d-en-GB.Single-Request-No-Display-Name.png | 3 + ...-iPad-en-GB.Single-Request-with-reason.png | 3 + ...tsBannerView-iPad-en-GB.Single-Request.png | 3 + ...nnerView-iPad-pseudo.Multiple-Requests.png | 3 + ...-pseudo.Single-Request-No-Display-Name.png | 3 + ...iPad-pseudo.Single-Request-with-reason.png | 3 + ...sBannerView-iPad-pseudo.Single-Request.png | 3 + ...View-iPhone-16-en-GB.Multiple-Requests.png | 3 + ...6-en-GB.Single-Request-No-Display-Name.png | 3 + ...ne-16-en-GB.Single-Request-with-reason.png | 3 + ...nerView-iPhone-16-en-GB.Single-Request.png | 3 + ...iew-iPhone-16-pseudo.Multiple-Requests.png | 3 + ...-pseudo.Single-Request-No-Display-Name.png | 3 + ...e-16-pseudo.Single-Request-with-reason.png | 3 + ...erView-iPhone-16-pseudo.Single-Request.png | 3 + 28 files changed, 317 insertions(+), 39 deletions(-) create mode 100644 ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Multiple-Requests.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-No-Display-Name.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-with-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Multiple-Requests.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-No-Display-Name.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-with-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Multiple-Requests.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-No-Display-Name.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-with-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Multiple-Requests.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-No-Display-Name.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-with-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request.png diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 6f4f71e3f0..d9b25195c4 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 56; objects = { /* Begin PBXAggregateTarget section */ @@ -799,6 +799,7 @@ A6DEC1ADEC8FEEC206A0FA37 /* AttributedStringBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */; }; A6F345328CCC5C9B0DAE2257 /* LogViewerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB05221D7D941CC82DC8480 /* LogViewerScreenViewModel.swift */; }; A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; }; + A73316762CE3A9B200F6B613 /* KnockRequestsBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A73316752CE3A9A700F6B613 /* KnockRequestsBannerView.swift */; }; A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; }; A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; A808DC3F72D15C6C5A52317E /* TimelineItemDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCDA016D05107DED3B9495CB /* TimelineItemDebugView.swift */; }; @@ -1264,13 +1265,13 @@ 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; 0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = ""; }; - 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; + 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = ""; }; 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = ""; }; 044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = ""; }; 045253F9967A535EE5B16691 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; 046C0D3F53B0B5EF0A1F5BEA /* RoomSummaryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryTests.swift; sourceTree = ""; }; - 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.swift; sourceTree = ""; }; 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = ""; }; 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxyProtocol.swift; sourceTree = ""; }; @@ -1336,7 +1337,7 @@ 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 = ""; }; - 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = ""; }; + 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; 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 = ""; }; @@ -1430,7 +1431,7 @@ 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = ""; }; 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenCoordinator.swift; sourceTree = ""; }; 260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = ""; }; - 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; path = PreviewTests.xctestplan; sourceTree = ""; }; + 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = PreviewTests.xctestplan; sourceTree = ""; }; 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorder.swift; sourceTree = ""; }; 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceProtocol.swift; sourceTree = ""; }; 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1501,7 +1502,7 @@ 3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = ""; }; 35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; 35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = ""; }; - 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = ""; }; 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerURLBuildersTests.swift; sourceTree = ""; }; 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = ""; }; @@ -1611,7 +1612,7 @@ 4B41FABA2B0AEF4389986495 /* LoginMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMode.swift; sourceTree = ""; }; 4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenCoordinator.swift; sourceTree = ""; }; 4C8D988E82A8DFA13BE46F7C /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pl; path = pl.lproj/Localizable.stringsdict; sourceTree = ""; }; - 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreen.swift; sourceTree = ""; }; 4D3A7375AB22721C436EB056 /* ComposerToolbarModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarModels.swift; sourceTree = ""; }; 4E2245243369B99216C7D84E /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = ""; }; @@ -1882,7 +1883,7 @@ 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 8DA1E8F287680C8ED25EDBAC /* NetworkMonitorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitorMock.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = ""; }; + 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; 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 = ""; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = ""; }; @@ -1987,6 +1988,7 @@ A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = ""; }; A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriverProtocol.swift; sourceTree = ""; }; A6EA0D8B0BBD8805F7D5A133 /* TextBasedRoomTimelineViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineViewProtocol.swift; sourceTree = ""; }; + A73316752CE3A9A700F6B613 /* KnockRequestsBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsBannerView.swift; sourceTree = ""; }; A73A07BAEDD74C48795A996A /* AsyncSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncSequence.swift; sourceTree = ""; }; A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationTokenTests.swift; sourceTree = ""; }; A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = ""; }; @@ -2063,7 +2065,7 @@ B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyProtocol.swift; sourceTree = ""; }; B53AC78E49A297AC1D72A7CF /* AppMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediator.swift; sourceTree = ""; }; B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = ""; }; - B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = ""; }; 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 = ""; }; @@ -2181,7 +2183,7 @@ CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = ""; }; CDE3F3911FF7CC639BDE5844 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; 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 = ""; }; + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; D01FD1171FF40E34D707FD00 /* BigIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigIcon.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 = ""; }; @@ -2314,7 +2316,7 @@ ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = ""; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = ""; }; ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModel.swift; sourceTree = ""; }; - ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = ""; }; ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = ""; }; EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = ""; }; @@ -2337,7 +2339,7 @@ F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = ""; }; - F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; + F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = ""; }; F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = ""; }; F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = ""; }; F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = ""; }; @@ -2355,7 +2357,7 @@ F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineBubbleLayout.swift; sourceTree = ""; }; F5E23D8EE6CBACF32F1EC874 /* MediaPlayerProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProviderProtocol.swift; sourceTree = ""; }; F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModel.swift; sourceTree = ""; }; - F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; path = test_apple_image.heic; sourceTree = ""; }; + F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_apple_image.heic; sourceTree = ""; }; F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = ""; }; F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockUITests.swift; sourceTree = ""; }; F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderMock.swift; sourceTree = ""; }; @@ -4155,6 +4157,7 @@ 79023E5904B155E8E2B8B502 /* View */ = { isa = PBXGroup; children = ( + A73316752CE3A9A700F6B613 /* KnockRequestsBannerView.swift */, 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */, 4137900E28201C314C835C11 /* RoomScreenFooterView.swift */, 4552D3466B1453F287223ADA /* SwipeRightAction.swift */, @@ -6589,6 +6592,7 @@ D19A748E95E2FAB2940570F0 /* CallScreen.swift in Sources */, 763D69741D58D2B650BC1FC9 /* CallScreenCoordinator.swift in Sources */, B7C9E07F4F9CCC8DD7156A20 /* CallScreenModels.swift in Sources */, + A73316762CE3A9B200F6B613 /* KnockRequestsBannerView.swift in Sources */, 39A987B3E41B976D1DF944C6 /* CallScreenViewModel.swift in Sources */, 84CAE3E96D93194DA06B9194 /* CallScreenViewModelProtocol.swift in Sources */, BB6BF528BC7F5B87E08C4F18 /* CameraPicker.swift in Sources */, @@ -7533,9 +7537,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_NSE", - ); + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -7584,9 +7586,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_MAIN_APP", - ); + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7612,9 +7612,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_MAIN_APP", - ); + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7880,9 +7878,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_NSE", - ); + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 2633939413..16616e3676 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -378,10 +378,14 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "Notify the whole room"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ of %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Pinned messages"; "screen_room_pinned_banner_loading_description" = "Loading message…"; "screen_room_pinned_banner_view_all_button_title" = "View All"; +"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_details_pinned_events_row_title" = "Pinned messages"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; @@ -790,7 +794,7 @@ "screen_room_timeline_add_reaction" = "Add emoji"; "screen_room_timeline_beginning_of_room" = "This is the beginning of %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "This is the beginning of this conversation."; -"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use to the new Element X app."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Show less"; "screen_room_timeline_message_copied" = "Message copied"; "screen_room_timeline_no_permission_to_post" = "You do not have permission to post to this room"; diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/en.lproj/Localizable.stringsdict index 60f8827b54..31f348283d 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d people + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 1bb831c6b8..11565013c3 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -1846,6 +1846,12 @@ internal enum L10n { internal static var screenRoomMentionsAtRoomSubtitle: String { return L10n.tr("Localizable", "screen_room_mentions_at_room_subtitle") } /// Everyone internal static var screenRoomMentionsAtRoomTitle: String { return L10n.tr("Localizable", "screen_room_mentions_at_room_title") } + /// Plural format key: "%#@COUNT@" + internal static func screenRoomMultipleKnockRequestsTitle(_ p1: Int) -> String { + return L10n.tr("Localizable", "screen_room_multiple_knock_requests_title", p1) + } + /// View all + internal static var screenRoomMultipleKnockRequestsViewAllButtonTitle: String { return L10n.tr("Localizable", "screen_room_multiple_knock_requests_view_all_button_title") } /// Allow custom setting internal static var screenRoomNotificationSettingsAllowCustom: String { return L10n.tr("Localizable", "screen_room_notification_settings_allow_custom") } /// Turning this on will override your default setting @@ -1920,6 +1926,14 @@ internal enum L10n { internal static var screenRoomRolesAndPermissionsRoomDetails: String { return L10n.tr("Localizable", "screen_room_roles_and_permissions_room_details") } /// Roles and permissions internal static var screenRoomRolesAndPermissionsTitle: String { return L10n.tr("Localizable", "screen_room_roles_and_permissions_title") } + /// Accept + internal static var screenRoomSingleKnockRequestAcceptButtonTitle: String { return L10n.tr("Localizable", "screen_room_single_knock_request_accept_button_title") } + /// %1$@ wants to join this room + internal static func screenRoomSingleKnockRequestTitle(_ p1: Any) -> String { + return L10n.tr("Localizable", "screen_room_single_knock_request_title", String(describing: p1)) + } + /// View + internal static var screenRoomSingleKnockRequestViewButtonTitle: String { return L10n.tr("Localizable", "screen_room_single_knock_request_view_button_title") } /// Add emoji internal static var screenRoomTimelineAddReaction: String { return L10n.tr("Localizable", "screen_room_timeline_add_reaction") } /// This is the beginning of %1$@. @@ -1928,7 +1942,7 @@ internal enum L10n { } /// This is the beginning of this conversation. internal static var screenRoomTimelineBeginningOfRoomNoName: String { return L10n.tr("Localizable", "screen_room_timeline_beginning_of_room_no_name") } - /// Unsupported call. Ask if the caller can use to the new Element X app. + /// Unsupported call. Ask if the caller can use the new Element X app. internal static var screenRoomTimelineLegacyCall: String { return L10n.tr("Localizable", "screen_room_timeline_legacy_call") } /// Show less internal static var screenRoomTimelineLessReactions: String { return L10n.tr("Localizable", "screen_room_timeline_less_reactions") } diff --git a/ElementX/Sources/Other/Avatars.swift b/ElementX/Sources/Other/Avatars.swift index fab60ce616..aae173e64e 100644 --- a/ElementX/Sources/Other/Avatars.swift +++ b/ElementX/Sources/Other/Avatars.swift @@ -72,7 +72,8 @@ enum UserAvatarSizeOnScreen { case editUserDetails case suggestions case blockedUsers - case knockingUsers + case knockingUsersStack + case knockingUser var value: CGFloat { switch self { @@ -102,8 +103,10 @@ enum UserAvatarSizeOnScreen { return 96 case .dmDetails: return 75 - case .knockingUsers: + case .knockingUsersStack: return 28 + case .knockingUser: + return 32 } } } diff --git a/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift b/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift index b2ee66f1ce..83cf78c0aa 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift @@ -53,13 +53,13 @@ struct StackedAvatarsView_Previews: PreviewProvider, TestablePreview { StackedAvatarsView(overlap: 16, lineWidth: 2, avatars: avatars, - avatarSize: .user(on: .knockingUsers), + avatarSize: .user(on: .knockingUsersStack), mediaProvider: MediaProviderMock()) StackedAvatarsView(overlap: 16, lineWidth: 2, shouldStackFromLast: true, avatars: avatars, - avatarSize: .user(on: .knockingUsers), + avatarSize: .user(on: .knockingUsersStack), mediaProvider: MediaProviderMock()) } } diff --git a/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift b/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift new file mode 100644 index 0000000000..c414979327 --- /dev/null +++ b/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift @@ -0,0 +1,191 @@ +// +// 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 KnockRequestInfo { + let displayName: String? + let avatarURL: URL? + let userID: String + let reason: String? +} + +struct KnockRequestsBannerView: View { + let requests: [KnockRequestInfo] + let onDismiss: () -> Void + let onAccept: (String) -> Void + let onViewAll: () -> Void + var mediaProvider: MediaProviderProtocol? + + var body: some View { + mainContent + .padding(16) + .background(.compound.bgCanvasDefault, 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) + } + + @ViewBuilder + private var mainContent: some View { + if requests.count == 1 { + SingleKnockRequestBannerContent(request: requests[0], onDismiss: onDismiss, onAccept: onAccept, onViewAll: onViewAll) + } else if requests.count > 1 { + MultipleKnockRequestsBannerContent(requests: requests, onDismiss: onDismiss, onViewAll: onViewAll) + } else { + EmptyView() + } + } +} + +private struct SingleKnockRequestBannerContent: View { + let request: KnockRequestInfo + let onDismiss: () -> Void + let onAccept: (String) -> Void + let onViewAll: () -> Void + var mediaProvider: MediaProviderProtocol? + + var body: some View { + VStack(spacing: 14) { + header + if let reason = request.reason { + Text(reason) + .lineLimit(2) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textPrimary) + .frame(maxWidth: .infinity, alignment: .leading) + } + actions + } + } + + private var header: some View { + HStack(spacing: 10) { + LoadableAvatarImage(url: request.avatarURL, + name: request.displayName, + contentID: request.userID, + avatarSize: .user(on: .knockingUser), mediaProvider: mediaProvider) + VStack(spacing: 0) { + HStack(alignment: .top, spacing: 0) { + Text(L10n.screenRoomSingleKnockRequestTitle(request.displayName ?? request.userID)) + .lineLimit(2) + .font(.compound.bodyMDSemibold) + .foregroundStyle(.compound.textPrimary) + .frame(maxWidth: .infinity, alignment: .leading) + KnockRequestsBannerDismissButton(onDismiss: onDismiss) + } + if request.displayName != nil { + Text(request.userID) + .lineLimit(2) + .font(.compound.bodySM) + .foregroundStyle(.compound.textSecondary) + .frame(maxWidth: .infinity, alignment: .leading) + } + } + } + } + + private var actions: some View { + HStack(spacing: 12) { + Button(L10n.screenRoomSingleKnockRequestViewButtonTitle, action: onViewAll) + .buttonStyle(.compound(.secondary)) + Button(L10n.screenRoomSingleKnockRequestAcceptButtonTitle, action: { + onAccept(request.userID) + }) + .buttonStyle(.compound(.primary)) + } + .padding(.top, request.reason == nil ? 0 : 2) + .frame(maxWidth: .infinity) + } +} + +private struct MultipleKnockRequestsBannerContent: View { + let requests: [KnockRequestInfo] + let onDismiss: () -> Void + let onViewAll: () -> Void + var mediaProvider: MediaProviderProtocol? + + private var avatars: [StackedAvatarInfo] { + requests + .prefix(3) + .map { .init(url: $0.avatarURL, name: $0.displayName, contentID: $0.userID) } + .reversed() + } + + private var multipleKnockRequestsTitle: String { + guard let first = requests.first else { + return "" + } + + let string = first.displayName ?? first.userID + return L10n.tr("Localizable", "screen_room_multiple_knock_requests_title", string, avatars.count - 1) + } + + var body: some View { + VStack(spacing: 14) { + HStack(spacing: 10) { + StackedAvatarsView(overlap: 16, lineWidth: 2, shouldStackFromLast: true, avatars: avatars, avatarSize: .user(on: .knockingUsersStack), mediaProvider: mediaProvider) + HStack(alignment: .top, spacing: 0) { + Text(multipleKnockRequestsTitle) + .lineLimit(2) + .font(.compound.bodyMDSemibold) + .foregroundStyle(.compound.textPrimary) + .frame(maxWidth: .infinity, alignment: .leading) + KnockRequestsBannerDismissButton(onDismiss: onDismiss) + } + } + Button(L10n.screenRoomMultipleKnockRequestsViewAllButtonTitle) { + onViewAll() + } + .buttonStyle(.compound(.primary)) + } + } +} + +private struct KnockRequestsBannerDismissButton: View { + let onDismiss: () -> Void + + var body: some View { + Button { + onDismiss() + } label: { + CompoundIcon(\.close, size: .medium, relativeTo: .compound.bodySMSemibold) + .foregroundColor(.compound.iconTertiary) + } + .alignmentGuide(.top, computeValue: { _ in + 3 + }) + } +} + +struct KnockRequestsBannerView_Previews: PreviewProvider, TestablePreview { + static let singleRequest: [KnockRequestInfo] = [.init(displayName: "Alice", avatarURL: nil, userID: "@alice:matrix.org", reason: nil)] + + 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 singleRequestNoDisplayName: [KnockRequestInfo] = [.init(displayName: nil, avatarURL: nil, userID: "@alice:matrix.org", reason: nil)] + + 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) + ] + + static var previews: some View { + KnockRequestsBannerView(requests: singleRequest, onDismiss: { }, onAccept: { _ in }, onViewAll: { }) + .previewDisplayName("Single Request") + KnockRequestsBannerView(requests: singleRequestWithReason, onDismiss: { }, onAccept: { _ in }, onViewAll: { }) + .previewDisplayName("Single Request with reason") + KnockRequestsBannerView(requests: singleRequestNoDisplayName, onDismiss: { }, onAccept: { _ in }, onViewAll: { }) + .previewDisplayName("Single Request, No Display Name") + KnockRequestsBannerView(requests: multipleRequests, onDismiss: { }, onAccept: { _ in }, onViewAll: { }) + .previewDisplayName("Multiple Requests") + } +} diff --git a/PreviewTests/Sources/GeneratedPreviewTests.swift b/PreviewTests/Sources/GeneratedPreviewTests.swift index 926ad7802a..bac6116695 100644 --- a/PreviewTests/Sources/GeneratedPreviewTests.swift +++ b/PreviewTests/Sources/GeneratedPreviewTests.swift @@ -305,6 +305,12 @@ extension PreviewTests { } } + func test_knockRequestsBannerView() { + for preview in KnockRequestsBannerView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_legalInformationScreen() { for preview in LegalInformationScreen_Previews._allPreviews { assertSnapshots(matching: preview) diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png index b81a7696c9..83f128840c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83c70644604dc70c886dea41fc3935e9d8d7bed388e0d57619bbdfe026c3b0c5 -size 78127 +oid sha256:7a5ce2597845f5f89870a44a493787d8406203a63a3df8a7baceee5cabf49da2 +size 77671 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png index a667d1bf06..976f31d220 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d22830f81bb98725d9e25e49814b3263269ffd6f59a0af60fe19d55e13ab1448 -size 84129 +oid sha256:7905467ec2400211fa10bf7e94d50a305eb60322223e75b4f105964e118c4fea +size 81453 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-en-GB.1.png index a3aa4dbc25..fbe201059f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f9beb2df735de7ad5d2c3c187b236672813db91a987992b13e2a344c663e3cf -size 38721 +oid sha256:1c30a240f5bfd1bfb6a87e64c6e5183151345b6644c860304cdf00689bf13d3a +size 37863 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-pseudo.1.png index abb75a6173..75c75f4a61 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_callInviteRoomTimelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7210cfeed3af08712b88d2f845118d284adf441f11f5cf03b84ea7b3d02d6205 -size 47915 +oid sha256:f407835b62ade17fece213a80179c4c8ab7f65633dccabdc33f42bff97ebd542 +size 46992 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 new file mode 100644 index 0000000000..64654e9a21 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Multiple-Requests.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a00d27886b5820fc2f46d201f9e40460010470702c4de0c1889173e0e9b7a3bf +size 93142 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-No-Display-Name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-No-Display-Name.png new file mode 100644 index 0000000000..85c1395791 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-No-Display-Name.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bece9623232e1204708162f137c93120d8da2a75b88787b233aa2cb09b54f630 +size 97166 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-with-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-with-reason.png new file mode 100644 index 0000000000..7f7b2389a9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-with-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00dbd02aed2799c2bd9d87ae1c551e0327fae075d4fc772f526572ed8771791d +size 111929 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request.png new file mode 100644 index 0000000000..bc47f76b82 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0526b9fca57c50bf32249b9b3557916eae97c430b430a19cedaa06d4dfaa0ce3 +size 99219 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 new file mode 100644 index 0000000000..7b7b1c6189 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Multiple-Requests.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04db101605f075891d02b3d46dff7cd12577e93808de4b58297147f81f9c4d00 +size 94022 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-No-Display-Name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-No-Display-Name.png new file mode 100644 index 0000000000..ff83bdd77d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-No-Display-Name.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac5e83a0da72ff4f45cfa53ea53e97b45ace007d44ba6278f476f15b72e711e2 +size 100502 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-with-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-with-reason.png new file mode 100644 index 0000000000..aa7ff64ae0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-with-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:401ba2ecfaea3b01487163af4b49c23b2ec0677356f240fec177da2e839cc188 +size 116728 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request.png new file mode 100644 index 0000000000..8d47a0657f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b75c803de335663b3447151060475fdcd9f1e488da36f96da250ecd1bea01bd +size 104073 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 new file mode 100644 index 0000000000..ee92977682 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Multiple-Requests.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b4b78c20f278e17836ebf1685bd2c7a55c6f22f54f7cbadd430f606f369272d +size 50876 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-No-Display-Name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-No-Display-Name.png new file mode 100644 index 0000000000..12c868d368 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-No-Display-Name.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8c1312811b4df9e02203b4f6a1e72546311b1b6c5a476088e66b21712b15005 +size 54839 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-with-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-with-reason.png new file mode 100644 index 0000000000..32cfbe4834 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-with-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:248c6ebf2601a23aa6c58642f4001e62d299e36c426e8948e3dac744a32ee801 +size 67213 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request.png new file mode 100644 index 0000000000..adefebe187 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc821155dedf651cb75fd830fe8436be1d5c2e1131a6c491934f8eb357f08024 +size 54814 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 new file mode 100644 index 0000000000..a0bde28117 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Multiple-Requests.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c3e3e0747511cf80b1d0e546a0e16e9eac85dbd4bcfdda0585d21a6fc525d07 +size 50476 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-No-Display-Name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-No-Display-Name.png new file mode 100644 index 0000000000..2001e846ed --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-No-Display-Name.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6b08d7f64d1719c39a1d9ce22725e1615f47843eb5b1918d926a4f30b13552d +size 61108 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-with-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-with-reason.png new file mode 100644 index 0000000000..8e472ff40f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-with-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f13de390d5293d48e7a360ce61c5bd0a363726a451a61b29a05444d00428bde +size 74128 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request.png new file mode 100644 index 0000000000..d1672d5ec8 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1291268bc8c285e9908505c371b3419c943bf694c267a959ab99c65779cdf6ff +size 63143 From 79473ef2e911333ec6bdedabbaaa24b56e219906 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 13 Nov 2024 20:03:30 +0200 Subject: [PATCH 18/74] Bump the RustSDK to v1.0.67 (#3512) * Bump the RustSDK to v1.0.67 * PR comments --------- Co-authored-by: Doug --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../RoomFlowCoordinator.swift | 14 +- .../Mocks/Generated/GeneratedMocks.swift | 166 ++----- .../Mocks/Generated/SDKGeneratedMocks.swift | 434 ++++++++++++------ .../Sources/Mocks/JoinedRoomProxyMock.swift | 5 +- .../Other/Extensions/ClientBuilder.swift | 4 +- ...fiedUserSendFailureScreenCoordinator.swift | 4 +- ...rifiedUserSendFailureScreenViewModel.swift | 12 +- ...ResolveVerifiedUserSendFailureScreen.swift | 4 +- .../RoomScreen/RoomScreenCoordinator.swift | 6 +- .../Screens/Timeline/TimelineModels.swift | 2 +- .../Screens/Timeline/TimelineViewModel.swift | 9 +- .../Sources/Services/Client/ClientProxy.swift | 5 +- .../Services/Room/JoinedRoomProxy.swift | 37 +- .../Services/Room/RoomProxyProtocol.swift | 6 +- .../RoomSummary/RoomEventStringBuilder.swift | 8 +- .../RoomMessageEventStringBuilder.swift | 42 +- .../MockRoomTimelineController.swift | 4 + .../RoomTimelineController.swift | 15 + .../RoomTimelineControllerProtocol.swift | 2 + .../Services/Timeline/TimelineItemProxy.swift | 36 ++ .../RoomTimelineItemFactory.swift | 10 +- .../NotificationServiceExtension.swift | 2 +- UnitTests/Sources/LoggingTests.swift | 21 +- ...dUserSendFailureScreenViewModelTests.swift | 2 +- project.yml | 2 +- 27 files changed, 499 insertions(+), 359 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index d9b25195c4..146e06614b 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -8109,7 +8109,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.66; + version = 1.0.67; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 0d3eb39468..7607c0996c 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "902979581ff4f35e54a83cd7c5c340745d6f0d0e", - "version" : "1.0.66" + "revision" : "5f23a9b8e210aa9962b420bcd7065d5f9cf142c9", + "version" : "1.0.67" } }, { diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index 51163c8c43..459aebc86e 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -556,8 +556,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { case (.roomMemberDetails, .dismissUserProfile, .roomDetails): break - case (.room, .presentResolveSendFailure(let failure, let itemID), .resolveSendFailure): - presentResolveSendFailure(failure: failure, itemID: itemID) + case (.room, .presentResolveSendFailure(let failure, let sendHandle), .resolveSendFailure): + presentResolveSendFailure(failure: failure, sendHandle: sendHandle) case (.resolveSendFailure, .dismissResolveSendFailure, .room): break @@ -691,8 +691,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { actionsSubject.send(.presentCallScreen(roomProxy: roomProxy)) case .presentPinnedEventsTimeline: stateMachine.tryEvent(.presentPinnedEventsTimeline) - case .presentResolveSendFailure(failure: let failure, itemID: let itemID): - stateMachine.tryEvent(.presentResolveSendFailure(failure: failure, itemID: itemID)) + case .presentResolveSendFailure(failure: let failure, sendHandle: let sendHandle): + stateMachine.tryEvent(.presentResolveSendFailure(failure: failure, sendHandle: sendHandle)) } } .store(in: &cancellables) @@ -1438,9 +1438,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { coordinator.start() } - private func presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, itemID: TimelineItemIdentifier) { + private func presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, sendHandle: SendHandleProxy) { let coordinator = ResolveVerifiedUserSendFailureScreenCoordinator(parameters: .init(failure: failure, - itemID: itemID, + sendHandle: sendHandle, roomProxy: roomProxy, userIndicatorController: userIndicatorController)) coordinator.actionsPublisher.sink { [weak self] action in @@ -1607,7 +1607,7 @@ private extension RoomFlowCoordinator { case presentPinnedEventsTimeline case dismissPinnedEventsTimeline - case presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, itemID: TimelineItemIdentifier) + case presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, sendHandle: SendHandleProxy) case dismissResolveSendFailure // Child room flow events diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 6dac05ec44..d7f3f69ccf 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -7039,87 +7039,17 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol { return sendTypingNotificationIsTypingReturnValue } } - //MARK: - resend - - var resendItemIDUnderlyingCallsCount = 0 - var resendItemIDCallsCount: Int { - get { - if Thread.isMainThread { - return resendItemIDUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = resendItemIDUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - resendItemIDUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - resendItemIDUnderlyingCallsCount = newValue - } - } - } - } - var resendItemIDCalled: Bool { - return resendItemIDCallsCount > 0 - } - var resendItemIDReceivedItemID: TimelineItemIdentifier? - var resendItemIDReceivedInvocations: [TimelineItemIdentifier] = [] - - var resendItemIDUnderlyingReturnValue: Result! - var resendItemIDReturnValue: Result! { - get { - if Thread.isMainThread { - return resendItemIDUnderlyingReturnValue - } else { - var returnValue: Result? = nil - DispatchQueue.main.sync { - returnValue = resendItemIDUnderlyingReturnValue - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - resendItemIDUnderlyingReturnValue = newValue - } else { - DispatchQueue.main.sync { - resendItemIDUnderlyingReturnValue = newValue - } - } - } - } - var resendItemIDClosure: ((TimelineItemIdentifier) async -> Result)? - - func resend(itemID: TimelineItemIdentifier) async -> Result { - resendItemIDCallsCount += 1 - resendItemIDReceivedItemID = itemID - DispatchQueue.main.async { - self.resendItemIDReceivedInvocations.append(itemID) - } - if let resendItemIDClosure = resendItemIDClosure { - return await resendItemIDClosure(itemID) - } else { - return resendItemIDReturnValue - } - } //MARK: - ignoreDeviceTrustAndResend - var ignoreDeviceTrustAndResendDevicesItemIDUnderlyingCallsCount = 0 - var ignoreDeviceTrustAndResendDevicesItemIDCallsCount: Int { + var ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingCallsCount = 0 + var ignoreDeviceTrustAndResendDevicesSendHandleCallsCount: Int { get { if Thread.isMainThread { - return ignoreDeviceTrustAndResendDevicesItemIDUnderlyingCallsCount + return ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = ignoreDeviceTrustAndResendDevicesItemIDUnderlyingCallsCount + returnValue = ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingCallsCount } return returnValue! @@ -7127,29 +7057,29 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol { } set { if Thread.isMainThread { - ignoreDeviceTrustAndResendDevicesItemIDUnderlyingCallsCount = newValue + ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - ignoreDeviceTrustAndResendDevicesItemIDUnderlyingCallsCount = newValue + ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingCallsCount = newValue } } } } - var ignoreDeviceTrustAndResendDevicesItemIDCalled: Bool { - return ignoreDeviceTrustAndResendDevicesItemIDCallsCount > 0 + var ignoreDeviceTrustAndResendDevicesSendHandleCalled: Bool { + return ignoreDeviceTrustAndResendDevicesSendHandleCallsCount > 0 } - var ignoreDeviceTrustAndResendDevicesItemIDReceivedArguments: (devices: [String: [String]], itemID: TimelineItemIdentifier)? - var ignoreDeviceTrustAndResendDevicesItemIDReceivedInvocations: [(devices: [String: [String]], itemID: TimelineItemIdentifier)] = [] + var ignoreDeviceTrustAndResendDevicesSendHandleReceivedArguments: (devices: [String: [String]], sendHandle: SendHandleProxy)? + var ignoreDeviceTrustAndResendDevicesSendHandleReceivedInvocations: [(devices: [String: [String]], sendHandle: SendHandleProxy)] = [] - var ignoreDeviceTrustAndResendDevicesItemIDUnderlyingReturnValue: Result! - var ignoreDeviceTrustAndResendDevicesItemIDReturnValue: Result! { + var ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingReturnValue: Result! + var ignoreDeviceTrustAndResendDevicesSendHandleReturnValue: Result! { get { if Thread.isMainThread { - return ignoreDeviceTrustAndResendDevicesItemIDUnderlyingReturnValue + return ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = ignoreDeviceTrustAndResendDevicesItemIDUnderlyingReturnValue + returnValue = ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingReturnValue } return returnValue! @@ -7157,39 +7087,39 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol { } set { if Thread.isMainThread { - ignoreDeviceTrustAndResendDevicesItemIDUnderlyingReturnValue = newValue + ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - ignoreDeviceTrustAndResendDevicesItemIDUnderlyingReturnValue = newValue + ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingReturnValue = newValue } } } } - var ignoreDeviceTrustAndResendDevicesItemIDClosure: (([String: [String]], TimelineItemIdentifier) async -> Result)? + var ignoreDeviceTrustAndResendDevicesSendHandleClosure: (([String: [String]], SendHandleProxy) async -> Result)? - func ignoreDeviceTrustAndResend(devices: [String: [String]], itemID: TimelineItemIdentifier) async -> Result { - ignoreDeviceTrustAndResendDevicesItemIDCallsCount += 1 - ignoreDeviceTrustAndResendDevicesItemIDReceivedArguments = (devices: devices, itemID: itemID) + func ignoreDeviceTrustAndResend(devices: [String: [String]], sendHandle: SendHandleProxy) async -> Result { + ignoreDeviceTrustAndResendDevicesSendHandleCallsCount += 1 + ignoreDeviceTrustAndResendDevicesSendHandleReceivedArguments = (devices: devices, sendHandle: sendHandle) DispatchQueue.main.async { - self.ignoreDeviceTrustAndResendDevicesItemIDReceivedInvocations.append((devices: devices, itemID: itemID)) + self.ignoreDeviceTrustAndResendDevicesSendHandleReceivedInvocations.append((devices: devices, sendHandle: sendHandle)) } - if let ignoreDeviceTrustAndResendDevicesItemIDClosure = ignoreDeviceTrustAndResendDevicesItemIDClosure { - return await ignoreDeviceTrustAndResendDevicesItemIDClosure(devices, itemID) + if let ignoreDeviceTrustAndResendDevicesSendHandleClosure = ignoreDeviceTrustAndResendDevicesSendHandleClosure { + return await ignoreDeviceTrustAndResendDevicesSendHandleClosure(devices, sendHandle) } else { - return ignoreDeviceTrustAndResendDevicesItemIDReturnValue + return ignoreDeviceTrustAndResendDevicesSendHandleReturnValue } } //MARK: - withdrawVerificationAndResend - var withdrawVerificationAndResendUserIDsItemIDUnderlyingCallsCount = 0 - var withdrawVerificationAndResendUserIDsItemIDCallsCount: Int { + var withdrawVerificationAndResendUserIDsSendHandleUnderlyingCallsCount = 0 + var withdrawVerificationAndResendUserIDsSendHandleCallsCount: Int { get { if Thread.isMainThread { - return withdrawVerificationAndResendUserIDsItemIDUnderlyingCallsCount + return withdrawVerificationAndResendUserIDsSendHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = withdrawVerificationAndResendUserIDsItemIDUnderlyingCallsCount + returnValue = withdrawVerificationAndResendUserIDsSendHandleUnderlyingCallsCount } return returnValue! @@ -7197,29 +7127,29 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol { } set { if Thread.isMainThread { - withdrawVerificationAndResendUserIDsItemIDUnderlyingCallsCount = newValue + withdrawVerificationAndResendUserIDsSendHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - withdrawVerificationAndResendUserIDsItemIDUnderlyingCallsCount = newValue + withdrawVerificationAndResendUserIDsSendHandleUnderlyingCallsCount = newValue } } } } - var withdrawVerificationAndResendUserIDsItemIDCalled: Bool { - return withdrawVerificationAndResendUserIDsItemIDCallsCount > 0 + var withdrawVerificationAndResendUserIDsSendHandleCalled: Bool { + return withdrawVerificationAndResendUserIDsSendHandleCallsCount > 0 } - var withdrawVerificationAndResendUserIDsItemIDReceivedArguments: (userIDs: [String], itemID: TimelineItemIdentifier)? - var withdrawVerificationAndResendUserIDsItemIDReceivedInvocations: [(userIDs: [String], itemID: TimelineItemIdentifier)] = [] + var withdrawVerificationAndResendUserIDsSendHandleReceivedArguments: (userIDs: [String], sendHandle: SendHandleProxy)? + var withdrawVerificationAndResendUserIDsSendHandleReceivedInvocations: [(userIDs: [String], sendHandle: SendHandleProxy)] = [] - var withdrawVerificationAndResendUserIDsItemIDUnderlyingReturnValue: Result! - var withdrawVerificationAndResendUserIDsItemIDReturnValue: Result! { + var withdrawVerificationAndResendUserIDsSendHandleUnderlyingReturnValue: Result! + var withdrawVerificationAndResendUserIDsSendHandleReturnValue: Result! { get { if Thread.isMainThread { - return withdrawVerificationAndResendUserIDsItemIDUnderlyingReturnValue + return withdrawVerificationAndResendUserIDsSendHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = withdrawVerificationAndResendUserIDsItemIDUnderlyingReturnValue + returnValue = withdrawVerificationAndResendUserIDsSendHandleUnderlyingReturnValue } return returnValue! @@ -7227,26 +7157,26 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol { } set { if Thread.isMainThread { - withdrawVerificationAndResendUserIDsItemIDUnderlyingReturnValue = newValue + withdrawVerificationAndResendUserIDsSendHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - withdrawVerificationAndResendUserIDsItemIDUnderlyingReturnValue = newValue + withdrawVerificationAndResendUserIDsSendHandleUnderlyingReturnValue = newValue } } } } - var withdrawVerificationAndResendUserIDsItemIDClosure: (([String], TimelineItemIdentifier) async -> Result)? + var withdrawVerificationAndResendUserIDsSendHandleClosure: (([String], SendHandleProxy) async -> Result)? - func withdrawVerificationAndResend(userIDs: [String], itemID: TimelineItemIdentifier) async -> Result { - withdrawVerificationAndResendUserIDsItemIDCallsCount += 1 - withdrawVerificationAndResendUserIDsItemIDReceivedArguments = (userIDs: userIDs, itemID: itemID) + func withdrawVerificationAndResend(userIDs: [String], sendHandle: SendHandleProxy) async -> Result { + withdrawVerificationAndResendUserIDsSendHandleCallsCount += 1 + withdrawVerificationAndResendUserIDsSendHandleReceivedArguments = (userIDs: userIDs, sendHandle: sendHandle) DispatchQueue.main.async { - self.withdrawVerificationAndResendUserIDsItemIDReceivedInvocations.append((userIDs: userIDs, itemID: itemID)) + self.withdrawVerificationAndResendUserIDsSendHandleReceivedInvocations.append((userIDs: userIDs, sendHandle: sendHandle)) } - if let withdrawVerificationAndResendUserIDsItemIDClosure = withdrawVerificationAndResendUserIDsItemIDClosure { - return await withdrawVerificationAndResendUserIDsItemIDClosure(userIDs, itemID) + if let withdrawVerificationAndResendUserIDsSendHandleClosure = withdrawVerificationAndResendUserIDsSendHandleClosure { + return await withdrawVerificationAndResendUserIDsSendHandleClosure(userIDs, sendHandle) } else { - return withdrawVerificationAndResendUserIDsItemIDReturnValue + return withdrawVerificationAndResendUserIDsSendHandleReturnValue } } //MARK: - flagAsUnread diff --git a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift index 43a24c5c6f..689ef2fdee 100644 --- a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift @@ -625,6 +625,52 @@ open class ClientSDKMock: MatrixRustSDK.Client { } } + //MARK: - createRoomAlias + + open var createRoomAliasRoomAliasRoomIdThrowableError: Error? + var createRoomAliasRoomAliasRoomIdUnderlyingCallsCount = 0 + open var createRoomAliasRoomAliasRoomIdCallsCount: Int { + get { + if Thread.isMainThread { + return createRoomAliasRoomAliasRoomIdUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = createRoomAliasRoomAliasRoomIdUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + createRoomAliasRoomAliasRoomIdUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + createRoomAliasRoomAliasRoomIdUnderlyingCallsCount = newValue + } + } + } + } + open var createRoomAliasRoomAliasRoomIdCalled: Bool { + return createRoomAliasRoomAliasRoomIdCallsCount > 0 + } + open var createRoomAliasRoomAliasRoomIdReceivedArguments: (roomAlias: String, roomId: String)? + open var createRoomAliasRoomAliasRoomIdReceivedInvocations: [(roomAlias: String, roomId: String)] = [] + open var createRoomAliasRoomAliasRoomIdClosure: ((String, String) async throws -> Void)? + + open override func createRoomAlias(roomAlias: String, roomId: String) async throws { + if let error = createRoomAliasRoomAliasRoomIdThrowableError { + throw error + } + createRoomAliasRoomAliasRoomIdCallsCount += 1 + createRoomAliasRoomAliasRoomIdReceivedArguments = (roomAlias: roomAlias, roomId: roomId) + DispatchQueue.main.async { + self.createRoomAliasRoomAliasRoomIdReceivedInvocations.append((roomAlias: roomAlias, roomId: roomId)) + } + try await createRoomAliasRoomAliasRoomIdClosure?(roomAlias, roomId) + } + //MARK: - customLoginWithJwt open var customLoginWithJwtJwtInitialDeviceNameDeviceIdThrowableError: Error? @@ -4674,6 +4720,77 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } } + //MARK: - crossProcessStoreLocksHolderName + + var crossProcessStoreLocksHolderNameHolderNameUnderlyingCallsCount = 0 + open var crossProcessStoreLocksHolderNameHolderNameCallsCount: Int { + get { + if Thread.isMainThread { + return crossProcessStoreLocksHolderNameHolderNameUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = crossProcessStoreLocksHolderNameHolderNameUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + crossProcessStoreLocksHolderNameHolderNameUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + crossProcessStoreLocksHolderNameHolderNameUnderlyingCallsCount = newValue + } + } + } + } + open var crossProcessStoreLocksHolderNameHolderNameCalled: Bool { + return crossProcessStoreLocksHolderNameHolderNameCallsCount > 0 + } + open var crossProcessStoreLocksHolderNameHolderNameReceivedHolderName: String? + open var crossProcessStoreLocksHolderNameHolderNameReceivedInvocations: [String] = [] + + var crossProcessStoreLocksHolderNameHolderNameUnderlyingReturnValue: ClientBuilder! + open var crossProcessStoreLocksHolderNameHolderNameReturnValue: ClientBuilder! { + get { + if Thread.isMainThread { + return crossProcessStoreLocksHolderNameHolderNameUnderlyingReturnValue + } else { + var returnValue: ClientBuilder? = nil + DispatchQueue.main.sync { + returnValue = crossProcessStoreLocksHolderNameHolderNameUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + crossProcessStoreLocksHolderNameHolderNameUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + crossProcessStoreLocksHolderNameHolderNameUnderlyingReturnValue = newValue + } + } + } + } + open var crossProcessStoreLocksHolderNameHolderNameClosure: ((String) -> ClientBuilder)? + + open override func crossProcessStoreLocksHolderName(holderName: String) -> ClientBuilder { + crossProcessStoreLocksHolderNameHolderNameCallsCount += 1 + crossProcessStoreLocksHolderNameHolderNameReceivedHolderName = holderName + DispatchQueue.main.async { + self.crossProcessStoreLocksHolderNameHolderNameReceivedInvocations.append(holderName) + } + if let crossProcessStoreLocksHolderNameHolderNameClosure = crossProcessStoreLocksHolderNameHolderNameClosure { + return crossProcessStoreLocksHolderNameHolderNameClosure(holderName) + } else { + return crossProcessStoreLocksHolderNameHolderNameReturnValue + } + } + //MARK: - disableAutomaticTokenRefresh var disableAutomaticTokenRefreshUnderlyingCallsCount = 0 @@ -4869,17 +4986,17 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } } - //MARK: - enableCrossProcessRefreshLock + //MARK: - enableOidcRefreshLock - var enableCrossProcessRefreshLockProcessIdSessionDelegateUnderlyingCallsCount = 0 - open var enableCrossProcessRefreshLockProcessIdSessionDelegateCallsCount: Int { + var enableOidcRefreshLockUnderlyingCallsCount = 0 + open var enableOidcRefreshLockCallsCount: Int { get { if Thread.isMainThread { - return enableCrossProcessRefreshLockProcessIdSessionDelegateUnderlyingCallsCount + return enableOidcRefreshLockUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = enableCrossProcessRefreshLockProcessIdSessionDelegateUnderlyingCallsCount + returnValue = enableOidcRefreshLockUnderlyingCallsCount } return returnValue! @@ -4887,29 +5004,27 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } set { if Thread.isMainThread { - enableCrossProcessRefreshLockProcessIdSessionDelegateUnderlyingCallsCount = newValue + enableOidcRefreshLockUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - enableCrossProcessRefreshLockProcessIdSessionDelegateUnderlyingCallsCount = newValue + enableOidcRefreshLockUnderlyingCallsCount = newValue } } } } - open var enableCrossProcessRefreshLockProcessIdSessionDelegateCalled: Bool { - return enableCrossProcessRefreshLockProcessIdSessionDelegateCallsCount > 0 + open var enableOidcRefreshLockCalled: Bool { + return enableOidcRefreshLockCallsCount > 0 } - open var enableCrossProcessRefreshLockProcessIdSessionDelegateReceivedArguments: (processId: String, sessionDelegate: ClientSessionDelegate)? - open var enableCrossProcessRefreshLockProcessIdSessionDelegateReceivedInvocations: [(processId: String, sessionDelegate: ClientSessionDelegate)] = [] - var enableCrossProcessRefreshLockProcessIdSessionDelegateUnderlyingReturnValue: ClientBuilder! - open var enableCrossProcessRefreshLockProcessIdSessionDelegateReturnValue: ClientBuilder! { + var enableOidcRefreshLockUnderlyingReturnValue: ClientBuilder! + open var enableOidcRefreshLockReturnValue: ClientBuilder! { get { if Thread.isMainThread { - return enableCrossProcessRefreshLockProcessIdSessionDelegateUnderlyingReturnValue + return enableOidcRefreshLockUnderlyingReturnValue } else { var returnValue: ClientBuilder? = nil DispatchQueue.main.sync { - returnValue = enableCrossProcessRefreshLockProcessIdSessionDelegateUnderlyingReturnValue + returnValue = enableOidcRefreshLockUnderlyingReturnValue } return returnValue! @@ -4917,26 +5032,22 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder { } set { if Thread.isMainThread { - enableCrossProcessRefreshLockProcessIdSessionDelegateUnderlyingReturnValue = newValue + enableOidcRefreshLockUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - enableCrossProcessRefreshLockProcessIdSessionDelegateUnderlyingReturnValue = newValue + enableOidcRefreshLockUnderlyingReturnValue = newValue } } } } - open var enableCrossProcessRefreshLockProcessIdSessionDelegateClosure: ((String, ClientSessionDelegate) -> ClientBuilder)? + open var enableOidcRefreshLockClosure: (() -> ClientBuilder)? - open override func enableCrossProcessRefreshLock(processId: String, sessionDelegate: ClientSessionDelegate) -> ClientBuilder { - enableCrossProcessRefreshLockProcessIdSessionDelegateCallsCount += 1 - enableCrossProcessRefreshLockProcessIdSessionDelegateReceivedArguments = (processId: processId, sessionDelegate: sessionDelegate) - DispatchQueue.main.async { - self.enableCrossProcessRefreshLockProcessIdSessionDelegateReceivedInvocations.append((processId: processId, sessionDelegate: sessionDelegate)) - } - if let enableCrossProcessRefreshLockProcessIdSessionDelegateClosure = enableCrossProcessRefreshLockProcessIdSessionDelegateClosure { - return enableCrossProcessRefreshLockProcessIdSessionDelegateClosure(processId, sessionDelegate) + open override func enableOidcRefreshLock() -> ClientBuilder { + enableOidcRefreshLockCallsCount += 1 + if let enableOidcRefreshLockClosure = enableOidcRefreshLockClosure { + return enableOidcRefreshLockClosure() } else { - return enableCrossProcessRefreshLockProcessIdSessionDelegateReturnValue + return enableOidcRefreshLockReturnValue } } @@ -7832,6 +7943,71 @@ open class LazyTimelineItemProviderSDKMock: MatrixRustSDK.LazyTimelineItemProvid } } + //MARK: - getSendHandle + + var getSendHandleUnderlyingCallsCount = 0 + open var getSendHandleCallsCount: Int { + get { + if Thread.isMainThread { + return getSendHandleUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = getSendHandleUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + getSendHandleUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + getSendHandleUnderlyingCallsCount = newValue + } + } + } + } + open var getSendHandleCalled: Bool { + return getSendHandleCallsCount > 0 + } + + var getSendHandleUnderlyingReturnValue: SendHandle? + open var getSendHandleReturnValue: SendHandle? { + get { + if Thread.isMainThread { + return getSendHandleUnderlyingReturnValue + } else { + var returnValue: SendHandle?? = nil + DispatchQueue.main.sync { + returnValue = getSendHandleUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + getSendHandleUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + getSendHandleUnderlyingReturnValue = newValue + } + } + } + } + open var getSendHandleClosure: (() -> SendHandle?)? + + open override func getSendHandle() -> SendHandle? { + getSendHandleCallsCount += 1 + if let getSendHandleClosure = getSendHandleClosure { + return getSendHandleClosure() + } else { + return getSendHandleReturnValue + } + } + //MARK: - getShields var getShieldsStrictUnderlyingCallsCount = 0 @@ -11164,16 +11340,16 @@ open class RoomSDKMock: MatrixRustSDK.Room { //MARK: - ignoreDeviceTrustAndResend - open var ignoreDeviceTrustAndResendDevicesTransactionIdThrowableError: Error? - var ignoreDeviceTrustAndResendDevicesTransactionIdUnderlyingCallsCount = 0 - open var ignoreDeviceTrustAndResendDevicesTransactionIdCallsCount: Int { + open var ignoreDeviceTrustAndResendDevicesSendHandleThrowableError: Error? + var ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingCallsCount = 0 + open var ignoreDeviceTrustAndResendDevicesSendHandleCallsCount: Int { get { if Thread.isMainThread { - return ignoreDeviceTrustAndResendDevicesTransactionIdUnderlyingCallsCount + return ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = ignoreDeviceTrustAndResendDevicesTransactionIdUnderlyingCallsCount + returnValue = ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingCallsCount } return returnValue! @@ -11181,31 +11357,31 @@ open class RoomSDKMock: MatrixRustSDK.Room { } set { if Thread.isMainThread { - ignoreDeviceTrustAndResendDevicesTransactionIdUnderlyingCallsCount = newValue + ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - ignoreDeviceTrustAndResendDevicesTransactionIdUnderlyingCallsCount = newValue + ignoreDeviceTrustAndResendDevicesSendHandleUnderlyingCallsCount = newValue } } } } - open var ignoreDeviceTrustAndResendDevicesTransactionIdCalled: Bool { - return ignoreDeviceTrustAndResendDevicesTransactionIdCallsCount > 0 + open var ignoreDeviceTrustAndResendDevicesSendHandleCalled: Bool { + return ignoreDeviceTrustAndResendDevicesSendHandleCallsCount > 0 } - open var ignoreDeviceTrustAndResendDevicesTransactionIdReceivedArguments: (devices: [String: [String]], transactionId: String)? - open var ignoreDeviceTrustAndResendDevicesTransactionIdReceivedInvocations: [(devices: [String: [String]], transactionId: String)] = [] - open var ignoreDeviceTrustAndResendDevicesTransactionIdClosure: (([String: [String]], String) async throws -> Void)? + open var ignoreDeviceTrustAndResendDevicesSendHandleReceivedArguments: (devices: [String: [String]], sendHandle: SendHandle)? + open var ignoreDeviceTrustAndResendDevicesSendHandleReceivedInvocations: [(devices: [String: [String]], sendHandle: SendHandle)] = [] + open var ignoreDeviceTrustAndResendDevicesSendHandleClosure: (([String: [String]], SendHandle) async throws -> Void)? - open override func ignoreDeviceTrustAndResend(devices: [String: [String]], transactionId: String) async throws { - if let error = ignoreDeviceTrustAndResendDevicesTransactionIdThrowableError { + open override func ignoreDeviceTrustAndResend(devices: [String: [String]], sendHandle: SendHandle) async throws { + if let error = ignoreDeviceTrustAndResendDevicesSendHandleThrowableError { throw error } - ignoreDeviceTrustAndResendDevicesTransactionIdCallsCount += 1 - ignoreDeviceTrustAndResendDevicesTransactionIdReceivedArguments = (devices: devices, transactionId: transactionId) + ignoreDeviceTrustAndResendDevicesSendHandleCallsCount += 1 + ignoreDeviceTrustAndResendDevicesSendHandleReceivedArguments = (devices: devices, sendHandle: sendHandle) DispatchQueue.main.async { - self.ignoreDeviceTrustAndResendDevicesTransactionIdReceivedInvocations.append((devices: devices, transactionId: transactionId)) + self.ignoreDeviceTrustAndResendDevicesSendHandleReceivedInvocations.append((devices: devices, sendHandle: sendHandle)) } - try await ignoreDeviceTrustAndResendDevicesTransactionIdClosure?(devices, transactionId) + try await ignoreDeviceTrustAndResendDevicesSendHandleClosure?(devices, sendHandle) } //MARK: - ignoreUser @@ -14036,52 +14212,6 @@ open class RoomSDKMock: MatrixRustSDK.Room { } } - //MARK: - tryResend - - open var tryResendTransactionIdThrowableError: Error? - var tryResendTransactionIdUnderlyingCallsCount = 0 - open var tryResendTransactionIdCallsCount: Int { - get { - if Thread.isMainThread { - return tryResendTransactionIdUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = tryResendTransactionIdUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - tryResendTransactionIdUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - tryResendTransactionIdUnderlyingCallsCount = newValue - } - } - } - } - open var tryResendTransactionIdCalled: Bool { - return tryResendTransactionIdCallsCount > 0 - } - open var tryResendTransactionIdReceivedTransactionId: String? - open var tryResendTransactionIdReceivedInvocations: [String] = [] - open var tryResendTransactionIdClosure: ((String) async throws -> Void)? - - open override func tryResend(transactionId: String) async throws { - if let error = tryResendTransactionIdThrowableError { - throw error - } - tryResendTransactionIdCallsCount += 1 - tryResendTransactionIdReceivedTransactionId = transactionId - DispatchQueue.main.async { - self.tryResendTransactionIdReceivedInvocations.append(transactionId) - } - try await tryResendTransactionIdClosure?(transactionId) - } - //MARK: - typingNotice open var typingNoticeIsTypingThrowableError: Error? @@ -14268,16 +14398,16 @@ open class RoomSDKMock: MatrixRustSDK.Room { //MARK: - withdrawVerificationAndResend - open var withdrawVerificationAndResendUserIdsTransactionIdThrowableError: Error? - var withdrawVerificationAndResendUserIdsTransactionIdUnderlyingCallsCount = 0 - open var withdrawVerificationAndResendUserIdsTransactionIdCallsCount: Int { + open var withdrawVerificationAndResendUserIdsSendHandleThrowableError: Error? + var withdrawVerificationAndResendUserIdsSendHandleUnderlyingCallsCount = 0 + open var withdrawVerificationAndResendUserIdsSendHandleCallsCount: Int { get { if Thread.isMainThread { - return withdrawVerificationAndResendUserIdsTransactionIdUnderlyingCallsCount + return withdrawVerificationAndResendUserIdsSendHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = withdrawVerificationAndResendUserIdsTransactionIdUnderlyingCallsCount + returnValue = withdrawVerificationAndResendUserIdsSendHandleUnderlyingCallsCount } return returnValue! @@ -14285,31 +14415,31 @@ open class RoomSDKMock: MatrixRustSDK.Room { } set { if Thread.isMainThread { - withdrawVerificationAndResendUserIdsTransactionIdUnderlyingCallsCount = newValue + withdrawVerificationAndResendUserIdsSendHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - withdrawVerificationAndResendUserIdsTransactionIdUnderlyingCallsCount = newValue + withdrawVerificationAndResendUserIdsSendHandleUnderlyingCallsCount = newValue } } } } - open var withdrawVerificationAndResendUserIdsTransactionIdCalled: Bool { - return withdrawVerificationAndResendUserIdsTransactionIdCallsCount > 0 + open var withdrawVerificationAndResendUserIdsSendHandleCalled: Bool { + return withdrawVerificationAndResendUserIdsSendHandleCallsCount > 0 } - open var withdrawVerificationAndResendUserIdsTransactionIdReceivedArguments: (userIds: [String], transactionId: String)? - open var withdrawVerificationAndResendUserIdsTransactionIdReceivedInvocations: [(userIds: [String], transactionId: String)] = [] - open var withdrawVerificationAndResendUserIdsTransactionIdClosure: (([String], String) async throws -> Void)? + open var withdrawVerificationAndResendUserIdsSendHandleReceivedArguments: (userIds: [String], sendHandle: SendHandle)? + open var withdrawVerificationAndResendUserIdsSendHandleReceivedInvocations: [(userIds: [String], sendHandle: SendHandle)] = [] + open var withdrawVerificationAndResendUserIdsSendHandleClosure: (([String], SendHandle) async throws -> Void)? - open override func withdrawVerificationAndResend(userIds: [String], transactionId: String) async throws { - if let error = withdrawVerificationAndResendUserIdsTransactionIdThrowableError { + open override func withdrawVerificationAndResend(userIds: [String], sendHandle: SendHandle) async throws { + if let error = withdrawVerificationAndResendUserIdsSendHandleThrowableError { throw error } - withdrawVerificationAndResendUserIdsTransactionIdCallsCount += 1 - withdrawVerificationAndResendUserIdsTransactionIdReceivedArguments = (userIds: userIds, transactionId: transactionId) + withdrawVerificationAndResendUserIdsSendHandleCallsCount += 1 + withdrawVerificationAndResendUserIdsSendHandleReceivedArguments = (userIds: userIds, sendHandle: sendHandle) DispatchQueue.main.async { - self.withdrawVerificationAndResendUserIdsTransactionIdReceivedInvocations.append((userIds: userIds, transactionId: transactionId)) + self.withdrawVerificationAndResendUserIdsSendHandleReceivedInvocations.append((userIds: userIds, sendHandle: sendHandle)) } - try await withdrawVerificationAndResendUserIdsTransactionIdClosure?(userIds, transactionId) + try await withdrawVerificationAndResendUserIdsSendHandleClosure?(userIds, sendHandle) } } open class RoomDirectorySearchSDKMock: MatrixRustSDK.RoomDirectorySearch { @@ -16927,6 +17057,46 @@ open class SendHandleSDKMock: MatrixRustSDK.SendHandle { return abortReturnValue } } + + //MARK: - tryResend + + open var tryResendThrowableError: Error? + var tryResendUnderlyingCallsCount = 0 + open var tryResendCallsCount: Int { + get { + if Thread.isMainThread { + return tryResendUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = tryResendUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + tryResendUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + tryResendUnderlyingCallsCount = newValue + } + } + } + } + open var tryResendCalled: Bool { + return tryResendCallsCount > 0 + } + open var tryResendClosure: (() async throws -> Void)? + + open override func tryResend() async throws { + if let error = tryResendThrowableError { + throw error + } + tryResendCallsCount += 1 + try await tryResendClosure?() + } } open class SessionVerificationControllerSDKMock: MatrixRustSDK.SessionVerificationController { init() { @@ -17986,15 +18156,15 @@ open class SyncServiceBuilderSDKMock: MatrixRustSDK.SyncServiceBuilder { //MARK: - withCrossProcessLock - var withCrossProcessLockAppIdentifierUnderlyingCallsCount = 0 - open var withCrossProcessLockAppIdentifierCallsCount: Int { + var withCrossProcessLockUnderlyingCallsCount = 0 + open var withCrossProcessLockCallsCount: Int { get { if Thread.isMainThread { - return withCrossProcessLockAppIdentifierUnderlyingCallsCount + return withCrossProcessLockUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = withCrossProcessLockAppIdentifierUnderlyingCallsCount + returnValue = withCrossProcessLockUnderlyingCallsCount } return returnValue! @@ -18002,29 +18172,27 @@ open class SyncServiceBuilderSDKMock: MatrixRustSDK.SyncServiceBuilder { } set { if Thread.isMainThread { - withCrossProcessLockAppIdentifierUnderlyingCallsCount = newValue + withCrossProcessLockUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - withCrossProcessLockAppIdentifierUnderlyingCallsCount = newValue + withCrossProcessLockUnderlyingCallsCount = newValue } } } } - open var withCrossProcessLockAppIdentifierCalled: Bool { - return withCrossProcessLockAppIdentifierCallsCount > 0 + open var withCrossProcessLockCalled: Bool { + return withCrossProcessLockCallsCount > 0 } - open var withCrossProcessLockAppIdentifierReceivedAppIdentifier: String? - open var withCrossProcessLockAppIdentifierReceivedInvocations: [String?] = [] - var withCrossProcessLockAppIdentifierUnderlyingReturnValue: SyncServiceBuilder! - open var withCrossProcessLockAppIdentifierReturnValue: SyncServiceBuilder! { + var withCrossProcessLockUnderlyingReturnValue: SyncServiceBuilder! + open var withCrossProcessLockReturnValue: SyncServiceBuilder! { get { if Thread.isMainThread { - return withCrossProcessLockAppIdentifierUnderlyingReturnValue + return withCrossProcessLockUnderlyingReturnValue } else { var returnValue: SyncServiceBuilder? = nil DispatchQueue.main.sync { - returnValue = withCrossProcessLockAppIdentifierUnderlyingReturnValue + returnValue = withCrossProcessLockUnderlyingReturnValue } return returnValue! @@ -18032,26 +18200,22 @@ open class SyncServiceBuilderSDKMock: MatrixRustSDK.SyncServiceBuilder { } set { if Thread.isMainThread { - withCrossProcessLockAppIdentifierUnderlyingReturnValue = newValue + withCrossProcessLockUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - withCrossProcessLockAppIdentifierUnderlyingReturnValue = newValue + withCrossProcessLockUnderlyingReturnValue = newValue } } } } - open var withCrossProcessLockAppIdentifierClosure: ((String?) -> SyncServiceBuilder)? + open var withCrossProcessLockClosure: (() -> SyncServiceBuilder)? - open override func withCrossProcessLock(appIdentifier: String?) -> SyncServiceBuilder { - withCrossProcessLockAppIdentifierCallsCount += 1 - withCrossProcessLockAppIdentifierReceivedAppIdentifier = appIdentifier - DispatchQueue.main.async { - self.withCrossProcessLockAppIdentifierReceivedInvocations.append(appIdentifier) - } - if let withCrossProcessLockAppIdentifierClosure = withCrossProcessLockAppIdentifierClosure { - return withCrossProcessLockAppIdentifierClosure(appIdentifier) + open override func withCrossProcessLock() -> SyncServiceBuilder { + withCrossProcessLockCallsCount += 1 + if let withCrossProcessLockClosure = withCrossProcessLockClosure { + return withCrossProcessLockClosure() } else { - return withCrossProcessLockAppIdentifierReturnValue + return withCrossProcessLockReturnValue } } diff --git a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift index 2f147104fb..75a1a5c373 100644 --- a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift @@ -83,9 +83,8 @@ extension JoinedRoomProxyMock { return .success(member) } - resendItemIDReturnValue = .success(()) - ignoreDeviceTrustAndResendDevicesItemIDReturnValue = .success(()) - withdrawVerificationAndResendUserIDsItemIDReturnValue = .success(()) + ignoreDeviceTrustAndResendDevicesSendHandleReturnValue = .success(()) + withdrawVerificationAndResendUserIDsSendHandleReturnValue = .success(()) flagAsUnreadReturnValue = .success(()) markAsReadReceiptTypeReturnValue = .success(()) diff --git a/ElementX/Sources/Other/Extensions/ClientBuilder.swift b/ElementX/Sources/Other/Extensions/ClientBuilder.swift index 6abce9a3b7..6ca8cb335a 100644 --- a/ElementX/Sources/Other/Extensions/ClientBuilder.swift +++ b/ElementX/Sources/Other/Extensions/ClientBuilder.swift @@ -17,7 +17,9 @@ extension ClientBuilder { appHooks: AppHooks, enableOnlySignedDeviceIsolationMode: Bool) -> ClientBuilder { var builder = ClientBuilder() - .enableCrossProcessRefreshLock(processId: InfoPlistReader.main.bundleIdentifier, sessionDelegate: sessionDelegate) + .crossProcessStoreLocksHolderName(holderName: InfoPlistReader.main.bundleIdentifier) + .enableOidcRefreshLock() + .setSessionDelegate(sessionDelegate: sessionDelegate) .userAgent(userAgent: UserAgentBuilder.makeASCIIUserAgent()) .requestConfig(config: .init(retryLimit: 0, timeout: 30000, maxConcurrentRequests: nil, retryTimeout: nil)) diff --git a/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenCoordinator.swift b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenCoordinator.swift index 6331383322..8b8073db4d 100644 --- a/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenCoordinator.swift +++ b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenCoordinator.swift @@ -19,7 +19,7 @@ import SwiftUI struct ResolveVerifiedUserSendFailureScreenCoordinatorParameters { let failure: TimelineItemSendFailure.VerifiedUser - let itemID: TimelineItemIdentifier + let sendHandle: SendHandleProxy let roomProxy: JoinedRoomProxyProtocol let userIndicatorController: UserIndicatorControllerProtocol } @@ -43,7 +43,7 @@ final class ResolveVerifiedUserSendFailureScreenCoordinator: CoordinatorProtocol self.parameters = parameters viewModel = ResolveVerifiedUserSendFailureScreenViewModel(failure: parameters.failure, - itemID: parameters.itemID, + sendHandle: parameters.sendHandle, roomProxy: parameters.roomProxy, userIndicatorController: parameters.userIndicatorController) } diff --git a/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenViewModel.swift b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenViewModel.swift index 58b60a5aae..dd7b454f1d 100644 --- a/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenViewModel.swift +++ b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/ResolveVerifiedUserSendFailureScreenViewModel.swift @@ -22,7 +22,7 @@ typealias ResolveVerifiedUserSendFailureScreenViewModelType = StateStoreViewMode class ResolveVerifiedUserSendFailureScreenViewModel: ResolveVerifiedUserSendFailureScreenViewModelType, ResolveVerifiedUserSendFailureScreenViewModelProtocol { private let iterator: VerifiedUserSendFailureIterator private let failure: TimelineItemSendFailure.VerifiedUser - private let itemID: TimelineItemIdentifier + private let sendHandle: SendHandleProxy private let roomProxy: JoinedRoomProxyProtocol private var members: [String: RoomMemberProxyProtocol] @@ -34,7 +34,7 @@ class ResolveVerifiedUserSendFailureScreenViewModel: ResolveVerifiedUserSendFail } init(failure: TimelineItemSendFailure.VerifiedUser, - itemID: TimelineItemIdentifier, + sendHandle: SendHandleProxy, roomProxy: JoinedRoomProxyProtocol, userIndicatorController: UserIndicatorControllerProtocol) { iterator = switch failure { @@ -43,7 +43,7 @@ class ResolveVerifiedUserSendFailureScreenViewModel: ResolveVerifiedUserSendFail } self.failure = failure - self.itemID = itemID + self.sendHandle = sendHandle self.roomProxy = roomProxy self.userIndicatorController = userIndicatorController @@ -77,9 +77,9 @@ class ResolveVerifiedUserSendFailureScreenViewModel: ResolveVerifiedUserSendFail private func resolveAndResend() async { let result = switch failure { case .hasUnsignedDevice(let devices): - await roomProxy.ignoreDeviceTrustAndResend(devices: devices, itemID: itemID) + await roomProxy.ignoreDeviceTrustAndResend(devices: devices, sendHandle: sendHandle) case .changedIdentity(let users): - await roomProxy.withdrawVerificationAndResend(userIDs: users, itemID: itemID) + await roomProxy.withdrawVerificationAndResend(userIDs: users, sendHandle: sendHandle) } if case let .failure(error) = result { @@ -98,7 +98,7 @@ class ResolveVerifiedUserSendFailureScreenViewModel: ResolveVerifiedUserSendFail } private func resend() async { - switch await roomProxy.resend(itemID: itemID) { + switch await sendHandle.resend() { case .success: actionsSubject.send(.dismiss) case .failure(let error): diff --git a/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/View/ResolveVerifiedUserSendFailureScreen.swift b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/View/ResolveVerifiedUserSendFailureScreen.swift index b0ef698b15..4f35ae0955 100644 --- a/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/View/ResolveVerifiedUserSendFailureScreen.swift +++ b/ElementX/Sources/Screens/ResolveVerifiedUserSendFailureScreen/View/ResolveVerifiedUserSendFailureScreen.swift @@ -94,7 +94,7 @@ struct ResolveVerifiedUserSendFailureScreen_Previews: PreviewProvider, TestableP static func makeViewModel(failure: TimelineItemSendFailure.VerifiedUser) -> ResolveVerifiedUserSendFailureScreenViewModel { ResolveVerifiedUserSendFailureScreenViewModel(failure: failure, - itemID: .randomEvent, + sendHandle: .mock, roomProxy: JoinedRoomProxyMock(.init()), userIndicatorController: UserIndicatorControllerMock()) } @@ -102,7 +102,7 @@ struct ResolveVerifiedUserSendFailureScreen_Previews: PreviewProvider, TestableP struct ResolveVerifiedUserSendFailureScreenSheet_Previews: PreviewProvider { static let viewModel = ResolveVerifiedUserSendFailureScreenViewModel(failure: .changedIdentity(users: ["@alice:matrix.org"]), - itemID: .randomEvent, + sendHandle: .mock, roomProxy: JoinedRoomProxyMock(.init()), userIndicatorController: UserIndicatorControllerMock()) diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift index 1f63793857..500461ea0e 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift @@ -40,7 +40,7 @@ enum RoomScreenCoordinatorAction { case presentMessageForwarding(forwardingItem: MessageForwardingItem) case presentCallScreen case presentPinnedEventsTimeline - case presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, itemID: TimelineItemIdentifier) + case presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, sendHandle: SendHandleProxy) } final class RoomScreenCoordinator: CoordinatorProtocol { @@ -132,8 +132,8 @@ final class RoomScreenCoordinator: CoordinatorProtocol { actionsSubject.send(.presentMessageForwarding(forwardingItem: forwardingItem)) case .displayLocation(let body, let geoURI, let description): actionsSubject.send(.presentLocationViewer(body: body, geoURI: geoURI, description: description)) - case .displayResolveSendFailure(let failure, let itemID): - actionsSubject.send(.presentResolveSendFailure(failure: failure, itemID: itemID)) + case .displayResolveSendFailure(let failure, let sendHandle): + actionsSubject.send(.presentResolveSendFailure(failure: failure, sendHandle: sendHandle)) case .composer(let action): composerViewModel.process(timelineAction: action) case .hasScrolled(direction: let direction): diff --git a/ElementX/Sources/Screens/Timeline/TimelineModels.swift b/ElementX/Sources/Screens/Timeline/TimelineModels.swift index 363ddb9fa1..0d407cf939 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineModels.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineModels.swift @@ -22,7 +22,7 @@ enum TimelineViewModelAction { case tappedOnSenderDetails(userID: String) case displayMessageForwarding(forwardingItem: MessageForwardingItem) case displayLocation(body: String, geoURI: GeoURI, description: String?) - case displayResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, itemID: TimelineItemIdentifier) + case displayResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, sendHandle: SendHandleProxy) case composer(action: TimelineComposerAction) case hasScrolled(direction: ScrollDirection) case viewInRoomTimeline(eventID: String) diff --git a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift index 7a7103499d..94db414a07 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift @@ -562,7 +562,14 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { if case .sendingFailed(.unknown) = eventTimelineItem.properties.deliveryStatus { displayAlert(.sendingFailed) } else if case let .sendingFailed(.verifiedUser(failure)) = eventTimelineItem.properties.deliveryStatus { - actionsSubject.send(.displayResolveSendFailure(failure: failure, itemID: itemID)) + guard let sendHandle = timelineController.sendHandle(for: itemID) else { + MXLog.error("Cannot find send handle for \(itemID).") + return + } + + actionsSubject.send(.displayResolveSendFailure(failure: failure, + sendHandle: sendHandle)) + } else if let authenticityMessage = eventTimelineItem.properties.encryptionAuthenticity?.message { displayAlert(.encryptionAuthenticity(authenticityMessage)) } diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index c8f948be3a..11ec6dcfaa 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -811,13 +811,14 @@ class ClientProxy: ClientProxyProtocol { do { let syncService = try await client .syncService() - .withCrossProcessLock(appIdentifier: "MainApp") + .withCrossProcessLock() .withUtdHook(delegate: ClientDecryptionErrorDelegate(actionsSubject: actionsSubject)) .finish() + let roomListService = syncService.roomListService() let roomMessageEventStringBuilder = RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(cacheKey: "roomList", - mentionBuilder: PlainMentionBuilder()), prefix: .senderName) + mentionBuilder: PlainMentionBuilder()), destination: .roomList) let eventStringBuilder = RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID, shouldDisambiguateDisplayNames: false), messageEventStringBuilder: roomMessageEventStringBuilder, shouldDisambiguateDisplayNames: false, diff --git a/ElementX/Sources/Services/Room/JoinedRoomProxy.swift b/ElementX/Sources/Services/Room/JoinedRoomProxy.swift index 30211cc367..021d5df53d 100644 --- a/ElementX/Sources/Services/Room/JoinedRoomProxy.swift +++ b/ElementX/Sources/Services/Room/JoinedRoomProxy.swift @@ -315,47 +315,22 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol { } } - func resend(itemID: TimelineItemIdentifier) async -> Result { - guard let transactionID = itemID.transactionID else { - MXLog.error("Attempting to resend an item that has no transaction ID: \(itemID)") - return .failure(.missingTransactionID) - } - + func ignoreDeviceTrustAndResend(devices: [String: [String]], sendHandle: SendHandleProxy) async -> Result { do { - try await room.tryResend(transactionId: transactionID) + try await room.ignoreDeviceTrustAndResend(devices: devices, sendHandle: sendHandle.underlyingHandle) return .success(()) } catch { - MXLog.error("Failed resending \(transactionID) with error: \(error)") + MXLog.error("Failed trusting devices \(devices) and resending \(sendHandle.itemID) with error: \(error)") return .failure(.sdkError(error)) } } - func ignoreDeviceTrustAndResend(devices: [String: [String]], itemID: TimelineItemIdentifier) async -> Result { - guard let transactionID = itemID.transactionID else { - MXLog.error("Attempting to resend an item that has no transaction ID: \(itemID)") - return .failure(.missingTransactionID) - } - - do { - try await room.ignoreDeviceTrustAndResend(devices: devices, transactionId: transactionID) - return .success(()) - } catch { - MXLog.error("Failed trusting devices \(devices) and resending \(transactionID) with error: \(error)") - return .failure(.sdkError(error)) - } - } - - func withdrawVerificationAndResend(userIDs: [String], itemID: TimelineItemIdentifier) async -> Result { - guard let transactionID = itemID.transactionID else { - MXLog.error("Attempting to resend an item that has no transaction ID: \(itemID)") - return .failure(.missingTransactionID) - } - + func withdrawVerificationAndResend(userIDs: [String], sendHandle: SendHandleProxy) async -> Result { do { - try await room.withdrawVerificationAndResend(userIds: userIDs, transactionId: transactionID) + try await room.withdrawVerificationAndResend(userIds: userIDs, sendHandle: sendHandle.underlyingHandle) return .success(()) } catch { - MXLog.error("Failed withdrawing verification of \(userIDs) and resending \(transactionID) with error: \(error)") + MXLog.error("Failed withdrawing verification of \(userIDs) and resending \(sendHandle.itemID) with error: \(error)") return .failure(.sdkError(error)) } } diff --git a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift index cf9c01fd8e..c1f1f53352 100644 --- a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift @@ -97,11 +97,9 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol { /// https://spec.matrix.org/v1.9/client-server-api/#typing-notifications @discardableResult func sendTypingNotification(isTyping: Bool) async -> Result - func resend(itemID: TimelineItemIdentifier) async -> Result + func ignoreDeviceTrustAndResend(devices: [String: [String]], sendHandle: SendHandleProxy) async -> Result - func ignoreDeviceTrustAndResend(devices: [String: [String]], itemID: TimelineItemIdentifier) async -> Result - - func withdrawVerificationAndResend(userIDs: [String], itemID: TimelineItemIdentifier) async -> Result + func withdrawVerificationAndResend(userIDs: [String], sendHandle: SendHandleProxy) async -> Result // MARK: - Room Flags diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift index 1e3222a29d..70728678ba 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift @@ -35,7 +35,7 @@ struct RoomEventStringBuilder { case .redactedMessage: return prefix(L10n.commonMessageRemoved, with: displayName) case .sticker: - if messageEventStringBuilder.prefix == .messageType { + if messageEventStringBuilder.destination == .pinnedEvent { var string = AttributedString(L10n.commonSticker) string.bold() return string @@ -49,7 +49,7 @@ struct RoomEventStringBuilder { return stateEventStringBuilder .buildString(for: state, sender: sender, isOutgoing: isOutgoing) .map(AttributedString.init) - case .roomMembership(let userID, let displayName, let change): + case .roomMembership(let userID, let displayName, let change, _): return stateEventStringBuilder .buildString(for: change, memberUserID: userID, memberDisplayName: displayName, sender: sender, isOutgoing: isOutgoing) .map(AttributedString.init) @@ -63,7 +63,7 @@ struct RoomEventStringBuilder { memberIsYou: isOutgoing) .map(AttributedString.init) case .poll(let question, _, _, _, _, _, _): - if messageEventStringBuilder.prefix == .messageType { + if messageEventStringBuilder.destination == .pinnedEvent { let questionPlaceholder = "{question}" var finalString = AttributedString(L10n.commonPollSummary(questionPlaceholder)) finalString.bold() @@ -96,7 +96,7 @@ struct RoomEventStringBuilder { RoomEventStringBuilder(stateEventStringBuilder: .init(userID: userID, shouldDisambiguateDisplayNames: false), messageEventStringBuilder: .init(attributedStringBuilder: AttributedStringBuilder(cacheKey: "pinnedEvents", mentionBuilder: PlainMentionBuilder()), - prefix: .messageType), + destination: .pinnedEvent), shouldDisambiguateDisplayNames: false, shouldPrefixSenderName: false) } diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift index 2c7a1e07e2..444bba60ee 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift @@ -9,42 +9,46 @@ import Foundation import MatrixRustSDK struct RoomMessageEventStringBuilder { - enum Prefix { - case senderName - case messageType - case none + enum Destination { + /// Strings show on the room list as the last message + /// The sender will be prefixed in bold + case roomList + /// Events pinned to the banner on the top of the timeline + /// The message type will be prefixed in bold + case pinnedEvent + /// Shown in push notifications + /// No prefix + case notification } let attributedStringBuilder: AttributedStringBuilderProtocol - let prefix: Prefix + let destination: Destination func buildAttributedString(for messageType: MessageType, senderDisplayName: String) -> AttributedString { let message: AttributedString switch messageType { - // Message types that don't need a prefix. case .emote(content: let content): if let attributedMessage = attributedMessageFrom(formattedBody: content.formatted) { return AttributedString(L10n.commonEmote(senderDisplayName, String(attributedMessage.characters))) } else { return AttributedString(L10n.commonEmote(senderDisplayName, content.body)) } - // Message types that should be prefixed with the sender's name. case .audio(content: let content): let isVoiceMessage = content.voice != nil var content = AttributedString(isVoiceMessage ? L10n.commonVoiceMessage : L10n.commonAudio) - if prefix == .messageType { + if destination == .pinnedEvent { content.bold() } message = content case .image(let content): - message = prefix == .messageType ? prefix(AttributedString(content.body), with: L10n.commonImage) : AttributedString("\(L10n.commonImage) - \(content.body)") + message = buildMessage(for: destination, caption: content.caption, type: L10n.commonImage) case .video(let content): - message = prefix == .messageType ? prefix(AttributedString(content.body), with: L10n.commonVideo) : AttributedString("\(L10n.commonVideo) - \(content.body)") + message = buildMessage(for: destination, caption: content.caption, type: L10n.commonVideo) case .file(let content): - message = prefix == .messageType ? prefix(AttributedString(content.body), with: L10n.commonFile) : AttributedString("\(L10n.commonFile) - \(content.body)") + message = buildMessage(for: destination, caption: content.caption, type: L10n.commonFile) case .location: var content = AttributedString(L10n.commonSharedLocation) - if prefix == .messageType { + if destination == .pinnedEvent { content.bold() } message = content @@ -64,13 +68,25 @@ struct RoomMessageEventStringBuilder { message = AttributedString(body) } - if prefix == .senderName { + if destination == .roomList { return prefix(message, with: senderDisplayName) } else { return message } } + private func buildMessage(for destination: Destination, caption: String?, type: String) -> AttributedString { + guard let caption else { + return AttributedString(type) + } + + if destination == .pinnedEvent { + return prefix(AttributedString(caption), with: type) + } else { + return AttributedString("\(type) - \(caption)") + } + } + private func prefix(_ eventSummary: AttributedString, with textToBold: String) -> AttributedString { let attributedEventSummary = AttributedString(eventSummary.string.trimmingCharacters(in: .whitespacesAndNewlines)) diff --git a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift index e615165936..0ec25915e7 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift @@ -104,6 +104,10 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { func debugInfo(for itemID: TimelineItemIdentifier) -> TimelineItemDebugInfo { .init(model: "Mock debug description", originalJSON: nil, latestEditJSON: nil) } + + func sendHandle(for itemID: TimelineItemIdentifier) -> SendHandleProxy? { + nil + } func retryDecryption(for sessionID: String) async { } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift index 50ac8ef321..edcf2ef221 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift @@ -308,6 +308,21 @@ class RoomTimelineController: RoomTimelineControllerProtocol { return .init(model: "Unknown item", originalJSON: nil, latestEditJSON: nil) } + func sendHandle(for itemID: TimelineItemIdentifier) -> SendHandleProxy? { + for timelineItemProxy in activeTimelineProvider.itemProxies { + switch timelineItemProxy { + case .event(let item): + if item.id == itemID { + return item.sendHandle.map { .init(itemID: itemID, underlyingHandle: $0) } + } + default: + continue + } + } + + return nil + } + func retryDecryption(for sessionID: String) async { await activeTimeline.retryDecryption(for: sessionID) } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift index 125454d3cc..0d13a2994a 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift @@ -68,6 +68,8 @@ protocol RoomTimelineControllerProtocol { func debugInfo(for itemID: TimelineItemIdentifier) -> TimelineItemDebugInfo + 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/TimelineItemProxy.swift b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift index 346fad5845..93e8f94d95 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift @@ -135,6 +135,8 @@ class EventTimelineItemProxy { lazy var shieldState = item.lazyProvider.getShields(strict: false) + lazy var sendHandle = item.lazyProvider.getSendHandle() + lazy var readReceipts = item.readReceipts } @@ -179,6 +181,40 @@ struct TimelineItemDebugInfo: Identifiable, CustomStringConvertible { } } +struct SendHandleProxy: Hashable { + enum Error: Swift.Error { + case sdkError(Swift.Error) + } + + let itemID: TimelineItemIdentifier + let underlyingHandle: SendHandle + + func resend() async -> Result { + do { + try await underlyingHandle.tryResend() + return .success(()) + } catch { + return .failure(.sdkError(error)) + } + } + + // MARK: - Hashable + + static func == (lhs: SendHandleProxy, rhs: SendHandleProxy) -> Bool { + lhs.itemID == rhs.itemID + } + + func hash(into hasher: inout Hasher) { + hasher.combine(itemID) + } + + static var mock: SendHandleProxy { + .init(itemID: .event(uniqueID: .init(id: UUID().uuidString), + eventOrTransactionID: .eventId(eventId: UUID().uuidString)), + underlyingHandle: .init(noPointer: .init())) + } +} + extension Receipt { var dateTimestamp: Date? { guard let timestamp else { diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index 7a3d1e9ba3..f2794fbf47 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -50,7 +50,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { return nil } return buildStateTimelineItem(for: eventItemProxy, state: content, isOutgoing: isOutgoing) - case .roomMembership(userId: let userID, let displayName, change: let change): + case .roomMembership(userId: let userID, let displayName, change: let change, _): if isDM, change == .joined, userID == self.userID { return nil } @@ -511,7 +511,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { duration: messageContent.audio?.duration ?? 0, waveform: waveform, source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype), - contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.body)) + contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename)) } private func buildImageTimelineItemContent(_ messageContent: ImageMessageContent) -> ImageRoomTimelineItemContent { @@ -537,7 +537,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { height: height, aspectRatio: aspectRatio, blurhash: messageContent.info?.blurhash, - contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.body)) + contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename)) } private func buildVideoTimelineItemContent(_ messageContent: VideoMessageContent) -> VideoRoomTimelineItemContent { @@ -564,7 +564,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { height: height, aspectRatio: aspectRatio, blurhash: messageContent.info?.blurhash, - contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.body)) + contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename)) } private func buildLocationTimelineItemContent(_ locationContent: LocationContent) -> LocationRoomTimelineItemContent { @@ -585,7 +585,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { formattedCaptionHTMLString: htmlCaption, source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype), thumbnailSource: thumbnailSource, - contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.body)) + contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename)) } private func buildNoticeTimelineItemContent(_ messageContent: NoticeMessageContent) -> NoticeRoomTimelineItemContent { diff --git a/NSE/Sources/NotificationServiceExtension.swift b/NSE/Sources/NotificationServiceExtension.swift index c55123454e..0df8b17c13 100644 --- a/NSE/Sources/NotificationServiceExtension.swift +++ b/NSE/Sources/NotificationServiceExtension.swift @@ -33,7 +33,7 @@ import UserNotifications // database, logging, etc. are only ever setup once per *process* private let settings: CommonSettingsProtocol = AppSettings() -private let notificationContentBuilder = NotificationContentBuilder(messageEventStringBuilder: RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(mentionBuilder: PlainMentionBuilder()), prefix: .none), +private let notificationContentBuilder = NotificationContentBuilder(messageEventStringBuilder: RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(mentionBuilder: PlainMentionBuilder()), destination: .notification), settings: settings) private let keychainController = KeychainController(service: .sessions, accessGroup: InfoPlistReader.main.keychainAccessGroupIdentifier) diff --git a/UnitTests/Sources/LoggingTests.swift b/UnitTests/Sources/LoggingTests.swift index 3ab0e77fdd..9e2c34e7de 100644 --- a/UnitTests/Sources/LoggingTests.swift +++ b/UnitTests/Sources/LoggingTests.swift @@ -228,28 +228,19 @@ class LoggingTests: XCTestCase { let rustEmoteMessage = EmoteMessageContent(body: emoteString, formatted: FormattedBody(format: .html, body: "\(emoteString)")) - let rustImageMessage = ImageMessageContent(body: "ImageString", - formatted: nil, - rawFilename: "ImageString", - filename: "ImageString", + let rustImageMessage = ImageMessageContent(filename: "ImageString", caption: "ImageString", formattedCaption: nil, source: MediaSource(noPointer: .init()), info: nil) - let rustVideoMessage = VideoMessageContent(body: "VideoString", - formatted: nil, - rawFilename: "VideoString", - filename: "VideoString", + let rustVideoMessage = VideoMessageContent(filename: "VideoString", caption: "VideoString", formattedCaption: nil, source: MediaSource(noPointer: .init()), info: nil) - let rustFileMessage = FileMessageContent(body: "FileString", - formatted: nil, - rawFilename: "FileString", - filename: "FileString", + let rustFileMessage = FileMessageContent(filename: "FileString", caption: "FileString", formattedCaption: nil, source: MediaSource(noPointer: .init()), @@ -280,13 +271,13 @@ class LoggingTests: XCTestCase { XCTAssertFalse(content.contains(emoteString)) XCTAssertTrue(content.contains(String(describing: ImageMessageContent.self))) - XCTAssertFalse(content.contains(rustImageMessage.body)) + XCTAssertFalse(content.contains(rustImageMessage.filename)) XCTAssertTrue(content.contains(String(describing: VideoMessageContent.self))) - XCTAssertFalse(content.contains(rustVideoMessage.body)) + XCTAssertFalse(content.contains(rustVideoMessage.filename)) XCTAssertTrue(content.contains(String(describing: FileMessageContent.self))) - XCTAssertFalse(content.contains(rustFileMessage.body)) + XCTAssertFalse(content.contains(rustFileMessage.filename)) } func testLogFileSorting() async throws { diff --git a/UnitTests/Sources/ResolveVerifiedUserSendFailureScreenViewModelTests.swift b/UnitTests/Sources/ResolveVerifiedUserSendFailureScreenViewModelTests.swift index f690d00367..6b738a65c6 100644 --- a/UnitTests/Sources/ResolveVerifiedUserSendFailureScreenViewModelTests.swift +++ b/UnitTests/Sources/ResolveVerifiedUserSendFailureScreenViewModelTests.swift @@ -61,7 +61,7 @@ class ResolveVerifiedUserSendFailureScreenViewModelTests: XCTestCase { private func makeViewModel(with failure: TimelineItemSendFailure.VerifiedUser) -> ResolveVerifiedUserSendFailureScreenViewModel { ResolveVerifiedUserSendFailureScreenViewModel(failure: failure, - itemID: .randomEvent, + sendHandle: .mock, roomProxy: roomProxy, userIndicatorController: UserIndicatorControllerMock()) } diff --git a/project.yml b/project.yml index 4363aa49b4..e7fb8dda2f 100644 --- a/project.yml +++ b/project.yml @@ -61,7 +61,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.66 + exactVersion: 1.0.67 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From 9746da78a20eeb3b87bd95e2a85e99388fd3ecf6 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 13 Nov 2024 15:22:54 +0200 Subject: [PATCH 19/74] Fix UI tests following Xcode 16.1 migration --- UITests/Sources/BugReportUITests.swift | 4 ++-- UITests/Sources/PollFormScreenUITests.swift | 6 +++--- .../sessionVerification-0-iPad-10th-generation-en-GB.UI.png | 4 ++-- .../sessionVerification-0-iPhone-16-en-GB.UI.png | 4 ++-- .../sessionVerification-1-iPad-10th-generation-en-GB.UI.png | 4 ++-- .../sessionVerification-1-iPhone-16-en-GB.UI.png | 4 ++-- .../sessionVerification-2-iPad-10th-generation-en-GB.UI.png | 4 ++-- .../sessionVerification-2-iPhone-16-en-GB.UI.png | 4 ++-- .../sessionVerification-3-iPad-10th-generation-en-GB.UI.png | 4 ++-- .../sessionVerification-3-iPhone-16-en-GB.UI.png | 4 ++-- .../sessionVerification-4-iPad-10th-generation-en-GB.UI.png | 4 ++-- .../sessionVerification-4-iPhone-16-en-GB.UI.png | 4 ++-- .../sessionVerification-5-iPad-10th-generation-en-GB.UI.png | 4 ++-- .../sessionVerification-5-iPhone-16-en-GB.UI.png | 4 ++-- .../sessionVerification-6-iPad-10th-generation-en-GB.UI.png | 4 ++-- .../sessionVerification-6-iPhone-16-en-GB.UI.png | 4 ++-- .../sessionVerification-7-iPad-10th-generation-en-GB.UI.png | 4 ++-- .../sessionVerification-7-iPhone-16-en-GB.UI.png | 4 ++-- 18 files changed, 37 insertions(+), 37 deletions(-) diff --git a/UITests/Sources/BugReportUITests.swift b/UITests/Sources/BugReportUITests.swift index d87441c964..954da3b4ac 100644 --- a/UITests/Sources/BugReportUITests.swift +++ b/UITests/Sources/BugReportUITests.swift @@ -20,13 +20,13 @@ class BugReportUITests: XCTestCase { let app = Application.launch(.bugReport) // Type 4 characters and the send button should be disabled. - app.textViews[A11yIdentifiers.bugReportScreen.report].clearAndTypeText("Text", app: app) + app.textFields[A11yIdentifiers.bugReportScreen.report].clearAndTypeText("Text", app: app) XCTAssert(app.switches[A11yIdentifiers.bugReportScreen.sendLogs].isOn) XCTAssert(!app.switches[A11yIdentifiers.bugReportScreen.canContact].isOn) try await app.assertScreenshot(.bugReport, step: 2) // Type more than 4 characters and send the button should become enabled. - app.textViews[A11yIdentifiers.bugReportScreen.report].clearAndTypeText("Longer text", app: app) + app.textFields[A11yIdentifiers.bugReportScreen.report].clearAndTypeText("Longer text", app: app) XCTAssert(app.switches[A11yIdentifiers.bugReportScreen.sendLogs].isOn) XCTAssert(!app.switches[A11yIdentifiers.bugReportScreen.canContact].isOn) try await app.assertScreenshot(.bugReport, step: 3) diff --git a/UITests/Sources/PollFormScreenUITests.swift b/UITests/Sources/PollFormScreenUITests.swift index fa02f72b9d..2456a474e9 100644 --- a/UITests/Sources/PollFormScreenUITests.swift +++ b/UITests/Sources/PollFormScreenUITests.swift @@ -16,15 +16,15 @@ class PollFormScreenUITests: XCTestCase { func testFilledPoll() async throws { let app = Application.launch(.createPoll) - let questionTextField = app.textViews[A11yIdentifiers.pollFormScreen.question] + let questionTextField = app.textFields[A11yIdentifiers.pollFormScreen.question] questionTextField.tapCenter() questionTextField.typeText("Do you like polls?") - let option1TextField = app.textViews[A11yIdentifiers.pollFormScreen.optionID(0)] + let option1TextField = app.textFields[A11yIdentifiers.pollFormScreen.optionID(0)] option1TextField.tapCenter() option1TextField.typeText("Yes") - let option2TextField = app.textViews[A11yIdentifiers.pollFormScreen.optionID(1)] + let option2TextField = app.textFields[A11yIdentifiers.pollFormScreen.optionID(1)] option2TextField.tapCenter() option2TextField.typeText("No") diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-10th-generation-en-GB.UI.png index e5abbd6329..3e66ca2c58 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c548364f9ad63a7d7c1d53e53600572c3e1477b3fa1ea13d4b941a73cda76a8a -size 85908 +oid sha256:e99fc8db5cc8c6b19986913f62b22479ce8279d5822c16d51eeb0de07d37fd6c +size 91224 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-16-en-GB.UI.png index f9d2ed4895..72cadef058 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-16-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-16-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73dadf138c13037272559f46962e8cbacfc7bf4de07e589a92c6e3d5848a2c93 -size 88038 +oid sha256:2b1e81541dbc3fadce76438542cc6f49b8315b0c5e66e60d435ecdc0deccd24a +size 94106 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-10th-generation-en-GB.UI.png index 268b46e9d6..aaf17fd84a 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccf7b17e2bad6bbce72d5b29e32a309865b2b2b9cb76a5af2447b675613b14c4 -size 89009 +oid sha256:c38f676abce80dd515607cc5f894c5d4848f35d6225a54235d733fdb2061251d +size 88120 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-16-en-GB.UI.png index 90dc376ddf..e50945997d 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-16-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-16-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7970d3cce906d1e1947407d7a9de5e8994069bd2b191ef3dc7c0a6b6b889d3bf -size 93417 +oid sha256:a411e0410bfaea1668c813590141b1ed710ce4ffc710df372f29029235dda33b +size 91531 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-10th-generation-en-GB.UI.png index 2bc9fada1e..caa1abedb8 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b375d9b216880cd6feea614a8ae9f722d1705e31e443d6c1620c20edb4a1a89 -size 83942 +oid sha256:8dcd756e7e80c4a8d49f542083b672a713068fdc12914d923fc10bb7d936aa4b +size 83046 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-16-en-GB.UI.png index b48b291b3a..50591c6d31 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-16-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-16-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf16f963d57f00a55133201b3fadd5820dc22d9af158d0d2163b088b675fe918 -size 84194 +oid sha256:26f50b02c39447b506edcceaa7cfba115bc594a727e3d51e600859f6d6f6e248 +size 82600 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-10th-generation-en-GB.UI.png index 29a661411f..34bb09c21a 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd87a89399242622d8176b1f4eb43f72b1f51314b0b8a01f0b5ac060516e65b3 -size 64449 +oid sha256:56c987c9acf140105a08e34fcebdec9827befd8b2d13100115d7a532fb33a082 +size 63514 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-16-en-GB.UI.png index 5645d68add..63d68fbc2b 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-16-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-16-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7f4dd44b1ca63ee19ab316d3dfa4da2fa3dc65bbc875a94659074b7d454d4bb -size 56996 +oid sha256:6689e6832ccdc6e608d8c64aba0bb9f400afa8cde98b3bf2a127b51fc6701555 +size 55165 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-10th-generation-en-GB.UI.png index 7ca009ad61..69dadd20f1 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6dbe259250888fe47d35e40c377a88032e4cde2d1fdc5cbe7395afdd304cbae -size 147532 +oid sha256:f7377e97c8da85ed52887c06816fb0ae445a241c89bf857fe92b40546533f8bd +size 146619 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-16-en-GB.UI.png index c9bdb57b5f..5eb62cb390 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-16-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-16-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe8a672f763bde80b901e4e8a0074658850942ed4f48e819b60bd67fef8bd025 -size 200840 +oid sha256:f3c5b416699192346ab3a9c1d03e44eeacd06f52d277e6a36730a5adba604559 +size 199057 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPad-10th-generation-en-GB.UI.png index 2d75cee457..a3a9a91488 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:050893bf116964c98d46d78d850cbcbfd92d11d612e5018c291f23d0ab4fffdd -size 144601 +oid sha256:4fd9a9b664c47e605793447d96bc0229a9db6c2edb8f104eac4453641a7329f8 +size 145090 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-16-en-GB.UI.png index 4b33967bf6..2c95e43d7a 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-16-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-16-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9651e8d3e5ccc6f2a0ea0da2b4054f901ef28de0e2175ecb457d12ac318be64a -size 195662 +oid sha256:fb0841f55e5958348cc279f0ae20dffc3a29526731a277e216764aef04451de5 +size 196081 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPad-10th-generation-en-GB.UI.png index 133318a2f6..fb240151e7 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35a2456bd43b0c5f15392cf37bad123ac10ca4362bde64e6a096f77be597d67e -size 84840 +oid sha256:49d13da337dc0375468cf3f265dcb468d8605b1f5f06d2cc3ed092f0b32441a4 +size 84097 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-16-en-GB.UI.png index aa48c2e651..4593e46a3f 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-16-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-16-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63d77933b2bc5d6dafde832081e02db26ce779b1c83d5b18bf664b059a297ad5 -size 85933 +oid sha256:b8aa9b54c86da44cb8b7e0b86f7cdca862b7bfadb1c05e10ae8c2385e20a46b6 +size 84619 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPad-10th-generation-en-GB.UI.png index 5b13865b03..cd665be759 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPad-10th-generation-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPad-10th-generation-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d0d342544d63dd9df0dd3f94e2a40d3bca7d9b91227e8b8b4e883efef85f19a -size 86265 +oid sha256:a4f60780487823206ce8749b6594e245d81d2996c609872c8b5829df6a364fc2 +size 84901 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-16-en-GB.UI.png index a0dd6b4208..ce3c4e2d9b 100644 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-16-en-GB.UI.png +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-16-en-GB.UI.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c59e4b368e0bcb294803118a66eb88f6bdc51460067cbd2527ac0c878a094e5 -size 87335 +oid sha256:04d11a84c66697b8ce469ef1b8032e409015c844e1b5ed1e5e9ee5e457e0d1e3 +size 85177 From 2cb7faca88f846e3e5a1dea58c8ceb71d346e7d0 Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:43:40 +0100 Subject: [PATCH 20/74] Fix Rooms that user has knocked not displaying the request sent screen (#3513) * fix knocked state * pr suggestion * code improvement --- ElementX.xcodeproj/project.pbxproj | 50 +++++++++++-------- .../Mocks/Generated/GeneratedMocks.swift | 4 +- .../JoinRoomScreenViewModel.swift | 18 +++---- .../Sources/Services/Client/ClientProxy.swift | 3 +- .../Services/Room/KnockedRoomProxy.swift | 19 +++---- .../Sources/Services/Room/RoomInfoProxy.swift | 27 +++++++++- .../Services/Room/RoomProxyProtocol.swift | 2 +- 7 files changed, 79 insertions(+), 44 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 146e06614b..fc98a27b95 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -799,7 +799,6 @@ A6DEC1ADEC8FEEC206A0FA37 /* AttributedStringBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */; }; A6F345328CCC5C9B0DAE2257 /* LogViewerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB05221D7D941CC82DC8480 /* LogViewerScreenViewModel.swift */; }; A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; }; - A73316762CE3A9B200F6B613 /* KnockRequestsBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A73316752CE3A9A700F6B613 /* KnockRequestsBannerView.swift */; }; A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; }; A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; A808DC3F72D15C6C5A52317E /* TimelineItemDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCDA016D05107DED3B9495CB /* TimelineItemDebugView.swift */; }; @@ -1001,6 +1000,7 @@ D5681C80D8281560AACE0035 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045253F9967A535EE5B16691 /* Label.swift */; }; D5B1531A72387D432939D4E0 /* RoomDirectorySearchProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */; }; D5E771132BB36240DE38102F /* RoomMessageEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */; }; + D5E8EE8A288EFCCF646860EA /* KnockRequestsBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47F441A78A5CAA9E2937E463 /* KnockRequestsBannerView.swift */; }; D5FE90A6AF5FD5AE91BD37C7 /* NotificationSettingsEditScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 780258F1B9D15E30549FF4BE /* NotificationSettingsEditScreenViewModel.swift */; }; D6152E21036B88C44ECB22E7 /* EncryptionResetPasswordScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 303D9438EFB481F57A366E82 /* EncryptionResetPasswordScreenViewModel.swift */; }; D63974A88CF2BC721F109C77 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = DCA3C4A997AD28E6918D4CE5 /* Compound */; }; @@ -1265,13 +1265,13 @@ 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; 0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = ""; }; - 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = ""; }; + 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = ""; }; 044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = ""; }; 045253F9967A535EE5B16691 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; 046C0D3F53B0B5EF0A1F5BEA /* RoomSummaryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryTests.swift; sourceTree = ""; }; - 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.swift; sourceTree = ""; }; 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = ""; }; 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxyProtocol.swift; sourceTree = ""; }; @@ -1337,7 +1337,7 @@ 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 = ""; }; - 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = IntegrationTests.xctestplan; 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 = ""; }; @@ -1431,7 +1431,7 @@ 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = ""; }; 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenCoordinator.swift; sourceTree = ""; }; 260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = ""; }; - 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = PreviewTests.xctestplan; sourceTree = ""; }; + 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; path = PreviewTests.xctestplan; sourceTree = ""; }; 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorder.swift; sourceTree = ""; }; 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceProtocol.swift; sourceTree = ""; }; 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1502,7 +1502,7 @@ 3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = ""; }; 35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; 35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = ""; }; - 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = ""; }; 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerURLBuildersTests.swift; sourceTree = ""; }; 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = ""; }; @@ -1593,6 +1593,7 @@ 47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenModels.swift; sourceTree = ""; }; 47EBB5D698CE9A25BB553A2D /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = ""; }; 47F29139BC2A804CE5E0757E /* MediaUploadPreviewScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModel.swift; sourceTree = ""; }; + 47F441A78A5CAA9E2937E463 /* KnockRequestsBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsBannerView.swift; sourceTree = ""; }; 4853C923A1AF43711D025EAF /* TextRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineView.swift; sourceTree = ""; }; 48A5C34C4E4268EF65D171EF /* RoomChangeRolesScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenModels.swift; sourceTree = ""; }; 48CE6BF18E542B32FA52CE06 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = fa; path = fa.lproj/Localizable.stringsdict; sourceTree = ""; }; @@ -1612,7 +1613,7 @@ 4B41FABA2B0AEF4389986495 /* LoginMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMode.swift; sourceTree = ""; }; 4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenCoordinator.swift; sourceTree = ""; }; 4C8D988E82A8DFA13BE46F7C /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pl; path = pl.lproj/Localizable.stringsdict; sourceTree = ""; }; - 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreen.swift; sourceTree = ""; }; 4D3A7375AB22721C436EB056 /* ComposerToolbarModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarModels.swift; sourceTree = ""; }; 4E2245243369B99216C7D84E /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = ""; }; @@ -1883,7 +1884,7 @@ 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 8DA1E8F287680C8ED25EDBAC /* NetworkMonitorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitorMock.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = ""; }; + 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 = ""; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = ""; }; @@ -1988,7 +1989,6 @@ A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = ""; }; A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriverProtocol.swift; sourceTree = ""; }; A6EA0D8B0BBD8805F7D5A133 /* TextBasedRoomTimelineViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineViewProtocol.swift; sourceTree = ""; }; - A73316752CE3A9A700F6B613 /* KnockRequestsBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsBannerView.swift; sourceTree = ""; }; A73A07BAEDD74C48795A996A /* AsyncSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncSequence.swift; sourceTree = ""; }; A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationTokenTests.swift; sourceTree = ""; }; A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = ""; }; @@ -2065,7 +2065,7 @@ B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyProtocol.swift; sourceTree = ""; }; B53AC78E49A297AC1D72A7CF /* AppMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediator.swift; sourceTree = ""; }; B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = ""; }; - B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = ""; }; + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; 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 = ""; }; @@ -2183,7 +2183,7 @@ CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = ""; }; CDE3F3911FF7CC639BDE5844 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = ""; }; - CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = ""; }; D01FD1171FF40E34D707FD00 /* BigIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigIcon.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 = ""; }; @@ -2316,7 +2316,7 @@ ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = ""; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = ""; }; ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModel.swift; sourceTree = ""; }; - ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = ""; }; ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = ""; }; EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = ""; }; @@ -2339,7 +2339,7 @@ F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = ""; }; - F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = ""; }; + F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = ""; }; F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = ""; }; F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = ""; }; @@ -2357,7 +2357,7 @@ F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineBubbleLayout.swift; sourceTree = ""; }; F5E23D8EE6CBACF32F1EC874 /* MediaPlayerProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProviderProtocol.swift; sourceTree = ""; }; F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModel.swift; sourceTree = ""; }; - F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_apple_image.heic; sourceTree = ""; }; + F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; path = test_apple_image.heic; sourceTree = ""; }; F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = ""; }; F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockUITests.swift; sourceTree = ""; }; F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderMock.swift; sourceTree = ""; }; @@ -4157,7 +4157,7 @@ 79023E5904B155E8E2B8B502 /* View */ = { isa = PBXGroup; children = ( - A73316752CE3A9A700F6B613 /* KnockRequestsBannerView.swift */, + 47F441A78A5CAA9E2937E463 /* KnockRequestsBannerView.swift */, 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */, 4137900E28201C314C835C11 /* RoomScreenFooterView.swift */, 4552D3466B1453F287223ADA /* SwipeRightAction.swift */, @@ -6592,7 +6592,6 @@ D19A748E95E2FAB2940570F0 /* CallScreen.swift in Sources */, 763D69741D58D2B650BC1FC9 /* CallScreenCoordinator.swift in Sources */, B7C9E07F4F9CCC8DD7156A20 /* CallScreenModels.swift in Sources */, - A73316762CE3A9B200F6B613 /* KnockRequestsBannerView.swift in Sources */, 39A987B3E41B976D1DF944C6 /* CallScreenViewModel.swift in Sources */, 84CAE3E96D93194DA06B9194 /* CallScreenViewModelProtocol.swift in Sources */, BB6BF528BC7F5B87E08C4F18 /* CameraPicker.swift in Sources */, @@ -6769,6 +6768,7 @@ 1FE593ECEC40A43789105D80 /* KeychainController.swift in Sources */, FD29471C72872F8B7580E3E1 /* KeychainControllerMock.swift in Sources */, CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */, + D5E8EE8A288EFCCF646860EA /* KnockRequestsBannerView.swift in Sources */, C969A62F3D9F14318481A33B /* KnockedRoomProxy.swift in Sources */, 6681D6D3ADF69EBD2625F29A /* KnockedRoomProxyMock.swift in Sources */, 454F8DDC4442C0DE54094902 /* LABiometryType.swift in Sources */, @@ -7537,7 +7537,9 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_NSE"; + OTHER_SWIFT_FLAGS = ( + "-DIS_NSE", + ); PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -7586,7 +7588,9 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; + OTHER_SWIFT_FLAGS = ( + "-DIS_MAIN_APP", + ); PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7612,7 +7616,9 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; + OTHER_SWIFT_FLAGS = ( + "-DIS_MAIN_APP", + ); PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7878,7 +7884,9 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_NSE"; + OTHER_SWIFT_FLAGS = ( + "-DIS_NSE", + ); PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index d7f3f69ccf..c6361567d1 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -9569,11 +9569,11 @@ class KeychainControllerMock: KeychainControllerProtocol { } } class KnockedRoomProxyMock: KnockedRoomProxyProtocol { - var info: RoomInfoProxy { + var info: BaseRoomInfoProxyProtocol { get { return underlyingInfo } set(value) { underlyingInfo = value } } - var underlyingInfo: RoomInfoProxy! + var underlyingInfo: BaseRoomInfoProxyProtocol! var id: String { get { return underlyingId } set(value) { underlyingId = value } diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift index 2d88bfb14e..828d1a28cd 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift @@ -102,27 +102,27 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo } private func updateRoomDetails() { - var roomInfo: RoomInfoProxy? + var roomPreviewInfo: BaseRoomInfoProxyProtocol? var inviter: RoomInviterDetails? switch room { case .joined(let joinedRoomProxy): - roomInfo = joinedRoomProxy.infoPublisher.value + roomPreviewInfo = joinedRoomProxy.infoPublisher.value case .invited(let invitedRoomProxy): inviter = invitedRoomProxy.info.inviter.flatMap(RoomInviterDetails.init) - roomInfo = invitedRoomProxy.info + roomPreviewInfo = invitedRoomProxy.info case .knocked(let knockedRoomProxy): - roomInfo = knockedRoomProxy.info + roomPreviewInfo = knockedRoomProxy.info default: break } - let name = roomInfo?.displayName ?? roomPreviewDetails?.name + let name = roomPreviewInfo?.displayName ?? roomPreviewDetails?.name state.roomDetails = JoinRoomScreenRoomDetails(name: name, - topic: roomInfo?.topic ?? roomPreviewDetails?.topic, - canonicalAlias: roomInfo?.canonicalAlias ?? roomPreviewDetails?.canonicalAlias, - avatar: roomInfo?.avatar ?? .room(id: roomID, name: name ?? "", avatarURL: roomPreviewDetails?.avatarURL), - memberCount: UInt(roomInfo?.activeMembersCount ?? Int(roomPreviewDetails?.memberCount ?? 0)), + topic: roomPreviewInfo?.topic ?? roomPreviewDetails?.topic, + canonicalAlias: roomPreviewInfo?.canonicalAlias ?? roomPreviewDetails?.canonicalAlias, + avatar: roomPreviewInfo?.avatar ?? .room(id: roomID, name: name ?? "", avatarURL: roomPreviewDetails?.avatarURL), + memberCount: UInt(roomPreviewInfo?.activeMembersCount ?? Int(roomPreviewDetails?.memberCount ?? 0)), inviter: inviter) updateMode() diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 11ec6dcfaa..f36ff6d7bb 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -934,7 +934,8 @@ class ClientProxy: ClientProxyProtocol { case .knocked: if appSettings.knockingEnabled { return try await .knocked(KnockedRoomProxy(roomListItem: roomListItem, - room: roomListItem.invitedRoom())) + roomPreview: roomListItem.previewRoom(via: []), + ownUserID: userID)) } else { return try await .invited(InvitedRoomProxy(roomListItem: roomListItem, room: roomListItem.invitedRoom())) diff --git a/ElementX/Sources/Services/Room/KnockedRoomProxy.swift b/ElementX/Sources/Services/Room/KnockedRoomProxy.swift index 74b640dc54..c2c35de056 100644 --- a/ElementX/Sources/Services/Room/KnockedRoomProxy.swift +++ b/ElementX/Sources/Services/Room/KnockedRoomProxy.swift @@ -11,26 +11,27 @@ import UIKit class KnockedRoomProxy: KnockedRoomProxyProtocol { private let roomListItem: RoomListItemProtocol - private let room: RoomProtocol + private let roomPreview: RoomPreviewProtocol + let info: BaseRoomInfoProxyProtocol // A room identifier is constant and lazy stops it from being fetched // multiple times over FFI - lazy var id: String = room.id() + lazy var id = info.id - var ownUserID: String { room.ownUserId() } - - let info: RoomInfoProxy + let ownUserID: String init(roomListItem: RoomListItemProtocol, - room: RoomProtocol) async throws { + roomPreview: RoomPreviewProtocol, + ownUserID: String) async throws { self.roomListItem = roomListItem - self.room = room - info = try await RoomInfoProxy(roomInfo: room.roomInfo()) + self.roomPreview = roomPreview + self.ownUserID = ownUserID + info = try RoomPreviewInfoProxy(roomPreviewInfo: roomPreview.info()) } func cancelKnock() async -> Result { do { - return try await .success(room.leave()) + return try await .success(roomPreview.leave()) } catch { MXLog.error("Failed cancelling the knock with error: \(error)") return .failure(.sdkError(error)) diff --git a/ElementX/Sources/Services/Room/RoomInfoProxy.swift b/ElementX/Sources/Services/Room/RoomInfoProxy.swift index e402031310..7fa274ff8d 100644 --- a/ElementX/Sources/Services/Room/RoomInfoProxy.swift +++ b/ElementX/Sources/Services/Room/RoomInfoProxy.swift @@ -8,7 +8,17 @@ import Foundation import MatrixRustSDK -struct RoomInfoProxy { +protocol BaseRoomInfoProxyProtocol { + var id: String { get } + var displayName: String? { get } + var avatar: RoomAvatar { get } + var topic: String? { get } + var canonicalAlias: String? { get } + var avatarURL: URL? { get } + var activeMembersCount: Int { get } +} + +struct RoomInfoProxy: BaseRoomInfoProxyProtocol { let roomInfo: RoomInfo var id: String { roomInfo.id } @@ -54,3 +64,18 @@ struct RoomInfoProxy { var unreadMentionsCount: UInt { UInt(roomInfo.numUnreadMentions) } var pinnedEventIDs: Set { Set(roomInfo.pinnedEventIds) } } + +struct RoomPreviewInfoProxy: BaseRoomInfoProxyProtocol { + let roomPreviewInfo: RoomPreviewInfo + + var id: String { roomPreviewInfo.roomId } + var displayName: String? { roomPreviewInfo.name } + var avatar: RoomAvatar { + .room(id: id, name: displayName, avatarURL: avatarURL) + } + + var topic: String? { roomPreviewInfo.topic } + var canonicalAlias: String? { roomPreviewInfo.canonicalAlias } + var avatarURL: URL? { roomPreviewInfo.avatarUrl.flatMap(URL.init) } + var activeMembersCount: Int { Int(roomPreviewInfo.numJoinedMembers) } +} diff --git a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift index c1f1f53352..550fcc0eaf 100644 --- a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift @@ -40,7 +40,7 @@ protocol InvitedRoomProxyProtocol: RoomProxyProtocol { // sourcery: AutoMockable protocol KnockedRoomProxyProtocol: RoomProxyProtocol { - var info: RoomInfoProxy { get } + var info: BaseRoomInfoProxyProtocol { get } func cancelKnock() async -> Result } From 5aadf4e65b0557db52c7226297073f103b16ec4b Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 14 Nov 2024 16:44:36 +0200 Subject: [PATCH 21/74] UI test fixes (#3515) * More UI test fixes * Update all UITest snapshots. * Wait for reset waiting indicator to be removed before snapshotting the encryption reset screen --- UITests/Sources/EncryptionResetUITests.swift | 3 +++ .../Application/appLockFlow-0-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/appLockFlow-0-iPhone-18-1-en-GB.UI.png | 3 +++ .../Application/appLockFlow-1-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/appLockFlow-1-iPhone-18-1-en-GB.UI.png | 3 +++ .../Application/appLockFlow-2-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/appLockFlow-2-iPhone-18-1-en-GB.UI.png | 3 +++ .../Application/appLockFlow-3-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/appLockFlow-3-iPhone-18-1-en-GB.UI.png | 3 +++ .../Application/appLockFlow-4-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/appLockFlow-4-iPhone-18-1-en-GB.UI.png | 3 +++ .../Application/appLockFlow-99-iPad-18-1-en-GB.UI.png | 3 +++ .../appLockFlow-99-iPhone-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-0-iPad-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-0-iPhone-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-1-iPad-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-1-iPhone-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-2-iPad-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-2-iPhone-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-3-iPad-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-3-iPhone-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-4-iPad-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-5-iPad-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-99-iPad-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlow-99-iPhone-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlowMandatory-0-iPad-18-1-en-GB.UI.png | 3 +++ ...ppLockSetupFlowMandatory-0-iPhone-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlowMandatory-1-iPad-18-1-en-GB.UI.png | 3 +++ ...ppLockSetupFlowMandatory-1-iPhone-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlowMandatory-2-iPad-18-1-en-GB.UI.png | 3 +++ ...ppLockSetupFlowMandatory-2-iPhone-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlowUnlock-iPad-18-1-en-GB.UI.png | 3 +++ .../appLockSetupFlowUnlock-iPhone-18-1-en-GB.UI.png | 3 +++ ...png => authenticationFlow-1-iPad-18-1-en-GB.UI.png} | 0 ...g => authenticationFlow-1-iPhone-18-1-en-GB.UI.png} | 0 ...I.png => authenticationFlow-iPad-18-1-en-GB.UI.png} | 0 ...png => authenticationFlow-iPhone-18-1-en-GB.UI.png} | 0 .../bugReport-0-iPad-10th-generation-en-GB.UI.png | 3 --- .../Application/bugReport-0-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/bugReport-0-iPhone-16-en-GB.UI.png | 3 --- .../Application/bugReport-0-iPhone-18-1-en-GB.UI.png | 3 +++ .../bugReport-2-iPad-10th-generation-en-GB.UI.png | 3 --- .../Application/bugReport-2-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/bugReport-2-iPhone-16-en-GB.UI.png | 3 --- .../Application/bugReport-2-iPhone-18-1-en-GB.UI.png | 3 +++ .../bugReport-3-iPad-10th-generation-en-GB.UI.png | 3 --- .../Application/bugReport-3-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/bugReport-3-iPhone-16-en-GB.UI.png | 3 --- .../Application/bugReport-3-iPhone-18-1-en-GB.UI.png | 3 +++ .../createPoll-1-iPad-10th-generation-en-GB.UI.png | 3 --- .../Application/createPoll-1-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/createPoll-1-iPhone-16-en-GB.UI.png | 3 --- .../Application/createPoll-1-iPhone-18-1-en-GB.UI.png | 3 +++ ...n-GB.UI.png => createPoll-2-iPad-18-1-en-GB.UI.png} | 0 .../Application/createPoll-2-iPhone-16-en-GB.UI.png | 3 --- .../Application/createPoll-2-iPhone-18-1-en-GB.UI.png | 3 +++ .../createPoll-iPad-10th-generation-en-GB.UI.png | 3 --- .../Application/createPoll-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/createPoll-iPhone-16-en-GB.UI.png | 3 --- .../Application/createPoll-iPhone-18-1-en-GB.UI.png | 3 +++ .../createRoom-1-iPad-10th-generation-en-GB.UI.png | 3 --- .../Application/createRoom-1-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/createRoom-1-iPhone-16-en-GB.UI.png | 3 --- .../Application/createRoom-1-iPhone-18-1-en-GB.UI.png | 3 +++ .../createRoom-iPad-10th-generation-en-GB.UI.png | 3 --- .../Application/createRoom-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/createRoom-iPhone-16-en-GB.UI.png | 3 --- .../Application/createRoom-iPhone-18-1-en-GB.UI.png | 3 +++ ...createRoomNoUsers-iPad-10th-generation-en-GB.UI.png | 3 --- .../createRoomNoUsers-iPad-18-1-en-GB.UI.png | 3 +++ .../createRoomNoUsers-iPhone-16-en-GB.UI.png | 3 --- .../createRoomNoUsers-iPhone-18-1-en-GB.UI.png | 3 +++ ...UI.png => encryptionReset-0-iPad-18-1-en-GB.UI.png} | 0 .../encryptionReset-0-iPhone-16-en-GB.UI.png | 3 --- .../encryptionReset-0-iPhone-18-1-en-GB.UI.png | 3 +++ ...UI.png => encryptionReset-1-iPad-18-1-en-GB.UI.png} | 0 ....png => encryptionReset-1-iPhone-18-1-en-GB.UI.png} | 0 ...UI.png => encryptionReset-2-iPad-18-1-en-GB.UI.png} | 0 ....png => encryptionReset-2-iPhone-18-1-en-GB.UI.png} | 0 ...png => encryptionSettings-0-iPad-18-1-en-GB.UI.png} | 0 .../encryptionSettings-0-iPhone-16-en-GB.UI.png | 3 --- .../encryptionSettings-0-iPhone-18-1-en-GB.UI.png | 3 +++ ...png => encryptionSettings-1-iPad-18-1-en-GB.UI.png} | 0 ...g => encryptionSettings-1-iPhone-18-1-en-GB.UI.png} | 0 ...png => encryptionSettings-2-iPad-18-1-en-GB.UI.png} | 0 ...g => encryptionSettings-2-iPhone-18-1-en-GB.UI.png} | 0 ...png => encryptionSettings-3-iPad-18-1-en-GB.UI.png} | 0 ...g => encryptionSettings-3-iPhone-18-1-en-GB.UI.png} | 0 ...png => encryptionSettings-4-iPad-18-1-en-GB.UI.png} | 0 ...g => encryptionSettings-4-iPhone-18-1-en-GB.UI.png} | 0 ...png => encryptionSettings-5-iPad-18-1-en-GB.UI.png} | 0 ...g => encryptionSettings-5-iPhone-18-1-en-GB.UI.png} | 0 ...png => encryptionSettings-6-iPad-18-1-en-GB.UI.png} | 0 ...g => encryptionSettings-6-iPhone-18-1-en-GB.UI.png} | 0 .../roomLayoutBottom-0-iPad-18-1-en-GB.UI.png | 3 +++ .../roomLayoutBottom-0-iPhone-18-1-en-GB.UI.png | 3 +++ .../roomLayoutBottom-1-iPad-18-1-en-GB.UI.png | 3 +++ .../roomLayoutBottom-1-iPhone-18-1-en-GB.UI.png | 3 +++ .../roomLayoutHighlight-0-iPad-18-1-en-GB.UI.png | 3 +++ .../roomLayoutHighlight-0-iPhone-18-1-en-GB.UI.png | 3 +++ ...-GB.UI.png => roomLayoutTop-iPad-18-1-en-GB.UI.png} | 0 ...B.UI.png => roomLayoutTop-iPhone-18-1-en-GB.UI.png} | 0 ...rsListScreenPendingInvites-1-iPad-18-1-en-GB.UI.png | 3 +++ ...ListScreenPendingInvites-1-iPhone-18-1-en-GB.UI.png | 3 +++ ...rsListScreenPendingInvites-2-iPad-18-1-en-GB.UI.png | 3 +++ ...ListScreenPendingInvites-2-iPhone-18-1-en-GB.UI.png | 3 +++ ...bersListScreenPendingInvites-iPad-18-1-en-GB.UI.png | 3 +++ ...rsListScreenPendingInvites-iPhone-18-1-en-GB.UI.png | 3 +++ ...roomPlainNoAvatar-iPad-10th-generation-en-GB.UI.png | 3 --- .../roomPlainNoAvatar-iPad-18-1-en-GB.UI.png | 3 +++ .../roomPlainNoAvatar-iPhone-16-en-GB.UI.png | 3 --- .../roomPlainNoAvatar-iPhone-18-1-en-GB.UI.png | 3 +++ ...oomRolesAndPermissionsFlow-0-iPad-18-1-en-GB.UI.png | 3 +++ ...mRolesAndPermissionsFlow-0-iPhone-18-1-en-GB.UI.png | 3 +++ ...oomRolesAndPermissionsFlow-1-iPad-18-1-en-GB.UI.png | 3 +++ ...mRolesAndPermissionsFlow-1-iPhone-18-1-en-GB.UI.png | 3 +++ ...oomRolesAndPermissionsFlow-2-iPad-18-1-en-GB.UI.png | 3 +++ ...mRolesAndPermissionsFlow-2-iPhone-18-1-en-GB.UI.png | 3 +++ ...oomRolesAndPermissionsFlow-3-iPad-18-1-en-GB.UI.png | 3 +++ ...mRolesAndPermissionsFlow-3-iPhone-18-1-en-GB.UI.png | 3 +++ ...oomRolesAndPermissionsFlow-4-iPad-18-1-en-GB.UI.png | 3 +++ ...mRolesAndPermissionsFlow-4-iPhone-18-1-en-GB.UI.png | 3 +++ ...oomRolesAndPermissionsFlow-5-iPad-18-1-en-GB.UI.png | 3 +++ ...mRolesAndPermissionsFlow-5-iPhone-18-1-en-GB.UI.png | 3 +++ ...roomSmallTimeline-iPad-10th-generation-en-GB.UI.png | 3 --- .../roomSmallTimeline-iPad-18-1-en-GB.UI.png | 3 +++ ....png => roomSmallTimeline-iPhone-18-1-en-GB.UI.png} | 0 ...neIncomingAndSmallPagination-iPad-18-1-en-GB.UI.png | 3 +++ ...IncomingAndSmallPagination-iPhone-18-1-en-GB.UI.png | 3 +++ ...SmallTimelineLargePagination-iPad-18-1-en-GB.UI.png | 3 +++ ...allTimelineLargePagination-iPhone-18-1-en-GB.UI.png | 3 +++ ...mallTimelineWithReadReceipts-iPad-18-1-en-GB.UI.png | 3 +++ ...llTimelineWithReadReceipts-iPhone-18-1-en-GB.UI.png | 3 +++ ...g => roomWithDisclosedPolls-iPad-18-1-en-GB.UI.png} | 0 ...=> roomWithDisclosedPolls-iPhone-18-1-en-GB.UI.png} | 0 ...ng => roomWithOutgoingPolls-iPad-18-1-en-GB.UI.png} | 0 ... => roomWithOutgoingPolls-iPhone-18-1-en-GB.UI.png} | 0 ...=> roomWithUndisclosedPolls-iPad-18-1-en-GB.UI.png} | 0 ... roomWithUndisclosedPolls-iPhone-18-1-en-GB.UI.png} | 0 ...serverSelection-0-iPad-10th-generation-en-GB.UI.png | 3 --- .../serverSelection-0-iPad-18-1-en-GB.UI.png | 3 +++ ....png => serverSelection-0-iPhone-18-1-en-GB.UI.png} | 0 ...serverSelection-1-iPad-10th-generation-en-GB.UI.png | 3 --- .../serverSelection-1-iPad-18-1-en-GB.UI.png | 3 +++ .../serverSelection-1-iPhone-16-en-GB.UI.png | 3 --- .../serverSelection-1-iPhone-18-1-en-GB.UI.png | 3 +++ ...UI.png => serverSelection-2-iPad-18-1-en-GB.UI.png} | 0 ....png => serverSelection-2-iPhone-18-1-en-GB.UI.png} | 0 ...ionVerification-0-iPad-10th-generation-en-GB.UI.png | 3 --- .../sessionVerification-0-iPad-18-1-en-GB.UI.png | 3 +++ .../sessionVerification-0-iPhone-16-en-GB.UI.png | 3 --- .../sessionVerification-0-iPhone-18-1-en-GB.UI.png | 3 +++ ...ionVerification-1-iPad-10th-generation-en-GB.UI.png | 3 --- .../sessionVerification-1-iPad-18-1-en-GB.UI.png | 3 +++ .../sessionVerification-1-iPhone-16-en-GB.UI.png | 3 --- .../sessionVerification-1-iPhone-18-1-en-GB.UI.png | 3 +++ ...ionVerification-2-iPad-10th-generation-en-GB.UI.png | 3 --- .../sessionVerification-2-iPad-18-1-en-GB.UI.png | 3 +++ .../sessionVerification-2-iPhone-16-en-GB.UI.png | 3 --- .../sessionVerification-2-iPhone-18-1-en-GB.UI.png | 3 +++ ...ionVerification-3-iPad-10th-generation-en-GB.UI.png | 3 --- .../sessionVerification-3-iPad-18-1-en-GB.UI.png | 3 +++ .../sessionVerification-3-iPhone-16-en-GB.UI.png | 3 --- .../sessionVerification-3-iPhone-18-1-en-GB.UI.png | 3 +++ ...ionVerification-4-iPad-10th-generation-en-GB.UI.png | 3 --- .../sessionVerification-4-iPad-18-1-en-GB.UI.png | 3 +++ .../sessionVerification-4-iPhone-16-en-GB.UI.png | 3 --- .../sessionVerification-4-iPhone-18-1-en-GB.UI.png | 3 +++ ...ng => sessionVerification-5-iPad-18-1-en-GB.UI.png} | 0 .../sessionVerification-5-iPhone-16-en-GB.UI.png | 3 --- .../sessionVerification-5-iPhone-18-1-en-GB.UI.png | 3 +++ ...ng => sessionVerification-6-iPad-18-1-en-GB.UI.png} | 0 .../sessionVerification-6-iPhone-16-en-GB.UI.png | 3 --- .../sessionVerification-6-iPhone-18-1-en-GB.UI.png | 3 +++ ...ng => sessionVerification-7-iPad-18-1-en-GB.UI.png} | 0 .../sessionVerification-7-iPhone-16-en-GB.UI.png | 3 --- .../sessionVerification-7-iPhone-18-1-en-GB.UI.png | 3 +++ .../startChat-1-iPad-10th-generation-en-GB.UI.png | 3 --- .../Application/startChat-1-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/startChat-1-iPhone-16-en-GB.UI.png | 3 --- .../Application/startChat-1-iPhone-18-1-en-GB.UI.png | 3 +++ .../startChat-2-iPad-10th-generation-en-GB.UI.png | 3 --- .../Application/startChat-2-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/startChat-2-iPhone-16-en-GB.UI.png | 3 --- .../Application/startChat-2-iPhone-18-1-en-GB.UI.png | 3 +++ .../startChat-iPad-10th-generation-en-GB.UI.png | 3 --- .../Application/startChat-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/startChat-iPhone-16-en-GB.UI.png | 3 --- .../Application/startChat-iPhone-18-1-en-GB.UI.png | 3 +++ .../templateScreen-iPad-10th-generation-en-GB.UI.png | 3 --- .../Application/templateScreen-iPad-18-1-en-GB.UI.png | 3 +++ .../Application/templateScreen-iPhone-16-en-GB.UI.png | 3 --- .../templateScreen-iPhone-18-1-en-GB.UI.png | 3 +++ .../userSessionScreen-1-iPad-18-1-en-GB.UI.png | 3 +++ .../userSessionScreen-1-iPhone-18-1-en-GB.UI.png | 3 +++ .../userSessionScreen-2-iPad-18-1-en-GB.UI.png | 3 +++ .../userSessionScreen-2-iPhone-18-1-en-GB.UI.png | 3 +++ .../userSessionScreen-3-iPad-18-1-en-GB.UI.png | 3 +++ .../userSessionScreen-3-iPhone-18-1-en-GB.UI.png | 3 +++ ...essionScreenReply-iPad-10th-generation-en-GB.UI.png | 3 --- .../userSessionScreenReply-iPad-18-1-en-GB.UI.png | 3 +++ .../userSessionScreenReply-iPhone-16-en-GB.UI.png | 3 --- .../userSessionScreenReply-iPhone-18-1-en-GB.UI.png | 3 +++ fastlane/Fastfile | 10 +++++----- 204 files changed, 356 insertions(+), 149 deletions(-) create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-4-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-5-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPhone-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{authenticationFlow-1-iPad-10th-generation-en-GB.UI.png => authenticationFlow-1-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{authenticationFlow-1-iPhone-16-en-GB.UI.png => authenticationFlow-1-iPhone-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{authenticationFlow-iPad-10th-generation-en-GB.UI.png => authenticationFlow-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{authenticationFlow-iPhone-16-en-GB.UI.png => authenticationFlow-iPhone-18-1-en-GB.UI.png} (100%) delete mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-0-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-0-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-2-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-2-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-3-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-3-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/createPoll-1-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/createPoll-1-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{createPoll-2-iPad-10th-generation-en-GB.UI.png => createPoll-2-iPad-18-1-en-GB.UI.png} (100%) delete mode 100644 UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/createPoll-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/createPoll-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/createPoll-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/createPoll-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/createRoom-1-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/createRoom-1-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/createRoom-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/createRoom-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/createRoom-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/createRoom-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{encryptionReset-0-iPad-10th-generation-en-GB.UI.png => encryptionReset-0-iPad-18-1-en-GB.UI.png} (100%) delete mode 100644 UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPhone-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{encryptionReset-1-iPad-10th-generation-en-GB.UI.png => encryptionReset-1-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionReset-1-iPhone-16-en-GB.UI.png => encryptionReset-1-iPhone-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionReset-2-iPad-10th-generation-en-GB.UI.png => encryptionReset-2-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionReset-2-iPhone-16-en-GB.UI.png => encryptionReset-2-iPhone-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-0-iPad-10th-generation-en-GB.UI.png => encryptionSettings-0-iPad-18-1-en-GB.UI.png} (100%) delete mode 100644 UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPhone-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-1-iPad-10th-generation-en-GB.UI.png => encryptionSettings-1-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-1-iPhone-16-en-GB.UI.png => encryptionSettings-1-iPhone-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-2-iPad-10th-generation-en-GB.UI.png => encryptionSettings-2-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-2-iPhone-16-en-GB.UI.png => encryptionSettings-2-iPhone-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-3-iPad-10th-generation-en-GB.UI.png => encryptionSettings-3-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-3-iPhone-16-en-GB.UI.png => encryptionSettings-3-iPhone-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-4-iPad-10th-generation-en-GB.UI.png => encryptionSettings-4-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-4-iPhone-16-en-GB.UI.png => encryptionSettings-4-iPhone-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-5-iPad-10th-generation-en-GB.UI.png => encryptionSettings-5-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-5-iPhone-16-en-GB.UI.png => encryptionSettings-5-iPhone-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-6-iPad-10th-generation-en-GB.UI.png => encryptionSettings-6-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{encryptionSettings-6-iPhone-16-en-GB.UI.png => encryptionSettings-6-iPhone-18-1-en-GB.UI.png} (100%) create mode 100644 UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{roomLayoutTop-iPad-10th-generation-en-GB.UI.png => roomLayoutTop-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{roomLayoutTop-iPhone-16-en-GB.UI.png => roomLayoutTop-iPhone-18-1-en-GB.UI.png} (100%) create mode 100644 UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPad-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{roomSmallTimeline-iPhone-16-en-GB.UI.png => roomSmallTimeline-iPhone-18-1-en-GB.UI.png} (100%) create mode 100644 UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{roomWithDisclosedPolls-iPad-10th-generation-en-GB.UI.png => roomWithDisclosedPolls-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{roomWithDisclosedPolls-iPhone-16-en-GB.UI.png => roomWithDisclosedPolls-iPhone-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{roomWithOutgoingPolls-iPad-10th-generation-en-GB.UI.png => roomWithOutgoingPolls-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{roomWithOutgoingPolls-iPhone-16-en-GB.UI.png => roomWithOutgoingPolls-iPhone-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{roomWithUndisclosedPolls-iPad-10th-generation-en-GB.UI.png => roomWithUndisclosedPolls-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{roomWithUndisclosedPolls-iPhone-16-en-GB.UI.png => roomWithUndisclosedPolls-iPhone-18-1-en-GB.UI.png} (100%) delete mode 100644 UITests/Sources/__Snapshots__/Application/serverSelection-0-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/serverSelection-0-iPad-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{serverSelection-0-iPhone-16-en-GB.UI.png => serverSelection-0-iPhone-18-1-en-GB.UI.png} (100%) delete mode 100644 UITests/Sources/__Snapshots__/Application/serverSelection-1-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/serverSelection-1-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{serverSelection-2-iPad-10th-generation-en-GB.UI.png => serverSelection-2-iPad-18-1-en-GB.UI.png} (100%) rename UITests/Sources/__Snapshots__/Application/{serverSelection-2-iPhone-16-en-GB.UI.png => serverSelection-2-iPhone-18-1-en-GB.UI.png} (100%) delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{sessionVerification-5-iPad-10th-generation-en-GB.UI.png => sessionVerification-5-iPad-18-1-en-GB.UI.png} (100%) delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{sessionVerification-6-iPad-10th-generation-en-GB.UI.png => sessionVerification-6-iPad-18-1-en-GB.UI.png} (100%) delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-18-1-en-GB.UI.png rename UITests/Sources/__Snapshots__/Application/{sessionVerification-7-iPad-10th-generation-en-GB.UI.png => sessionVerification-7-iPad-18-1-en-GB.UI.png} (100%) delete mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/startChat-1-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/startChat-1-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/startChat-2-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/startChat-2-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/startChat-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/startChat-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/startChat-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/startChat-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/templateScreen-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/templateScreen-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-18-1-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPad-10th-generation-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPad-18-1-en-GB.UI.png delete mode 100644 UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-16-en-GB.UI.png create mode 100644 UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/EncryptionResetUITests.swift b/UITests/Sources/EncryptionResetUITests.swift index 5bc5bea00d..6000b0d1c2 100644 --- a/UITests/Sources/EncryptionResetUITests.swift +++ b/UITests/Sources/EncryptionResetUITests.swift @@ -26,6 +26,9 @@ class EncryptionResetUITests: XCTestCase { // Confirm the intent to reset. app.buttons[A11yIdentifiers.encryptionResetScreen.continueReset].tap() app.buttons[A11yIdentifiers.alertInfo.primaryButton].tap() + + try await Task.sleep(for: .seconds(2.0)) + try await app.assertScreenshot(.encryptionReset, step: Step.passwordScreen) // Enter the password and submit. diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..582315f4a8 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67c559de04b481b370c3f02e4ad737403f393691cef4cb5ef9362a2946bc8adb +size 1298585 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..f9c2a670ca --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-0-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2129e9965746b2c46997831bfccfaf2ccc95d0a5a0087c14520cd33d910972c5 +size 948014 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..34d4bd11ba --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b16d8bffe575dbb20cd9ec78ef4750edcbbe75f7e9726771584b272935a1eff +size 107103 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..fb3006121a --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b32ae450f9873664aa7010f14bc5c32f764e7d8f2c8fb29c61b08342668ec820 +size 119196 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..6e8844768e --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ece1e4397aca92f8394aafdf7495ffeaaec3621bb31cc49cd5645e0b134f11f +size 108257 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..f4641cde63 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-2-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6eb0c25cd2a799a253b92f1b04b2a7b9cf7a734dc0f8b8610ad427d7b25ef48d +size 120307 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..8e2cc629d8 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:907d3be4bef23d70e41249c6b73006309822a8fb4a67e3b06382d2ee803392f3 +size 245970 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..a8449e1f76 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-3-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:991a0c6281fd3a7a280fb842b0adbcab4879a9bdbbdfba77d31dd6d751dafc49 +size 387057 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..b0a875906b --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:318cf076f437c24e2a878fcc4b5db1effb6f77c6ebe8a6a21e73657ef9315a0f +size 119247 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..8a1bdafe2d --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-4-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d38fd4080538033e0e56889cf375584b77e6045bb665f4db55362161b46f3af4 +size 134555 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 new file mode 100644 index 0000000000..565c1905d2 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:180743191fcf9af0de19525e3fa649e89cb24c9e5be1cd77b6da96272c71aa14 +size 66254 diff --git a/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..7a1721a541 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockFlow-99-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff7b6a42a6a36f2f9f717bc967bfd78d758fb3ce8b4a3d16220a2211fd24f61b +size 57129 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..8e24d84d47 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a9088fb4b320bdae5714e27ce37246287314086513751e4e295258110b7ef3a +size 152117 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..68f9ef1b05 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-0-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b84b3822271da60548b5377a15b691f29fe0342bdb1832ec2ca625e063f70fe +size 95862 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..7bd4df4f52 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3feacce0433a2c01983cece54991e07f900d4fcd1204293b7fbf086493744749 +size 151761 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..4b543334a0 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:69be9ad1028840f0647dd3bdf145792af5c71016083662954800660d9f705618 +size 95557 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..0309dcb73d --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c452ed8a368a75805d97ead98fd3b4121ac7ae6068ab2e07c7d099ab790bbb04 +size 154940 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..d387a52ab2 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-2-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71c33176495578537b76884e597b96d4b5f455f9501cc576c3536d7cda4b6c31 +size 93826 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 new file mode 100644 index 0000000000..029a8b6f81 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef84d325ff4f091c6e136f16416d90c3542ad358a70f08e4436ffd9946f5a999 +size 82486 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 new file mode 100644 index 0000000000..758394a12b --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-3-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7378f5adfd525aaee8a4ab42f2ed0cc98c54ca0a1c87faa9c61c5d1f824f960 +size 83655 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-4-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-4-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..fcee351985 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-4-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45c4fe3dea366978d7f5f2b2fdec5f4adc2b77eec2d9a06909aa93e0f9bdac98 +size 172282 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-5-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-5-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..091c79e6fc --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-5-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca28b102ed02b26d6136f28165d5859879a8def084c3e9312dfa6c80b63b20e8 +size 171874 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..83ca611ef8 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1246f8b0f5a56918a8a0dc11436fc44f981eece24b8876ebce1ef9922fd93d67 +size 64833 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..e1178f6617 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlow-99-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3648ac4fc1c98576a3516afdf280a37c00e44d0c4ee1519b849291c34660aef9 +size 56204 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..d74f5b63ff --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:29451cacdf506cf7fcb458bdb9dcc922bded3b655ad35a7334579d0477d92a48 +size 89891 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..7062050fad --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-0-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d385efc1e1bc3e2353a172a370e5c8d7c24016af24b657f1528b091593abc000 +size 90772 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..7fdcb524ef --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc04a1b65075e130ea2334746496f1547188b3e84c14608877aa6217f2a2d2d5 +size 89507 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..6fb1ea53bf --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e28519408070f07c0812f419476c56fe440c8effd9b9e5c491092259a29292b +size 90458 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..52e1293a50 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efbe245aca461954d911e0c67a81c684e390e1730ce4416964490c7ba8213a6e +size 96179 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..0560e34a44 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowMandatory-2-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a90145ce7432b3d17a33b640ed01676e7e2438f77bd46ae462343eb889edee34 +size 92579 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..3edccb7986 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a54d207472a94758bc5fb6c98dc99593176f6593c6ba8ae33890d8ba4b50507e +size 139710 diff --git a/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..8d12c66ca9 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/appLockSetupFlowUnlock-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79c998e7c0d5ce6fe9eb5c4040a0a59b0a0806a2ab710173db4c4785946076d6 +size 82753 diff --git a/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/authenticationFlow-1-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/authenticationFlow-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/authenticationFlow-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/authenticationFlow-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/authenticationFlow-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/authenticationFlow-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/authenticationFlow-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/authenticationFlow-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/authenticationFlow-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-0-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 918eeefe26..0000000000 --- a/UITests/Sources/__Snapshots__/Application/bugReport-0-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3d518ea2480d228493d083b4818cd472f7b5d62bfe03ade4dc35b9ace5486924 -size 136714 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 new file mode 100644 index 0000000000..9cd7690959 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/bugReport-0-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4513735733d5bd1cf618f5f698c05cf3bfc9e3f7e1d8d2f0f16f59473228b9d2 +size 137089 diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-16-en-GB.UI.png deleted file mode 100644 index 529429face..0000000000 --- a/UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:975c4e0a3ab5c1d872593840beaf796d9830909a50107ae7c7e2e0c81155b50a -size 172448 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 new file mode 100644 index 0000000000..b02a22a4cc --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/bugReport-0-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad2fdc22c0f151aac2550afc480759f8d944bf1dab858648c88482a19675b0d9 +size 172949 diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-2-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index bfd2c1adf8..0000000000 --- a/UITests/Sources/__Snapshots__/Application/bugReport-2-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:330f7ae4f3c6d771c91bf4bdc3a119a3ef694f1c7392b0445ed8772e2da89c67 -size 204376 diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-2-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-2-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..8521f366ea --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/bugReport-2-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b14d8fc973cf920445b2dbcda93908ced0bf2cd4ac4135e133a6bb6fbee7f00 +size 204746 diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-16-en-GB.UI.png deleted file mode 100644 index b3bc1b5cf0..0000000000 --- a/UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a53780ca00fdaf8e4e17df95dc15690bf06bc8d3f048086de6ecd5ea2d8ebde0 -size 195913 diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..3465967556 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/bugReport-2-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27f6ae4c920ade62e2c6078d16d3f6cf6c2988f76869a413d2b92a2a6ec0d497 +size 198666 diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-3-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-3-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 6853515c70..0000000000 --- a/UITests/Sources/__Snapshots__/Application/bugReport-3-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c439f48591ea77ac9e0cc9258eb258ba37f1ec196b6f8838106e9a073fe9a36b -size 208416 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 new file mode 100644 index 0000000000..b0e7f98397 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/bugReport-3-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea346e28081c79301e2787150a5107049307c89834d7fc42532dafd5b9fc93d5 +size 207252 diff --git a/UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-16-en-GB.UI.png deleted file mode 100644 index 9c36be7680..0000000000 --- a/UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b2b016c9771059f877be7d047763f903fbed45b266fe45929299d0b85b211913 -size 201273 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 new file mode 100644 index 0000000000..fa7e1a940a --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/bugReport-3-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0004b008911fb30aa37abe05843a068d52d627d95302cf77296cd2c1d410690 +size 201890 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-1-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 3fd6f850d3..0000000000 --- a/UITests/Sources/__Snapshots__/Application/createPoll-1-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6447671f7cfd17d4d01260e67f6770aaa5f00a67c5fae9fc158829289fa0314a -size 93714 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-1-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-1-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..bf89b8066f --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/createPoll-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:657524ca3ea9c08c5fc601a2a646f339567d2a8e8c7e6de57623de7a846afa7a +size 93651 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-16-en-GB.UI.png deleted file mode 100644 index fdab4b0e28..0000000000 --- a/UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:61d392b6ca3dfc9ba284eb116e6fe89abdfeedac6c07f002043f90c4ac84b519 -size 103354 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..7954a1a9a5 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/createPoll-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4fc263b4a8b497c869c6d16b98da492d1d51e30e7588144c9091279ae00b7cc +size 103936 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/createPoll-2-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-16-en-GB.UI.png deleted file mode 100644 index 93ccc4de59..0000000000 --- a/UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a0bbe1b3187af8bccef12d15dd89e4aa4529d047a77b516750052a863645fefa -size 310986 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 new file mode 100644 index 0000000000..a62fa153ae --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/createPoll-2-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8be3fb5f322bd4028ce149fd51c28a86cb60e78cca8962b375a0c37819d87844 +size 315126 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 53b9e1d12c..0000000000 --- a/UITests/Sources/__Snapshots__/Application/createPoll-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:92678bbd82c099ef562933fb106c22c0416ea8fb7bd4f36e62db0ec09fc80c80 -size 100325 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 new file mode 100644 index 0000000000..3635ba5185 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/createPoll-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62bfb31ceedb4a68fd7be3a1ba02b62de8c424bce5bc47326c55e746018a6ef7 +size 100266 diff --git a/UITests/Sources/__Snapshots__/Application/createPoll-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createPoll-iPhone-16-en-GB.UI.png deleted file mode 100644 index 5980cebc65..0000000000 --- a/UITests/Sources/__Snapshots__/Application/createPoll-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b79b01da90a0d7ce3a5d6c1dc6de6d395084176de3e55fb88dc9f3e54bcae942 -size 113630 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 new file mode 100644 index 0000000000..0df96ed7aa --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/createPoll-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d3d1e04abea59afd29cbe35b09ccc0f52e6e53dd4dbb60200460b9d4dd140dc9 +size 113207 diff --git a/UITests/Sources/__Snapshots__/Application/createRoom-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoom-1-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 8ae26267ca..0000000000 --- a/UITests/Sources/__Snapshots__/Application/createRoom-1-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c41e07b1476f8742d3d0bf6eb63bf03942715d40437082b9a3c6cb322742e860 -size 136314 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 new file mode 100644 index 0000000000..745e3b3d0e --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/createRoom-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8864c6394f1b76a8bd23e6082d91028d540ac921395de23e3e3259f95f0b7a89 +size 137279 diff --git a/UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-16-en-GB.UI.png deleted file mode 100644 index 8e531cb362..0000000000 --- a/UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2616b3ce1d12360d6c2d151d0647989bdd1ee452ea2efa6c7a24c25e8382c136 -size 167378 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 new file mode 100644 index 0000000000..d491194b7e --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/createRoom-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e5d2f5b6d9d011f562b14a4cdf1e7aba531dc021c791a85d3f87a3179fb3fa5 +size 169105 diff --git a/UITests/Sources/__Snapshots__/Application/createRoom-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoom-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 971eb34596..0000000000 --- a/UITests/Sources/__Snapshots__/Application/createRoom-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8e0ace29cb70b56c0a4b23a44fa2a019036a6c29b8e5fcf5e72aa04c1e9cfeaa -size 138956 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 new file mode 100644 index 0000000000..13d32967c3 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/createRoom-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2176064b78a69e98258825bba091872ea1067f5c64de31d7085a6c8838079f01 +size 141319 diff --git a/UITests/Sources/__Snapshots__/Application/createRoom-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoom-iPhone-16-en-GB.UI.png deleted file mode 100644 index 6a134b2a74..0000000000 --- a/UITests/Sources/__Snapshots__/Application/createRoom-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:40a328061699a3e9435f799bf20b009eaa48f66f6028037804f0435b16501fd5 -size 172709 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 new file mode 100644 index 0000000000..826b183c40 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/createRoom-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c44af2a13202b66ade79afb7047638280744d487f39b096ae947a35e4e11165 +size 174442 diff --git a/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 3cc86974e6..0000000000 --- a/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7be6325cac7408df468f547a3cc1ef241c24efb652160fde4150e97109b2753c -size 119761 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 new file mode 100644 index 0000000000..f5eeb8955b --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b927cde4aeaf48a0e9305d083c371dc3e29e5ce3751ebe15deea73087963c8fa +size 122104 diff --git a/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-16-en-GB.UI.png deleted file mode 100644 index 4bfa63870e..0000000000 --- a/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9ab4ce7eee2d029601e4d45b92aaac783df97a9b3ecb80b208a3d9cb2e9a1ce0 -size 144339 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 new file mode 100644 index 0000000000..ff9c3de51b --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/createRoomNoUsers-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77c3d1f0c3f779a35f5551afaf663540921598a642d9870f08f77e5b89696d85 +size 146875 diff --git a/UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPhone-16-en-GB.UI.png deleted file mode 100644 index 70d68529b1..0000000000 --- a/UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e9dfc381ac69b5e415c4bdf05175ceb6df08cec2db54f3f4b02172eda1f6dd64 -size 162470 diff --git a/UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..a4312362c9 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/encryptionReset-0-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:98b359d5f3e5d21c8a2002a26c5a31e905b6523def3b8f46a50bbb78090c0f5b +size 163462 diff --git a/UITests/Sources/__Snapshots__/Application/encryptionReset-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionReset-1-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionReset-1-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionReset-1-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionReset-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionReset-1-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionReset-1-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionReset-1-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionReset-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionReset-2-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionReset-2-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionReset-2-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionReset-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionReset-2-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionReset-2-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionReset-2-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPhone-16-en-GB.UI.png deleted file mode 100644 index 72cb8d5020..0000000000 --- a/UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9c7753ecb9a032c14ac1b53ec94dfaf055da89c3d053b0dd095b15b291129730 -size 141912 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 new file mode 100644 index 0000000000..7149f053b2 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/encryptionSettings-0-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cfb972eed3d11d9ebe4e13f106e4add77b44c928a8df5f140334a28b157a9de5 +size 142884 diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-1-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-1-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-1-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-1-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-1-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-1-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-2-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-2-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-2-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-2-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-2-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-2-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-3-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-3-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-3-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-3-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-3-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-3-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-3-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-3-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-4-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-4-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-4-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-4-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-4-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-4-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-4-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-4-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-5-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-5-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-5-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-5-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-5-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-5-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-5-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-5-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-6-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-6-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-6-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-6-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/encryptionSettings-6-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/encryptionSettings-6-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/encryptionSettings-6-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/encryptionSettings-6-iPhone-18-1-en-GB.UI.png 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 new file mode 100644 index 0000000000..f4d5dee0af --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a3cddf27c919a33e268efbc56584e069848b9b8d773bcbce30b8bf9ec56f460 +size 323389 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 new file mode 100644 index 0000000000..612652406f --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-0-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f2b1bb7cd121631f9064509e6d7be090abd62c5a4afb09d083ab0b33d67a355 +size 329861 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 new file mode 100644 index 0000000000..0d626f39e6 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25540c75506376d5fbeb195541710ea0c33a68150fcb316c309aa74dc0535d76 +size 328838 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 new file mode 100644 index 0000000000..c8ddc5e371 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutBottom-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d9f2ef1657b0af2a483f2ebfcce728ceb0df29f2ac38f1f67f1a794b54e6130f +size 317795 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 new file mode 100644 index 0000000000..2aa6e0a8a3 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c767089cde753c220be4155f44f5a80596ee2b12d452665e65d1310c2f2782a +size 232850 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 new file mode 100644 index 0000000000..292642f97e --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomLayoutHighlight-0-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f5a0569910e56f38be84e6d14bc721d5ab09ac90229a46eccbadcf54b2b88eec +size 326819 diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomLayoutTop-iPhone-18-1-en-GB.UI.png 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 new file mode 100644 index 0000000000..4e9abf67b7 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45e3a2173dc9b142b62c0209823c6d7fb1cfd15d9cfe93d54698ed654151e3ce +size 74611 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 new file mode 100644 index 0000000000..a44af6322a --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a260107ff9eab5f8efdc2a83225b48730fcb1d5526321a37fbe00c622adbd29 +size 72978 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 new file mode 100644 index 0000000000..61a5643d77 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eceaa9d579094a7fb6678fac242359dd9aedfdf362f149ccf5ce3f06b819ddd0 +size 74151 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 new file mode 100644 index 0000000000..d308a5382b --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-2-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:43ac02669327b7810031808e01159734dab7076a5c0cd5bdfabd69b3e9e9b1fd +size 71605 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 new file mode 100644 index 0000000000..018237d628 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf3e8b383f3e59aab88fe5872c6ac1e9b75079999246c255443f50b4f8a8e257 +size 97711 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 new file mode 100644 index 0000000000..9f5fc4ba47 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomMembersListScreenPendingInvites-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b5c5a6c6e4324308a23cd68ac4a8ffa16703ad7c4a2eb993f6a6b39850ee259d +size 107464 diff --git a/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index c97d2da1b6..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a48bca99e1534738c818eb248917411f13faac77ae71ab0870cba794a77af6e9 -size 292335 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 new file mode 100644 index 0000000000..5a3e67c0b4 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c68739d109d5bb560a60bed2bc20dab57c0f09324e52c63f9a732423d684e79 +size 292066 diff --git a/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-16-en-GB.UI.png deleted file mode 100644 index ef5bf35dd4..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5eb3e3ca8c28ba9f1e4fcd5b7dcf30d162a98ec3cf8539bb8e60ac8802928bf7 -size 369833 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 new file mode 100644 index 0000000000..2c15481ece --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomPlainNoAvatar-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d93c86fe9c295fe9cc8b9c8fffb0768211a63c75de990aba029cf64a386789a +size 370242 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..20a5793ed0 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e015006857411aae9ba920db2297bfd789d2edc6b7303ac0d11d513fd7eb494b +size 113558 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..8474c40e3e --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-0-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5cba14eb68f298db207b5d2cd860669878ba39672a3c64fe888d5dbf8306dbff +size 133186 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 new file mode 100644 index 0000000000..55ff85893b --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3c22b8ccc407b58b26c4ccc8652a9ceb3dca67bebf00df27cc2b1fc47ab8e16 +size 193781 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 new file mode 100644 index 0000000000..3b993d967c --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8028502d3db47f9c64e2aba1a9a08a62de878853a6e967953c3599e0171dede9 +size 222509 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 new file mode 100644 index 0000000000..7050aa564f --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b39b803f6063e112d1d4666efad916821fd4f6dc93ea96d1ddc72b7a5b0f347a +size 187175 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 new file mode 100644 index 0000000000..c13deb9596 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-2-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d48281b6ed613203ff01f454558546603e9d7d43436481ee873fe36888bfcc1f +size 194702 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..3d6d49c3f2 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4fb3c0ae057a6d0d93aeff3e545d507c02e00c7a48ff91662e1a2b962346f047 +size 119860 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..05c64f2f69 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-3-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7dbf4941aa6cfd1f434dcea77c909f8371518c1fa6d9a57220137612efe5102f +size 135878 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..1c0f382515 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e95ecb045b7e88a1598fde5acce674d52f33ac6f76f9453959c230d479fb980 +size 101618 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..2b8bd25a97 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-4-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7186a444f24f39e56a6479635c52b02583e69f871f395f3c7c5bdc2b621ff65 +size 111038 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..c22af0ec3c --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7775d30af00a992d473ae2691765427442f8a793a3a6375d65188b928c29c9ac +size 116678 diff --git a/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..b124427ca2 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomRolesAndPermissionsFlow-5-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:92860ccd5b1d1bf4127d26cd1c5aeb5f9868566b5d078661eb0865c6ca48b1d5 +size 130468 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 30bd79d5b0..0000000000 --- a/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:487241ee65b911df1aee81bfa44dadb391fa00934033917aeb848c6e1d6eaa5f -size 109509 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 new file mode 100644 index 0000000000..c754293037 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e95f468f417f14e84c2d91253d06fec9058b188fead7841975faeb30b59d62d +size 110487 diff --git a/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomSmallTimeline-iPhone-18-1-en-GB.UI.png 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 new file mode 100644 index 0000000000..26adee6218 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a0011a448b569a6a143de24296b3cf2559fdb485237cc143563bb7f2c9b0798 +size 133652 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 new file mode 100644 index 0000000000..9ad65331e0 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineIncomingAndSmallPagination-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7816944b84404a010641d131a766b06a8bddab609204ebb58b9b8f13e94562e +size 216901 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 new file mode 100644 index 0000000000..4ca9322f85 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46a30b63dd8fe655bdd33f2d9d4d2d638bc62f5ddea1d2fddc168b07cf9775d9 +size 330970 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 new file mode 100644 index 0000000000..26e12acc16 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineLargePagination-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a083dfcee55c1be624d228589a041712b8d8f5669bd167fefb92aa8e203a6a4 +size 342283 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 new file mode 100644 index 0000000000..0430561c19 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44d8f128567adb45ddba5e30b181184641c2818498af165aa9135139b5eed891 +size 131897 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 new file mode 100644 index 0000000000..1313e8699d --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/roomSmallTimelineWithReadReceipts-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd37d5f0deee1e90a8fe2e1de121503e522de43cebd407eaad5da19b6f5adf37 +size 212425 diff --git a/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomWithDisclosedPolls-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomWithOutgoingPolls-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/roomWithUndisclosedPolls-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index dc09fb8c88..0000000000 --- a/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:56c5eef68d4fbc9ff878efb77940dbdf6d088b117a4902f23c997bac4dc3eeda -size 103993 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 new file mode 100644 index 0000000000..a1ed7d76ad --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f10c10b83869bd9dcab608f3b234270a0dc062ba6937519852f53a6d3c9d2d07 +size 105094 diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-0-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/serverSelection-0-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/serverSelection-0-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 1dae430747..0000000000 --- a/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:189edb922c5409a11b14638e7f7dab4fc48e7dd270a256b55f59e00c238812a9 -size 176925 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 new file mode 100644 index 0000000000..1f1e01833a --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aeaf5705a6f473df0bcd6a0fc0f8c6468167bf7ca127d115d7b66fc3a8a41e42 +size 176945 diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-16-en-GB.UI.png deleted file mode 100644 index 0c134c0319..0000000000 --- a/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d6fb61933ade921e10beec051261fb7d194bd59e69729345c213a1220c4a0fb1 -size 179444 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 new file mode 100644 index 0000000000..3454a2e75d --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/serverSelection-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c565f358656384dddde59f62ee5485730d610a4d3642a77f1e3c9193ce0d4164 +size 179685 diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-2-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/serverSelection-2-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/serverSelection-2-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/serverSelection-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/serverSelection-2-iPhone-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/serverSelection-2-iPhone-16-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/serverSelection-2-iPhone-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 3e66ca2c58..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e99fc8db5cc8c6b19986913f62b22479ce8279d5822c16d51eeb0de07d37fd6c -size 91224 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 new file mode 100644 index 0000000000..1d64e09494 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57bb3ef3d039c2017d8bb6a7c9953b0f171d636544c9580668a0de1ff64eebe1 +size 92312 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-16-en-GB.UI.png deleted file mode 100644 index 72cadef058..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2b1e81541dbc3fadce76438542cc6f49b8315b0c5e66e60d435ecdc0deccd24a -size 94106 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..d35968b6e9 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-0-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef1d4a39d181b7f9c52ee41c5edf82b69b4a9a7902cc23179c06b83e3cb9df17 +size 94456 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index aaf17fd84a..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c38f676abce80dd515607cc5f894c5d4848f35d6225a54235d733fdb2061251d -size 88120 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 new file mode 100644 index 0000000000..586f2fcfc7 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f00671f198ade30eabc3447ad8385a2ba59001e739b62765753c9187a5d867c +size 89264 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-16-en-GB.UI.png deleted file mode 100644 index e50945997d..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a411e0410bfaea1668c813590141b1ed710ce4ffc710df372f29029235dda33b -size 91531 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..5e88cbe847 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e42a7ed539357127101ee4e28f93110c1261cc6fc2bf433e09e7d5610bdfc2c4 +size 91895 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index caa1abedb8..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8dcd756e7e80c4a8d49f542083b672a713068fdc12914d923fc10bb7d936aa4b -size 83046 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 new file mode 100644 index 0000000000..3c8fdb5a18 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9cd59cc028d74b4a4357483c1cb3ff73a4d3d5add61994ce30c91003943a305 +size 84163 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-16-en-GB.UI.png deleted file mode 100644 index 50591c6d31..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:26f50b02c39447b506edcceaa7cfba115bc594a727e3d51e600859f6d6f6e248 -size 82600 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..cbcabaa0a1 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-2-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd2522bdd450b1aa60c38687859dccadbee3d149b2e63a6f51cc58a2250f307a +size 82959 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 34bb09c21a..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:56c987c9acf140105a08e34fcebdec9827befd8b2d13100115d7a532fb33a082 -size 63514 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 new file mode 100644 index 0000000000..da0f3a4788 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5fc095ecf4181b2fff162ef5d467008de764cc2025dde1046ef872cf6ce80e36 +size 64615 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-16-en-GB.UI.png deleted file mode 100644 index 63d68fbc2b..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6689e6832ccdc6e608d8c64aba0bb9f400afa8cde98b3bf2a127b51fc6701555 -size 55165 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..ec9ed5e3ff --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-3-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:abdea86b06e1d4dfba71a38e79ff81475163fb3fc7a361c670b6f59897e42c5e +size 55560 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 69dadd20f1..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f7377e97c8da85ed52887c06816fb0ae445a241c89bf857fe92b40546533f8bd -size 146619 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 new file mode 100644 index 0000000000..2b6cd16c85 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ead3eef56f6049cf3842109963655b09a82640de3eae21f8a2cefd0a4fd3df4b +size 147648 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-16-en-GB.UI.png deleted file mode 100644 index 5eb62cb390..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f3c5b416699192346ab3a9c1d03e44eeacd06f52d277e6a36730a5adba604559 -size 199057 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..4034390641 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-4-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b394f04e05d85bd262ae341b014ed29cc8a9701445f1e42b546998e558b20a4 +size 199507 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-16-en-GB.UI.png deleted file mode 100644 index 2c95e43d7a..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fb0841f55e5958348cc279f0ae20dffc3a29526731a277e216764aef04451de5 -size 196081 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..00204cbf8e --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-5-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:98df840c92f8bd5fa6ae10e5ead7a74e95edf5947ef90aa495e03888d7e3043a +size 196453 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-16-en-GB.UI.png deleted file mode 100644 index 4593e46a3f..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b8aa9b54c86da44cb8b7e0b86f7cdca862b7bfadb1c05e10ae8c2385e20a46b6 -size 84619 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..8300267ff4 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-6-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:347d58e216ccac261b4af480349ed0249c28edd863ca6b6d7625e6d042e7b8f8 +size 85014 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPad-18-1-en-GB.UI.png similarity index 100% rename from UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPad-10th-generation-en-GB.UI.png rename to UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPad-18-1-en-GB.UI.png diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-16-en-GB.UI.png deleted file mode 100644 index ce3c4e2d9b..0000000000 --- a/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:04d11a84c66697b8ce469ef1b8032e409015c844e1b5ed1e5e9ee5e457e0d1e3 -size 85177 diff --git a/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..79001f01c2 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/sessionVerification-7-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9061b8277f48df1f48ba24a28d03d6d7350053259ad44223c30ec8b091b67bfb +size 85540 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-1-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-1-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index b280408837..0000000000 --- a/UITests/Sources/__Snapshots__/Application/startChat-1-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ff9bd2451f91fa34af70ef1768819b8d46b3f340f2c0e050abcf16f0f29dc855 -size 71686 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 new file mode 100644 index 0000000000..d958b67e27 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/startChat-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88e8193b05536f647a147f2cc206d2266fe6783373bff80d4854b149f23c3f0b +size 71653 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-16-en-GB.UI.png deleted file mode 100644 index 1ea911311c..0000000000 --- a/UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e51ff6e6eb0c9a28c13a98ebe2cdc1f572096e10d64fb73f16730eb6313daeed -size 66798 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 new file mode 100644 index 0000000000..762d405983 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/startChat-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0892b6f31d8b6b1bde00cf0deb9e5717d7d029e50a5d05ff1d9427ad1c3aebf8 +size 66914 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-2-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-2-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 2ec52963e2..0000000000 --- a/UITests/Sources/__Snapshots__/Application/startChat-2-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0a5bbf4ff2af17c69ef43386e6d6283be02fd4a8b6edb80cb31f6e1230317c08 -size 85586 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 new file mode 100644 index 0000000000..55b64b6654 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/startChat-2-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca3610ee7a4e07c97e346a7b2ce4e88f1f133643751281c98694433a80c9cb3d +size 85526 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-16-en-GB.UI.png deleted file mode 100644 index a13ada6fbb..0000000000 --- a/UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f6a0ee0267849ea50a0efd156bca1a7df4d4904c64110857581f9ce4f05543e5 -size 86207 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 new file mode 100644 index 0000000000..434f7a7007 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/startChat-2-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5c2b8283fb54af48fad4f860077f0a36326660f3f646f8d78f2012bd27cdaee +size 86290 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index fac42e2fe3..0000000000 --- a/UITests/Sources/__Snapshots__/Application/startChat-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2c6df5f8389eef25dd4ad323a05df5db1f023b96aa9995011d76c97e54143bfb -size 82083 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 new file mode 100644 index 0000000000..83528b0e54 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/startChat-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e46a8df777fe9496fa53e43d45d6fd812b6fb813767e38da512e58d3c1ff8a6 +size 82066 diff --git a/UITests/Sources/__Snapshots__/Application/startChat-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/startChat-iPhone-16-en-GB.UI.png deleted file mode 100644 index 33b763d7b2..0000000000 --- a/UITests/Sources/__Snapshots__/Application/startChat-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4526f1d4956abbf17a55947462083e4b2b01ea80fea9f3adbb35b85fd7c9f20e -size 82387 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 new file mode 100644 index 0000000000..4e6b7c19a4 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/startChat-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:875c6e4d9f5202a13b6396d067c4272c3df21603f5baf593fe21f46c651008f8 +size 83293 diff --git a/UITests/Sources/__Snapshots__/Application/templateScreen-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/templateScreen-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index e41bb042ee..0000000000 --- a/UITests/Sources/__Snapshots__/Application/templateScreen-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ff9d01a6e461218c1d51b4a5b9184cbb00cb0cc12ad139cc6640b8698d0a3388 -size 72741 diff --git a/UITests/Sources/__Snapshots__/Application/templateScreen-iPad-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/templateScreen-iPad-18-1-en-GB.UI.png new file mode 100644 index 0000000000..3d0eaff0c4 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/templateScreen-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a08af0ee7b494b7d1d3932141c743d1e0700e4cbb734fb66abd72696472bf12 +size 72787 diff --git a/UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-16-en-GB.UI.png deleted file mode 100644 index 23639697d9..0000000000 --- a/UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7636d6a53f1bc918c5ce39fd8cc7bd473e0b9e69f4640f133c861d118a658c64 -size 70324 diff --git a/UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-18-1-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-18-1-en-GB.UI.png new file mode 100644 index 0000000000..c193b9c376 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/templateScreen-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:569e5ddc8cc188045103a62124f65f1ad550ee8b52b9d0f56b3692d00497dca3 +size 70422 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 new file mode 100644 index 0000000000..0ad0f4e475 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b705d6bf2dfe32cd18751f7a72c524047face164c63faf7d0e276f4097aabe0 +size 316315 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 new file mode 100644 index 0000000000..73ca50197e --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-1-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4cb185b178ebb46a41234ae11723446627393ecc1022f52f0ce72c3adb0a363 +size 299987 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 new file mode 100644 index 0000000000..e4dd9086d8 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ab055b4aed25baff5715521523bbebd9bf91d563914ebcca885b15a8f6a98de +size 461977 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 new file mode 100644 index 0000000000..5f12a52f95 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-2-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:deddf48697d6fa5f8ff44e54ef41201accf59de271aaa092ef2af20e3a94cd63 +size 346116 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 new file mode 100644 index 0000000000..b48dad3f22 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ede54c8caf251097eacab4da82359978233aeb7f9cc5c9e4024894ede70dcf77 +size 746883 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 new file mode 100644 index 0000000000..3c527200c2 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreen-3-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16e3b6828475d9263b50bddca1b124c0f667ffeb14ad918e259ff0c3b6a8ade0 +size 869012 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPad-10th-generation-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPad-10th-generation-en-GB.UI.png deleted file mode 100644 index 2c60f79341..0000000000 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPad-10th-generation-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:709a17b15a259e2383b97b885597f2815fae10ac81867e78b4de95eb9e23f96d -size 461940 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 new file mode 100644 index 0000000000..ffb38ecef4 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPad-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0bbe68370f35930d0c2cb1fb3f739cbab8d8f1c095e22e1ac5cd605327ede89 +size 461903 diff --git a/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-16-en-GB.UI.png b/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-16-en-GB.UI.png deleted file mode 100644 index a4ca218e2e..0000000000 --- a/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-16-en-GB.UI.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0870e0bfa1c8b07a56f03103ed5a1ba4e6a54474c956299f9de5d618fbf4f2aa -size 333096 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 new file mode 100644 index 0000000000..40307c846b --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/userSessionScreenReply-iPhone-18-1-en-GB.UI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ea90452a2924f7872bd307dfbf7aa10bdf772758bf74171ade7b5bc5cb20e36 +size 334104 diff --git a/fastlane/Fastfile b/fastlane/Fastfile index c27dc3e3cb..cd4d3b3e28 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -107,13 +107,13 @@ end lane :ui_tests do |options| create_simulator_if_necessary( - name: "iPhone 16 (18.1)", + name: "iPhone-18.1", type: "com.apple.CoreSimulator.SimDeviceType.iPhone-16", runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-1" ) create_simulator_if_necessary( - name: "iPad (10th generation) (18.1)", + name: "iPad-18.1", type: "com.apple.CoreSimulator.SimDeviceType.iPad-10th-generation", runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-1" ) @@ -128,7 +128,7 @@ lane :ui_tests do |options| run_tests( scheme: "UITests", - devices: ["iPhone 16 (18.1)", "iPad (10th generation) (18.1)"], + devices: ["iPhone-18.1", "iPad-18.1"], ensure_devices_found: true, prelaunch_simulator: true, result_bundle: true, @@ -143,7 +143,7 @@ lane :integration_tests do clear_derived_data() create_simulator_if_necessary( - name: "iPhone 16 Pro (18.1)", + name: "iPhone-18.1", type: "com.apple.CoreSimulator.SimDeviceType.iPhone-16-Pro", runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-1" ) @@ -152,7 +152,7 @@ lane :integration_tests do run_tests( scheme: "IntegrationTests", - device: "iPhone 16 Pro (18.1)", + device: "iPhone-18.1", ensure_devices_found: true, result_bundle: true, reset_simulator: reset_simulator From 7e192b757170423ac22ac2ed2ed65177b303f3d5 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 14 Nov 2024 18:33:37 +0200 Subject: [PATCH 22/74] Enable local echoes for media uploads on development builds. (#3514) * Enable local echoes for media uploads on development builds. * Use media sizes when loading timeline items so they can take advantage of the cached local echo data. --- .../MediaUploadPreviewScreenViewModel.swift | 16 +++- .../ImageRoomTimelineView.swift | 57 ++++++----- .../StickerRoomTimelineView.swift | 3 +- .../VideoRoomTimelineView.swift | 5 +- .../Fixtures/RoomTimelineItemFixtures.swift | 10 +- .../ImageRoomTimelineItemContent.swift | 9 +- .../VideoRoomTimelineItemContent.swift | 10 +- .../Items/Other/StickerRoomTimelineItem.swift | 3 +- .../RoomTimelineItemFactory.swift | 94 ++++++++++++++----- .../Services/Timeline/TimelineProxy.swift | 10 +- ...est_imageRoomTimelineView-iPad-en-GB.1.png | 4 +- ...st_imageRoomTimelineView-iPad-pseudo.1.png | 4 +- ...mageRoomTimelineView-iPhone-16-en-GB.1.png | 4 +- ...ageRoomTimelineView-iPhone-16-pseudo.1.png | 4 +- 14 files changed, 149 insertions(+), 84 deletions(-) diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift index d1610f673f..cca94f2cc3 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift @@ -45,9 +45,9 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, switch viewAction { case .send: Task { - let progressSubject = CurrentValueSubject(0.0) + let progressSubject = AppSettings.isDevelopmentBuild ? nil : CurrentValueSubject(0.0) - startLoading(progressPublisher: progressSubject.asCurrentValuePublisher()) + startLoading(progressPublisher: progressSubject?.asCurrentValuePublisher()) switch await mediaUploadingPreprocessor.processMedia(at: url) { case .success(let mediaInfo): @@ -75,7 +75,7 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, // MARK: - Private - private func sendAttachment(mediaInfo: MediaInfo, progressSubject: CurrentValueSubject) async -> Result { + private func sendAttachment(mediaInfo: MediaInfo, progressSubject: CurrentValueSubject?) async -> Result { let requestHandle: ((SendAttachmentJoinHandleProtocol) -> Void) = { [weak self] handle in self?.requestHandle = handle } @@ -94,10 +94,16 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, private static let loadingIndicatorIdentifier = "\(MediaUploadPreviewScreenViewModel.self)-Loading" - private func startLoading(progressPublisher: CurrentValuePublisher) { + private func startLoading(progressPublisher: CurrentValuePublisher?) { + let progress: UserIndicator.Progress = if let progressPublisher { + .published(progressPublisher) + } else { + .indeterminate + } + userIndicatorController.submitIndicator( UserIndicator(id: Self.loadingIndicatorIdentifier, - type: .modal(progress: .published(progressPublisher), interactiveDismissDisabled: false, allowsInteraction: true), + type: .modal(progress: progress, interactiveDismissDisabled: false, allowsInteraction: true), title: L10n.commonSending, persistent: true) ) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift index 63cb9b04ef..2047c0ccef 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift @@ -17,19 +17,12 @@ struct ImageRoomTimelineView: View { var body: some View { TimelineStyler(timelineItem: timelineItem) { VStack(alignment: .leading, spacing: 4) { - LoadableImage(mediaSource: source, - mediaType: .timelineItem, - blurhash: timelineItem.content.blurhash, - mediaProvider: context.mediaProvider) { - placeholder - } - .timelineMediaFrame(height: timelineItem.content.height, - aspectRatio: timelineItem.content.aspectRatio) - .accessibilityElement(children: .ignore) - .accessibilityLabel(L10n.commonImage) - // This clip shape is distinct from the one in the styler as that one - // operates on the entire message so wouldn't round the bottom corners. - .clipShape(RoundedRectangle(cornerRadius: hasMediaCaption ? 6 : 0)) + loadableImage + .accessibilityElement(children: .ignore) + .accessibilityLabel(L10n.commonImage) + // This clip shape is distinct from the one in the styler as that one + // operates on the entire message so wouldn't round the bottom corners. + .clipShape(RoundedRectangle(cornerRadius: hasMediaCaption ? 6 : 0)) if let attributedCaption = timelineItem.content.formattedCaption { FormattedBodyText(attributedString: attributedCaption, @@ -44,15 +37,32 @@ struct ImageRoomTimelineView: View { } } - var source: MediaSourceProxy { - guard timelineItem.content.contentType != .gif, let thumbnailSource = timelineItem.content.thumbnailSource else { - return timelineItem.content.source + @ViewBuilder + private var loadableImage: some View { + if timelineItem.content.contentType == .gif { + LoadableImage(mediaSource: timelineItem.content.source, + mediaType: .timelineItem, + blurhash: timelineItem.content.blurhash, + size: timelineItem.content.size, + mediaProvider: context.mediaProvider) { + placeholder + } + .timelineMediaFrame(height: timelineItem.content.thumbnailSize?.height, + aspectRatio: timelineItem.content.aspectRatio) + } else { + LoadableImage(mediaSource: timelineItem.content.thumbnailSource ?? timelineItem.content.source, + mediaType: .timelineItem, + blurhash: timelineItem.content.blurhash, + size: timelineItem.content.thumbnailSize ?? timelineItem.content.size, + mediaProvider: context.mediaProvider) { + placeholder + } + .timelineMediaFrame(height: timelineItem.content.thumbnailSize?.height ?? timelineItem.content.size?.height, + aspectRatio: timelineItem.content.thumbnailAspectRatio ?? timelineItem.content.aspectRatio) } - - return thumbnailSource } - - var placeholder: some View { + + private var placeholder: some View { Rectangle() .foregroundColor(timelineItem.isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming) .opacity(0.3) @@ -100,8 +110,8 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview { sender: .init(id: "Bob"), content: .init(filename: "Blurhashed.jpg", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/gif"), - thumbnailSource: nil, aspectRatio: 0.7, + thumbnailSource: nil, blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW", contentType: .gif))) @@ -115,10 +125,9 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview { content: .init(filename: "Blurhashed.jpg", caption: "This is a great image 😎", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), - thumbnailSource: nil, - width: 50, - height: 50, + size: .init(width: 50, height: 50), aspectRatio: 1, + thumbnailSource: nil, blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW", contentType: .gif))) } diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift index 65f155f53a..c0f4480ede 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift @@ -17,10 +17,11 @@ struct StickerRoomTimelineView: View { LoadableImage(url: timelineItem.imageURL, mediaType: .timelineItem, blurhash: timelineItem.blurhash, + size: timelineItem.size, mediaProvider: context.mediaProvider) { placeholder } - .timelineMediaFrame(height: timelineItem.height, + .timelineMediaFrame(height: timelineItem.size?.height, aspectRatio: timelineItem.aspectRatio) .accessibilityElement(children: .ignore) .accessibilityLabel("\(L10n.commonSticker), \(timelineItem.body)") diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift index 27b0ddd69e..ea072fda76 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift @@ -18,7 +18,7 @@ struct VideoRoomTimelineView: View { TimelineStyler(timelineItem: timelineItem) { VStack(alignment: .leading, spacing: 4) { thumbnail - .timelineMediaFrame(height: timelineItem.content.height, + .timelineMediaFrame(height: timelineItem.content.thumbnailSize?.height, aspectRatio: timelineItem.content.aspectRatio) .accessibilityElement(children: .ignore) .accessibilityLabel(L10n.commonVideo) @@ -45,6 +45,7 @@ struct VideoRoomTimelineView: View { LoadableImage(mediaSource: thumbnailSource, mediaType: .timelineItem, blurhash: timelineItem.content.blurhash, + size: timelineItem.content.thumbnailSize, mediaProvider: context.mediaProvider) { imageView in imageView .overlay { playIcon } @@ -114,8 +115,8 @@ struct VideoRoomTimelineView_Previews: PreviewProvider, TestablePreview { content: .init(filename: "Blurhashed.mp4", duration: 23, source: nil, - thumbnailSource: nil, aspectRatio: 0.7, + thumbnailSource: nil, blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW"))) VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .randomEvent, diff --git a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift index cf77fa6da9..79b9eace51 100644 --- a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift +++ b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift @@ -260,10 +260,9 @@ enum RoomTimelineItemFixtures { content: .init(filename: "video.mp4", duration: 100, source: .init(url: .picturesDirectory, mimeType: nil), - thumbnailSource: .init(url: .picturesDirectory, mimeType: nil), - width: 1920, - height: 1080, + size: .init(width: 1920, height: 1080), aspectRatio: 1.78, + thumbnailSource: .init(url: .picturesDirectory, mimeType: nil), blurhash: "KtI~70X5V?yss9oyrYs:t6")), ImageRoomTimelineItem(id: .randomEvent, timestamp: "10:47 am", @@ -274,10 +273,9 @@ enum RoomTimelineItemFixtures { sender: .init(id: ""), content: .init(filename: "image.jpg", source: .init(url: .picturesDirectory, mimeType: nil), - thumbnailSource: nil, - width: 5120, - height: 3412, + size: .init(width: 5120, height: 3412), aspectRatio: 1.5, + thumbnailSource: nil, blurhash: "KpE4oyayR5|GbHb];3j@of")) ] } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift index 01eb841510..4bf326422e 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift @@ -15,10 +15,13 @@ struct ImageRoomTimelineItemContent: Hashable { /// The original textual representation of the formatted caption directly from the event (usually HTML code) var formattedCaptionHTMLString: String? let source: MediaSourceProxy - let thumbnailSource: MediaSourceProxy? - var width: CGFloat? - var height: CGFloat? + var size: CGSize? var aspectRatio: CGFloat? + + let thumbnailSource: MediaSourceProxy? + var thumbnailSize: CGSize? + var thumbnailAspectRatio: CGFloat? + var blurhash: String? var contentType: UTType? } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift index 0790970edf..ff9ea5aa85 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift @@ -15,11 +15,15 @@ struct VideoRoomTimelineItemContent: Hashable { /// The original textual representation of the formatted caption directly from the event (usually HTML code) var formattedCaptionHTMLString: String? let duration: TimeInterval + let source: MediaSourceProxy? - let thumbnailSource: MediaSourceProxy? - var width: CGFloat? - var height: CGFloat? + var size: CGSize? var aspectRatio: CGFloat? + + let thumbnailSource: MediaSourceProxy? + var thumbnailSize: CGSize? + var thumbnailAspectRatio: CGFloat? + var blurhash: String? var contentType: UTType? } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift index 8c64723186..be7613d56e 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift @@ -19,8 +19,7 @@ struct StickerRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable { let imageURL: URL - var width: CGFloat? - var height: CGFloat? + var size: CGSize? var aspectRatio: CGFloat? var blurhash: String? diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index f2794fbf47..13be1ddd38 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -121,11 +121,16 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { _ imageInfo: ImageInfo, _ imageURL: URL, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { - var aspectRatio: CGFloat? - let width = imageInfo.width.map(CGFloat.init) - let height = imageInfo.height.map(CGFloat.init) - if let width, let height, width > 0, height > 0 { - aspectRatio = width / height + var imageSize: CGSize? + var imageAspectRatio: CGFloat? + + if let height = imageInfo.height, + let width = imageInfo.width { + imageSize = .init(width: CGFloat(width), height: CGFloat(height)) + + if width > 0, height > 0 { + imageAspectRatio = CGFloat(width) / CGFloat(height) + } } return StickerRoomTimelineItem(id: eventItemProxy.id, @@ -136,9 +141,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { canBeRepliedTo: eventItemProxy.canBeRepliedTo, sender: eventItemProxy.sender, imageURL: imageURL, - width: width, - height: height, - aspectRatio: aspectRatio, + size: imageSize, + aspectRatio: imageAspectRatio, blurhash: imageInfo.blurhash, properties: RoomTimelineItemProperties(reactions: aggregateReactions(eventItemProxy.reactions), deliveryStatus: eventItemProxy.deliveryStatus, @@ -513,18 +517,37 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype), contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename)) } - + private func buildImageTimelineItemContent(_ messageContent: ImageMessageContent) -> ImageRoomTimelineItemContent { let htmlCaption = messageContent.formattedCaption?.format == .html ? messageContent.formattedCaption?.body : nil let formattedCaption = htmlCaption != nil ? attributedStringBuilder.fromHTML(htmlCaption) : attributedStringBuilder.fromPlain(messageContent.caption) let thumbnailSource = messageContent.info?.thumbnailSource.map { MediaSourceProxy(source: $0, mimeType: messageContent.info?.thumbnailInfo?.mimetype) } - let width = messageContent.info?.width.map(CGFloat.init) - let height = messageContent.info?.height.map(CGFloat.init) - var aspectRatio: CGFloat? - if let width, let height, width > 0, height > 0 { - aspectRatio = width / height + var thumbnailSize: CGSize? + var thumbnailAspectRatio: CGFloat? + + if let thumbnailInfo = messageContent.info?.thumbnailInfo, + let height = thumbnailInfo.height, + let width = thumbnailInfo.width { + thumbnailSize = .init(width: CGFloat(width), height: CGFloat(height)) + + if width > 0, height > 0 { + thumbnailAspectRatio = CGFloat(width) / CGFloat(height) + } + } + + var imageSize: CGSize? + var imageAspectRatio: CGFloat? + + if let imageInfo = messageContent.info, + let height = imageInfo.height, + let width = imageInfo.width { + imageSize = .init(width: CGFloat(width), height: CGFloat(height)) + + if width > 0, height > 0 { + imageAspectRatio = CGFloat(width) / CGFloat(height) + } } return .init(filename: messageContent.filename, @@ -532,10 +555,11 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { formattedCaption: formattedCaption, formattedCaptionHTMLString: htmlCaption, source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype), + size: imageSize, + aspectRatio: imageAspectRatio, thumbnailSource: thumbnailSource, - width: width, - height: height, - aspectRatio: aspectRatio, + thumbnailSize: thumbnailSize, + thumbnailAspectRatio: thumbnailAspectRatio, blurhash: messageContent.info?.blurhash, contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename)) } @@ -545,12 +569,31 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { let formattedCaption = htmlCaption != nil ? attributedStringBuilder.fromHTML(htmlCaption) : attributedStringBuilder.fromPlain(messageContent.caption) let thumbnailSource = messageContent.info?.thumbnailSource.map { MediaSourceProxy(source: $0, mimeType: messageContent.info?.thumbnailInfo?.mimetype) } - let width = messageContent.info?.width.map(CGFloat.init) - let height = messageContent.info?.height.map(CGFloat.init) + + var thumbnailSize: CGSize? + var thumbnailAspectRatio: CGFloat? + + if let thumbnailInfo = messageContent.info?.thumbnailInfo, + let height = thumbnailInfo.height, + let width = thumbnailInfo.width { + thumbnailSize = .init(width: CGFloat(width), height: CGFloat(height)) + + if width > 0, height > 0 { + thumbnailAspectRatio = CGFloat(width) / CGFloat(height) + } + } + + var videoSize: CGSize? + var videoAspectRatio: CGFloat? - var aspectRatio: CGFloat? - if let width, let height, width > 0, height > 0 { - aspectRatio = width / height + if let videoInfo = messageContent.info, + let height = videoInfo.height, + let width = videoInfo.width { + videoSize = .init(width: CGFloat(width), height: CGFloat(height)) + + if width > 0, height > 0 { + videoAspectRatio = CGFloat(width) / CGFloat(height) + } } return .init(filename: messageContent.filename, @@ -559,10 +602,11 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { formattedCaptionHTMLString: htmlCaption, duration: messageContent.info?.duration ?? 0, source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype), + size: videoSize, + aspectRatio: videoAspectRatio, thumbnailSource: thumbnailSource, - width: width, - height: height, - aspectRatio: aspectRatio, + thumbnailSize: thumbnailSize, + thumbnailAspectRatio: thumbnailAspectRatio, blurhash: messageContent.info?.blurhash, contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename)) } diff --git a/ElementX/Sources/Services/Timeline/TimelineProxy.swift b/ElementX/Sources/Services/Timeline/TimelineProxy.swift index 64b5152d69..798ee7f4eb 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxy.swift @@ -234,7 +234,7 @@ final class TimelineProxy: TimelineProxyProtocol { progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) }, - useSendQueue: false) + useSendQueue: AppSettings.isDevelopmentBuild) await requestHandle(handle) @@ -260,7 +260,7 @@ final class TimelineProxy: TimelineProxyProtocol { progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) }, - useSendQueue: false) + useSendQueue: AppSettings.isDevelopmentBuild) await requestHandle(handle) @@ -290,7 +290,7 @@ final class TimelineProxy: TimelineProxyProtocol { progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) }, - useSendQueue: false) + useSendQueue: AppSettings.isDevelopmentBuild) await requestHandle(handle) @@ -338,7 +338,7 @@ final class TimelineProxy: TimelineProxyProtocol { progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) }, - useSendQueue: false) + useSendQueue: AppSettings.isDevelopmentBuild) await requestHandle(handle) @@ -368,7 +368,7 @@ final class TimelineProxy: TimelineProxyProtocol { progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) }, - useSendQueue: false) + useSendQueue: AppSettings.isDevelopmentBuild) await requestHandle(handle) 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 df4ec92cfe..cd99b8548f 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:6cf2fd3de65756ae06e150b5353386e9b5bb554d18da2f77b0cf54246c3920eb -size 285656 +oid sha256:e96e572bd736c19bb9f3bd37216bd464276c9a1ebbd715fdae27973f9b6f36cc +size 333847 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 df4ec92cfe..cd99b8548f 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:6cf2fd3de65756ae06e150b5353386e9b5bb554d18da2f77b0cf54246c3920eb -size 285656 +oid sha256:e96e572bd736c19bb9f3bd37216bd464276c9a1ebbd715fdae27973f9b6f36cc +size 333847 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 70f26febce..2180dd9b0f 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:0b2d7c9d9bf570589eb48fbbb11bf11f2970229599a5be9b06d3f54e855e0d06 -size 224889 +oid sha256:13f6dfd3e07222ae3757076e453cf99695424db88c8cc85fede448ea64e70519 +size 276862 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 70f26febce..2180dd9b0f 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:0b2d7c9d9bf570589eb48fbbb11bf11f2970229599a5be9b06d3f54e855e0d06 -size 224889 +oid sha256:13f6dfd3e07222ae3757076e453cf99695424db88c8cc85fede448ea64e70519 +size 276862 From e17a4d5275daa9a17777701436cf9d006f7b2ebb Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Fri, 15 Nov 2024 13:42:30 +0100 Subject: [PATCH 23/74] Knocking Request Cell (#3516) * knocking request cell * moved media provider --- ElementX.xcodeproj/project.pbxproj | 62 ++++--- .../en.lproj/Localizable.strings | 2 +- ElementX/Sources/Generated/Strings.swift | 4 +- ElementX/Sources/Other/Avatars.swift | 11 +- .../SwiftUI/Views/StackedAvatarsView.swift | 4 +- .../View/KnockRequestCell.swift | 162 ++++++++++++++++++ .../View/KnockRequestsBannerView.swift | 4 +- .../Sources/GeneratedPreviewTests.swift | 6 + ...nockRequestCell-iPad-en-GB.Long-reason.png | 3 + ...st_knockRequestCell-iPad-en-GB.No-name.png | 3 + ..._knockRequestCell-iPad-en-GB.No-reason.png | 3 + ...ockRequestCell-iPad-en-GB.Short-reason.png | 3 + ...ockRequestCell-iPad-pseudo.Long-reason.png | 3 + ...t_knockRequestCell-iPad-pseudo.No-name.png | 3 + ...knockRequestCell-iPad-pseudo.No-reason.png | 3 + ...ckRequestCell-iPad-pseudo.Short-reason.png | 3 + ...equestCell-iPhone-16-en-GB.Long-reason.png | 3 + ...ockRequestCell-iPhone-16-en-GB.No-name.png | 3 + ...kRequestCell-iPhone-16-en-GB.No-reason.png | 3 + ...questCell-iPhone-16-en-GB.Short-reason.png | 3 + ...questCell-iPhone-16-pseudo.Long-reason.png | 3 + ...ckRequestCell-iPhone-16-pseudo.No-name.png | 3 + ...RequestCell-iPhone-16-pseudo.No-reason.png | 3 + ...uestCell-iPhone-16-pseudo.Short-reason.png | 3 + 24 files changed, 267 insertions(+), 36 deletions(-) create mode 100644 ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Long-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-name.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Short-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Long-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-name.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Short-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Long-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-name.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Short-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Long-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-name.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-reason.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Short-reason.png diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index fc98a27b95..f09a8d4bbd 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 56; objects = { /* Begin PBXAggregateTarget section */ @@ -800,6 +800,7 @@ A6F345328CCC5C9B0DAE2257 /* LogViewerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB05221D7D941CC82DC8480 /* LogViewerScreenViewModel.swift */; }; A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; }; A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; }; + A7A369F22CE62AF800819CCB /* KnockRequestCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A369F12CE62AE900819CCB /* KnockRequestCell.swift */; }; A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; A808DC3F72D15C6C5A52317E /* TimelineItemDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCDA016D05107DED3B9495CB /* TimelineItemDebugView.swift */; }; A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; }; @@ -1265,13 +1266,13 @@ 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; 0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = ""; }; - 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; + 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = ""; }; 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = ""; }; 044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = ""; }; 045253F9967A535EE5B16691 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; 046C0D3F53B0B5EF0A1F5BEA /* RoomSummaryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryTests.swift; sourceTree = ""; }; - 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.swift; sourceTree = ""; }; 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = ""; }; 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxyProtocol.swift; sourceTree = ""; }; @@ -1337,7 +1338,7 @@ 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 = ""; }; - 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = ""; }; + 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; 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 = ""; }; @@ -1431,7 +1432,7 @@ 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = ""; }; 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenCoordinator.swift; sourceTree = ""; }; 260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = ""; }; - 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; path = PreviewTests.xctestplan; sourceTree = ""; }; + 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = PreviewTests.xctestplan; sourceTree = ""; }; 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorder.swift; sourceTree = ""; }; 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceProtocol.swift; sourceTree = ""; }; 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1502,7 +1503,7 @@ 3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = ""; }; 35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; 35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = ""; }; - 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = ""; }; 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerURLBuildersTests.swift; sourceTree = ""; }; 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = ""; }; @@ -1613,7 +1614,7 @@ 4B41FABA2B0AEF4389986495 /* LoginMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMode.swift; sourceTree = ""; }; 4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenCoordinator.swift; sourceTree = ""; }; 4C8D988E82A8DFA13BE46F7C /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pl; path = pl.lproj/Localizable.stringsdict; sourceTree = ""; }; - 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreen.swift; sourceTree = ""; }; 4D3A7375AB22721C436EB056 /* ComposerToolbarModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarModels.swift; sourceTree = ""; }; 4E2245243369B99216C7D84E /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = ""; }; @@ -1884,7 +1885,7 @@ 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 8DA1E8F287680C8ED25EDBAC /* NetworkMonitorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitorMock.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = ""; }; + 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; 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 = ""; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = ""; }; @@ -1991,6 +1992,7 @@ A6EA0D8B0BBD8805F7D5A133 /* TextBasedRoomTimelineViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineViewProtocol.swift; sourceTree = ""; }; A73A07BAEDD74C48795A996A /* AsyncSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncSequence.swift; sourceTree = ""; }; A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationTokenTests.swift; sourceTree = ""; }; + A7A369F12CE62AE900819CCB /* KnockRequestCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestCell.swift; sourceTree = ""; }; A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = ""; }; A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModelProtocol.swift; sourceTree = ""; }; A7E37072597F67C4DD8CC2DB /* ComposerDraftServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerDraftServiceProtocol.swift; sourceTree = ""; }; @@ -2065,7 +2067,7 @@ B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyProtocol.swift; sourceTree = ""; }; B53AC78E49A297AC1D72A7CF /* AppMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediator.swift; sourceTree = ""; }; B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = ""; }; - B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = ""; }; 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 = ""; }; @@ -2183,7 +2185,7 @@ CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = ""; }; CDE3F3911FF7CC639BDE5844 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; 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 = ""; }; + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; D01FD1171FF40E34D707FD00 /* BigIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigIcon.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 = ""; }; @@ -2316,7 +2318,7 @@ ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = ""; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = ""; }; ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModel.swift; sourceTree = ""; }; - ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = ""; }; ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = ""; }; EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = ""; }; @@ -2339,7 +2341,7 @@ F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = ""; }; - F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; + F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = ""; }; F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = ""; }; F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = ""; }; F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = ""; }; @@ -2357,7 +2359,7 @@ F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineBubbleLayout.swift; sourceTree = ""; }; F5E23D8EE6CBACF32F1EC874 /* MediaPlayerProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProviderProtocol.swift; sourceTree = ""; }; F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModel.swift; sourceTree = ""; }; - F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; path = test_apple_image.heic; sourceTree = ""; }; + F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_apple_image.heic; sourceTree = ""; }; F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = ""; }; F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockUITests.swift; sourceTree = ""; }; F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderMock.swift; sourceTree = ""; }; @@ -4801,6 +4803,22 @@ path = Application; sourceTree = ""; }; + A7A369EF2CE62AB300819CCB /* KnockRequestsListScreen */ = { + isa = PBXGroup; + children = ( + A7A369F02CE62AC900819CCB /* View */, + ); + path = KnockRequestsListScreen; + sourceTree = ""; + }; + A7A369F02CE62AC900819CCB /* View */ = { + isa = PBXGroup; + children = ( + A7A369F12CE62AE900819CCB /* KnockRequestCell.swift */, + ); + path = View; + sourceTree = ""; + }; A7F3784CAF9F4CF654BC52CD /* View */ = { isa = PBXGroup; children = ( @@ -5368,6 +5386,7 @@ E59565F441830B19DBAE567C /* Screens */ = { isa = PBXGroup; children = ( + A7A369EF2CE62AB300819CCB /* KnockRequestsListScreen */, 13263FFEA7749D822B51AA90 /* AppLock */, E74CD7681375AD2EAA34D66B /* Authentication */, 295BCC81AB45927F5F2033B1 /* AuthenticationStartScreen */, @@ -6938,6 +6957,7 @@ C8C7AF33AADF88B306CD2695 /* QRCodeLoginService.swift in Sources */, BB04B1D8E7401C90506D401E /* QRCodeLoginServiceProtocol.swift in Sources */, FDD5B4B616D9FF4DE3E9A418 /* QRCodeScannerView.swift in Sources */, + A7A369F22CE62AF800819CCB /* KnockRequestCell.swift in Sources */, C9A631FD968249B4BA0B7B3C /* ReactionsSummaryView.swift in Sources */, 743790BF6A5B0577EA74AF14 /* ReadMarkerRoomTimelineItem.swift in Sources */, 2BBC0EB1E07963810A5D7423 /* ReadMarkerRoomTimelineView.swift in Sources */, @@ -7537,9 +7557,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_NSE", - ); + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -7588,9 +7606,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_MAIN_APP", - ); + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7616,9 +7632,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_MAIN_APP", - ); + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7884,9 +7898,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_NSE", - ); + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 16616e3676..5cbc8e5a29 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Audio"; "common_blocked_users" = "Blocked users"; "common_bubbles" = "Bubbles"; -"common_call_invite" = "Call in progress (unsupported)"; "common_call_started" = "Call started"; "common_chat_backup" = "Chat backup"; "common_copyright" = "Copyright"; @@ -366,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 11565013c3..012eec9e9a 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -288,8 +288,6 @@ internal enum L10n { internal static var commonBlockedUsers: String { return L10n.tr("Localizable", "common_blocked_users") } /// Bubbles internal static var commonBubbles: String { return L10n.tr("Localizable", "common_bubbles") } - /// Call in progress (unsupported) - internal static var commonCallInvite: String { return L10n.tr("Localizable", "common_call_invite") } /// Call started internal static var commonCallStarted: String { return L10n.tr("Localizable", "common_call_started") } /// Chat backup @@ -1290,6 +1288,8 @@ internal enum L10n { } /// Are you sure you want to turn off key storage and delete it? internal static var screenKeyBackupDisableTitle: String { return L10n.tr("Localizable", "screen_key_backup_disable_title") } + /// Decline and ban + internal static var screenKnockRequestsListDeclineAndBanActionTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_and_ban_action_title") } /// This account has been deactivated. internal static var screenLoginErrorDeactivatedAccount: String { return L10n.tr("Localizable", "screen_login_error_deactivated_account") } /// Incorrect username and/or password diff --git a/ElementX/Sources/Other/Avatars.swift b/ElementX/Sources/Other/Avatars.swift index aae173e64e..96fc58aaaa 100644 --- a/ElementX/Sources/Other/Avatars.swift +++ b/ElementX/Sources/Other/Avatars.swift @@ -72,8 +72,9 @@ enum UserAvatarSizeOnScreen { case editUserDetails case suggestions case blockedUsers - case knockingUsersStack - case knockingUser + case knockingUsersBannerStack + case knockingUserBanner + case knockingUserList var value: CGFloat { switch self { @@ -103,10 +104,12 @@ enum UserAvatarSizeOnScreen { return 96 case .dmDetails: return 75 - case .knockingUsersStack: + case .knockingUsersBannerStack: return 28 - case .knockingUser: + case .knockingUserBanner: return 32 + case .knockingUserList: + return 52 } } } diff --git a/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift b/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift index 83cf78c0aa..81db43cb88 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/StackedAvatarsView.swift @@ -53,13 +53,13 @@ struct StackedAvatarsView_Previews: PreviewProvider, TestablePreview { StackedAvatarsView(overlap: 16, lineWidth: 2, avatars: avatars, - avatarSize: .user(on: .knockingUsersStack), + avatarSize: .user(on: .knockingUsersBannerStack), mediaProvider: MediaProviderMock()) StackedAvatarsView(overlap: 16, lineWidth: 2, shouldStackFromLast: true, avatars: avatars, - avatarSize: .user(on: .knockingUsersStack), + avatarSize: .user(on: .knockingUsersBannerStack), mediaProvider: MediaProviderMock()) } } diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift new file mode 100644 index 0000000000..837f6d33d4 --- /dev/null +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift @@ -0,0 +1,162 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +// +// 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 KnockRequestCellInfo { + let userID: String + let displayName: String? + let avatarUrl: URL? + let timestamp: String? + let reason: String? +} + +struct KnockRequestCell: View { + let cellInfo: KnockRequestCellInfo + var mediaProvider: MediaProviderProtocol? + let onAccept: (String) -> Void + let onDecline: (String) -> Void + let onDeclineAndBan: (String) -> Void + + var body: some View { + VStack(spacing: 0) { + HStack(alignment: .top, spacing: 16) { + LoadableAvatarImage(url: cellInfo.avatarUrl, + name: cellInfo.displayName, + contentID: cellInfo.userID, + avatarSize: .user(on: .knockingUserList), + mediaProvider: mediaProvider) + VStack(alignment: .leading, spacing: 12) { + VStack(alignment: .leading, spacing: 0) { + HStack(alignment: .top, spacing: 0) { + Text(cellInfo.displayName ?? cellInfo.userID) + .font(.compound.bodyLGSemibold) + .foregroundStyle(.compound.textPrimary) + .frame(maxWidth: .infinity, alignment: .leading) + if let timestamp = cellInfo.timestamp { + Text(timestamp) + .font(.compound.bodySM) + .foregroundStyle(.compound.textSecondary) + } + } + if cellInfo.displayName != nil { + Text(cellInfo.userID) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textSecondary) + } + } + if let reason = cellInfo.reason { + DisclosableText(text: reason) + } + actions + } + } + .padding(16) + Divider() + } + } + + @ViewBuilder + private var actions: some View { + HStack(spacing: 16) { + Button(L10n.actionDecline) { + onDecline(cellInfo.userID) + } + .buttonStyle(.compound(.secondary)) + Button(L10n.actionAccept) { + onAccept(cellInfo.userID) + } + .buttonStyle(.compound(.primary)) + } + Button(L10n.screenKnockRequestsListDeclineAndBanActionTitle, role: .destructive) { + onDeclineAndBan(cellInfo.userID) + } + .buttonStyle(.compound(.plain)) + .frame(maxWidth: .infinity) + .padding(.top, 12) + .padding(.bottom, 4) + } +} + +private struct DisclosableText: View { + let text: String + @State private var collapsedHeight = CGFloat.zero + @State private var expandedHeight = CGFloat.zero + @State private var isExpanded = false + + var body: some View { + HStack(alignment: .top, spacing: 4) { + Text(text) + .multilineTextAlignment(.leading) + .lineLimit(isExpanded ? nil : 3) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textPrimary) + .frame(maxWidth: .infinity, alignment: .leading) + .onGeometryChange(for: CGFloat.self) { geometry in + geometry.size.height + } action: { newValue in + if !isExpanded { + collapsedHeight = newValue + } + } + .background { + Text(text) + .multilineTextAlignment(.leading) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textPrimary) + .fixedSize(horizontal: false, vertical: true) + .onGeometryChange(for: CGFloat.self) { geometry in + geometry.size.height + } action: { newValue in + expandedHeight = newValue + } + .hidden() + } + Button { + withAnimation { + isExpanded.toggle() + } + } label: { + CompoundIcon(\.chevronDown, size: .medium, relativeTo: .compound.bodyMD) + } + .rotationEffect(.degrees(isExpanded ? 180 : 0)) + .foregroundStyle(.compound.iconTertiary) + .opacity(collapsedHeight < expandedHeight ? 1 : 0) + .disabled(collapsedHeight >= expandedHeight) + } + } +} + +struct KnockRequestCell_Previews: PreviewProvider, TestablePreview { + // swiftlint:disable:next line_length + static let aliceWithLongReason = KnockRequestCellInfo(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(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(userID: "@alice:matrix.org", displayName: "Alice", avatarUrl: nil, timestamp: "20 Nov 2024", reason: nil) + + static let aliceWithNoName = KnockRequestCellInfo(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 }) + .previewDisplayName("Long reason") + KnockRequestCell(cellInfo: aliceWithShortReason, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in }) + .previewDisplayName("Short reason") + KnockRequestCell(cellInfo: aliceWithNoReason, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in }) + .previewDisplayName("No reason") + KnockRequestCell(cellInfo: aliceWithNoName, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in }) + .previewDisplayName("No name") + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift b/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift index c414979327..dab249999c 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift @@ -69,7 +69,7 @@ private struct SingleKnockRequestBannerContent: View { LoadableAvatarImage(url: request.avatarURL, name: request.displayName, contentID: request.userID, - avatarSize: .user(on: .knockingUser), mediaProvider: mediaProvider) + avatarSize: .user(on: .knockingUserBanner), mediaProvider: mediaProvider) VStack(spacing: 0) { HStack(alignment: .top, spacing: 0) { Text(L10n.screenRoomSingleKnockRequestTitle(request.displayName ?? request.userID)) @@ -129,7 +129,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: .knockingUsersStack), mediaProvider: mediaProvider) + StackedAvatarsView(overlap: 16, lineWidth: 2, shouldStackFromLast: true, avatars: avatars, avatarSize: .user(on: .knockingUsersBannerStack), mediaProvider: mediaProvider) HStack(alignment: .top, spacing: 0) { Text(multipleKnockRequestsTitle) .lineLimit(2) diff --git a/PreviewTests/Sources/GeneratedPreviewTests.swift b/PreviewTests/Sources/GeneratedPreviewTests.swift index bac6116695..f18c1d9278 100644 --- a/PreviewTests/Sources/GeneratedPreviewTests.swift +++ b/PreviewTests/Sources/GeneratedPreviewTests.swift @@ -305,6 +305,12 @@ extension PreviewTests { } } + func test_knockRequestCell() { + for preview in KnockRequestCell_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_knockRequestsBannerView() { for preview in KnockRequestsBannerView_Previews._allPreviews { assertSnapshots(matching: preview) diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Long-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Long-reason.png new file mode 100644 index 0000000000..e3ea93d796 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Long-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5466569f96a2d74dc598b7d870ae76d237c0e7dbf181f3e0adf497b0956e2649 +size 119491 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-name.png new file mode 100644 index 0000000000..c7c77c488c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-name.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b61e8c99338ff1316736d3f8945cbc32c407a276493a63de0ffe9f1325479cc3 +size 93546 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-reason.png new file mode 100644 index 0000000000..cbd704292e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79a32205860de5d076cbf226156962519586058e50a89ea7c29cf15b2d66fb75 +size 94500 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Short-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Short-reason.png new file mode 100644 index 0000000000..afb85ca2e7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Short-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc9ebf6bcd889f2d0a0a855404b6be2ae140d40a69a21767dc9ecc3958539a79 +size 103862 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Long-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Long-reason.png new file mode 100644 index 0000000000..049a445c87 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Long-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af31b5df7d0f0d97a8c306ece8cbaa611bfbc3a98e78a189ed5349f16faa5cc5 +size 121175 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-name.png new file mode 100644 index 0000000000..ef4aebf232 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-name.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:98eec884b96bcaa6eec3510a8c362762d2a0d3238eecd287782e2d41a778af83 +size 95103 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-reason.png new file mode 100644 index 0000000000..9f63dd5294 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b974d372c92c5fb724778d384fc3072d95cc2bea1c9662d123fc24fbfba6890a +size 96049 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Short-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Short-reason.png new file mode 100644 index 0000000000..bb5e34c8ab --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Short-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97c9af346e966100a44f1db6814e516455ba90c3a4154de9a5f657f955dfefa3 +size 105493 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Long-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Long-reason.png new file mode 100644 index 0000000000..403ce85c6d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Long-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce6497c50fbf9e9b0f6bb6713cacb55bb389a31232785faa1368b341d300b563 +size 62895 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-name.png new file mode 100644 index 0000000000..0e554bf98f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-name.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b6360a04a6d30220c3b8d9aed2de8309aa54b4234824fa73cc44ac40c0c89ed2 +size 50804 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-reason.png new file mode 100644 index 0000000000..19c432cb94 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ca01bbaee8ec50a79370b222b15fcb9d028db3b3782d5ab0757cce738497821 +size 51417 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Short-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Short-reason.png new file mode 100644 index 0000000000..fc89ccaedd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Short-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb2cfa269efe2a538abd7c93d577878366b84f4e44701f8a4314a2f4eb53a3d8 +size 60576 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Long-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Long-reason.png new file mode 100644 index 0000000000..9f39dd4ad3 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Long-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14478f6bac6fb2a792c369f8568e4cf51a89029dd4b9434262db4eb0e76e7328 +size 70929 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-name.png new file mode 100644 index 0000000000..41e77b4ff1 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-name.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:388b944b239c1dd130e6c1463e777c9aa85186e3bf70402d8853e88b7c19be22 +size 59396 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-reason.png new file mode 100644 index 0000000000..101c51af89 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1257061c8bef2b9fd9173e696ffecbfbd017b0f06eabe1228e80d3873007e271 +size 60458 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Short-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Short-reason.png new file mode 100644 index 0000000000..c0c7df2611 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Short-reason.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e982a79556a5fdef82435ec63dca8a24970e8c80248c751fb89f06b09fa6061 +size 68971 From 4ea276dc991e7eb6ba0392c40ca096900ddccbde Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Fri, 15 Nov 2024 14:42:28 +0200 Subject: [PATCH 24/74] Fix share extension app group so it works for nightlies too --- ShareExtension/SupportingFiles/ShareExtension.entitlements | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ShareExtension/SupportingFiles/ShareExtension.entitlements b/ShareExtension/SupportingFiles/ShareExtension.entitlements index 8cb4a1a418..d9849a816d 100644 --- a/ShareExtension/SupportingFiles/ShareExtension.entitlements +++ b/ShareExtension/SupportingFiles/ShareExtension.entitlements @@ -4,7 +4,7 @@ com.apple.security.application-groups - group.io.element + $(APP_GROUP_IDENTIFIER) From ef288a9662142fca4785893a5fc8d62c4a93a483 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Fri, 15 Nov 2024 15:00:27 +0200 Subject: [PATCH 25/74] Group image and video metadata in specialised structs (#3518) --- .../SwiftUI/Layout/TimelineMediaFrame.swift | 10 +- .../View/MessageComposer.swift | 9 +- .../Timeline/TimelineInteractionHandler.swift | 4 +- .../View/Replies/TimelineReplyView.swift | 19 ++- .../Style/TimelineItemBubbledStylerView.swift | 8 +- .../ImageRoomTimelineView.swift | 33 +++-- .../StickerRoomTimelineView.swift | 14 +-- .../VideoRoomTimelineView.swift | 28 ++--- .../Fixtures/RoomTimelineItemFixtures.swift | 13 +- .../Services/Timeline/TimelineItemProxy.swift | 108 +++++++++++++++- .../ImageRoomTimelineItemContent.swift | 8 +- .../VideoRoomTimelineItemContent.swift | 10 +- .../Items/Other/StickerRoomTimelineItem.swift | 4 +- .../RoomTimelineItemFactory.swift | 117 ++++++------------ ...est_imageRoomTimelineView-iPad-en-GB.1.png | 4 +- ...st_imageRoomTimelineView-iPad-pseudo.1.png | 4 +- ...mageRoomTimelineView-iPhone-16-en-GB.1.png | 4 +- ...ageRoomTimelineView-iPhone-16-pseudo.1.png | 4 +- ...t_stickerRoomTimelineView-iPad-en-GB.1.png | 4 +- ..._stickerRoomTimelineView-iPad-pseudo.1.png | 4 +- ...ckerRoomTimelineView-iPhone-16-en-GB.1.png | 4 +- ...kerRoomTimelineView-iPhone-16-pseudo.1.png | 4 +- ...est_videoRoomTimelineView-iPad-en-GB.1.png | 4 +- ...st_videoRoomTimelineView-iPad-pseudo.1.png | 4 +- ...ideoRoomTimelineView-iPhone-16-en-GB.1.png | 4 +- ...deoRoomTimelineView-iPhone-16-pseudo.1.png | 4 +- UnitTests/Sources/LoggingTests.swift | 9 +- 27 files changed, 230 insertions(+), 212 deletions(-) diff --git a/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift b/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift index 1cec148401..c715f5fc93 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/TimelineMediaFrame.swift @@ -10,18 +10,18 @@ import SwiftUI extension View { /// Constrains the max height of a media item in the timeline, whilst preserving its aspect ratio. @ViewBuilder - func timelineMediaFrame(height contentHeight: CGFloat?, aspectRatio contentAspectRatio: CGFloat?) -> some View { + func timelineMediaFrame(imageInfo: ImageInfoProxy?) -> some View { let defaultMediaSize = 100.0 let minMediaHeight = 100.0 let maxMediaHeight = 300.0 - if let contentHeight, contentHeight < minMediaHeight { // Special case very small images - aspectRatio(contentAspectRatio, contentMode: .fit) + if let contentHeight = imageInfo?.size?.height, contentHeight < minMediaHeight { // Special case very small images + aspectRatio(imageInfo?.aspectRatio, contentMode: .fit) .frame(minHeight: minMediaHeight, maxHeight: minMediaHeight) } else { - if let contentAspectRatio { + if let contentAspectRatio = imageInfo?.aspectRatio { aspectRatio(contentAspectRatio, contentMode: .fit) - .frame(maxHeight: min(maxMediaHeight, max(minMediaHeight, contentHeight ?? .infinity))) + .frame(maxHeight: min(maxMediaHeight, max(minMediaHeight, imageInfo?.size?.height ?? .infinity))) // Required to prevent the reply details to get higher priority in rendering the width of the view. .aspectRatio(contentAspectRatio, contentMode: .fit) } else { // Otherwise force the image to be `defaultMediaSize` x `defaultMediaSize` diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift index 0a142b37a1..809c80279f 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift @@ -226,8 +226,8 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview { eventID: "123", eventContent: .message(.image(.init(filename: "head.png", caption: "Image: Pushead", - source: .init(url: .picturesDirectory, mimeType: nil), - thumbnailSource: .init(url: .picturesDirectory, mimeType: nil))))), + imageInfo: .mockImage, + thumbnailInfo: .mockThumbnail)))), .loaded(sender: .init(id: "Jason"), eventID: "123", eventContent: .message(.notice(.init(body: "Notice: Too far gone?")))), @@ -238,9 +238,8 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview { eventID: "123", eventContent: .message(.video(.init(filename: "never.mov", caption: "Video: Through the never", - duration: 100, - source: nil, - thumbnailSource: .init(url: .picturesDirectory, mimeType: nil))))), + videoInfo: .mockVideo, + thumbnailInfo: .mockThumbnail)))), .loading(eventID: "") ] diff --git a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift index 83b2bd23dd..a70c982758 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift @@ -553,11 +553,11 @@ class TimelineInteractionHandler { switch timelineItem { case let item as ImageRoomTimelineItem: - source = item.content.source + source = item.content.imageInfo.source filename = item.content.filename caption = item.content.caption case let item as VideoRoomTimelineItem: - source = item.content.source + source = item.content.videoInfo.source filename = item.content.filename caption = item.content.caption case let item as FileRoomTimelineItem: diff --git a/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift b/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift index 6326e84a32..bd82866912 100644 --- a/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift @@ -42,7 +42,7 @@ struct TimelineReplyView: View { ReplyView(sender: sender, plainBody: content.caption ?? content.filename, formattedBody: content.formattedCaption, - icon: .init(kind: .mediaSource(content.thumbnailSource ?? content.source), cornerRadii: iconCornerRadii)) + icon: .init(kind: .mediaSource(content.thumbnailInfo?.source ?? content.imageInfo.source), cornerRadii: iconCornerRadii)) case .notice(let content): ReplyView(sender: sender, plainBody: content.body, @@ -55,7 +55,7 @@ struct TimelineReplyView: View { ReplyView(sender: sender, plainBody: content.caption ?? content.filename, formattedBody: content.formattedCaption, - icon: content.thumbnailSource.map { .init(kind: .mediaSource($0), cornerRadii: iconCornerRadii) }) + icon: content.thumbnailInfo.map { .init(kind: .mediaSource($0.source), cornerRadii: iconCornerRadii) }) case .voice: ReplyView(sender: sender, plainBody: L10n.commonVoiceMessage, @@ -222,9 +222,7 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview { }() static var previewItems: [TimelineReplyView] { - let imageSource = MediaSourceProxy(url: "https://mock.com", mimeType: "image/png") - - return [ + [ TimelineReplyView(placement: .timeline, timelineItemReplyDetails: .notLoaded(eventID: "")), TimelineReplyView(placement: .timeline, timelineItemReplyDetails: .loading(eventID: "")), @@ -268,17 +266,16 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview { eventID: "123", eventContent: .message(.image(.init(filename: "image.jpg", caption: "Some image", - source: imageSource, - thumbnailSource: imageSource))))), + imageInfo: .mockImage, + thumbnailInfo: .mockThumbnail))))), TimelineReplyView(placement: .timeline, timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), eventID: "123", eventContent: .message(.video(.init(filename: "video.mp4", caption: "Some video", - duration: 0, - source: nil, - thumbnailSource: imageSource))))), + videoInfo: .mockVideo, + thumbnailInfo: .mockThumbnail))))), TimelineReplyView(placement: .timeline, timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Alice"), eventID: "123", @@ -321,7 +318,7 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview { } .padding() .environmentObject(viewModel.context) - // Allow member names to load. Reduce precission as the `imageSource` randomly renders slightly differently + // Allow member names to load. Reduce precission as the `mockThumbnail` randomly renders slightly differently .snapshotPreferences(delay: 0.2, precision: 0.98) .previewLayout(.sizeThatFits) } diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift index 61ed78ee82..e1b025cec9 100644 --- a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift @@ -498,8 +498,8 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview isThreaded: false, sender: .init(id: "Bob"), content: .init(filename: "other.png", - source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), - thumbnailSource: nil), + imageInfo: .mockImage, + thumbnailInfo: nil), properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray)))) @@ -577,8 +577,8 @@ private struct MockTimelineContent: View { isThreaded: isThreaded, sender: .init(id: ""), content: .init(filename: "image.jpg", - source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), - thumbnailSource: nil), + imageInfo: .mockImage, + thumbnailInfo: nil), replyDetails: replyDetails)) LocationRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(), diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift index 2047c0ccef..beb06037db 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift @@ -40,25 +40,23 @@ struct ImageRoomTimelineView: View { @ViewBuilder private var loadableImage: some View { if timelineItem.content.contentType == .gif { - LoadableImage(mediaSource: timelineItem.content.source, + LoadableImage(mediaSource: timelineItem.content.imageInfo.source, mediaType: .timelineItem, blurhash: timelineItem.content.blurhash, - size: timelineItem.content.size, + size: timelineItem.content.imageInfo.size, mediaProvider: context.mediaProvider) { placeholder } - .timelineMediaFrame(height: timelineItem.content.thumbnailSize?.height, - aspectRatio: timelineItem.content.aspectRatio) + .timelineMediaFrame(imageInfo: timelineItem.content.imageInfo) } else { - LoadableImage(mediaSource: timelineItem.content.thumbnailSource ?? timelineItem.content.source, + LoadableImage(mediaSource: timelineItem.content.thumbnailInfo?.source ?? timelineItem.content.imageInfo.source, mediaType: .timelineItem, blurhash: timelineItem.content.blurhash, - size: timelineItem.content.thumbnailSize ?? timelineItem.content.size, + size: timelineItem.content.thumbnailInfo?.size ?? timelineItem.content.imageInfo.size, mediaProvider: context.mediaProvider) { placeholder } - .timelineMediaFrame(height: timelineItem.content.thumbnailSize?.height ?? timelineItem.content.size?.height, - aspectRatio: timelineItem.content.thumbnailAspectRatio ?? timelineItem.content.aspectRatio) + .timelineMediaFrame(imageInfo: timelineItem.content.thumbnailInfo ?? timelineItem.content.imageInfo) } } @@ -87,8 +85,8 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview { isThreaded: false, sender: .init(id: "Bob"), content: .init(filename: "image.jpg", - source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/jpg"), - thumbnailSource: nil))) + imageInfo: .mockImage, + thumbnailInfo: nil))) ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .randomEvent, timestamp: "Now", @@ -98,8 +96,8 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview { isThreaded: false, sender: .init(id: "Bob"), content: .init(filename: "other.png", - source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), - thumbnailSource: nil))) + imageInfo: .mockImage, + thumbnailInfo: nil))) ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: .randomEvent, timestamp: "Now", @@ -109,9 +107,8 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview { isThreaded: false, sender: .init(id: "Bob"), content: .init(filename: "Blurhashed.jpg", - source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/gif"), - aspectRatio: 0.7, - thumbnailSource: nil, + imageInfo: .mockImage, + thumbnailInfo: nil, blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW", contentType: .gif))) @@ -124,10 +121,8 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview { sender: .init(id: "Bob"), content: .init(filename: "Blurhashed.jpg", caption: "This is a great image 😎", - source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), - size: .init(width: 50, height: 50), - aspectRatio: 1, - thumbnailSource: nil, + imageInfo: .mockImage, + thumbnailInfo: .mockThumbnail, blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW", contentType: .gif))) } diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift index c0f4480ede..2763bb1313 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift @@ -14,15 +14,14 @@ struct StickerRoomTimelineView: View { var body: some View { TimelineStyler(timelineItem: timelineItem) { - LoadableImage(url: timelineItem.imageURL, + LoadableImage(mediaSource: timelineItem.imageInfo.source, mediaType: .timelineItem, blurhash: timelineItem.blurhash, - size: timelineItem.size, + size: timelineItem.imageInfo.size, mediaProvider: context.mediaProvider) { placeholder } - .timelineMediaFrame(height: timelineItem.size?.height, - aspectRatio: timelineItem.aspectRatio) + .timelineMediaFrame(imageInfo: timelineItem.imageInfo) .accessibilityElement(children: .ignore) .accessibilityLabel("\(L10n.commonSticker), \(timelineItem.body)") } @@ -51,7 +50,7 @@ struct StickerRoomTimelineView_Previews: PreviewProvider, TestablePreview { isEditable: false, canBeRepliedTo: true, sender: .init(id: "Bob"), - imageURL: URL.picturesDirectory)) + imageInfo: .mockImage)) StickerRoomTimelineView(timelineItem: StickerRoomTimelineItem(id: .randomEvent, body: "Some other image", @@ -60,7 +59,7 @@ struct StickerRoomTimelineView_Previews: PreviewProvider, TestablePreview { isEditable: false, canBeRepliedTo: true, sender: .init(id: "Bob"), - imageURL: URL.picturesDirectory)) + imageInfo: .mockImage)) StickerRoomTimelineView(timelineItem: StickerRoomTimelineItem(id: .randomEvent, body: "Blurhashed image", @@ -69,8 +68,7 @@ struct StickerRoomTimelineView_Previews: PreviewProvider, TestablePreview { isEditable: false, canBeRepliedTo: true, sender: .init(id: "Bob"), - imageURL: URL.picturesDirectory, - aspectRatio: 0.7, + imageInfo: .mockImage, blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW")) } } diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift index ea072fda76..d64d93c284 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift @@ -18,8 +18,7 @@ struct VideoRoomTimelineView: View { TimelineStyler(timelineItem: timelineItem) { VStack(alignment: .leading, spacing: 4) { thumbnail - .timelineMediaFrame(height: timelineItem.content.thumbnailSize?.height, - aspectRatio: timelineItem.content.aspectRatio) + .timelineMediaFrame(imageInfo: timelineItem.content.thumbnailInfo) .accessibilityElement(children: .ignore) .accessibilityLabel(L10n.commonVideo) // This clip shape is distinct from the one in the styler as that one @@ -41,11 +40,11 @@ struct VideoRoomTimelineView: View { @ViewBuilder var thumbnail: some View { - if let thumbnailSource = timelineItem.content.thumbnailSource { + if let thumbnailSource = timelineItem.content.thumbnailInfo?.source { LoadableImage(mediaSource: thumbnailSource, mediaType: .timelineItem, blurhash: timelineItem.content.blurhash, - size: timelineItem.content.thumbnailSize, + size: timelineItem.content.thumbnailInfo?.size, mediaProvider: context.mediaProvider) { imageView in imageView .overlay { playIcon } @@ -89,9 +88,8 @@ struct VideoRoomTimelineView_Previews: PreviewProvider, TestablePreview { isThreaded: false, sender: .init(id: "Bob"), content: .init(filename: "video.mp4", - duration: 21, - source: nil, - thumbnailSource: nil))) + videoInfo: .mockVideo, + thumbnailInfo: nil))) VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .randomEvent, timestamp: "Now", @@ -101,9 +99,8 @@ struct VideoRoomTimelineView_Previews: PreviewProvider, TestablePreview { isThreaded: false, sender: .init(id: "Bob"), content: .init(filename: "other.mp4", - duration: 22, - source: nil, - thumbnailSource: nil))) + videoInfo: .mockVideo, + thumbnailInfo: nil))) VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .randomEvent, timestamp: "Now", @@ -113,10 +110,8 @@ struct VideoRoomTimelineView_Previews: PreviewProvider, TestablePreview { isThreaded: false, sender: .init(id: "Bob"), content: .init(filename: "Blurhashed.mp4", - duration: 23, - source: nil, - aspectRatio: 0.7, - thumbnailSource: nil, + videoInfo: .mockVideo, + thumbnailInfo: nil, blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW"))) VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: .randomEvent, @@ -128,9 +123,8 @@ struct VideoRoomTimelineView_Previews: PreviewProvider, TestablePreview { sender: .init(id: "Bob"), content: .init(filename: "video.mp4", caption: "This is a caption", - duration: 21, - source: nil, - thumbnailSource: nil))) + videoInfo: .mockVideo, + thumbnailInfo: nil))) } } } diff --git a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift index 79b9eace51..da67a49fcc 100644 --- a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift +++ b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift @@ -258,11 +258,8 @@ enum RoomTimelineItemFixtures { isThreaded: false, sender: .init(id: ""), content: .init(filename: "video.mp4", - duration: 100, - source: .init(url: .picturesDirectory, mimeType: nil), - size: .init(width: 1920, height: 1080), - aspectRatio: 1.78, - thumbnailSource: .init(url: .picturesDirectory, mimeType: nil), + videoInfo: .mockVideo, + thumbnailInfo: .mockThumbnail, blurhash: "KtI~70X5V?yss9oyrYs:t6")), ImageRoomTimelineItem(id: .randomEvent, timestamp: "10:47 am", @@ -272,10 +269,8 @@ enum RoomTimelineItemFixtures { isThreaded: false, sender: .init(id: ""), content: .init(filename: "image.jpg", - source: .init(url: .picturesDirectory, mimeType: nil), - size: .init(width: 5120, height: 3412), - aspectRatio: 1.5, - thumbnailSource: nil, + imageInfo: .mockImage, + thumbnailInfo: nil, blurhash: "KpE4oyayR5|GbHb];3j@of")) ] } diff --git a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift index 93e8f94d95..11177b93bf 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift @@ -215,11 +215,111 @@ struct SendHandleProxy: Hashable { } } -extension Receipt { - var dateTimestamp: Date? { - guard let timestamp else { +struct VideoInfoProxy: Hashable { + let source: MediaSourceProxy + private(set) var duration: TimeInterval + private(set) var size: CGSize? + private(set) var aspectRatio: CGFloat? + private(set) var mimeType: String? + + init(source: MediaSource, duration: TimeInterval, width: UInt64?, height: UInt64?, mimeType: String?) { + self.source = MediaSourceProxy(source: source, mimeType: mimeType) + self.duration = duration + + let mediaInfo = MediaInfoProxy(width: width, height: height, mimeType: mimeType) + size = mediaInfo.size + aspectRatio = mediaInfo.aspectRatio + self.mimeType = mediaInfo.mimeType + } + + // MARK: - Mocks + + private init(source: MediaSourceProxy, duration: TimeInterval, size: CGSize?, aspectRatio: CGFloat?, mimeType: String?) { + self.source = source + self.duration = duration + self.size = size + self.aspectRatio = aspectRatio + self.mimeType = mimeType + } + + static var mockVideo: VideoInfoProxy { + .init(source: .init(url: .picturesDirectory, mimeType: nil), + duration: 100, + size: .init(width: 1920, height: 1080), + aspectRatio: 1.78, + mimeType: nil) + } +} + +struct ImageInfoProxy: Hashable { + let source: MediaSourceProxy + private(set) var size: CGSize? + private(set) var aspectRatio: CGFloat? + private(set) var mimeType: String? + + init?(source: MediaSource?, width: UInt64?, height: UInt64?, mimeType: String?) { + guard let source else { return nil } - return Date(timeIntervalSince1970: TimeInterval(timestamp / 1000)) + + self.init(source: .init(source: source, mimeType: mimeType), width: width, height: height, mimeType: mimeType) + } + + init(source: MediaSource, width: UInt64?, height: UInt64?, mimeType: String?) { + self.init(source: .init(source: source, mimeType: mimeType), width: width, height: height, mimeType: mimeType) + } + + init(url: URL, width: UInt64?, height: UInt64?, mimeType: String?) { + self.init(source: .init(url: url, mimeType: mimeType), width: width, height: height, mimeType: mimeType) + } + + init(source: MediaSourceProxy, width: UInt64?, height: UInt64?, mimeType: String?) { + self.source = source + + let mediaInfo = MediaInfoProxy(width: width, height: height, mimeType: mimeType) + size = mediaInfo.size + aspectRatio = mediaInfo.aspectRatio + self.mimeType = mediaInfo.mimeType + } + + // MARK: - Mocks + + private init(source: MediaSourceProxy, size: CGSize?, aspectRatio: CGFloat?, mimeType: String?) { + self.source = source + self.size = size + self.aspectRatio = aspectRatio + self.mimeType = mimeType + } + + static var mockImage: ImageInfoProxy { + .init(source: .init(url: .picturesDirectory, mimeType: "image/png"), + size: .init(width: 100, height: 100), + aspectRatio: 1, + mimeType: "image/png") + } + + static var mockThumbnail: ImageInfoProxy { + .init(source: .init(url: .picturesDirectory, mimeType: nil), + size: nil, + aspectRatio: nil, + mimeType: nil) + } +} + +struct MediaInfoProxy: Hashable { + private(set) var size: CGSize? + private(set) var mimeType: String? + private(set) var aspectRatio: CGFloat? + + init(width: UInt64?, height: UInt64?, mimeType: String?) { + if let width, let height { + size = .init(width: CGFloat(width), height: CGFloat(height)) + + if width > 0, height > 0 { + aspectRatio = CGFloat(width) / CGFloat(height) + } + } + + self.mimeType = mimeType } } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift index 4bf326422e..f4c601d054 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/ImageRoomTimelineItemContent.swift @@ -14,13 +14,9 @@ struct ImageRoomTimelineItemContent: Hashable { var formattedCaption: AttributedString? /// The original textual representation of the formatted caption directly from the event (usually HTML code) var formattedCaptionHTMLString: String? - let source: MediaSourceProxy - var size: CGSize? - var aspectRatio: CGFloat? - let thumbnailSource: MediaSourceProxy? - var thumbnailSize: CGSize? - var thumbnailAspectRatio: CGFloat? + let imageInfo: ImageInfoProxy + let thumbnailInfo: ImageInfoProxy? var blurhash: String? var contentType: UTType? diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift index ff9ea5aa85..ea50f20781 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VideoRoomTimelineItemContent.swift @@ -14,15 +14,9 @@ struct VideoRoomTimelineItemContent: Hashable { var formattedCaption: AttributedString? /// The original textual representation of the formatted caption directly from the event (usually HTML code) var formattedCaptionHTMLString: String? - let duration: TimeInterval - let source: MediaSourceProxy? - var size: CGSize? - var aspectRatio: CGFloat? - - let thumbnailSource: MediaSourceProxy? - var thumbnailSize: CGSize? - var thumbnailAspectRatio: CGFloat? + let videoInfo: VideoInfoProxy + let thumbnailInfo: ImageInfoProxy? var blurhash: String? var contentType: UTType? diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift index be7613d56e..466ba2a0f4 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/StickerRoomTimelineItem.swift @@ -17,10 +17,8 @@ struct StickerRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable { let sender: TimelineItemSender - let imageURL: URL + let imageInfo: ImageInfoProxy - var size: CGSize? - var aspectRatio: CGFloat? var blurhash: String? var properties = RoomTimelineItemProperties() diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index 13be1ddd38..4f0401a4b6 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -118,20 +118,10 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { private func buildStickerTimelineItem(_ eventItemProxy: EventTimelineItemProxy, _ body: String, - _ imageInfo: ImageInfo, + _ info: MatrixRustSDK.ImageInfo, _ imageURL: URL, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { - var imageSize: CGSize? - var imageAspectRatio: CGFloat? - - if let height = imageInfo.height, - let width = imageInfo.width { - imageSize = .init(width: CGFloat(width), height: CGFloat(height)) - - if width > 0, height > 0 { - imageAspectRatio = CGFloat(width) / CGFloat(height) - } - } + let imageInfo = ImageInfoProxy(url: imageURL, width: info.width, height: info.height, mimeType: info.mimetype) return StickerRoomTimelineItem(id: eventItemProxy.id, body: body, @@ -140,10 +130,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { isEditable: eventItemProxy.isEditable, canBeRepliedTo: eventItemProxy.canBeRepliedTo, sender: eventItemProxy.sender, - imageURL: imageURL, - size: imageSize, - aspectRatio: imageAspectRatio, - blurhash: imageInfo.blurhash, + imageInfo: imageInfo, + blurhash: info.blurhash, properties: RoomTimelineItemProperties(reactions: aggregateReactions(eventItemProxy.reactions), deliveryStatus: eventItemProxy.deliveryStatus, orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts), @@ -522,91 +510,47 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { let htmlCaption = messageContent.formattedCaption?.format == .html ? messageContent.formattedCaption?.body : nil let formattedCaption = htmlCaption != nil ? attributedStringBuilder.fromHTML(htmlCaption) : attributedStringBuilder.fromPlain(messageContent.caption) - let thumbnailSource = messageContent.info?.thumbnailSource.map { MediaSourceProxy(source: $0, mimeType: messageContent.info?.thumbnailInfo?.mimetype) } - - var thumbnailSize: CGSize? - var thumbnailAspectRatio: CGFloat? - - if let thumbnailInfo = messageContent.info?.thumbnailInfo, - let height = thumbnailInfo.height, - let width = thumbnailInfo.width { - thumbnailSize = .init(width: CGFloat(width), height: CGFloat(height)) - - if width > 0, height > 0 { - thumbnailAspectRatio = CGFloat(width) / CGFloat(height) - } - } - - var imageSize: CGSize? - var imageAspectRatio: CGFloat? + let thumbnailInfo = ImageInfoProxy(source: messageContent.info?.thumbnailSource, + width: messageContent.info?.thumbnailInfo?.width, + height: messageContent.info?.thumbnailInfo?.height, + mimeType: messageContent.info?.thumbnailInfo?.mimetype) - if let imageInfo = messageContent.info, - let height = imageInfo.height, - let width = imageInfo.width { - imageSize = .init(width: CGFloat(width), height: CGFloat(height)) - - if width > 0, height > 0 { - imageAspectRatio = CGFloat(width) / CGFloat(height) - } - } + let imageInfo = ImageInfoProxy(source: messageContent.source, + width: messageContent.info?.width, + height: messageContent.info?.height, + mimeType: messageContent.info?.mimetype) return .init(filename: messageContent.filename, caption: messageContent.caption, formattedCaption: formattedCaption, formattedCaptionHTMLString: htmlCaption, - source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype), - size: imageSize, - aspectRatio: imageAspectRatio, - thumbnailSource: thumbnailSource, - thumbnailSize: thumbnailSize, - thumbnailAspectRatio: thumbnailAspectRatio, + imageInfo: imageInfo, + thumbnailInfo: thumbnailInfo, blurhash: messageContent.info?.blurhash, contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename)) } - + private func buildVideoTimelineItemContent(_ messageContent: VideoMessageContent) -> VideoRoomTimelineItemContent { let htmlCaption = messageContent.formattedCaption?.format == .html ? messageContent.formattedCaption?.body : nil let formattedCaption = htmlCaption != nil ? attributedStringBuilder.fromHTML(htmlCaption) : attributedStringBuilder.fromPlain(messageContent.caption) - let thumbnailSource = messageContent.info?.thumbnailSource.map { MediaSourceProxy(source: $0, mimeType: messageContent.info?.thumbnailInfo?.mimetype) } - - var thumbnailSize: CGSize? - var thumbnailAspectRatio: CGFloat? + let thumbnailInfo = ImageInfoProxy(source: messageContent.info?.thumbnailSource, + width: messageContent.info?.thumbnailInfo?.width, + height: messageContent.info?.thumbnailInfo?.height, + mimeType: messageContent.info?.thumbnailInfo?.mimetype) - if let thumbnailInfo = messageContent.info?.thumbnailInfo, - let height = thumbnailInfo.height, - let width = thumbnailInfo.width { - thumbnailSize = .init(width: CGFloat(width), height: CGFloat(height)) - - if width > 0, height > 0 { - thumbnailAspectRatio = CGFloat(width) / CGFloat(height) - } - } - - var videoSize: CGSize? - var videoAspectRatio: CGFloat? - - if let videoInfo = messageContent.info, - let height = videoInfo.height, - let width = videoInfo.width { - videoSize = .init(width: CGFloat(width), height: CGFloat(height)) - - if width > 0, height > 0 { - videoAspectRatio = CGFloat(width) / CGFloat(height) - } - } + let videoInfo = VideoInfoProxy(source: messageContent.source, + duration: messageContent.info?.duration ?? 0, + width: messageContent.info?.width, + height: messageContent.info?.height, + mimeType: messageContent.info?.mimetype) return .init(filename: messageContent.filename, caption: messageContent.caption, formattedCaption: formattedCaption, formattedCaptionHTMLString: htmlCaption, - duration: messageContent.info?.duration ?? 0, - source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype), - size: videoSize, - aspectRatio: videoAspectRatio, - thumbnailSource: thumbnailSource, - thumbnailSize: thumbnailSize, - thumbnailAspectRatio: thumbnailAspectRatio, + videoInfo: videoInfo, + thumbnailInfo: thumbnailInfo, blurhash: messageContent.info?.blurhash, contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename)) } @@ -821,3 +765,12 @@ private extension RepliedToEventDetails { } } } + +private extension Receipt { + var dateTimestamp: Date? { + guard let timestamp else { + return nil + } + return Date(timeIntervalSince1970: TimeInterval(timestamp / 1000)) + } +} 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 cd99b8548f..92fed002bb 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:e96e572bd736c19bb9f3bd37216bd464276c9a1ebbd715fdae27973f9b6f36cc -size 333847 +oid sha256:82ce96aa44eb950fb131e85d6ceeab485a5985fb48c30b4d954c65602e77686a +size 281497 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 cd99b8548f..92fed002bb 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:e96e572bd736c19bb9f3bd37216bd464276c9a1ebbd715fdae27973f9b6f36cc -size 333847 +oid sha256:82ce96aa44eb950fb131e85d6ceeab485a5985fb48c30b4d954c65602e77686a +size 281497 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 2180dd9b0f..43321c49a7 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:13f6dfd3e07222ae3757076e453cf99695424db88c8cc85fede448ea64e70519 -size 276862 +oid sha256:d08539366199fb29c4f2b01b6b399426b928a0eaae94306441d0a6cf34be4a13 +size 225250 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 2180dd9b0f..43321c49a7 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:13f6dfd3e07222ae3757076e453cf99695424db88c8cc85fede448ea64e70519 -size 276862 +oid sha256:d08539366199fb29c4f2b01b6b399426b928a0eaae94306441d0a6cf34be4a13 +size 225250 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 a40034429b..dea3683a8d 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:bd110afc7d00be27146e58474b810415af9dc7d5ed6faf1536419f01f41f9a3a -size 404161 +oid sha256:26f2e07fa87d8ae6a910f30e992cf45e528715093663f40739e085c1349a6b31 +size 218285 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 a40034429b..dea3683a8d 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:bd110afc7d00be27146e58474b810415af9dc7d5ed6faf1536419f01f41f9a3a -size 404161 +oid sha256:26f2e07fa87d8ae6a910f30e992cf45e528715093663f40739e085c1349a6b31 +size 218285 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 3ab5d2b0bd..7ab6b4378a 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:ef76e5d6f293ae298df0e70744ffed330e1fcb4a1e1157fbd7578e59bbe52fd4 -size 336667 +oid sha256:23b75089dd40fc4c0c8cbaeb97f9659b19c22621133442e09ec7fc962cbae091 +size 167471 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 3ab5d2b0bd..7ab6b4378a 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:ef76e5d6f293ae298df0e70744ffed330e1fcb4a1e1157fbd7578e59bbe52fd4 -size 336667 +oid sha256:23b75089dd40fc4c0c8cbaeb97f9659b19c22621133442e09ec7fc962cbae091 +size 167471 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 18df7f1a0b..c11fbddd93 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:f0f9e472dd0a7675c25bc5856aca8f3e8ed94b157aa2dea3683e8a7cf17b588c -size 94892 +oid sha256:ba0a7cbad0cae44f11230bfd240445eeca207ddf22d6e3b5882e69d448cf2a9b +size 95167 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 18df7f1a0b..c11fbddd93 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:f0f9e472dd0a7675c25bc5856aca8f3e8ed94b157aa2dea3683e8a7cf17b588c -size 94892 +oid sha256:ba0a7cbad0cae44f11230bfd240445eeca207ddf22d6e3b5882e69d448cf2a9b +size 95167 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 d3bd5b56d3..4bb5d6f1f0 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:8e4e25d87b4335854f8cd67072ef0e8e89a50a9a56dbc10b6cf01ee725731767 -size 52197 +oid sha256:d74e45a7d9ceb6b72d3c64aa300fbc122f18aef4c3b6cef630850c3cd242a8c4 +size 52016 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 d3bd5b56d3..4bb5d6f1f0 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:8e4e25d87b4335854f8cd67072ef0e8e89a50a9a56dbc10b6cf01ee725731767 -size 52197 +oid sha256:d74e45a7d9ceb6b72d3c64aa300fbc122f18aef4c3b6cef630850c3cd242a8c4 +size 52016 diff --git a/UnitTests/Sources/LoggingTests.swift b/UnitTests/Sources/LoggingTests.swift index 9e2c34e7de..26595f3613 100644 --- a/UnitTests/Sources/LoggingTests.swift +++ b/UnitTests/Sources/LoggingTests.swift @@ -150,8 +150,8 @@ class LoggingTests: XCTestCase { sender: .init(id: "sender"), content: .init(filename: "ImageString", caption: "ImageString", - source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/gif"), - thumbnailSource: nil)) + imageInfo: .mockImage, + thumbnailInfo: nil)) let videoMessage = VideoRoomTimelineItem(id: .randomEvent, timestamp: "", isOutgoing: false, @@ -161,9 +161,8 @@ class LoggingTests: XCTestCase { sender: .init(id: "sender"), content: .init(filename: "VideoString", caption: "VideoString", - duration: 0, - source: nil, - thumbnailSource: nil)) + videoInfo: .mockVideo, + thumbnailInfo: nil)) let fileMessage = FileRoomTimelineItem(id: .randomEvent, timestamp: "", isOutgoing: false, From c888a5b4aa3e565af77d517190009655abd5640e Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Fri, 15 Nov 2024 13:42:53 +0000 Subject: [PATCH 26/74] Update compound (#3519) * Update compound textPlaceholder is now textSecondary. * Update compound again with support for button shapes on the plain button style. --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 6 +++--- .../Sources/Other/SwiftUI/Views/SFNumberedListView.swift | 2 +- .../Authentication/AuthenticationTextFieldStyle.swift | 2 +- .../Authentication/LoginScreen/View/LoginScreen.swift | 4 ++-- .../Sources/Screens/CreateRoom/View/CreateRoomScreen.swift | 2 +- .../Screens/HomeScreen/View/HomeScreenInviteCell.swift | 4 ++-- .../Screens/HomeScreen/View/HomeScreenKnockedCell.swift | 4 ++-- .../Sources/Screens/Timeline/View/TypingIndicatorView.swift | 2 +- .../PreviewTests/test_bugReport-iPad-en-GB.1.png | 4 ++-- .../PreviewTests/test_bugReport-iPad-en-GB.2.png | 4 ++-- .../PreviewTests/test_bugReport-iPad-pseudo.1.png | 4 ++-- .../PreviewTests/test_bugReport-iPad-pseudo.2.png | 4 ++-- .../PreviewTests/test_bugReport-iPhone-16-en-GB.1.png | 4 ++-- .../PreviewTests/test_bugReport-iPhone-16-en-GB.2.png | 4 ++-- .../PreviewTests/test_bugReport-iPhone-16-pseudo.1.png | 4 ++-- .../PreviewTests/test_bugReport-iPhone-16-pseudo.2.png | 4 ++-- ...ateRoom-iPad-en-GB.Create-Public-Room-existing-alias.png | 4 ++-- ...eateRoom-iPad-en-GB.Create-Public-Room-invalid-alias.png | 4 ++-- .../test_createRoom-iPad-en-GB.Create-Public-Room.png | 4 ++-- ...test_createRoom-iPad-en-GB.Create-Room-without-users.png | 4 ++-- .../PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png | 4 ++-- ...teRoom-iPad-pseudo.Create-Public-Room-existing-alias.png | 4 ++-- ...ateRoom-iPad-pseudo.Create-Public-Room-invalid-alias.png | 4 ++-- .../test_createRoom-iPad-pseudo.Create-Public-Room.png | 4 ++-- ...est_createRoom-iPad-pseudo.Create-Room-without-users.png | 4 ++-- .../test_createRoom-iPad-pseudo.Create-Room.png | 4 ++-- ...om-iPhone-16-en-GB.Create-Public-Room-existing-alias.png | 4 ++-- ...oom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png | 4 ++-- .../test_createRoom-iPhone-16-en-GB.Create-Public-Room.png | 4 ++-- ...createRoom-iPhone-16-en-GB.Create-Room-without-users.png | 4 ++-- .../test_createRoom-iPhone-16-en-GB.Create-Room.png | 4 ++-- ...m-iPhone-16-pseudo.Create-Public-Room-existing-alias.png | 4 ++-- ...om-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png | 4 ++-- .../test_createRoom-iPhone-16-pseudo.Create-Public-Room.png | 4 ++-- ...reateRoom-iPhone-16-pseudo.Create-Room-without-users.png | 4 ++-- .../test_createRoom-iPhone-16-pseudo.Create-Room.png | 4 ++-- .../test_deactivateAccountScreen-iPad-en-GB.1.png | 4 ++-- .../test_deactivateAccountScreen-iPad-pseudo.1.png | 4 ++-- .../test_deactivateAccountScreen-iPhone-16-en-GB.1.png | 4 ++-- .../test_deactivateAccountScreen-iPhone-16-pseudo.1.png | 4 ++-- .../test_emojiPickerScreen-iPad-en-GB.Screen.png | 4 ++-- .../test_emojiPickerScreen-iPad-pseudo.Screen.png | 4 ++-- .../test_emojiPickerScreen-iPhone-16-en-GB.Screen.png | 4 ++-- .../test_emojiPickerScreen-iPhone-16-pseudo.Screen.png | 4 ++-- .../PreviewTests/test_homeScreen-iPad-en-GB.Loaded.png | 4 ++-- .../PreviewTests/test_homeScreen-iPad-pseudo.Loaded.png | 4 ++-- .../PreviewTests/test_homeScreen-iPhone-16-en-GB.Loaded.png | 4 ++-- .../test_homeScreen-iPhone-16-pseudo.Loaded.png | 4 ++-- .../PreviewTests/test_homeScreenInviteCell-iPad-en-GB.1.png | 4 ++-- .../test_homeScreenInviteCell-iPad-pseudo.1.png | 4 ++-- .../test_homeScreenInviteCell-iPhone-16-en-GB.1.png | 4 ++-- .../test_homeScreenInviteCell-iPhone-16-pseudo.1.png | 4 ++-- .../test_homeScreenKnockedCell-iPad-en-GB.1.png | 4 ++-- .../test_homeScreenKnockedCell-iPad-pseudo.1.png | 4 ++-- .../test_homeScreenKnockedCell-iPhone-16-en-GB.1.png | 4 ++-- .../test_homeScreenKnockedCell-iPhone-16-pseudo.1.png | 4 ++-- .../PreviewTests/test_inviteUsersScreen-iPad-en-GB.1.png | 4 ++-- .../PreviewTests/test_inviteUsersScreen-iPad-pseudo.1.png | 4 ++-- .../test_inviteUsersScreen-iPhone-16-en-GB.1.png | 4 ++-- .../test_inviteUsersScreen-iPhone-16-pseudo.1.png | 4 ++-- .../PreviewTests/test_loginScreen-iPad-en-GB.matrix-org.png | 4 ++-- .../test_loginScreen-iPad-pseudo.matrix-org.png | 4 ++-- .../test_loginScreen-iPhone-16-en-GB.matrix-org.png | 4 ++-- .../test_loginScreen-iPhone-16-pseudo.matrix-org.png | 4 ++-- .../test_messageForwardingScreen-iPad-en-GB.1.png | 4 ++-- .../test_messageForwardingScreen-iPad-pseudo.1.png | 4 ++-- .../test_messageForwardingScreen-iPhone-16-en-GB.1.png | 4 ++-- .../test_messageForwardingScreen-iPhone-16-pseudo.1.png | 4 ++-- .../PreviewTests/test_pollFormScreen-iPad-en-GB.New.png | 4 ++-- .../PreviewTests/test_pollFormScreen-iPad-pseudo.New.png | 4 ++-- .../test_pollFormScreen-iPhone-16-en-GB.New.png | 4 ++-- .../test_pollFormScreen-iPhone-16-pseudo.New.png | 4 ++-- ...t_qRCodeLoginScreen-iPad-en-GB.Connection-not-secure.png | 4 ++-- .../test_qRCodeLoginScreen-iPad-en-GB.Initial.png | 4 ++-- ..._qRCodeLoginScreen-iPad-pseudo.Connection-not-secure.png | 4 ++-- .../test_qRCodeLoginScreen-iPad-pseudo.Initial.png | 4 ++-- ...odeLoginScreen-iPhone-16-en-GB.Connection-not-secure.png | 4 ++-- .../test_qRCodeLoginScreen-iPhone-16-en-GB.Initial.png | 4 ++-- ...deLoginScreen-iPhone-16-pseudo.Connection-not-secure.png | 4 ++-- .../test_qRCodeLoginScreen-iPhone-16-pseudo.Initial.png | 4 ++-- .../PreviewTests/test_reportContentScreen-iPad-en-GB.1.png | 4 ++-- .../PreviewTests/test_reportContentScreen-iPad-pseudo.1.png | 4 ++-- .../test_reportContentScreen-iPhone-16-en-GB.1.png | 4 ++-- .../test_reportContentScreen-iPhone-16-pseudo.1.png | 4 ++-- ...test_roomChangeRolesScreen-iPad-en-GB.Administrators.png | 4 ++-- .../test_roomChangeRolesScreen-iPad-en-GB.Moderators.png | 4 ++-- ...est_roomChangeRolesScreen-iPad-pseudo.Administrators.png | 4 ++-- .../test_roomChangeRolesScreen-iPad-pseudo.Moderators.png | 4 ++-- ...roomChangeRolesScreen-iPhone-16-en-GB.Administrators.png | 4 ++-- ...est_roomChangeRolesScreen-iPhone-16-en-GB.Moderators.png | 4 ++-- ...oomChangeRolesScreen-iPhone-16-pseudo.Administrators.png | 4 ++-- ...st_roomChangeRolesScreen-iPhone-16-pseudo.Moderators.png | 4 ++-- .../test_roomDetailsEditScreen-iPad-en-GB.Editable.png | 4 ++-- .../test_roomDetailsEditScreen-iPad-pseudo.Editable.png | 4 ++-- .../test_roomDetailsEditScreen-iPhone-16-en-GB.Editable.png | 4 ++-- ...test_roomDetailsEditScreen-iPhone-16-pseudo.Editable.png | 4 ++-- .../test_roomMembersListScreen-iPad-en-GB.Admin-Banned.png | 4 ++-- ..._roomMembersListScreen-iPad-en-GB.Admin-Empty-Banned.png | 4 ++-- .../test_roomMembersListScreen-iPad-en-GB.Admin-Members.png | 4 ++-- .../test_roomMembersListScreen-iPad-en-GB.Invites.png | 4 ++-- .../test_roomMembersListScreen-iPad-en-GB.Member.png | 4 ++-- .../test_roomMembersListScreen-iPad-pseudo.Admin-Banned.png | 4 ++-- ...roomMembersListScreen-iPad-pseudo.Admin-Empty-Banned.png | 4 ++-- ...test_roomMembersListScreen-iPad-pseudo.Admin-Members.png | 4 ++-- .../test_roomMembersListScreen-iPad-pseudo.Invites.png | 4 ++-- .../test_roomMembersListScreen-iPad-pseudo.Member.png | 4 ++-- ...t_roomMembersListScreen-iPhone-16-en-GB.Admin-Banned.png | 4 ++-- ...MembersListScreen-iPhone-16-en-GB.Admin-Empty-Banned.png | 4 ++-- ..._roomMembersListScreen-iPhone-16-en-GB.Admin-Members.png | 4 ++-- .../test_roomMembersListScreen-iPhone-16-en-GB.Invites.png | 4 ++-- .../test_roomMembersListScreen-iPhone-16-en-GB.Member.png | 4 ++-- ..._roomMembersListScreen-iPhone-16-pseudo.Admin-Banned.png | 4 ++-- ...embersListScreen-iPhone-16-pseudo.Admin-Empty-Banned.png | 4 ++-- ...roomMembersListScreen-iPhone-16-pseudo.Admin-Members.png | 4 ++-- .../test_roomMembersListScreen-iPhone-16-pseudo.Invites.png | 4 ++-- .../test_roomMembersListScreen-iPhone-16-pseudo.Member.png | 4 ++-- .../PreviewTests/test_roomSelectionScreen-iPad-en-GB.1.png | 4 ++-- .../PreviewTests/test_roomSelectionScreen-iPad-pseudo.1.png | 4 ++-- .../test_roomSelectionScreen-iPhone-16-en-GB.1.png | 4 ++-- .../test_roomSelectionScreen-iPhone-16-pseudo.1.png | 4 ++-- .../PreviewTests/test_sFNumberedListView-iPad-en-GB.1.png | 4 ++-- .../PreviewTests/test_sFNumberedListView-iPad-pseudo.1.png | 4 ++-- .../test_sFNumberedListView-iPhone-16-en-GB.1.png | 4 ++-- .../test_sFNumberedListView-iPhone-16-pseudo.1.png | 4 ++-- .../PreviewTests/test_serverSelection-iPad-en-GB.2.png | 4 ++-- .../PreviewTests/test_serverSelection-iPad-pseudo.2.png | 4 ++-- .../PreviewTests/test_serverSelection-iPhone-16-en-GB.2.png | 4 ++-- .../test_serverSelection-iPhone-16-pseudo.2.png | 4 ++-- .../PreviewTests/test_softLogoutScreen-iPad-en-GB.1.png | 4 ++-- .../PreviewTests/test_softLogoutScreen-iPad-en-GB.5.png | 4 ++-- .../PreviewTests/test_softLogoutScreen-iPad-pseudo.1.png | 4 ++-- .../PreviewTests/test_softLogoutScreen-iPad-pseudo.5.png | 4 ++-- .../test_softLogoutScreen-iPhone-16-en-GB.1.png | 4 ++-- .../test_softLogoutScreen-iPhone-16-en-GB.5.png | 4 ++-- .../test_softLogoutScreen-iPhone-16-pseudo.1.png | 4 ++-- .../test_softLogoutScreen-iPhone-16-pseudo.5.png | 4 ++-- .../PreviewTests/test_startChatScreen-iPad-en-GB.1.png | 4 ++-- .../PreviewTests/test_startChatScreen-iPad-pseudo.1.png | 4 ++-- .../PreviewTests/test_startChatScreen-iPhone-16-en-GB.1.png | 4 ++-- .../test_startChatScreen-iPhone-16-pseudo.1.png | 4 ++-- .../PreviewTests/test_typingIndicatorView-iPad-en-GB.1.png | 4 ++-- .../PreviewTests/test_typingIndicatorView-iPad-pseudo.1.png | 4 ++-- .../test_typingIndicatorView-iPhone-16-en-GB.1.png | 4 ++-- .../test_typingIndicatorView-iPhone-16-pseudo.1.png | 4 ++-- .../test_userDetailsEditScreen-iPad-en-GB.1.png | 4 ++-- .../test_userDetailsEditScreen-iPad-pseudo.1.png | 4 ++-- .../test_userDetailsEditScreen-iPhone-16-en-GB.1.png | 4 ++-- .../test_userDetailsEditScreen-iPhone-16-pseudo.1.png | 4 ++-- project.yml | 2 +- 150 files changed, 295 insertions(+), 295 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index f09a8d4bbd..3d48cc4cb9 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -8249,7 +8249,7 @@ repositoryURL = "https://github.com/element-hq/compound-ios"; requirement = { kind = revision; - revision = 950a8884e269194e6030cbddabebbb116cdfe02a; + revision = 4af41551fb7a7b9da0fd95171f2dec554726fadd; }; }; 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 7607c0996c..fe9b061d23 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" : "f9510e9d309b5aeefe9a7ef6b8c073c84337d4e9", - "version" : "1.9.1" + "revision" : "6190515a2af1eb1cb02114270fd536f1b6daa518", + "version" : "2.0.1" } }, { @@ -15,7 +15,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/compound-ios", "state" : { - "revision" : "950a8884e269194e6030cbddabebbb116cdfe02a" + "revision" : "4af41551fb7a7b9da0fd95171f2dec554726fadd" } }, { diff --git a/ElementX/Sources/Other/SwiftUI/Views/SFNumberedListView.swift b/ElementX/Sources/Other/SwiftUI/Views/SFNumberedListView.swift index b3e4e36026..c3f78573ad 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/SFNumberedListView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/SFNumberedListView.swift @@ -21,7 +21,7 @@ struct SFNumberedListView: View { Image(systemSymbol: getSymbol(for: index)) .imageScale(.large) .fontWeight(.light) - .foregroundColor(.compound.textPlaceholder) + .foregroundColor(.compound.textSecondary) } .foregroundColor(.compound.textPrimary) .font(.compound.bodyMD) diff --git a/ElementX/Sources/Screens/Authentication/AuthenticationTextFieldStyle.swift b/ElementX/Sources/Screens/Authentication/AuthenticationTextFieldStyle.swift index 1255344931..bb89fe58bb 100644 --- a/ElementX/Sources/Screens/Authentication/AuthenticationTextFieldStyle.swift +++ b/ElementX/Sources/Screens/Authentication/AuthenticationTextFieldStyle.swift @@ -68,7 +68,7 @@ public struct AuthenticationTextFieldStyle: TextFieldStyle { /// The color of the placeholder text inside the text field. private var placeholderColor: UIColor { - .compound.textPlaceholder + .compound.textSecondary } /// The color of the label above the text field. diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift index 3226fcd928..1d782858e6 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift @@ -66,7 +66,7 @@ struct LoginScreen: View { .padding(.bottom, 8) TextField(text: $context.username) { - Text(L10n.commonUsername).foregroundColor(.compound.textPlaceholder) + Text(L10n.commonUsername).foregroundColor(.compound.textSecondary) } .focused($isUsernameFocused) .textFieldStyle(.authentication(accessibilityIdentifier: A11yIdentifiers.loginScreen.emailUsername)) @@ -81,7 +81,7 @@ struct LoginScreen: View { .padding(.bottom, 20) SecureField(text: $context.password) { - Text(L10n.commonPassword).foregroundColor(.compound.textPlaceholder) + Text(L10n.commonPassword).foregroundColor(.compound.textSecondary) } .focused($isPasswordFocused) .textFieldStyle(.authentication(accessibilityIdentifier: A11yIdentifiers.loginScreen.password)) diff --git a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift index be52464a9f..ff7fae7d93 100644 --- a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift +++ b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift @@ -66,7 +66,7 @@ struct CreateRoomScreen: View { TextField(L10n.screenCreateRoomRoomNameLabel, text: roomNameBinding, - prompt: Text(L10n.commonRoomNamePlaceholder).foregroundColor(.compound.textPlaceholder), + prompt: Text(L10n.commonRoomNamePlaceholder).foregroundColor(.compound.textSecondary), axis: .horizontal) .focused($focus, equals: .name) .accessibilityIdentifier(A11yIdentifiers.createRoomScreen.roomName) diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift index 2abc3a7701..4eb7606ff9 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift @@ -73,7 +73,7 @@ struct HomeScreenInviteCell: View { !room.isDirect { RoomInviterLabel(inviter: inviter, mediaProvider: context.mediaProvider) .font(.compound.bodyMD) - .foregroundStyle(.compound.textPlaceholder) + .foregroundStyle(.compound.textSecondary) } } @@ -88,7 +88,7 @@ struct HomeScreenInviteCell: View { if let subtitle { Text(subtitle) .font(.compound.bodyMD) - .foregroundColor(.compound.textPlaceholder) + .foregroundColor(.compound.textSecondary) } } .frame(maxWidth: .infinity, alignment: .leading) diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift index a1cdf9bfb4..0f0f64717e 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift @@ -56,7 +56,7 @@ struct HomeScreenKnockedCell: View { Text(L10n.screenRoomlistKnockEventSentDescription) .font(.compound.bodyMD) - .foregroundStyle(.compound.textPlaceholder) + .foregroundStyle(.compound.textSecondary) .padding(.top, room.canonicalAlias == nil ? 0 : 4) .padding(.trailing, 16) } @@ -76,7 +76,7 @@ struct HomeScreenKnockedCell: View { if let subtitle { Text(subtitle) .font(.compound.bodyMD) - .foregroundColor(.compound.textPlaceholder) + .foregroundColor(.compound.textSecondary) } } .frame(maxWidth: .infinity, alignment: .leading) diff --git a/ElementX/Sources/Screens/Timeline/View/TypingIndicatorView.swift b/ElementX/Sources/Screens/Timeline/View/TypingIndicatorView.swift index e927cda08d..458b9c8ebf 100644 --- a/ElementX/Sources/Screens/Timeline/View/TypingIndicatorView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TypingIndicatorView.swift @@ -14,7 +14,7 @@ struct TypingIndicatorView: View { var body: some View { content .font(.compound.bodySM) - .foregroundColor(.compound.textPlaceholder) + .foregroundColor(.compound.textSecondary) .lineLimit(1) .truncationMode(.middle) .padding(.horizontal, 4) diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.1.png index b828a03bc4..9a6c649937 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a630df63ebb09adbc2a582c467c245664bb590e3da2ccee4543522cb4222c384 -size 156374 +oid sha256:fecd3111a0fa214ddd4abee38ed961dd8fc466a12c9364d835ffe63689317b84 +size 156583 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.2.png index fb5ea2c6a4..b73c8919c6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.2.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-en-GB.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:388c30b2d7eb90e90331c5c05b3a7850c073bc27f6c7978fa306cb320cda6b38 -size 205646 +oid sha256:e2f6e093ef7e0b912b729c33e94d6c16cc7c825468a7277d6f3c015eebeabed6 +size 205892 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.1.png index 73d3529729..3f23b4180c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b94e9e5b8929235c3dc577b61cce527d95b0f499760a55b9e48b9451d100fa9 -size 195199 +oid sha256:112b92c11fe9d9a02aafe75882d0a8be2f15498155a895f1cd2852e4cc8cc7fe +size 195537 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.2.png index 42b009a8de..5b6e899189 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.2.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPad-pseudo.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:261467174d0e96432d963ca4a9924dc0ecabef796670410bacf6d30c60028229 -size 241882 +oid sha256:4285cf44166fdb0238c19f54d30bcb280f2f7492b288d120bb90340f71bfc147 +size 242121 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.1.png index 3ccb34510e..d45824d539 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f25c322c0d96697ebbfe37cc8f41968437e85b87f97e748cdea491488f8cb75 -size 112639 +oid sha256:abdea04bd52cee2f739b7fdad40f355be6963a7b10ca99e58a4100a9c68446f7 +size 112957 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.2.png index e499cdfb02..456ed6a591 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.2.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-en-GB.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e63f79d033afa74e531694a0c12494e35338d6ec8ae79af4994329b1cfa9760 -size 157066 +oid sha256:0b5cb32e67d806808b7f6a96c7a5d55dc35176664986a9a14180db9e9ad1d0d4 +size 157365 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.1.png index e5ab66f18f..dd7cf09cfa 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbfaf0931f09c371773b709625af2043bb071466f2747a0b103bfeac35ccb418 -size 165823 +oid sha256:38a2bb03bbc411215d00c4fc7eff2eb2249558c63a9d52d51281f7371b56341c +size 166303 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.2.png index 1dd2e71f1f..cd2b345c4b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.2.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_bugReport-iPhone-16-pseudo.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b423001dd6139ac4c68427bb5eab3200af160c65f445eb9eca4028d4cba653ee -size 192079 +oid sha256:c5740a2364880425b8667d6d32f83b04e8380637e32c59e4fd310db1fbc413e0 +size 192547 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png index a048c452d3..36ad9e2928 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9650c6b430799996d02b0d34cf9d8657c94a5b5627dde3cb74755b5020619cf6 -size 202009 +oid sha256:45b5411fcb1ccc302a743d6d09374ca862f0d53a2b38efcfe67a44d316384bf9 +size 202406 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-invalid-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-invalid-alias.png index 8ce2cc596c..58132b902f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-invalid-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-invalid-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7563d6820945006a48db647fed692d4458338d63669ea4c344052f5a63a4a2ee -size 204578 +oid sha256:a013f5a13f6ec97393b54bd59f6278b86238b572859cdbb7806585b00157cd8f +size 204975 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room.png index 93564aa4d5..8ee0ab7768 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f630b2ae196d0f8d9b98b68482863ea78aa84eb5e9b82e78d77430ec81dc007 -size 194309 +oid sha256:b459497a44a178d228198987e87ab236685a3272b08e381a93eb4e28876d74b6 +size 194706 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png index 107a06bd65..800cdc97c2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room-without-users.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:860a4367f4ab161be805df36b2723829e023db753c45f9f49ecc126f6a2cc128 -size 145345 +oid sha256:34f2c510e9e203264258aeb9cc9a06f184ee95cb6a29214ce0bfb7a52e67341a +size 145737 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png index c06ac05586..68fa1a3c8b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0a28cc070627724c44111ee0736006650e1453d85be6038783073d911f3d909 -size 144730 +oid sha256:6f54af4eb05cbab2d2466403a05fd2c0ca08d8ee17d105af580398d323fbbc98 +size 145252 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-existing-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-existing-alias.png index 35ad913994..7b0e1da3db 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-existing-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-existing-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f255ed8f26b1f9efd108b7b0422262185f45152495727578822fb0691bfe08a9 -size 228341 +oid sha256:c9cbd086e76c99df68fea889bf0b14f03fc528de6edaedda31cc91c65f09dc6d +size 228726 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-invalid-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-invalid-alias.png index 8b49055f95..e7247b79ad 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-invalid-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room-invalid-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b42242042ad3adf3b953a29ff58792511076930892a7bda4d813b3e3218f39e0 -size 226407 +oid sha256:7cbfcf9b956ebba52ed6cc5c50cb3e55330e03b2b0dedd30c79f6defc8a2fb06 +size 226792 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room.png index e383e0a7ce..1f245ed40f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Public-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6f47df77fca87c83e7668b95a500c5b7d0a0640d694a7b92c58365573d0abd6 -size 224351 +oid sha256:d62227f967a95c7c2e39c9aa17343869bd4828899c2b8570f66fbc2d45118427 +size 224736 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png index 8ca3e931d6..5c220ab47f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room-without-users.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9311de66c92307e15ac5d62c025c953d20ce42e946eaaab30604f754ce6d395 -size 171925 +oid sha256:6e42fb371b03dd14fade9da3ee085314adf68cc9c5e39f6d97087ffe81fbabdd +size 172311 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png index 800e0982e7..0f9f6a9cb8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-pseudo.Create-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:662701144b88061103f80d08c078a28ca918e768e4907e4100fd56941098acfa -size 173078 +oid sha256:f73825a4aa70c6a55d7f062fe674b0f2b766469343c6b4411f4af1940524c634 +size 173492 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png index 0c9b80f2e0..638b6da4f2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-existing-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2eae9a04d15e762cf6b176bb3bd5821b89bdb211699117afb808861bddd78a22 -size 129989 +oid sha256:43b54cc80fa66318f51aab25bf1da468d5fb80bd1a3e3e421a09976a099b5f2b +size 130312 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png index 1fa9061ceb..3e731c7a7a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room-invalid-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6888c9b3c1a7040d71398aeb79c1a4573dd5596eee4c914ab58b2aca3954de0e -size 128543 +oid sha256:243f03c80c7b5cfb73a8e7dd974b95b20b97e08dc0c39bfb452f874a12f4d7a7 +size 128866 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png index e716343e71..14cb645161 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Public-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:899d2b2ed4da2bf70ada0e6fd4321aef6b962f6da3a35eeeed7f6b56b7d6fe59 -size 126876 +oid sha256:0860ca1766635147002c8f3253cd96342fd5db0da8a0e8507d8f1bb6da81a7ea +size 127199 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png index b45b2e80ef..9c40d31727 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room-without-users.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:edf83c0605163d2207d25c80a1a4114f80c7a132655da7c4f2e02fb278e1aeda -size 95990 +oid sha256:87798e15e4929dd518b4733e89ed88576a775ac395137094d26fc799ebd6ca7d +size 96316 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png index 0749b3e7a3..6be6f42c34 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-en-GB.Create-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90b9741e61b00917ccfbd419f34af981eb9f944a30e15620ec269d70dafa66a8 -size 96294 +oid sha256:1d046772ea3846acbe9ef68f573171d28fbc83188fbed21430e1d21528f0d895 +size 96665 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png index 580ea9f7d9..bd9864db04 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-existing-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80d33358e3425fc1997f4e88d60b49b0a239302e9addc2e82c104e06fc6e4827 -size 163893 +oid sha256:9eef46ce00dd0109951470ae8b12423e9f6675d3e6ed12d28635febb157aec5a +size 164509 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png index 580ea9f7d9..bd9864db04 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room-invalid-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80d33358e3425fc1997f4e88d60b49b0a239302e9addc2e82c104e06fc6e4827 -size 163893 +oid sha256:9eef46ce00dd0109951470ae8b12423e9f6675d3e6ed12d28635febb157aec5a +size 164509 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png index 580ea9f7d9..bd9864db04 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Public-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80d33358e3425fc1997f4e88d60b49b0a239302e9addc2e82c104e06fc6e4827 -size 163893 +oid sha256:9eef46ce00dd0109951470ae8b12423e9f6675d3e6ed12d28635febb157aec5a +size 164509 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png index 8d1c9f7cc7..64177d2ba3 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room-without-users.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02db1a440a19b94afd8d5d8876b83d003459c76c95c8c76ebd2a351fb8177b94 -size 126452 +oid sha256:600ce81a26eb906ab40462af4c73badf5a5c12fe8e84376f43eb58a66068561a +size 127069 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png index 4ee0a1009a..90de44a1de 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPhone-16-pseudo.Create-Room.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4c2d75263491ba4ab1153d3281a14d752b22381c4f49bf853b8e0f68f6b324e -size 126969 +oid sha256:8ed123ad17a24c3d49629ff7fe006095e55a7e11b00d9223410cbd5cc26ced45 +size 127639 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-en-GB.1.png index b0c7cf957a..308b4f50e5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eb884b89ca3e8cbcc7db88df0fa167e83548ea66a56b60afab6ef21b669e76db -size 169987 +oid sha256:b6c83a5751c9c7cf6e625f6af70348cfa79eab795b2e1980b62c86453bde39c5 +size 170117 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-pseudo.1.png index 313b7ce595..abc56ecaa8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0258e979e9ecabb3632bfdec3f4b6a5f599ca37a9a6a465af6d2e5a8680f50d7 -size 219349 +oid sha256:86b1112d409e95c0b11b79beda379df9c9001af10a23d3f4c28d7860b50f6911 +size 219450 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPhone-16-en-GB.1.png index 2b79870842..a23c6f8ae5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f84fd74f90a963fda1925746366c51b3db2226499bb2d0e3eb84841f20bc399 -size 121896 +oid sha256:52f61c472fe2b3bf53a0f8087f22afacfce046b2c6f891006efd307cb937a298 +size 122018 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPhone-16-pseudo.1.png index 677ea9520c..1d2021ea44 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_deactivateAccountScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:18f70a5032d165efc76a409665a2a25ada0b4a69874b394485b0623d672146f7 -size 190128 +oid sha256:b731365369df302aff21aa68778ab4b505f4618ea40edd9858e863cb0d1e2635 +size 190318 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-en-GB.Screen.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-en-GB.Screen.png index d86c93fce4..21bebd48bc 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-en-GB.Screen.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-en-GB.Screen.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2b48d32a6432c287245037691aa0f576e3ca63468656bf96c73bbc408a45592 -size 983108 +oid sha256:54bbf2be960ebae83cf6eb21d7d428f3e1afe81e4c83c4724c6845d7da7ba989 +size 983177 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-pseudo.Screen.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-pseudo.Screen.png index 42a40ca7d0..800d54a4a8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-pseudo.Screen.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPad-pseudo.Screen.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12609820bc5591c07fc2c8c2701906199f7e083d278b32e87ae1793f1c338728 -size 986590 +oid sha256:3fd1b1598d6166d0e50c03b9fb83eec32dbe498ecc84096ac38f9ffbff9189e7 +size 986603 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-16-en-GB.Screen.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-16-en-GB.Screen.png index afcfe3ebff..3f9d12ae36 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-16-en-GB.Screen.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-16-en-GB.Screen.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:719a9f2d4a69ff30f6eedf146bb6cef2e79e4a6dabcdcc10a8429435531eb75d -size 362302 +oid sha256:56297f717ebe6fab68ef4988cca7eac9345c376e95b88038b9faf69d6aefcd9a +size 362368 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-16-pseudo.Screen.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-16-pseudo.Screen.png index 680877471f..6b2c400824 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-16-pseudo.Screen.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_emojiPickerScreen-iPhone-16-pseudo.Screen.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7bd897cd6531b60437deda1a94f0a87c21e5ea33fdaf483eb699e99a4fd44908 -size 365397 +oid sha256:51e9b020c76b49031a34cb532afbc9c9339ae7eaf20248d748758556be649849 +size 365501 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 d3262ec39a..6ca74c12df 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:6446cbff232a333151b62687164c119345a6b59f9bfb4f9f6684df607d6e7063 -size 242207 +oid sha256:495dbe5adefdc1598ec80beea331d0f78de7021992cbca9459060e9956fe006a +size 242329 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 3e869c730a..756bbda259 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:1ad49c6c1b92c9e7c474fd232ff063b38ba82b6ca7d9836ddf81221e06c00756 -size 245418 +oid sha256:8f8540714ee55258a4e4bc904ad249bad76664987a37e43f027fca0fbf88319c +size 245488 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 45e17c03c9..d5443fc4e6 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:5090cca7e3b49782ad27006c8c6980f264f4e493fd8fa2b35c0a1ee6164b0b3a -size 178329 +oid sha256:1f147d11e7430cee9703d6ffd1d77aff7eaaaea933f563391864ea05d7a4ee0c +size 178416 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 4499b658e6..981a244a45 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:806e066b3632f2a73012c2bea9993f2f5026304235fd5ea072321a5f3db7e4f3 -size 180923 +oid sha256:bdf467b1fe27e468487ec97153f7e25b12305c30397b4ebf74e85fe260da576c +size 181049 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 bcb4a921f3..ecb5e6d2eb 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:3420eee65c57587b3287a61345c17ca75fc79a75c7a85e23c13c8a03ddf640f5 -size 257422 +oid sha256:5a992e048e1aac5508ad22d87a7765e44b8a9aee0b6a39b1ba49b11193a2ecaf +size 259331 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 d49724e39d..201e0ee906 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:886597e8eff82ba4a4cbaa47452ae9c3e702856a8935fca30a41c9f860be53ad -size 273084 +oid sha256:5197c5a72cb20ed5e560c1066d667baf08430356e7a4c9d4afa8791d43fb2b58 +size 274945 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 4dd1bc0e8b..815ed49fb6 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:6941a571d3966f2d5de5066a95703bd10e942c8fa1d8ab7e1ea67e50877a6f21 -size 174158 +oid sha256:0c5a0737e9311c83483d6c11a80ace664ff9cf6c0f197aa908eea125b524f8e2 +size 175689 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 c0ac14816b..3fe419dde8 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:9a96f9368397992073d5f58d6e136182cfcb592b67c341a7d9fab4f1e4a71752 -size 193454 +oid sha256:553f92fd699ac9280c3f8d5cadbdafd7e79a266e68fcdd0bfdedadc760cd8269 +size 194749 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 874d536301..22451945c0 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:37d4585f90bb64bf739101413ed1a7e24db10161670bd0ba38409e146b31645f -size 175190 +oid sha256:05bd2d1fcf45e1027fcda440616ad6244b6652ce6088d654b27d5ac0461669cc +size 176959 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 750e5a441f..792d286ff0 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:216f3373784519707d3659d6282a1c59202f189407c2f1226bdff510a5f9261c -size 188573 +oid sha256:45b8896561b5b8b0dcb899a7a684eb0057383d668076198b3eba38c8fbf8fc17 +size 190293 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 b819d05cd5..2ac478ebdf 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:c674069ca803e934769bb070a528e415ca12de00f722fbb67bf0624a1f24305f -size 120759 +oid sha256:1d385a376913dbe1fd2f89357e66be6a93272deeb88ef2c68c4fbcf5626e2bf7 +size 122079 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 adc229bec1..e0790c12f4 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:1d39cc8560c7f57e27764b782dd5ef07e31d883d265f675d8e4f394dccd82e69 -size 142235 +oid sha256:a9a7709d84f25f4e66acc254ca04eac7a7361f87312bb34297bc88762c3601b5 +size 144308 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-en-GB.1.png index 658e8341f9..b430df0bab 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:137a69e36ec893a296f561ee7cfea1dea12150af45230333913f0a59a6d89a5b -size 86547 +oid sha256:96ca7ca00c3a67797876ca1aca2318dbdcfdb47703a620b84af6131296c031f9 +size 86557 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-pseudo.1.png index 65f03ff89c..d15213997c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee7e2090ff06b5594acd6df4410c8b160c7ede89cf630ad5b432caae39d33054 -size 89052 +oid sha256:fd6cc6daa3e574ed76b6ae02084fbcd73e9982b703200139f680532aa1bc32ef +size 89063 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-16-en-GB.1.png index 39842c8146..ac24977068 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2adccdf1a50ac993c1022959f955214ebd57c06d1a937b5ce24dade3a7c407e -size 41195 +oid sha256:88013d3102b7d37ff7844887fa99986b00f032556804593d924e792a2205dd24 +size 41296 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-16-pseudo.1.png index 872f01fd7c..1677bf8269 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_inviteUsersScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ac705453f81bd9dc87b8e446c9f7d0a88762015d6e30854b0c1ce106eff113a -size 43291 +oid sha256:511d2ac95d2f19aaa1876da61fe9dffcfe3b6a7d54e9c81ff859092b4aa5dff1 +size 43366 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.matrix-org.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.matrix-org.png index 48d2bffdc4..dc8891ee92 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.matrix-org.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-en-GB.matrix-org.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42c3d1d51c27e4c9ad7d35688d4050d97fd7d165e77223e609c82dc6631b7ac6 -size 94453 +oid sha256:fdc91c454b7c333d706198e526b7340287514c6ff1fbce07eb89dca7167df8cb +size 94615 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.matrix-org.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.matrix-org.png index 120e71f320..1f17b82326 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.matrix-org.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPad-pseudo.matrix-org.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7dd98bf3e8d9450b90902c5d9b78c33fc01a9cf76f1bdb3084a619b97bf09f04 -size 99360 +oid sha256:88e8820497ae40c1ac56d8f0a46ff323554de3d2b1a26b13323bd5bda6e08e1a +size 99601 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.matrix-org.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.matrix-org.png index 3a6bd61b01..7c21f7b877 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.matrix-org.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-en-GB.matrix-org.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e8f48a5189f53a45cf504da4d6828677df479036011660e218fa9582e6a53f5 -size 50317 +oid sha256:7cf3bfb6a9a040f3b880bed7b8c4bc6de4830fff2f4bb9293957661bf5aef61b +size 50497 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.matrix-org.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.matrix-org.png index 2a3f6df701..6b2db86f08 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.matrix-org.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_loginScreen-iPhone-16-pseudo.matrix-org.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b311840717a31f6fe7a70a6bf61a8a2556941bdad9c2caee94dbea781fe5fe76 -size 59181 +oid sha256:c39569a892c1d6df94c18b6bc879ccc99a65d24a8f5ea426d33343166969a83c +size 59466 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 a484a78c47..ecac4d2963 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:1705df7384f16656d63d4efca503b4533cd3d67f54733855f284ddc49cdf973f -size 149086 +oid sha256:7d2de8898d28006764b1800937cb310b8e1cc0412ee7307c793096f050a80f9a +size 149110 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 e2223527cd..00d2660199 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:de6fe930505a8b4e9ab2b3052ebd1345118eaa64149381f28b3142447722d61a -size 151009 +oid sha256:b071f66bb5f21fb1bb8362dd2814252c648cb096d7018d085677312854942520 +size 150997 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 8e24daa0ca..8c1cbc6d3b 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:96596029a45f8bc48da6f8cbd77f09eb65236ac111534d9dec7d45e0e083cf32 -size 99144 +oid sha256:5399fdd67f117a607c064937bdda1ca9982d22ce19050b7f4cc9cd919f9fc8bd +size 99181 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 4c51e28475..e76c8e5ba8 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:dd2bd5da5c119e827b8b195971a34b645d5e47f577bf622e5856412c91d616e2 -size 98976 +oid sha256:0bdb9abcd374036fed3db3f52a0cce19c645fafd38117b20f986ec1921fc8f32 +size 99018 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.New.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.New.png index c3d3f73b59..3c4c6c3d86 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.New.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-en-GB.New.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a4304db38a7991bcaa33d1266968f023811bc2184fdf0b34b1ecc27b5a841d2 -size 122158 +oid sha256:4491fd198f3b9bd21cbb07f466ada9cba753975eef4db7c4e0f229484f0eb038 +size 122633 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.New.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.New.png index 802cc7f1bd..982e497b05 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.New.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPad-pseudo.New.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e45b9a0ba61580509d623751b5fba479a39e2d8394ea46b0b1af52c08581822 -size 132210 +oid sha256:39bc16d2356c9c28d54a7f221ff31caefb6d7d1c51f8b1243421a7d0f5754f6c +size 133043 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.New.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.New.png index 7c2aae7658..90c3033b24 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.New.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-en-GB.New.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9be456bd194cff211021f905cd730221cf906e236b0b8879962a38e1d43e4598 -size 71615 +oid sha256:1a16f5eb36c8f0c8e4b95afe8379663b1b78a2b35275e403c7b79821653e9ff2 +size 72339 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.New.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.New.png index e794b6aeb5..52d5eb3c3c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.New.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_pollFormScreen-iPhone-16-pseudo.New.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42b87fe104dff813561d71281324db46beeb6ff13983e392e63ae50234758705 -size 87830 +oid sha256:45cf38fe9c24b4cfae54aacc09321df3ac3e5f022bf44eaa25d200bcc315a1f4 +size 88655 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connection-not-secure.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connection-not-secure.png index 7a7baaf94d..27bf5d8649 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connection-not-secure.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Connection-not-secure.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2438be958a801fe7938c2e7df5a0ced027f9179ca1d42479d03b9db25a97f5d9 -size 160064 +oid sha256:788557eb44410a4cd9cc681a83d8ae81d7fb816a846145e99d34e982150815d8 +size 160069 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Initial.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Initial.png index c68afdc757..7cbb572e2d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Initial.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Initial.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2721166398d184d26983211c370bc4f6ea9e1d280f3466945bfe1c6ae5420528 -size 145904 +oid sha256:5da92420d8e93c51ea65372adffdf5e97cb6ccc4f36701d7405fff73f43b3825 +size 145952 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connection-not-secure.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connection-not-secure.png index 975d0f9a05..2a20826921 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connection-not-secure.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Connection-not-secure.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:afeb94794158a4a94e286a824403b6a1a608f4af9ee5a82d0a189567ae9bd474 -size 212113 +oid sha256:5355925a6e3145c780034847cf41e4255be3c6dd98fcae06e662579b9e2a2986 +size 212206 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Initial.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Initial.png index 5aaff947e5..411799e3b4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Initial.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Initial.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc3e0790ee7dcbc0801fdb324423ac11a6075c384a2b3a455dcf3695022633c6 -size 179327 +oid sha256:38cbdca8e6246eb8e64654050c451651667007ec126ecd4bfe7403ddffdd6518 +size 179450 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Connection-not-secure.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Connection-not-secure.png index e465712048..50ec94b2e6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Connection-not-secure.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Connection-not-secure.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a7c7802476261e350ec1ea2b5b25b92f0482658983da5b5b689faac232d0064 -size 107679 +oid sha256:3741d7a3f96d3f4d36b1b99b724433ff2a1b0f1614db45647dfb3cb023f16bfd +size 107735 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Initial.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Initial.png index 0a4e391acc..d593ebcc43 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Initial.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-en-GB.Initial.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:795d23135ed05cb33aefb8e11caaf26adc8251c5fd912b571b15f56ff5eb707a -size 92756 +oid sha256:72b947b6b623c98a079e3b55904727a0c3b7d8bb0ce33ab0106aed2c09adfa49 +size 92776 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Connection-not-secure.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Connection-not-secure.png index 4ad6c4aac2..3541b0bf41 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Connection-not-secure.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Connection-not-secure.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d696e75100c016d520f2dfa2bc84bcea8fa6653a4eacc236eb0bfe78e815254d -size 165619 +oid sha256:7363eb88a746c17c4465f6c951aa88f6d42fab58e35173388cec6766f6f2fd88 +size 165735 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Initial.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Initial.png index fa5e41e8a1..eb1a8f6a61 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Initial.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-16-pseudo.Initial.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d35ebb140a4b6ae9f32e3fcd9e2b492efda4708661feb2c88d03437f102b5a28 -size 133491 +oid sha256:d3227e00e6575e59de30553a84b2f01c994c37fc5392cc5b18d91027bc89aa96 +size 133705 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-en-GB.1.png index 91723317e9..cf0afdbb8b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f232c3e6380680ee984f9aab0dea0c81ed730abd9822a174f36a25e56b5d36ad -size 123079 +oid sha256:075c0fe72d9a9e986fafba95c23c1e84c618f0fc237eaa6f674ee2cc90278479 +size 123244 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-pseudo.1.png index 9b69e8ae1c..471320b412 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f0ba1eecf3a7a4e2a0b9629292a07095640901001c714a87120735d9420dd3c -size 144852 +oid sha256:1b380c62be4ba81ab2d8801448b74ee931fc45468d51cdcc7c0476e47d3f9dab +size 145087 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-en-GB.1.png index 0b1a9cae13..ee2487ea1f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5dcdb831ac0280b214032b69541fb2477d7b7fe424ba8f736a4653ecffa15ecf -size 76949 +oid sha256:66d9c771298d57eb8f97ecde5faeb79897afe029bea3c714f24661dad889b8d5 +size 77107 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-pseudo.1.png index ccb0217769..e55e946810 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_reportContentScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10e930e4812753de6c21166119c60c770a4319eb143884eef1f095ccac661110 -size 108956 +oid sha256:35808c962645e246edc0787eec8d751c7f9f96f8ca4e7ed770dca54cc60c8db2 +size 109800 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 198ec0bb23..f2049aea96 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:988cea50144bdf8d69d6d1e3b973e2dabe4cb063b1d8b2b7c66eab31aaf17a98 -size 189938 +oid sha256:aa40acc4d971eb7adbc9f31a8a4921af1c22b6173a57805a4c0067a8a2dab4d4 +size 189949 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 3a284c366a..ace239f78e 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:697e1ccf98b419d86cec1a7cca617be7ef9308822756356713a9e840118e19ea -size 175223 +oid sha256:de6759b723c8b82abec292e26432c589408e883afe5c07b342487045476e1157 +size 175236 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 3af17f8ef8..0d56b1674a 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:f063d70cd89c19be28f7069000d536be933b759f39c87a15bf3fc88246c1570f -size 196100 +oid sha256:596a2aea404884e9deaa097c953e5504b6dacfbc1749ddaad75dd4b5beaa97c0 +size 196256 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 a1f7e413bc..020e1fa895 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:a8122c0fb9778e3a3478e820b354844249e68d70562232a57e349242a86d3de7 -size 185772 +oid sha256:c66c41ceec7479076a4812dbcc3400a061d1cb12c13401a5847851fd85621879 +size 185926 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 0eb1288bdb..3db96d2b6a 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:72dd7af6ed995597f92399822ea9469af8a6cc68a591090a19b8985533d24deb -size 141580 +oid sha256:c0ddd29baf3219e5fb197671e5c647588e5a155c2d2d1883bddb61f27cb00420 +size 141618 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 b1534c7bb8..9144f26602 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:7f39f2a11a561eabe2fe13409b346888df86b0e10d4786557f66afa7048bc239 -size 129716 +oid sha256:cab72ba2a03b47458fb68bbd6fd092c06e3a36861f13b67ccb69c839dd4cc292 +size 129780 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 6e05223bef..b6670f8f9c 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:2f023a7cbc6e069115c0749d0dff3f10ae86f67c785676cc53975416e534e1d9 -size 147174 +oid sha256:bbcc2243df8595b1b2b52b62a71dbdb6347fa6f727c944316b735d8f8ab0d1a2 +size 147223 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 458dcd036c..9276b3912e 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:4d822b8c18fc4b1c68f429504831f9305eed9fcebcced9c8f708a309f652db59 -size 138913 +oid sha256:2271fe92abc4118359f988344ea6f9ab86c41820780abe657881e72949003537 +size 138953 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Editable.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Editable.png index 8cf9f1de84..f49ca1c9b7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Editable.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-en-GB.Editable.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a86f66b790b99c27ef11be576c3d93d28263aac0660fd18c27066483dcbc7ae -size 104864 +oid sha256:78e0014fe20bad16e8d7992bbedc4369e79a8735f0a2284d179736252da46a54 +size 105151 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Editable.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Editable.png index 07bd24bef6..1655c38a26 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Editable.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPad-pseudo.Editable.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d98a0fdde21dd983e2423f291c87facecbd98e2e026576ba23152eeebd483d20 -size 109406 +oid sha256:b66cf4ce7738230aa1e2a6a9f72e63f0406df754706fb8e7517d2b219a0b7aed +size 109670 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Editable.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Editable.png index f8efbb1f06..d46a1a31f8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Editable.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-en-GB.Editable.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8056bc13948e460652ba7b76ac908f6490d1ce107724dd595ca53df5d4b02acd -size 57469 +oid sha256:cfc14a626a36d9d81d4728b8da2ed58a16055194c5f844593ad749558d078242 +size 57630 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Editable.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Editable.png index 10963df605..f2062e4b0b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Editable.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomDetailsEditScreen-iPhone-16-pseudo.Editable.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8743bd26c5c538b1e3419d5e32845c88dae8090d29eda408e6c979c3807f8ffe -size 67433 +oid sha256:aa1210ee381281688088ed723aa9f5bd7a7621ead20c26d7f3814ff68dcfb25a +size 67951 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Banned.png index 3983942497..8d43ff12ef 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Banned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Banned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f5ed0c823ac1281ccdb4bcfa28ca9dd3f8d1f99a19d3eb0ff8458e865ea8e4a -size 116814 +oid sha256:962866b742a57861845c44677886a5c187973a05e96ea845101954efc63651ec +size 116948 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Empty-Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Empty-Banned.png index 8628ed74fb..0e16115c03 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Empty-Banned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Empty-Banned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bfce5d9c391d24879f2085a58816ff539c87ecc63c0226d1fd41e28227b5d70 -size 92229 +oid sha256:56d0c27cf4eb527e893dea03102a17ff64c74081f52c19ae822620b70ac5cc5e +size 92365 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Members.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Members.png index 513043deb7..32d7124031 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Members.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Admin-Members.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b8e47d918ee9a42fce8d46ba5a8a7f4a5ffc8129f55a76a6061f3f8642b0246 -size 132835 +oid sha256:b1157284b4d3bd61c1ed44c4f8c49cfd693cea4634f785d78a738e291d39d08e +size 132965 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Invites.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Invites.png index 2545e36c02..7b2d6c4781 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Invites.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Invites.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9509b45509af3fb2f67033b37d93c2c357d6728640d297d5b5a4532d4ba9cf1 -size 136138 +oid sha256:765e253eb1ab6eb5d9a77bc8b0a6c5d7e3ed064343ac055f9702b5fc810763aa +size 136303 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Member.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Member.png index fadaf93815..ed51fc2be8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Member.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-en-GB.Member.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d964c7a297796f7df990fbdf40dd460f6486ddb604edccd17a59ac7561ca2c3f -size 125525 +oid sha256:02a3fb3f4dd20a12d2ff00ea73a6f88d4a30e96de1d6522b57a9c88ee1a7e05d +size 125648 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Banned.png index b35f188683..96bb232184 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Banned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Banned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:280ae20f285959f0b80c3c1a8493246733b6e4dfa1cad10aafbf70d5317e669d -size 121457 +oid sha256:7cf11bd211d33f4fab78632d9536ea09e690dee73e9140493ca516aa6d78d622 +size 121578 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Empty-Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Empty-Banned.png index b41282300b..c01ab601e0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Empty-Banned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Empty-Banned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a43d08d3ab0cffcee1e6fb1f119af93d1bcd75f5e57563192abdb22d0ce3830 -size 100570 +oid sha256:039ad736aba4c54094f1d17613a37ef86e9ba53371dc6d5a5582e67a7407474d +size 100688 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Members.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Members.png index 115d039f64..1c291d9ad5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Members.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Admin-Members.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80cfd43759ae038e93fb7bdc0754f4030e8c8bc364897b9420d3e92cfebfbf32 -size 141768 +oid sha256:5399631ce7f310512b85452f95230e717a1505787e612f3078f65f9ebd604857 +size 141900 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Invites.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Invites.png index abcbc8b24c..0507dca5c8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Invites.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Invites.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f8c8a3e0ad9b78832c0492cc95424018fea10c3b4726c8ab2bf657df47089d6 -size 144306 +oid sha256:d3be505a8d77dcef1b457e847e204efff0f7e76c81af095d3cfdd88f87a2e03c +size 144426 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Member.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Member.png index 31dc165a82..c438408976 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Member.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPad-pseudo.Member.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:479f6184c518caa0337a2605293dd1307e5cee839727c7adc2e64dfeddba0e8b -size 133441 +oid sha256:bf7e90926372085ad952e03139a9d3c0815b804cc2045145d878e00de65e4671 +size 133587 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Banned.png index 4ca9247c9d..45d8bfba0c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Banned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Banned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9716ab5589ae525ee33f7c8d56c8de6d75eadbd58de55be381d7b6d1d2fa72d2 -size 68373 +oid sha256:6ffb00a03c68b190b0576f8a5b3578b7994b51027af59c58948391915bbd6617 +size 68471 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Empty-Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Empty-Banned.png index 5db0a03b85..81ddf96fcb 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Empty-Banned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Empty-Banned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc8c8a45449ae6a45e03cc55abbb7daacc73437723386278049702d075b2dfec -size 48907 +oid sha256:a917e84b45eb17ce4a7d7dce79fa9a724b6fedf0635c651b39b8cf36d4d22b47 +size 49025 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Members.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Members.png index 42a29274d7..31dfb30dd6 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Members.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Admin-Members.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cb4f935ad16ab0e44d65f0f3865865ea493be1c882ac6c9dfa0b9ef1ce2b7de -size 83685 +oid sha256:3ebd4283903f8901a4fa2bcaca20b77a866d037581413f5908cc3a8d7dcfea03 +size 83790 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Invites.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Invites.png index ff9a367829..f4b6906b35 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Invites.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Invites.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b7a2e7b7d6f76a6e2a99608791995c03b938c3157386ccb874e0351989be485 -size 86192 +oid sha256:4429d4306851f0d7e6e07c216dfc1b7abb3b8380ce1d1ed53da6a54ae8220362 +size 86315 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Member.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Member.png index cea8e3bf1f..bc597d215b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Member.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-en-GB.Member.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b50eec37266cca3aaf324a6b477aba2c0e10ac37540ace2f84d9cfcc9b914c4 -size 77856 +oid sha256:6a5fa320eb70ec2e1181dd063e76cd26ba9c2594c64b02058e77e9f536dfa99c +size 77966 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Banned.png index e3e36b9ee2..c4fa14fb0e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Banned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Banned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d2c1fd3265cdb97ffe95cf0fd795bc0751c86de6d1e6f5228000d8daddbffb3 -size 73543 +oid sha256:fe763263cef3c5e8c6a3a2443f06b79962cb6d790f6337d47f75a9894cd74061 +size 73666 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Empty-Banned.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Empty-Banned.png index 5804ddf3ad..c66092090d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Empty-Banned.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Empty-Banned.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f81f36ffc30df200c36a8bb8c47e47564951262079850d3f3baffdac96a61a2 -size 59461 +oid sha256:4d421fdeb10cfda660c1bf2925b5000e0b2bc5722195c729fb1b032fa7fa1070 +size 59562 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Members.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Members.png index 97419a8ff9..b1197b502c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Members.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Admin-Members.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65d99cd60b4113ae8d91b8602b39800ea2643160952f1c5d59f9dd28628ea9b2 -size 93372 +oid sha256:c598dafaa1584f2b8886183b1d9273c9b607322b493710725feeaec2f4d4f7e6 +size 93516 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Invites.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Invites.png index b5753e4d3f..08f2872483 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Invites.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Invites.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e1487324353bcdd77881ba9ca264a05d7a932bb857d4f61accba7c28ea65d871 -size 96301 +oid sha256:d6ea9ff5daaa20a19ec8b822cba67eae0d8796b20a0121f33304b26c503e085d +size 96436 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Member.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Member.png index c7d567092b..bb8f251df3 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Member.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomMembersListScreen-iPhone-16-pseudo.Member.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:027180a5377922209a9b58f36c2ab352ae5f58dad3fa653982276ce07d155d38 -size 86305 +oid sha256:0951e99bb5bad9c5a5be23f56e7c302b38514c0760c47ef5a39d3ed982bb38f7 +size 86447 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 640b8a5dd1..5f64fb3646 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:75e855ee7f0e97644797ed467953cd618fbc64a1ca185e6784cd24aa5cdef613 -size 146330 +oid sha256:9c3f1273fccab87cd7cf2eaa9780feaff32c0bb7e2e2bb9328cd21d1b7ccbf79 +size 146341 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 9d16fb4425..932f8c2089 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:7749e68e119cf015e5110e889ef29f283af3b7f4f71840bba60b7abdfbea787b -size 147778 +oid sha256:8e1c59056fc8a6913b8b4c78544dab180d571f90235d8b7dddbac3b61fa64f9e +size 147763 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 47ca6ba736..bf88fe51e2 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:8f53f2f4cc267e92bab7d8bf4a1fdfd307609312cf7e623ae43a6a254971c1f6 -size 97028 +oid sha256:fd18cb33817fb2f7320067d3c8e3e0d6f4c66fac6d255a7ae962062025442f6e +size 97052 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 e839f735b8..9a15976c9c 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:3e76ee2d1d8b3dee92997af404d846a889e9ccea0862b848c8d2386d4489220b -size 98291 +oid sha256:436c1029eab8620c56caa7f38f0dcea3487a7fdb17cb7d40e75e8e619ed63766 +size 98326 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-en-GB.1.png index 97e45286c5..420921eab5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd5e118a74f0842e64539d604b995641aab413de29620c1e5480ea4fb778f1b4 -size 66806 +oid sha256:49094a594b13cc5b0308b4e81f53ee88a36c4179fe78cb8b09fec8e7d99cb2f1 +size 67159 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-pseudo.1.png index 97e45286c5..420921eab5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd5e118a74f0842e64539d604b995641aab413de29620c1e5480ea4fb778f1b4 -size 66806 +oid sha256:49094a594b13cc5b0308b4e81f53ee88a36c4179fe78cb8b09fec8e7d99cb2f1 +size 67159 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-16-en-GB.1.png index bebcfee580..10a8f54e93 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0e9118102591b2d3279204dc35d37e465cb2dcd37d523754ac4b4b8123e0367 -size 43491 +oid sha256:c8bb905e5cc50d1ebc474af6f79c3ff07f1d3222d1cdaffd5455d35b3ba57211 +size 43903 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-16-pseudo.1.png index bebcfee580..10a8f54e93 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_sFNumberedListView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0e9118102591b2d3279204dc35d37e465cb2dcd37d523754ac4b4b8123e0367 -size 43491 +oid sha256:c8bb905e5cc50d1ebc474af6f79c3ff07f1d3222d1cdaffd5455d35b3ba57211 +size 43903 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.2.png index f96dd6020d..06455e220e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.2.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-en-GB.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1533313c12b1a46a77ea33b1dee9a3f350df3103f0b335d9874c032abfd58b3c -size 116735 +oid sha256:1568aeab5ed2fa5b9b7cfb2c7831ab5fb8e60347993bdfff5ac88ddd77a994ea +size 116774 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.2.png index b6c54a7baa..ac9e66d4e7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.2.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPad-pseudo.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fedf30ec4ccf247e3271cf483e95e2db7ea9c8c2cd6229d64bd730a5f269ec0 -size 137968 +oid sha256:42369c71ada7f05b6c14ea1c479b2417647d9e4a86f0601b04f74e6153ce2922 +size 138013 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.2.png index 35b13faa22..950a803833 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.2.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-en-GB.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5386bd512f1f8e90328b1e50bf960debafb4362278ea64eef04ad34546a68ca -size 68967 +oid sha256:f5e5fc7b4b029fe17b64bd71b9e8a0ff4c707c1217748f837603d9d4d5ae66af +size 69040 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.2.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.2.png index 2604629caf..d6cb2f27f9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.2.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_serverSelection-iPhone-16-pseudo.2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:228b9c829fdbd200775c90175db63173686d68ad100a678a60bf3636508c50fa -size 93439 +oid sha256:612ed87898b58482546cb55f36694849daf6edf69c94f28adee957f5af56d3c8 +size 93536 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.1.png index 92488b20f8..6f920f9a69 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd99d237cb480802c9faf79cf5e86dc91f9a89cfc7ffe51bbb0c576564fc9ccd -size 149316 +oid sha256:5ef2dd67c1a888b56f7c03e83ed2db09097ec4497f15ea3af49bc1162cf770df +size 149286 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.5.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.5.png index b8758ccf1c..06444cb1fd 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.5.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-en-GB.5.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b8c777548a175dd0c5a192c44e63bf848e55dbbb5a48118ba3d19f3187d7b69f -size 169420 +oid sha256:7b1dc99164aa05f2f36cc4b61fd0a840370c5a7ba92ff2c674d4d509265cb5b5 +size 169401 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.1.png index b07b217552..e65b073606 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6558017cd0ce9941b83b48f259647f723ec121a4f528578d378432eaaf23c834 -size 192102 +oid sha256:38dfe4b80ca5dfc16a6a83b88dc52c97082b9f48d906322a749b7e7e19d59de3 +size 192141 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.5.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.5.png index ff48e350bb..e0ed5c6dd1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.5.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPad-pseudo.5.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6db075e99d1acfd5561dc7f99e0a44480392987aeb80ee41d7ae95c05891a886 -size 231453 +oid sha256:03428bc03ada73eeb18821cc892a01cf50bd2785efd35ff647825c922408fbfd +size 231459 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.1.png index fa72c0bc7c..5cc9e8f9df 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a5d9bdbe33f22ec290b1362aa3e90d1817d28c8150c3287597a0bba5e27b552 -size 105712 +oid sha256:f85763be5974fe4c541a217aa766879328817e281f2694d9f0823e32afea8fb6 +size 105945 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.5.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.5.png index 471b757070..49bcf5d8e2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.5.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-en-GB.5.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d692a7100c7c5f747180960a002a0580708feb67fa13d0b4c95a5e7a0baf1d5 -size 129418 +oid sha256:917b986b7ea4279ca09f303f427fff5dd91be1ea7bbe73e5c9f2739e832d68e8 +size 129633 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.1.png index 566909d332..d4a1e29bc8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc2c74ad2576f761dc06d206d10d1e4fdddbfa3c47567727f1ef23ece1c00bab -size 155064 +oid sha256:6700cc53874b15b5be1bc2aef7c4bee56a6510a2a1405cde10079f7b90a86838 +size 155364 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.5.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.5.png index a8dfe7997f..ad26c4556c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.5.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_softLogoutScreen-iPhone-16-pseudo.5.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a0a831fbcd4f7604a6f645a417105e3a0528ae3fc6261d27b5778c0f4b529cd -size 178974 +oid sha256:37c052788229991567f690c081710de7abd184a26c7522890a4d8af77e95557a +size 179266 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-en-GB.1.png index 5d2115edf4..6c58fdcb2d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddb7f965ab42a13e6bbbc554ac626d73591c7b8d08a99774d62aa8bc975d8630 -size 98582 +oid sha256:64090eca5f21a657af2f6f51b64e036a6a404a1db8577c39628c1275b5f7c98f +size 98588 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-pseudo.1.png index 5756279513..6d0ba01c0b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d6e81dbe187564ba5f35c650f8f45bf69f52f47579fb451d57da903cd15ee26 -size 104424 +oid sha256:856c98734ddb0d538b17f3a0e4a9abfb4f141703850704ff83abd36332c214c0 +size 104603 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-16-en-GB.1.png index 1eeb875046..da668e56e0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0473f29b5a1b07b7e6599105cfe8fb9caef968c1895fbd3c342af43c4402e4da -size 51015 +oid sha256:5bf28ddbc247642cc1b233ceaa0a57023684cf1d97284f4c2ed47c1dfce2af19 +size 51119 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-16-pseudo.1.png index 2f5a3a0dea..dd734b3400 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_startChatScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e499296604700dc37650b329b8ff03a82d3588f59990023bf205826f083ffd0f -size 58664 +oid sha256:39a516943fec545ff1bc26f34fb31567c4205c5060395260e30fb07d540ae42e +size 58735 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-en-GB.1.png index c9c42ca66b..e8583e703b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4d545206a971dc1aabc1421d8b3226e4bb922eb7a48f622ccf261820df837ff2 -size 103765 +oid sha256:84127273b7dda8725b04de646fd6315bd3e005e8e356a60dedb8de30735258f1 +size 105046 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-pseudo.1.png index 3ad367fcc7..f67a8d4e7e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:792dec94a1e36df2a8d34da45404c232dbf3b4f04a40ad6a6df2fae88836abd0 -size 112088 +oid sha256:65fc7565a8ed957b285ff507dd6647e7c9b90773a33e7fe8172f39585e689690 +size 113991 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-en-GB.1.png index 8de5e48ec2..f8c4fab8bf 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43d830880d17612b28bee8884b5ca46670c4d6ad1dd7cc617d6dddf551d66863 -size 58322 +oid sha256:da8cd343a022dc76acd84e905dd9e2661daaa01efffff9bb622e0e939c469d2b +size 59231 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-pseudo.1.png index ae19f3e17f..867ea608a7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_typingIndicatorView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b6b28e897734b95fccfa9282bf322e50d4e6418dd00e4363454b701cba902be -size 65267 +oid sha256:05bd5811e9e6551e6f4fc64af5ce635b1b6cf4a7efd98f9570c2a53c56ff1834 +size 66258 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-en-GB.1.png index 0860a9b4c0..09fff94652 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:361976f6d1d6b589568f339c30fa9e3842a15e85710384b5e57a1d088ac4798c -size 103492 +oid sha256:92512938efd2fc083b64a9947d32ea13e4dc6883056809eda8477e15c6195f56 +size 103667 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-pseudo.1.png index a2ac943d11..8bb934bf34 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4fd2ddd632040754d987a2554b87bd965c168201e35f08cb218b14db5d0f9b0 -size 105623 +oid sha256:1b4ee9effd10ef4bfe4b41c166901cd52c9a2ed0bd519a5e91e2605e5fa46cd5 +size 105771 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-16-en-GB.1.png index 0ba2b1bbe9..8f1539c626 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37939e37fb95a886500d75fd3a59074a06e47547402c7339a23de76a1d23d03e -size 54682 +oid sha256:bed3dc390726186b5c56404238b55f8e9969b647d694a6971d569dd7c9abc10f +size 54861 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-16-pseudo.1.png index 867dc9ad2e..cfb1718c00 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_userDetailsEditScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd4d09599c5a8ea2b74d7d61ea493f927c763dc53e7a71ef784852e93f2cd07a -size 57980 +oid sha256:a306a56f19116333567795febba79638ddd909b71091896e42b979e9ec921777 +size 58204 diff --git a/project.yml b/project.yml index e7fb8dda2f..1151ce093a 100644 --- a/project.yml +++ b/project.yml @@ -65,7 +65,7 @@ packages: # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios - revision: 950a8884e269194e6030cbddabebbb116cdfe02a + revision: 4af41551fb7a7b9da0fd95171f2dec554726fadd # path: ../compound-ios AnalyticsEvents: url: https://github.com/matrix-org/matrix-analytics-events From 9697d59710cb86789d0030b114a9d9e05c56b4dd Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Fri, 15 Nov 2024 17:01:11 +0200 Subject: [PATCH 27/74] Fixes #1918 - Revert `1a12c729de521d2dcb664bed6b19a75ec139bede` as #617 is no longer reproducible on iOS 18. --- .../Navigation/NavigationCoordinators.swift | 27 +++---------------- 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/ElementX/Sources/Application/Navigation/NavigationCoordinators.swift b/ElementX/Sources/Application/Navigation/NavigationCoordinators.swift index e17c247812..058b713c8e 100644 --- a/ElementX/Sources/Application/Navigation/NavigationCoordinators.swift +++ b/ElementX/Sources/Application/Navigation/NavigationCoordinators.swift @@ -412,19 +412,17 @@ class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomS private struct NavigationSplitCoordinatorView: View { @State private var columnVisibility = NavigationSplitViewVisibility.all - @State private var isInSplitMode = true @Environment(\.horizontalSizeClass) private var horizontalSizeClass - @Environment(\.scenePhase) private var scenePhase @ObservedObject var navigationSplitCoordinator: NavigationSplitCoordinator var body: some View { Group { - if isInSplitMode { - navigationSplitView - } else { + if horizontalSizeClass == .compact { navigationStack + } else { + navigationSplitView } } // This needs to be handled on the top level otherwise sheets @@ -450,25 +448,6 @@ private struct NavigationSplitCoordinatorView: View { .animation(.elementDefault, value: navigationSplitCoordinator.overlayPresentationMode) .animation(.elementDefault, value: navigationSplitCoordinator.overlayModule) } - // Handle `horizontalSizeClass` changes breaking the navigation bar - // https://github.com/element-hq/element-x-ios/issues/617 - .onChange(of: horizontalSizeClass) { _, newValue in - guard scenePhase != .background else { - return - } - - isInSplitMode = newValue == .regular - } - .onChange(of: scenePhase) { _, newValue in - guard newValue == .active else { - return - } - - isInSplitMode = horizontalSizeClass == .regular - } - .task { - isInSplitMode = horizontalSizeClass == .regular - } } /// The NavigationStack that will be used in compact layouts From 9157bf267e8e5c2626ebe0745e616f026cd7fa13 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Mon, 18 Nov 2024 10:59:17 +0000 Subject: [PATCH 28/74] Translations update (#3523) --- .../be.lproj/Localizable.strings | 9 +- .../be.lproj/Localizable.stringsdict | 16 + .../bg.lproj/Localizable.strings | 9 +- .../bg.lproj/Localizable.stringsdict | 16 + .../cs.lproj/Localizable.strings | 11 +- .../cs.lproj/Localizable.stringsdict | 18 + .../de.lproj/Localizable.strings | 9 +- .../de.lproj/Localizable.stringsdict | 16 + .../el.lproj/Localizable.strings | 47 +- .../el.lproj/Localizable.stringsdict | 16 + .../en.lproj/Localizable.strings | 1 + .../es.lproj/Localizable.strings | 9 +- .../es.lproj/Localizable.stringsdict | 16 + .../et.lproj/Localizable.strings | 9 +- .../et.lproj/Localizable.stringsdict | 16 + .../fa.lproj/Localizable.strings | 9 +- .../fa.lproj/Localizable.stringsdict | 16 + .../Localizations/fi.lproj/InfoPlist.strings | 5 + .../fi.lproj/Localizable.strings | 1081 +++++++++++++++++ .../fi.lproj/Localizable.stringsdict | 342 ++++++ .../Localizations/fi.lproj/SAS.strings | 64 + .../fr.lproj/Localizable.strings | 9 +- .../fr.lproj/Localizable.stringsdict | 16 + .../hu.lproj/Localizable.strings | 9 +- .../hu.lproj/Localizable.stringsdict | 16 + .../id.lproj/Localizable.strings | 23 +- .../id.lproj/Localizable.stringsdict | 16 + .../it.lproj/Localizable.strings | 9 +- .../it.lproj/Localizable.stringsdict | 16 + .../ka.lproj/Localizable.strings | 9 +- .../ka.lproj/Localizable.stringsdict | 16 + .../nl.lproj/Localizable.strings | 9 +- .../nl.lproj/Localizable.stringsdict | 16 + .../pl.lproj/Localizable.strings | 9 +- .../pl.lproj/Localizable.stringsdict | 16 + .../pt-BR.lproj/Localizable.strings | 9 +- .../pt-BR.lproj/Localizable.stringsdict | 16 + .../pt.lproj/Localizable.strings | 9 +- .../pt.lproj/Localizable.stringsdict | 16 + .../ro.lproj/Localizable.strings | 9 +- .../ro.lproj/Localizable.stringsdict | 16 + .../ru.lproj/Localizable.strings | 9 +- .../ru.lproj/Localizable.stringsdict | 18 + .../sk.lproj/Localizable.strings | 51 +- .../sk.lproj/Localizable.stringsdict | 18 + .../sv.lproj/Localizable.strings | 9 +- .../sv.lproj/Localizable.stringsdict | 16 + .../Localizations/uk.lproj/InfoPlist.strings | 6 +- .../uk.lproj/Localizable.strings | 657 +++++----- .../uk.lproj/Localizable.stringsdict | 44 +- .../uz.lproj/Localizable.strings | 9 +- .../uz.lproj/Localizable.stringsdict | 16 + .../zh-Hans.lproj/Localizable.strings | 361 +++--- .../zh-Hans.lproj/Localizable.stringsdict | 20 +- .../zh-Hant-TW.lproj/Localizable.strings | 9 +- .../zh-Hant-TW.lproj/Localizable.stringsdict | 16 + ElementX/Sources/Generated/Strings.swift | 2 + .../UITests/UITestsNotificationCenter.swift | 4 +- UITests/Sources/Application.swift | 2 +- 59 files changed, 2672 insertions(+), 594 deletions(-) create mode 100644 ElementX/Resources/Localizations/fi.lproj/InfoPlist.strings create mode 100644 ElementX/Resources/Localizations/fi.lproj/Localizable.strings create mode 100644 ElementX/Resources/Localizations/fi.lproj/Localizable.stringsdict create mode 100644 ElementX/Resources/Localizations/fi.lproj/SAS.strings diff --git a/ElementX/Resources/Localizations/be.lproj/Localizable.strings b/ElementX/Resources/Localizations/be.lproj/Localizable.strings index e5e67403c0..952ffd4c66 100644 --- a/ElementX/Resources/Localizations/be.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/be.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Аўдыя"; "common_blocked_users" = "Заблакіраваныя карыстальнікі"; "common_bubbles" = "Бурбалкі"; -"common_call_invite" = "Ідзе званок (не падтрымліваецца)"; "common_call_started" = "Званок пачаўся"; "common_chat_backup" = "Рэзервовае капіраванне чатаў"; "common_copyright" = "Аўтарскае права"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Немагчыма адправіць запрашэнне(я)"; "common_unlock" = "Разблакіраваць"; "common_unmute" = "Укл. гук"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Падзея не падтрымліваецца"; "common_username" = "Імя карыстальніка"; "common_verification_cancelled" = "Праверка адменена"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Націсніце на паведамленне і абярыце «%1$@ », каб уключыць сюды."; "screen_pinned_timeline_empty_state_headline" = "Замацуеце важныя паведамленні, каб іх можна было лёгка знайсці"; "screen_reset_encryption_password_error" = "Адбылася невядомая памылка. Калі ласка, праверце правільнасць пароля вашага ўліковага запісу і паўтарыце спробу."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "Апавясціць увесь пакой"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ з %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Замацаваныя паведамленні"; "screen_room_pinned_banner_loading_description" = "Загрузка паведамлення…"; "screen_room_pinned_banner_view_all_button_title" = "Паглядзець усе"; +"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_details_pinned_events_row_title" = "Замацаваныя паведамленні"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Дадаць эмодзі"; "screen_room_timeline_beginning_of_room" = "Гэта пачатак %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Гэта пачатак гэтай размовы."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Паказаць менш"; "screen_room_timeline_message_copied" = "Паведамленне скапіравана"; "screen_room_timeline_no_permission_to_post" = "У Вас няма дазволу на публікацыю ў гэтым пакоі"; diff --git a/ElementX/Resources/Localizations/be.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/be.lproj/Localizable.stringsdict index 954044d393..d6ff532944 100644 --- a/ElementX/Resources/Localizations/be.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/be.lproj/Localizable.stringsdict @@ -254,6 +254,22 @@ %1$d удзельнікаў + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings index 617936ad38..ebe91601ed 100644 --- a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Аудио"; "common_blocked_users" = "Блокирани потребители"; "common_bubbles" = "Bubbles"; -"common_call_invite" = "Call in progress (unsupported)"; "common_call_started" = "Call started"; "common_chat_backup" = "Резервно копие на чатовете"; "common_copyright" = "Copyright"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Не може да се изпрати покана(и)"; "common_unlock" = "Отключване"; "common_unmute" = "Раззаглушаване"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Неподдържано събитие"; "common_username" = "Потребителско име"; "common_verification_cancelled" = "Потвърждаването е отменено"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "Notify the whole room"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ of %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Pinned messages"; "screen_room_pinned_banner_loading_description" = "Loading message…"; "screen_room_pinned_banner_view_all_button_title" = "View All"; +"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_details_pinned_events_row_title" = "Pinned messages"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Добавяне на емоджи"; "screen_room_timeline_beginning_of_room" = "Това е началото на %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Това е началото на този разговор."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Показване на по-малко"; "screen_room_timeline_message_copied" = "Съобщението е копирано"; "screen_room_timeline_no_permission_to_post" = "You do not have permission to post to this room"; diff --git a/ElementX/Resources/Localizations/bg.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/bg.lproj/Localizable.stringsdict index 4cfc90f2ad..6336536516 100644 --- a/ElementX/Resources/Localizations/bg.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/bg.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d души + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings index b621c33010..44aa4500b5 100644 --- a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Zvuk"; "common_blocked_users" = "Blokovaní uživatelé"; "common_bubbles" = "Bubliny"; -"common_call_invite" = "Probíhá hovor (nepodporováno)"; "common_call_started" = "Hovor zahájen"; "common_chat_backup" = "Záloha chatu"; "common_copyright" = "Autorská práva"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Nelze odeslat pozvánky"; "common_unlock" = "Odemknout"; "common_unmute" = "Zrušit ztlumení"; +"common_unsupported_call" = "Nepodporované volání"; "common_unsupported_event" = "Nepodporovaná událost"; "common_username" = "Uživatelské jméno"; "common_verification_cancelled" = "Ověření zrušeno"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Odmítnout a vykázat"; "screen_pinned_timeline_empty_state_description" = "Přidržte zprávu a vyberte „%1$@“, kterou chcete zahrnout sem."; "screen_pinned_timeline_empty_state_headline" = "Připněte důležité zprávy, aby je bylo možné snadno najít"; "screen_reset_encryption_password_error" = "Došlo k neznámé chybě. Zkontrolujte, zda je heslo k účtu správné a zkuste to znovu."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Jedno nebo více vašich zařízení není ověřeno. Zprávu můžete přesto odeslat, nebo ji můžete prozatím zrušit a zkusit to znovu později, až ověříte všechna svá zařízení."; "screen_resolve_send_failure_you_unsigned_device_title" = "Vaše zpráva nebyla odeslána, protože jste neověřili jedno nebo více zařízení"; "screen_room_mentions_at_room_subtitle" = "Informujte celou místnost"; +"screen_room_multiple_knock_requests_view_all_button_title" = "Zobrazit vše"; "screen_room_pinned_banner_indicator" = "%1$@ z %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Připnuté zprávy"; "screen_room_pinned_banner_loading_description" = "Načítání zprávy..."; "screen_room_pinned_banner_view_all_button_title" = "Zobrazit vše"; +"screen_room_single_knock_request_accept_button_title" = "Přijmout"; +"screen_room_single_knock_request_title" = "%1$@ chce vstoupit do této místnosti"; +"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_roomlist_knock_event_sent_description" = "Žádost o vstup odeslána"; "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í."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Přidat emoji"; "screen_room_timeline_beginning_of_room" = "Toto je začátek %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Toto je začátek této konverzace."; +"screen_room_timeline_legacy_call" = "Nepodporované volání. Zeptejte se, zda volající může používat novou aplikaci Element X."; "screen_room_timeline_less_reactions" = "Zobrazit méně"; "screen_room_timeline_message_copied" = "Zpráva zkopírována"; "screen_room_timeline_no_permission_to_post" = "Nemáte oprávnění zveřejňovat příspěvky v této místnosti"; @@ -917,7 +924,7 @@ "state_event_room_invite_you" = "Pozvali jste %1$@"; "state_event_room_join" = "%1$@ vstoupil(a) do místnosti"; "state_event_room_join_by_you" = "Vstoupili jste do místnosti"; -"state_event_room_knock" = "%1$@ požádal(a) o vstup"; +"state_event_room_knock" = "%1$@ žádá o vstup"; "state_event_room_knock_accepted" = "%1$@ povolil(a) vstoupit %2$@"; "state_event_room_knock_accepted_by_you" = "Povolili jste %1$@ vstoupit"; "state_event_room_knock_by_you" = "Požádali jste o vstup"; diff --git a/ElementX/Resources/Localizations/cs.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/cs.lproj/Localizable.stringsdict index 4362b120c3..6c3a3959eb 100644 --- a/ElementX/Resources/Localizations/cs.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/cs.lproj/Localizable.stringsdict @@ -254,6 +254,24 @@ %1$d osob + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d další chce vstoupit do této místnosti + few + %1$@ +%2$d další chtějí vstoupit do této místnosti + other + %1$@ +%2$d dalších chce vstoupit do této místnosti + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/de.lproj/Localizable.strings b/ElementX/Resources/Localizations/de.lproj/Localizable.strings index 6e4634d9c6..64480a742c 100644 --- a/ElementX/Resources/Localizations/de.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/de.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Audio"; "common_blocked_users" = "Blockierte Nutzer"; "common_bubbles" = "Sprechblasen"; -"common_call_invite" = "Aktiver Anruf (nicht unterstützt)"; "common_call_started" = "Aufruf gestartet"; "common_chat_backup" = "Chat-Backup"; "common_copyright" = "Copyright"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Einladung(en) konnte(n) nicht gesendet werden"; "common_unlock" = "Entsperren"; "common_unmute" = "Stummschaltung aufheben"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Nicht unterstütztes Ereignis"; "common_username" = "Benutzername"; "common_verification_cancelled" = "Verifizierung abgebrochen"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Drücke auf eine Nachricht und wähle “%1$@”, um sie hier einzufügen."; "screen_pinned_timeline_empty_state_headline" = "Fixiere wichtige Nachrichten, so dass sie leicht gefunden werden können"; "screen_reset_encryption_password_error" = "Es ist ein unbekannter Fehler aufgetreten. Bitte überprüfe das Passwort deines Kontos und versuche es erneut."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "Alle Mitglieder benachrichtigen"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ von %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ fixierte Nachrichten"; "screen_room_pinned_banner_loading_description" = "Nachricht wird geladen…"; "screen_room_pinned_banner_view_all_button_title" = "Alle anzeigen"; +"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_details_pinned_events_row_title" = "Fixierte Nachrichten"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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"; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Emoji hinzufügen"; "screen_room_timeline_beginning_of_room" = "Dies ist der Anfang von %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Dies ist der Anfang dieses Gesprächs."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Weniger anzeigen"; "screen_room_timeline_message_copied" = "Nachricht wurde kopiert"; "screen_room_timeline_no_permission_to_post" = "Du bist nicht berechtigt, in diesem Raum zu schreiben"; diff --git a/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict index a0b5aa8da7..b31e5f4185 100644 --- a/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d Personen + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/el.lproj/Localizable.strings b/ElementX/Resources/Localizations/el.lproj/Localizable.strings index bb6265fffc..4d1647d964 100644 --- a/ElementX/Resources/Localizations/el.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/el.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Ήχος"; "common_blocked_users" = "Αποκλεισμένοι χρήστες"; "common_bubbles" = "Φυσαλίδες"; -"common_call_invite" = "Κλήση σε εξέλιξη (δεν υποστηρίζεται)"; "common_call_started" = "Η κλήση ξεκίνησε"; "common_chat_backup" = "Αντίγραφο ασφαλείας συνομιλίας"; "common_copyright" = "Πνευματικά δικαιώματα"; @@ -226,11 +225,12 @@ "common_unable_to_invite_title" = "Δεν είναι δυνατή η αποστολή προσκλήσεων"; "common_unlock" = "Ξεκλείδωμα"; "common_unmute" = "Άρση σίγασης"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Μη υποστηριζόμενο συμβάν"; "common_username" = "Όνομα χρήστη"; "common_verification_cancelled" = "Η επαλήθευση ακυρώθηκε"; "common_verification_complete" = "Η επαλήθευση ολοκληρώθηκε"; -"common_verification_failed" = "Verification failed"; +"common_verification_failed" = "Αποτυχία επαλήθευσης"; "common_verified" = "Επαληθεύτηκε"; "common_verify_device" = "Επαλήθευση συσκευής"; "common_verify_identity" = "Verify identity"; @@ -244,12 +244,12 @@ "common.pinned" = "Καρφιτσωμένο"; "common.send_to" = "Αποστολή σε"; "common.you" = "Εσύ"; -"common_unable_to_decrypt_insecure_device" = "Sent from an insecure device"; +"common_unable_to_decrypt_insecure_device" = "Στάλθηκε από μια μη ασφαλής συσκευή"; "common_unable_to_decrypt_verification_violation" = "Sender's verified identity has changed"; -"confirm_recovery_key_banner_message" = "Το αντίγραφο ασφαλείας της συνομιλίας σου δεν είναι συγχρονισμένο αυτήν τη στιγμή. Πρέπει να εισαγάγεις το κλειδί ανάκτησης για να διατηρήσεις την πρόσβαση στο αντίγραφο ασφαλείας της συνομιλίας σου."; +"confirm_recovery_key_banner_message" = "Επιβεβαίωσε το κλειδί ανάκτησης για να διατηρήσεις την πρόσβαση στο χώρο αποθήκευσης κλειδιών και στο ιστορικό μηνυμάτων."; "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" = "Εισήγαγε το κλειδί ανάκτησης"; +"confirm_recovery_key_banner_title" = "Ο χώρος αποθήκευσης κλειδιών σου δεν είναι συγχρονισμένος"; "crash_detection_dialog_content" = "Το %1$@ διακόπηκε την τελευταία φορά που χρησιμοποιήθηκε. Θα 'θελες να μοιραστείς μια αναφορά σφάλματος μαζί μας;"; "crypto_identity_change_pin_violation" = "Η ταυτότητα του χρήστη %1$@ φαίνεται να έχει αλλάξει. %2$@"; "crypto_identity_change_pin_violation_new" = "Η ταυτότητα του %1$@ %2$@ φαίνεται να έχει αλλάξει. %3$@"; @@ -359,12 +359,13 @@ "screen_create_room_room_address_section_title" = "Room address"; "screen_create_room_room_visibility_section_title" = "Room visibility"; "screen_join_room_cancel_knock_action" = "Ακύρωση αιτήματος"; -"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_cancel_knock_alert_confirmation" = "Ναι, ακύρωση"; +"screen_join_room_cancel_knock_alert_description" = "Σίγουρα θες να ακυρώσεις το αίτημά σου για συμμετοχή σε αυτό το δωμάτιο;"; +"screen_join_room_cancel_knock_alert_title" = "Ακύρωση αίτησης συμμετοχής"; "screen_join_room_knock_message_description" = "Μήνυμα (προαιρετικό)"; "screen_join_room_knock_sent_description" = "Θα λάβεις πρόσκληση για συμμετοχή στο δωμάτιο εάν το αίτημά σου γίνει αποδεκτό."; "screen_join_room_knock_sent_title" = "Το αίτημα συμμετοχής στάλθηκε"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Πάτα σε ένα μήνυμα και επέλεξε «%1$@» για να συμπεριληφθεί εδώ."; "screen_pinned_timeline_empty_state_headline" = "Καρφίτσωσε σημαντικά μηνύματα, ώστε να μπορούν να εντοπιστούν εύκολα"; "screen_reset_encryption_password_error" = "Συνέβη ένα άγνωστο σφάλμα. Έλεγξε ότι ο κωδικός πρόσβασης του λογαριασμού σου είναι σωστός και δοκίμασε ξανά."; @@ -377,12 +378,17 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Μία ή περισσότερες από τις συσκευές σου δεν έχουν επαληθευτεί. Μπορείς να στείλεις το μήνυμα ούτως ή άλλως, ή μπορείς να το ακυρώσεις προς το παρόν και να προσπαθήσεις ξανά αργότερα αφού επαληθεύσεις όλες τις συσκευές σου."; "screen_resolve_send_failure_you_unsigned_device_title" = "Το μήνυμά σου δεν στάλθηκε επειδή δεν έχεις επαληθεύσει τουλάχιστον μία από τις συσκευές σου"; "screen_room_mentions_at_room_subtitle" = "Ειδοποίησε όλο το δωμάτιο"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ από %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Καρφιτσωμένα μηνύματα"; "screen_room_pinned_banner_loading_description" = "Φόρτωση μηνύματος..."; "screen_room_pinned_banner_view_all_button_title" = "Προβολή Όλων"; +"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_details_pinned_events_row_title" = "Καρφιτσωμένα μηνύματα"; -"screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_roomlist_knock_event_sent_description" = "Το αίτημα συμμετοχής στάλθηκε"; "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" = "Το μήνυμα δεν στάλθηκε επειδή δεν έχεις επαληθεύσει τουλάχιστον μία από τις συσκευές σου."; @@ -469,7 +475,7 @@ "screen_chat_backup_key_storage_toggle_title" = "Allow key storage"; "screen_chat_backup_recovery_action_change" = "Αλλαγή κλειδιού ανάκτησης"; "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" = "Το αντίγραφο ασφαλείας της συνομιλίας σου δεν είναι συγχρονισμένο αυτήν τη στιγμή."; +"screen_chat_backup_recovery_action_confirm_description" = "Ο αποθηκευτικός χώρος κλειδιών σου δεν είναι συγχρονισμένος αυτήν τη στιγμή."; "screen_chat_backup_recovery_action_setup_description" = "Απόκτησε πρόσβαση στα κρυπτογραφημένα σου μηνύματα εάν χάσεις όλες τις συσκευές σου ή έχεις αποσυνδεθεί από το %1$@ παντού."; "screen_create_account_title" = "Δημιουργία λογαριασμού"; "screen_create_new_recovery_key_list_item_1" = "Άνοιγμα %1$@ σε συσκευή υπολογιστή"; @@ -644,7 +650,7 @@ "screen_recovery_key_change_title" = "Αλλαγή κλειδιού ανάκτησης;"; "screen_recovery_key_confirm_create_new_recovery_key" = "Δημιουργία νέου κλειδιού ανάκτησης"; "screen_recovery_key_confirm_description" = "Βεβαιώσου ότι κανείς δεν μπορεί να δει αυτήν την οθόνη!"; -"screen_recovery_key_confirm_error_content" = "Προσπάθησε ξανά για να επιβεβαιώσεις την πρόσβαση στο αντίγραφο ασφαλείας της συνομιλίας σου."; +"screen_recovery_key_confirm_error_content" = "Προσπάθησε ξανά για να επιβεβαιώσεις την πρόσβαση στον αποθηκευτικό χώρο κλειδιών σου."; "screen_recovery_key_confirm_error_title" = "Λανθασμένο κλειδί ανάκτησης"; "screen_recovery_key_confirm_key_description" = "Εάν έχεις ένα κλειδί ασφαλείας ή μια φράση ασφαλείας, θα λειτουργήσει επίσης."; "screen_recovery_key_confirm_key_placeholder" = "Εισαγωγή..."; @@ -734,8 +740,8 @@ "screen_room_member_details_unblock_alert_action" = "Άρση αποκλεισμού"; "screen_room_member_details_unblock_alert_description" = "Θα μπορείς να δεις ξανά όλα τα μηνύματα του."; "screen_room_member_details_unblock_user" = "Κατάργηση αποκλεισμού χρήστη"; -"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" = "Χρησιμοποίησε την εφαρμογή ιστού για να επαληθεύσεις αυτόν τον χρήστη."; +"screen_room_member_details_verify_button_title" = "Επαλήθευση %1$@"; "screen_room_member_list_ban_member_confirmation_action" = "Αποκλεισμός"; "screen_room_member_list_ban_member_confirmation_description" = "Δεν θα μπορεί να συμμετέχει ξανά σε αυτό το δωμάτιο εάν προσκληθεί."; "screen_room_member_list_ban_member_confirmation_title" = "Θες σίγουρα να αποκλείσεις αυτό το μέλος;"; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Προσθήκη emoji"; "screen_room_timeline_beginning_of_room" = "Αυτή είναι η αρχή του %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Αυτή είναι η αρχή τούτης της συνομιλίας."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Εμφάνιση λιγότερων"; "screen_room_timeline_message_copied" = "Το μήνυμα αντιγράφηκε"; "screen_room_timeline_no_permission_to_post" = "Δεν έχεις άδεια να δημοσιεύσεις σε αυτό το δωμάτιο"; @@ -832,7 +839,7 @@ "screen_session_verification_compare_numbers_title" = "Σύγκριση αριθμών"; "screen_session_verification_complete_subtitle" = "Η νέα σου συνεδρία έχει πλέον επαληθευτεί. Έχει πρόσβαση στα κρυπτογραφημένα μηνύματά σας και άλλοι χρήστες θα το βλέπουν ως αξιόπιστο."; "screen_session_verification_enter_recovery_key" = "Εισαγωγή κλειδιού ανάκτησης"; -"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" = "Είτε το αίτημα έληξε είτε απορρίφθηκε είτε υπήρξε αναντιστοιχία επαλήθευσης."; "screen_session_verification_open_existing_session_subtitle" = "Απέδειξε ότι είσαι εσύ για να αποκτήσεις πρόσβαση στο κρυπτογραφημένο ιστορικό μηνυμάτων σου."; "screen_session_verification_open_existing_session_title" = "Άνοιξε μια υπάρχουσα συνεδρία"; "screen_session_verification_positive_button_canceled" = "Επανάληψη επαλήθευσης"; @@ -840,10 +847,10 @@ "screen_session_verification_positive_button_verifying_ongoing" = "Αναμονή για αντιστοίχιση"; "screen_session_verification_ready_subtitle" = "Σύγκρινε ένα μοναδικό σύνολο emojis."; "screen_session_verification_request_accepted_subtitle" = "Σύγκρινε τα μοναδικά emoji και σιγουρέψου ότι εμφανίζονται με την ίδια σειρά."; -"screen_session_verification_request_details_timestamp" = "Signed in"; +"screen_session_verification_request_details_timestamp" = "Έχεις συνδεθεί"; "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_footer" = "Συνέχισε μόνο εάν ξεκίνησες εσύ αυτήν την επαλήθευση."; +"screen_session_verification_request_subtitle" = "Επαλήθευσε την άλλη συσκευή για να διατηρήσεις το ιστορικό μηνυμάτων σου ασφαλές."; "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" = "Ζητήθηκε επαλήθευση"; @@ -917,8 +924,8 @@ "state_event_room_invite_you" = "Ο χρήστης %1$@ σέ προσκάλεσε"; "state_event_room_join" = "Ο χρήστης %1$@ συμμετέχει στο δωμάτιο"; "state_event_room_join_by_you" = "Μπήκες στο δωμάτιο"; -"state_event_room_knock" = "Ο χρήστης %1$@ ζήτησε να συμμετάσχει"; -"state_event_room_knock_accepted" = "Ο χρήστης %1$@ επέτρεψε στον χρήστη %2$@ να συμμετάσχει"; +"state_event_room_knock" = "Ο χρήστης %1$@ ζητάει να συμμετάσχει"; +"state_event_room_knock_accepted" = "Ο χρήστης %1$@ επέτρεψε τον χρήστη %2$@"; "state_event_room_knock_accepted_by_you" = "Επέστρεψες στον χρήστη%1$@ να συμμετάσχει"; "state_event_room_knock_by_you" = "Ζήτησες να συμμετάσχεις"; "state_event_room_knock_denied" = "Ο χρήστης %1$@ απέρριψε το αίτημα του χρήστη %2$@ να συμμετάσχει"; @@ -1065,7 +1072,7 @@ "screen_room_timeline_reactions_show_less" = "Εμφάνιση λιγότερων"; "screen_roomlist_filter_people" = "Άτομα"; "screen_server_confirmation_change_server" = "Αλλαγή παρόχου λογαριασμού"; -"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" = "Είτε το αίτημα έληξε είτε απορρίφθηκε είτε υπήρξε αναντιστοιχία επαλήθευσης."; "screen_signout_confirmation_dialog_submit" = "Αποσύνδεση"; "screen_signout_confirmation_dialog_title" = "Αποσύνδεση"; "screen_signout_key_backup_offline_title" = "Εξακολουθούν να δημιουργούνται αντίγραφα ασφαλείας των κλειδιών σου"; diff --git a/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict index d17d98a85e..bb2306250e 100644 --- a/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d άτομα + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 5cbc8e5a29..1058c72968 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -387,6 +387,7 @@ "screen_room_single_knock_request_title" = "%1$@ wants to join this room"; "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_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; diff --git a/ElementX/Resources/Localizations/es.lproj/Localizable.strings b/ElementX/Resources/Localizations/es.lproj/Localizable.strings index bfffc8d937..98f3626bef 100644 --- a/ElementX/Resources/Localizations/es.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/es.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Sonido"; "common_blocked_users" = "Usuarios bloqueados"; "common_bubbles" = "Burbujas"; -"common_call_invite" = "Llamada en curso (no admitida)"; "common_call_started" = "Call started"; "common_chat_backup" = "Copia de seguridad del chat"; "common_copyright" = "Derechos de autor"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "No se pudo enviar la(s) invitación(es)"; "common_unlock" = "Desbloquear"; "common_unmute" = "Dejar de silenciar"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Evento no compatible"; "common_username" = "Usuario"; "common_verification_cancelled" = "Verificación cancelada"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "Notificar a toda la sala"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ of %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Pinned messages"; "screen_room_pinned_banner_loading_description" = "Loading message…"; "screen_room_pinned_banner_view_all_button_title" = "View All"; +"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_details_pinned_events_row_title" = "Pinned messages"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Añadir emoji"; "screen_room_timeline_beginning_of_room" = "Este es el principio de %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Este es el principio de esta conversación."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Mostrar menos"; "screen_room_timeline_message_copied" = "Mensaje copiado"; "screen_room_timeline_no_permission_to_post" = "No tienes permiso para publicar en esta sala"; diff --git a/ElementX/Resources/Localizations/es.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/es.lproj/Localizable.stringsdict index 738d81de9b..e57997a40c 100644 --- a/ElementX/Resources/Localizations/es.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/es.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d personas + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/et.lproj/Localizable.strings b/ElementX/Resources/Localizations/et.lproj/Localizable.strings index 99d2763205..3351125538 100644 --- a/ElementX/Resources/Localizations/et.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/et.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Heli"; "common_blocked_users" = "Blokeeritud kasutajad"; "common_bubbles" = "Mullid"; -"common_call_invite" = "Kõne on pooleli (pole toetatud)"; "common_call_started" = "Kõne algas"; "common_chat_backup" = "Vestluse varukoopia"; "common_copyright" = "Autoriõigused"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Kutse(te) saatmine ei õnnestunud"; "common_unlock" = "Eemalda lukustus"; "common_unmute" = "Lõpeta summutamine"; +"common_unsupported_call" = "See kõne pole toetatud"; "common_unsupported_event" = "Toetamata sündmus"; "common_username" = "Kasutajanimi"; "common_verification_cancelled" = "Verifitseerimine on katkestatud"; @@ -365,6 +365,7 @@ "screen_join_room_knock_message_description" = "Selgitus (kui soovid lisada)"; "screen_join_room_knock_sent_description" = "Kui sinu liitumispalvega ollakse nõus, siis saad kutse jututoaga liitumiseks."; "screen_join_room_knock_sent_title" = "Liitumispalve on saadetud"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Keeldu ja määra suhtluskeeld"; "screen_pinned_timeline_empty_state_description" = "Siia lisamiseks vajuta sõnumil ja vali „%1$@“."; "screen_pinned_timeline_empty_state_headline" = "Et olulisi sõnumeid oleks lihtsam leida, tõsta nad esile"; "screen_reset_encryption_password_error" = "Tekkis teadmata viga. Palun kontrolli, kas sinu kasutajakonto salasõna on õige ja proovi uuesti."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Üks või enam sinu seadet on verifitseerimata. Sa võid sõnumi ikkagi ära saata või katkestad saatmise ning proovid uuesti, kui oled kõik oma seadmed verifitseerinud."; "screen_resolve_send_failure_you_unsigned_device_title" = "Kuna sul on üks või enam verifitseerimata seadet, siis sinu sõnum jäi saatmata"; "screen_room_mentions_at_room_subtitle" = "Teavita kogu jututuba"; +"screen_room_multiple_knock_requests_view_all_button_title" = "Vaata kõiki"; "screen_room_pinned_banner_indicator" = "%1$@ / %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ esiletõstetud sõnumit"; "screen_room_pinned_banner_loading_description" = "Laadime sõnumit…"; "screen_room_pinned_banner_view_all_button_title" = "Näita kõiki"; +"screen_room_single_knock_request_accept_button_title" = "Nõustu"; +"screen_room_single_knock_request_title" = "%1$@ soovib selle jututoaga liituda"; +"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_roomlist_knock_event_sent_description" = "Liitumispäring on saadetud"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Lisa emotikon"; "screen_room_timeline_beginning_of_room" = "See on %1$@ jututoa algus."; "screen_room_timeline_beginning_of_room_no_name" = "See on antud vestluse algus."; +"screen_room_timeline_legacy_call" = "Kõne pole nende rakenduste vahel toetatud. Palun küsi teiselt osapoolelt, kas ta oleks nõus kasutama Element X rakendust."; "screen_room_timeline_less_reactions" = "Näita vähem"; "screen_room_timeline_message_copied" = "Sõnum on kopeeritud"; "screen_room_timeline_no_permission_to_post" = "Sul pole õigusi siia jututuppa kirjutada"; diff --git a/ElementX/Resources/Localizations/et.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/et.lproj/Localizable.stringsdict index b25b512850..643243c91b 100644 --- a/ElementX/Resources/Localizations/et.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/et.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d osalejat + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ + veel %2$d kasutaja soovivad selle jututoaga liituda + other + %1$@ + veel %2$d kasutajat soovivad selle jututoaga liituda + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/fa.lproj/Localizable.strings b/ElementX/Resources/Localizations/fa.lproj/Localizable.strings index 0dec8b1557..a6d5a0b676 100644 --- a/ElementX/Resources/Localizations/fa.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fa.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "صدا"; "common_blocked_users" = "کاربران مسدود"; "common_bubbles" = "حباب‌ها"; -"common_call_invite" = "تماس در جریان (پشتیبانی نشده)"; "common_call_started" = "تماس آغاز شد"; "common_chat_backup" = "پشتیبان گپ"; "common_copyright" = "حق رونوشت"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "ناتوان در فرستادن دعوت(ها)"; "common_unlock" = "قفل‌گشایی"; "common_unmute" = "باصدا"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "رویداد پشتیبانی نشده"; "common_username" = "نام کاربری"; "common_verification_cancelled" = "تأیید لغو شد"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "آگاهی به تمام اتاق"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ از %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ پیام‌های سنجاق شده"; "screen_room_pinned_banner_loading_description" = "بار کردن پشام‌ها…"; "screen_room_pinned_banner_view_all_button_title" = "نمایش همه"; +"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_details_pinned_events_row_title" = "پیام‌های سنجاق شده"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "افزودن شکلک"; "screen_room_timeline_beginning_of_room" = "آغاز %1$@ است."; "screen_room_timeline_beginning_of_room_no_name" = "این، آغاز گفت‌وگوست."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "نمایش کم‌تر"; "screen_room_timeline_message_copied" = "پیام رونوشت شد"; "screen_room_timeline_no_permission_to_post" = "اجازهٔ فرستادن به این اتاق را ندارید"; diff --git a/ElementX/Resources/Localizations/fa.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/fa.lproj/Localizable.stringsdict index 3babb9bf3a..ab275b9162 100644 --- a/ElementX/Resources/Localizations/fa.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/fa.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d people + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/fi.lproj/InfoPlist.strings b/ElementX/Resources/Localizations/fi.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9a792c8182 --- /dev/null +++ b/ElementX/Resources/Localizations/fi.lproj/InfoPlist.strings @@ -0,0 +1,5 @@ +"NSCameraUsageDescription" = "Ottaakseen kuvia tai videoita ja lähettääkseen ne viestinä, Element X tarvitsee luvan kameraan."; +"NSFaceIDUsageDescription" = "Face ID:tä käytetään sovelluksesi avaamiseen."; +"NSLocationWhenInUseUsageDescription" = "Myönnä lupa sijaintiisi, jotta Element X voi jakaa sen."; +"NSMicrophoneUsageDescription" = "Ääniviestien tallentamiseen ja lähettämiseen Element X:n on päästävä käsiksi mikrofoniin."; +"NSPhotoLibraryUsageDescription" = "Mahdollistaa valokuvien ja videoiden tallentamisen kirjastoosi."; diff --git a/ElementX/Resources/Localizations/fi.lproj/Localizable.strings b/ElementX/Resources/Localizations/fi.lproj/Localizable.strings new file mode 100644 index 0000000000..a53e3d8290 --- /dev/null +++ b/ElementX/Resources/Localizations/fi.lproj/Localizable.strings @@ -0,0 +1,1081 @@ +"Notification" = "Ilmoitus"; +"a11y_delete" = "Poista"; +"a11y_hide_password" = "Piilota salasana"; +"a11y_jump_to_bottom" = "Siirry loppuun"; +"a11y_notifications_mentions_only" = "Vain maininnat"; +"a11y_notifications_muted" = "Mykistetty"; +"a11y_page_n" = "Sivu %1$d"; +"a11y_pause" = "Keskeytä"; +"a11y_pin_field" = "PIN-kenttä"; +"a11y_play" = "Toista"; +"a11y_poll_end" = "Päättynyt kysely"; +"a11y_react_with" = "Reagoi emojilla %1$@"; +"a11y_react_with_other_emojis" = "Reagoi muilla emojeilla"; +"a11y_read_receipts_multiple" = "%1$@ ja %2$@ on lukenut viestin"; +"a11y_read_receipts_single" = "%1$@ on lukenut viestin"; +"a11y_read_receipts_tap_to_show_all" = "Näytä kaikki napauttamalla"; +"a11y_remove_reaction_with" = "Poista reaktio emojilla %1$@"; +"a11y_send_files" = "Lähetä tiedostoja"; +"a11y_show_password" = "Näytä salasana"; +"a11y_start_call" = "Aloita puhelu"; +"a11y_user_menu" = "Käyttäjävalikko"; +"a11y_voice_message_record" = "Nauhoita ääniviesti."; +"a11y_voice_message_stop_recording" = "Lopeta nauhoittaminen"; +"action_accept" = "Hyväksy"; +"action_add_to_timeline" = "Lisää aikajanalle"; +"action_back" = "Takaisin"; +"action_call" = "Soita"; +"action_cancel" = "Peruuta"; +"action_cancel_for_now" = "Peruuta toistaiseksi"; +"action_choose_photo" = "Valitse kuva"; +"action_clear" = "Tyhjennä"; +"action_close" = "Sulje"; +"action_complete_verification" = "Viimeistele vahvistus"; +"action_confirm" = "Vahvista"; +"action_confirm_password" = "Vahvista salasana"; +"action_continue" = "Jatka"; +"action_copy" = "Kopioi"; +"action_copy_link" = "Kopioi linkki"; +"action_copy_link_to_message" = "Kopioi linkki viestiin"; +"action_create" = "Luo"; +"action_create_a_room" = "Luo huone"; +"action_deactivate" = "Deaktivoi"; +"action_deactivate_account" = "Deaktivoi tili"; +"action_decline" = "Hylkää"; +"action_delete_poll" = "Poista kysely"; +"action_disable" = "Poista käytöstä"; +"action_discard" = "Hylkää"; +"action_done" = "Valmis"; +"action_edit" = "Muokkaa"; +"action_edit_poll" = "Muokkaa kyselyä"; +"action_enable" = "Ota käyttöön"; +"action_end_poll" = "Lopeta kysely"; +"action_enter_pin" = "Syötä PIN-koodi"; +"action_forgot_password" = "Unohditko salasanan?"; +"action_forward" = "Välitä"; +"action_go_back" = "Takaisin"; +"action_ignore" = "Ohita"; +"action_invite" = "Kutsu"; +"action_invite_friends" = "Kutsu ihmisiä"; +"action_invite_friends_to_app" = "Kutsu ihmisiä %1$@ -sovellukseen"; +"action_invite_people_to_app" = "Kutsu ihmisiä %1$@ -sovellukseen"; +"action_invites_list" = "Kutsut"; +"action_join" = "Liity"; +"action_learn_more" = "Lue lisää"; +"action_leave" = "Poistu"; +"action_leave_conversation" = "Poistu keskustelusta"; +"action_leave_room" = "Poistu huoneesta"; +"action_load_more" = "Lataa lisää"; +"action_manage_account" = "Hallitse tiliä"; +"action_manage_devices" = "Hallitse laitteita"; +"action_message" = "Lähetä viesti"; +"action_next" = "Seuraava"; +"action_no" = "Ei"; +"action_not_now" = "Ei nyt"; +"action_ok" = "OK"; +"action_open_settings" = "Asetukset"; +"action_open_with" = "Avaa sovelluksessa"; +"action_pin" = "Kiinnitä"; +"action_quick_reply" = "Pikavastaus"; +"action_quote" = "Lainaa"; +"action_react" = "Reagoi"; +"action_reject" = "Hylkää"; +"action_remove" = "Poista"; +"action_reply" = "Vastaa"; +"action_reply_in_thread" = "Vastaa ketjuun"; +"action_report_bug" = "Ilmoita virheestä"; +"action_report_content" = "Ilmoita sisällöstä"; +"action_reset" = "Nollaa"; +"action_reset_identity" = "Nollaa identiteetti"; +"action_retry" = "Yritä uudelleen"; +"action_retry_decryption" = "Yritä salauksen purkamista uudelleen"; +"action_save" = "Tallenna"; +"action_search" = "Hae"; +"action_send" = "Lähetä"; +"action_send_message" = "Lähetä viesti"; +"action_share" = "Jaa"; +"action_share_link" = "Jaa linkki"; +"action_show" = "Näytä"; +"action_sign_in_again" = "Kirjaudu uudelleen"; +"action_signout" = "Kirjaudu ulos"; +"action_signout_anyway" = "Kirjaudu ulos silti"; +"action_skip" = "Ohita"; +"action_start" = "Aloita"; +"action_start_chat" = "Aloita keskustelu"; +"action_start_verification" = "Aloita vahvistus"; +"action_static_map_load" = "Lataa kartta napauttamalla"; +"action_take_photo" = "Ota kuva"; +"action_tap_for_options" = "Näytä vaihtoehdot napauttamalla"; +"action_try_again" = "Yritä uudelleen"; +"action_unpin" = "Poista kiinnitys"; +"action_view_in_timeline" = "Näytä aikajanalla"; +"action_view_source" = "Näytä lähde"; +"action_yes" = "Kyllä"; +"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öä."; +"banner_migrate_to_native_sliding_sync_title" = "Päivitys saatavilla"; +"banner_set_up_recovery_content" = "Palauta kryptografinen identiteettisi ja viestihistoriasi palautusavaimella, mikäli menetät pääsyn kaikkiin laitteisiisi."; +"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_advanced_settings" = "Edistyneet asetukset"; +"common_analytics" = "Analytiikka"; +"common_appearance" = "Ulkoasu"; +"common_audio" = "Ääni"; +"common_blocked_users" = "Estetyt käyttäjät"; +"common_bubbles" = "Kuplat"; +"common_call_started" = "Puhelu alkoi"; +"common_chat_backup" = "Keskustelujen varmuuskopiointi"; +"common_copyright" = "Tekijänoikeudet"; +"common_creating_room" = "Luodaan huonetta..."; +"common_current_user_left_room" = "Poistuit huoneesta"; +"common_dark" = "Tumma"; +"common_decryption_error" = "Salauksen purkuvirhe"; +"common_developer_options" = "Kehittäjän asetukset"; +"common_device_id" = "Laitteen tunnus"; +"common_direct_chat" = "Yksityinen keskustelu"; +"common_edited_suffix" = "(muokattu)"; +"common_editing" = "Muokataan viestiä"; +"common_emote" = "* %1$@ %2$@"; +"common_encryption" = "Salaus"; +"common_encryption_enabled" = "Salaus käytössä"; +"common_enter_your_pin" = "Syötä PIN-koodisi"; +"common_error" = "Virhe"; +"common_everyone" = "Kaikki"; +"common_face_id_ios" = "Face ID"; +"common_failed" = "Epäonnistui"; +"common_favourite" = "Lisää suosikkeihin"; +"common_favourited" = "Lisätty suosikkeihin"; +"common_file" = "Tiedosto"; +"common_forward_message" = "Välitä viesti"; +"common_frequently_used" = "Usein käytetyt"; +"common_gif" = "GIF"; +"common_image" = "Kuva"; +"common_in_reply_to" = "Vastauksena käyttäjälle %1$@"; +"common_invite_unknown_profile" = "Tätä Matrix-tunnusta ei löytynyt, joten kutsu ei välttämättä mene perille."; +"common_leaving_room" = "Poistutaan huoneesta"; +"common_light" = "Vaalea"; +"common_link_copied_to_clipboard" = "Linkki kopioitu leikepöydälle"; +"common_loading" = "Ladataan…"; +"common_message" = "Viesti"; +"common_message_actions" = "Viestitoiminnot"; +"common_message_layout" = "Viestien asettelu"; +"common_message_removed" = "Viesti poistettu"; +"common_modern" = "Moderni"; +"common_mute" = "Mykistä"; +"common_no_results" = "Ei tuloksia"; +"common_no_room_name" = "Nimetön huone"; +"common_offline" = "Ei yhteyttä"; +"common_optic_id_ios" = "Optic ID"; +"common_or" = "tai"; +"common_password" = "Salasana"; +"common_people" = "Ihmiset"; +"common_permalink" = "Pysyvä linkki"; +"common_permission" = "Lupa"; +"common_please_wait" = "Odota hetki..."; +"common_poll_end_confirmation" = "Haluatko varmasti lopettaa tämän kyselyn?"; +"common_poll_summary" = "Kysely: %1$@"; +"common_poll_total_votes" = "Ääniä yhteensä: %1$@"; +"common_poll_undisclosed_text" = "Tulokset näkyvät kyselyn päätyttyä"; +"common_privacy_policy" = "Tietosuojakäytäntö"; +"common_reaction" = "Reaktio"; +"common_reactions" = "Reaktiot"; +"common_recovery_key" = "Palautusavain"; +"common_refreshing" = "Päivitetään..."; +"common_replying_to" = "Vastataan käyttäjälle %1$@"; +"common_report_a_bug" = "Ilmoita virheestä"; +"common_report_a_problem" = "Ilmoita ongelmasta"; +"common_report_submitted" = "Ilmoitus lähetetty"; +"common_rich_text_editor" = "Rikastettu tekstieditori"; +"common_room" = "Huone"; +"common_room_name" = "Huoneen nimi"; +"common_room_name_placeholder" = "esim. projektisi nimi"; +"common_saved_changes" = "Muutokset tallennettu"; +"common_saving" = "Tallennetaan"; +"common_screen_lock" = "Näyttölukko"; +"common_search_for_someone" = "Etsi jotakuta"; +"common_search_results" = "Hakutulokset"; +"common_security" = "Turvallisuus"; +"common_seen_by" = "Nähneet henkilöt"; +"common_sending" = "Lähetetään…"; +"common_sending_failed" = "Lähetys epäonnistui"; +"common_sent" = "Lähetetty"; +"common_server_not_supported" = "Palvelin ei ole tuettu"; +"common_server_url" = "Palvelimen osoite"; +"common_settings" = "Asetukset"; +"common_shared_location" = "Jaettu sijainti"; +"common_signing_out" = "Kirjaudutaan ulos"; +"common_something_went_wrong" = "Jokin meni pieleen"; +"common_starting_chat" = "Aloitetaan keskustelua..."; +"common_sticker" = "Tarra"; +"common_success" = "Onnistui"; +"common_suggestions" = "Ehdotukset"; +"common_syncing" = "Synkronoidaan"; +"common_system" = "Järjestelmän oletus"; +"common_text" = "Teksti"; +"common_third_party_notices" = "Kolmannen osapuolen ilmoitukset"; +"common_thread" = "Viestiketju"; +"common_topic" = "Aihe"; +"common_topic_placeholder" = "Mistä tässä huoneessa on kyse?"; +"common_touch_id_ios" = "Touch ID"; +"common_unable_to_decrypt" = "Salauksen purkaminen ei onnistunut"; +"common_unable_to_decrypt_no_access" = "Sinulla ei ole oikeutta lukea tätä viestiä"; +"common_unable_to_invite_message" = "Kutsujen ei voitu lähettää yhdelle tai useammalle käyttäjälle."; +"common_unable_to_invite_title" = "Kutsujen lähettäminen ei onnistunut"; +"common_unlock" = "Avaa"; +"common_unmute" = "Poista mykistys"; +"common_unsupported_call" = "Unsupported call"; +"common_unsupported_event" = "Tapahtumaa ei tueta"; +"common_username" = "Käyttäjänimi"; +"common_verification_cancelled" = "Vahvistus peruttu"; +"common_verification_complete" = "Vahvistus suoritettu"; +"common_verification_failed" = "Vahvistus epäonnistui"; +"common_verified" = "Vahvistettu"; +"common_verify_device" = "Vahvista laite"; +"common_verify_identity" = "Vahvista identiteetti"; +"common_video" = "Video"; +"common_voice_message" = "Ääniviesti"; +"common_waiting" = "Odotetaan…"; +"common_waiting_for_decryption_key" = "Odotetaan viestiä"; +"common.copied_to_clipboard" = "Kopioitu leikepöydälle"; +"common.do_not_show_this_again" = "Älä näytä tätä uudelleen"; +"common.open_source_licenses" = "Avoimen lähdekoodin lisenssit"; +"common.pinned" = "Kiinnitetty"; +"common.send_to" = "Jaa"; +"common.you" = "Sinä"; +"common_unable_to_decrypt_insecure_device" = "Lähetetty suojaamattomasta laitteesta"; +"common_unable_to_decrypt_verification_violation" = "Lähettäjän vahvistettu identiteetti on vaihtunut"; +"confirm_recovery_key_banner_message" = "Vahvista palautusavaimesi, jotta pääset edelleen käyttämään avainten säilytystä ja viestihistoriaa."; +"confirm_recovery_key_banner_primary_button_title" = "Syötä palautusavaimesi"; +"confirm_recovery_key_banner_secondary_button_title" = "Unohditko palautusavaimesi?"; +"confirm_recovery_key_banner_title" = "Avainten säilytys ei ole synkronoitu"; +"crash_detection_dialog_content" = "%1$@ kaatui edellisellä käyttökerralla. Haluatko jakaa virheraportin kanssamme?"; +"crypto_identity_change_pin_violation" = "Käyttäjän %1$@ identiteetti näyttää muuttuneen. %2$@"; +"crypto_identity_change_pin_violation_new" = "Käyttäjän %1$@ %2$@ identiteetti näyttää muuttuneen. %3$@"; +"crypto_identity_change_pin_violation_new_user_id" = "(%1$@)"; +"dialog_permission_camera" = "Jotta sovellus voisi käyttää kameraa, anna lupa järjestelmän asetuksista."; +"dialog_permission_generic" = "Anna lupa järjestelmän asetuksista."; +"dialog_permission_location_description_ios" = "Myönnä lupa laitteen sijaintiasetuksista."; +"dialog_permission_location_title_ios" = "%1$@ -sovelluksella ei ole lupaa sijaintiisi."; +"dialog_permission_microphone" = "Jotta sovellus voisi käyttää mikrofonia, anna lupa järjestelmän asetuksista."; +"dialog_permission_microphone_description_ios" = "Anna lupa, jotta voit nauhoittaa ja lähettää ääniviestejä."; +"dialog_permission_microphone_title_ios" = "%1$@ tarvitsee luvan mikrofonin käyttöön."; +"dialog_permission_notification" = "Jotta sovellus voisi näyttää ilmoituksia, anna lupa järjestelmän asetuksista."; +"dialog_title_confirmation" = "Vahvistus"; +"dialog_title_warning" = "Varoitus"; +"dialog_unsaved_changes_description_ios" = "Muutoksiasi ei tallenneta"; +"dialog_unsaved_changes_title" = "Tallenna muutokset?"; +"emoji_picker_category_activity" = "Aktiviteetit"; +"emoji_picker_category_flags" = "Liput"; +"emoji_picker_category_foods" = "Ruoka ja juoma"; +"emoji_picker_category_nature" = "Eläimet ja luonto"; +"emoji_picker_category_objects" = "Esineet"; +"emoji_picker_category_people" = "Hymiöt ja ihmiset"; +"emoji_picker_category_places" = "Matkustaminen ja paikat"; +"emoji_picker_category_symbols" = "Symbolit"; +"error_account_creation_not_possible" = "Kotipalvelimesi on päivitettävä tukemaan Matrix Authentication Serviceä ja tilin luomista."; +"error_failed_creating_the_permalink" = "Pysyvän linkin luominen epäonnistui"; +"error_failed_loading_map" = "%1$@ ei pystynyt lataamaan karttaa. Yritä myöhemmin uudelleen."; +"error_failed_loading_messages" = "Viestien lataaminen epäonnistui"; +"error_failed_locating_user" = "%1$@ ei päässyt käsiksi sijaintiisi. Yritä myöhemmin uudelleen."; +"error_failed_uploading_voice_message" = "Ääniviestin lähettäminen epäonnistui."; +"error_message_not_found" = "Viestiä ei löytynyt"; +"error_no_compatible_app_found" = "Yhteensopivaa sovellusta ei löytynyt käsittelemään tätä toimintoa."; +"error_some_messages_have_not_been_sent" = "Joitakin viestejä ei ole lähetetty"; +"error_unknown" = "Anteeksi, tapahtui virhe"; +"event_shield_reason_authenticity_not_guaranteed" = "Tämän salatun viestin aitoutta ei voida taata tällä laitteella."; +"event_shield_reason_previously_verified" = "Aiemmin vahvistetun käyttäjän salaama."; +"event_shield_reason_sent_in_clear" = "Ei salattu."; +"event_shield_reason_unknown_device" = "Tuntemattoman tai poistetun laitteen salaama."; +"event_shield_reason_unsigned_device" = "Salattu laitteella, jota sen omistaja ei ole vahvistanut."; +"event_shield_reason_unverified_identity" = "Vahvistamattoman käyttäjän salaama."; +"full_screen_intent_banner_message" = "Salli koko näytön ilmoitukset, kun laite on lukittu, jos et halua koskaan missata tärkeää puhelua."; +"full_screen_intent_banner_title" = "Paranna puhelukokemustasi"; +"invite_friends_rich_title" = "🔐️ Liity seuraani %1$@ -sovelluksessa"; +"invite_friends_text" = "Hei, keskustele kanssani %1$@ -sovelluksessa: %2$@"; +"leave_conversation_alert_subtitle" = "Haluatko varmasti poistua keskustelusta? Tämä keskustelu ei ole julkinen ja et voi liittyä takaisin ilman kutsua."; +"leave_room_alert_empty_subtitle" = "Haluatko varmasti poistua huoneesta? Olet huoneen ainoa jäsen. Jos poistut, kukaan ei voi liittyä takaisin, et edes sinä."; +"leave_room_alert_private_subtitle" = "Haluatko varmasti poistua huoneesta? Tämä huone ei ole julkinen ja et voi liittyä takaisin ilman kutsua."; +"leave_room_alert_subtitle" = "Haluatko varmasti poistua huoneesta?"; +"login_initial_device_name_ios" = "%1$@ iOS"; +"notification_channel_call" = "Puhelu"; +"notification_channel_listening_for_events" = "Tapahtumien kuuntelu"; +"notification_channel_noisy" = "Äänekkäät ilmoitukset"; +"notification_channel_ringing_calls" = "Soivat puhelut"; +"notification_channel_silent" = "Hiljaiset ilmoitukset"; +"notification_incoming_call" = "Saapuva puhelu"; +"notification_inline_reply_failed" = "** Lähetys epäonnistui - avaa huone"; +"notification_invite_body" = "Kutsui sinut keskustelemaan"; +"notification_invite_body_with_sender" = "%1$@ kutsui sinut keskustelemaan"; +"notification_mentioned_you_body" = "Mainitsi sinut: %1$@"; +"notification_new_messages" = "Uusia viestejä"; +"notification_reaction_body" = "Reagoi emojilla %1$@"; +"notification_room_invite_body" = "Kutsui sinut liittymään huoneeseen"; +"notification_room_invite_body_with_sender" = "%1$@ kutsui sinut liittymään huoneeseen"; +"notification_sender_me" = "Minä"; +"notification_sender_mention_reply" = "%1$@ mainitsi tai vastasi"; +"notification_test_push_notification_content" = "Katselet ilmoitusta! Klikkaa minua!"; +"notification_ticker_text_dm" = "%1$@: %2$@"; +"notification_ticker_text_group" = "%1$@: %2$@ %3$@"; +"notification_unread_notified_messages_and_invitation" = "%1$@ ja %2$@"; +"notification_unread_notified_messages_in_room" = "%1$@ %2$@"; +"notification_unread_notified_messages_in_room_and_invitation" = "%1$@ %2$@ ja %3$@"; +"preference_rageshake" = "Raivostunut ravistaminen ilmoittaa virheestä"; +"rageshake_detection_dialog_content" = "Näytät ravistelevan puhelinta turhautuneena. Haluatko avata vikailmoitusnäytön?"; +"rich_text_editor_bullet_list" = "Numeroimaton luettelo päälle/pois"; +"rich_text_editor_close_formatting_options" = "Sulje muotoiluasetukset"; +"rich_text_editor_code_block" = "Koodilohko päälle/pois"; +"rich_text_editor_composer_placeholder" = "Viesti..."; +"rich_text_editor_create_link" = "Luo linkki"; +"rich_text_editor_edit_link" = "Muokkaa linkkiä"; +"rich_text_editor_format_bold" = "Käytä lihavoitua muotoa"; +"rich_text_editor_format_italic" = "Käytä kursiivimuotoa"; +"rich_text_editor_format_strikethrough" = "Käytä yliviivausmuotoa"; +"rich_text_editor_format_underline" = "Käytä alleviivausmuotoa"; +"rich_text_editor_full_screen_toggle" = "Koko näytön tila päälle/pois"; +"rich_text_editor_indent" = "Sisennä"; +"rich_text_editor_inline_code" = "Käytä rivinsisäistä koodimuotoa"; +"rich_text_editor_link" = "Aseta linkki"; +"rich_text_editor_numbered_list" = "Numeroitu luettelo päälle/pois"; +"rich_text_editor_open_compose_options" = "Avaa kirjoitusvaihtoehdot"; +"rich_text_editor_quote" = "Lainaus päälle/pois"; +"rich_text_editor_remove_link" = "Poista linkki"; +"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..."; +"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."; +"screen_create_room_room_access_section_anyone_option_description" = "Kuka tahansa voi liittyä tähän huoneeseen"; +"screen_create_room_room_access_section_anyone_option_title" = "Kuka tahansa"; +"screen_create_room_room_access_section_header" = "Huoneeseen Pääsy"; +"screen_create_room_room_access_section_knocking_option_description" = "Kuka tahansa voi pyytää saada liittyä huoneeseen, mutta ylläpitäjän tai valvojan on hyväksyttävä pyyntö"; +"screen_create_room_room_access_section_knocking_option_title" = "Pyydä liittymistä"; +"screen_create_room_room_address_invalid_symbols_error_description" = "Jotkin merkit eivät ole sallittuja. Vain kirjaimet, numerot ja seuraavat symbolit ovat tuettuja ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Tämä huoneen osoite on jo käytössä, yritä muokata huoneen osoitekenttää tai muuta huoneen nimeä"; +"screen_create_room_room_address_section_footer" = "Jotta tämä huone näkyisi julkisessa huonehakemistossa, tarvitset huoneen osoitteen."; +"screen_create_room_room_address_section_title" = "Huoneen osoite"; +"screen_create_room_room_visibility_section_title" = "Huoneen näkyvyys"; +"screen_join_room_cancel_knock_action" = "Peruuta pyyntö"; +"screen_join_room_cancel_knock_alert_confirmation" = "Kyllä, peruuta"; +"screen_join_room_cancel_knock_alert_description" = "Haluatko varmasti peruuttaa pyyntösi liittyä tähän huoneeseen?"; +"screen_join_room_cancel_knock_alert_title" = "Peruuta liittymispyyntö"; +"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_decline_and_ban_action_title" = "Decline and ban"; +"screen_pinned_timeline_empty_state_description" = "Paina viestiä ja valitse “%1$@” lisätäksesi sen tänne."; +"screen_pinned_timeline_empty_state_headline" = "Kiinnitä tärkeät viestit, jotta ne löytyvät helposti."; +"screen_reset_encryption_password_error" = "Tapahtui tuntematon virhe. Tarkista, että tilisi salasana on oikein ja yritä uudelleen."; +"screen_resolve_send_failure_changed_identity_primary_button_title" = "Peruuta vahvistus ja lähetä"; +"screen_resolve_send_failure_changed_identity_subtitle" = "Voit peruuttaa vahvistuksen ja lähettää tämän viestin silti, tai voit peruuttaa viestin lähettämisen toistaiseksi ja yrittää uudelleen myöhemmin, kun olet vahvistanut käyttäjän %1$@ uudelleen."; +"screen_resolve_send_failure_changed_identity_title" = "Viestiäsi ei lähetetty, koska käyttäjän %1$@ vahvistettu identiteetti on muuttunut"; +"screen_resolve_send_failure_unsigned_device_primary_button_title" = "Lähetä viesti silti"; +"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ käyttää yhtä tai useampaa vahvistamatonta laitetta. Voit lähettää viestin silti tai voit peruuttaa sen toistaiseksi ja yrittää myöhemmin uudelleen, kun %2$@ on vahvistanut kaikki laitteensa."; +"screen_resolve_send_failure_unsigned_device_title" = "Viestiäsi ei lähetetty, koska %1$@ ei ole vahvistanut kaikkia laitteitaan."; +"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_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_details_pinned_events_row_title" = "Kiinnitetyt viestit"; +"screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_roomlist_knock_event_sent_description" = "Liittymispyyntö lähetetty"; +"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."; +"screen_account_provider_form_hint" = "Kotipalvelimen osoite"; +"screen_account_provider_form_notice" = "Kirjoita hakutermi tai osoite."; +"screen_account_provider_form_subtitle" = "Hae yritystä, yhteisöä tai yksityistä palvelinta."; +"screen_account_provider_form_title" = "Etsi palveluntarjoajaa"; +"screen_account_provider_signin_title" = "Olet kirjautumassa sisään %@-palvelimelle"; +"screen_account_provider_signup_title" = "Olet luomassa tiliä %@-palvelimelle"; +"screen_advanced_settings_developer_mode" = "Kehittäjätila"; +"screen_advanced_settings_developer_mode_description" = "Ottamalla käyttöön pääset käsiksi kehittäjille tarkoitettuihin ominaisuuksiin."; +"screen_advanced_settings_media_compression_description" = "Lähetä valokuvia ja videoita nopeammin ja vähennä datan käyttöä."; +"screen_advanced_settings_media_compression_title" = "Optimoi median laatu"; +"screen_advanced_settings_rich_text_editor_description" = "Ota rikastettu tekstieditori pois käytöstä, jotta voit kirjoittaa Markdownia manuaalisesti."; +"screen_advanced_settings_send_read_receipts" = "Lukukuittaukset"; +"screen_advanced_settings_send_read_receipts_description" = "Jos tämä on poissa päältä, sinun lukukuittauksia ei lähetetä kenellekään. Vastaanotat silti lukukuittauksia muilta käyttäjiltä."; +"screen_advanced_settings_share_presence" = "Jaa läsnäolo"; +"screen_advanced_settings_share_presence_description" = "Jos tämä on poissa päältä, et lähetä tai vastaanota lukukuittauksia tai kirjoitusilmotuksia."; +"screen_advanced_settings_view_source_description" = "Ota käyttöön mahdollisuus tarkastella viestin lähdettä aikajanalla."; +"screen_analytics_prompt_data_usage" = "Emme tallenna tai profiloi henkilötietoja"; +"screen_analytics_prompt_help_us_improve" = "Jaa anonyymejä käyttötietoja auttaaksesi meitä tunnistamaan ongelmat."; +"screen_analytics_prompt_read_terms" = "Voit lukea kaikki ehtomme %1$@."; +"screen_analytics_prompt_read_terms_content_link" = "täällä"; +"screen_analytics_prompt_settings" = "Voit poistaa tämän käytöstä milloin tahansa"; +"screen_analytics_prompt_third_party_sharing" = "Emme jaa tietojasi kolmansien osapuolien kanssa"; +"screen_analytics_prompt_title" = "Auta parantamaan %1$@ -sovellusta"; +"screen_analytics_settings_share_data" = "Jaa analytiikkatietoja"; +"screen_app_lock_biometric_authentication" = "biometrinen tunnistus"; +"screen_app_lock_biometric_unlock" = "biometrinen tunnistus"; +"screen_app_lock_biometric_unlock_reason_ios" = "Sovelluksen käyttö edellyttää tunnistautumista"; +"screen_app_lock_forgot_pin" = "Unohtuiko PIN-koodi?"; +"screen_app_lock_settings_change_pin" = "Vaihda PIN-koodi"; +"screen_app_lock_settings_enable_biometric_unlock" = "Salli biometrinen tunnistus"; +"screen_app_lock_settings_enable_face_id_ios" = "Salli Face ID"; +"screen_app_lock_settings_enable_optic_id_ios" = "Salli Optic ID"; +"screen_app_lock_settings_enable_touch_id_ios" = "Salli Touch ID"; +"screen_app_lock_settings_remove_pin" = "Poista PIN-koodi"; +"screen_app_lock_settings_remove_pin_alert_message" = "Haluatko varmasti poistaa PIN-koodin?"; +"screen_app_lock_settings_remove_pin_alert_title" = "Poista PIN-koodi?"; +"screen_app_lock_setup_biometric_unlock_allow_title" = "Salli %1$@"; +"screen_app_lock_setup_biometric_unlock_skip" = "Käytän mieluummin PIN-koodia"; +"screen_app_lock_setup_biometric_unlock_subtitle" = "Säästä aikaa ja ota käyttöön %1$@"; +"screen_app_lock_setup_choose_pin" = "Valitse PIN-koodi"; +"screen_app_lock_setup_confirm_pin" = "Vahvista PIN-koodi"; +"screen_app_lock_setup_pin_context" = "Lukitse %1$@ -sovellus lisätäksesi turvaa keskusteluihisi.\n\nValitse PIN-koodi, jonka muistat. Jos unohdat sen, joudut kirjautumaan ulos."; +"screen_app_lock_setup_pin_forbidden_dialog_content" = "Et voi valita tätä PIN-koodia turvallisuussyistä"; +"screen_app_lock_setup_pin_forbidden_dialog_title" = "Valitse toinen PIN-koodi"; +"screen_app_lock_setup_pin_mismatch_dialog_content" = "Anna sama PIN-koodi kahdesti"; +"screen_app_lock_setup_pin_mismatch_dialog_title" = "PIN-koodit eivät täsmää"; +"screen_app_lock_signout_alert_message" = "Sinun on kirjauduttava sisään uudelleen ja luotava uusi PIN-koodi jatkaaksesi"; +"screen_app_lock_signout_alert_title" = "Sinut kirjataan ulos"; +"screen_blocked_users_empty" = "Et ole estänyt ketään"; +"screen_blocked_users_unblocking" = "Poistetaan estoa..."; +"screen_bug_report_attach_screenshot" = "Liitä kuvakaappaus"; +"screen_bug_report_contact_me" = "Voitte ottaa minuun yhteyttä, jos teillä on lisäkysymyksiä."; +"screen_bug_report_contact_me_title" = "Ota minuun yhteyttä"; +"screen_bug_report_edit_screenshot" = "Muokkaa kuvakaappausta"; +"screen_bug_report_editor_description" = "Kuvaile ongelmaasi. Mitä teit? Mitä odotit tapahtuvan? Mitä oikeasti tapahtui? Kerro niin paljon kuin mahdollista."; +"screen_bug_report_editor_placeholder" = "Kuvaile ongelmaasi..."; +"screen_bug_report_editor_supporting" = "Jos mahdollista, kirjoita englanniksi."; +"screen_bug_report_error_description_too_short" = "Kuvaus on liian lyhyt. Kerro tarkemmin mitä tapahtui, kiitos!"; +"screen_bug_report_include_crash_logs" = "Lähetä kaatumislokit"; +"screen_bug_report_include_logs" = "Lähetä lokitiedostot"; +"screen_bug_report_include_screenshot" = "Lähetä kuvakaappaus"; +"screen_bug_report_logs_description" = "Lähetä lokitiedostot viestisi kanssa, jotta voimme varmistaa, että kaikki toimii oikein. Jos haluat lähettää viestisi ilman lokeja, jätä tämä asetus valitsematta."; +"screen_bug_report_view_logs" = "Näytä lokitiedostot"; +"screen_change_account_provider_matrix_org_subtitle" = "Matrix.org on suuri, ilmainen palvelin julkisessa Matrix-verkossa turvalliseen, hajautettuun viestintään, jota ylläpitää Matrix.org-säätiö."; +"screen_change_account_provider_other" = "Muu"; +"screen_change_account_provider_subtitle" = "Käytä toista palveluntarjoajaa, kuten omaa yksityistä palvelintasi tai työpaikkaasi."; +"screen_change_account_provider_title" = "Vaihda palveluntarjoajaa"; +"screen_change_server_error_invalid_homeserver" = "Kotipalvelimeen ei saatu yhteyttä. Varmista, että olet syöttänyt osoitteen oikein. Jos osoite on oikein, ota yhteyttä palvelimesi ylläpitäjään."; +"screen_change_server_error_invalid_well_known" = "Sliding sync ei ole saatavilla well-known tiedostossa olevan ongelman vuoksi:\n%1$@"; +"screen_change_server_error_no_sliding_sync_message" = "Tämä palvelin ei tällä hetkellä tue sliding syncia."; +"screen_change_server_form_header" = "Kotipalvelimen osoite"; +"screen_change_server_form_notice" = "Voit yhdistää vain olemassa olevaan palvelimeen, joka tukee sliding syncia. Kotipalvelimesi ylläpitäjän on otettava se käyttöön. %1$@"; +"screen_change_server_subtitle" = "Mikä on palvelimesi osoite?"; +"screen_change_server_title" = "Valitse palvelimesi"; +"screen_chat_backup_key_backup_action_disable" = "Ota avainten säilytys pois käytöstä"; +"screen_chat_backup_key_backup_action_enable" = "Ota varmuuskopiointi käyttöön"; +"screen_chat_backup_key_backup_description" = "Säilytä kryptografinen identiteettisi ja viestien avaimet turvallisesti palvelimellasi. Tämän avulla pääset käsiksi viestihistoriaan uusillakin laitteilla. %1$@."; +"screen_chat_backup_key_backup_title" = "Avainten säilytys"; +"screen_chat_backup_key_storage_disabled_error" = "Avainten säilytys on oltava käytössä, jotta palautus voidaan ottaa käyttöön."; +"screen_chat_backup_key_storage_toggle_description" = "Lataa avaimet tästä laitteesta"; +"screen_chat_backup_key_storage_toggle_title" = "Salli avainten säilytys"; +"screen_chat_backup_recovery_action_change" = "Vaihda palautusavain"; +"screen_chat_backup_recovery_action_change_description" = "Palauta kryptografinen identiteettisi ja viestihistoriasi palautusavaimella, jos olet menettänyt kaikki nykyiset laitteesi."; +"screen_chat_backup_recovery_action_confirm_description" = "Avainten säilytys ei ole tällä hetkellä synkronoitu."; +"screen_chat_backup_recovery_action_setup_description" = "Pääset käsiksi salattuihin viesteihisi, jos menetät kaikki laitteesi tai olet kirjautunut ulos %1$@ -sovelluksesta kaikkialla."; +"screen_create_account_title" = "Luo tili"; +"screen_create_new_recovery_key_list_item_1" = "Avaa %1$@ tietokoneella"; +"screen_create_new_recovery_key_list_item_2" = "Kirjaudu tilillesi uudelleen"; +"screen_create_new_recovery_key_list_item_3" = "Kun sinua pyydetään vahvistamaan laitteesi, valitse %1$@"; +"screen_create_new_recovery_key_list_item_3_reset_all" = "“Nollaa kaikki”"; +"screen_create_new_recovery_key_list_item_4" = "Seuraa ohjeita uuden palautusavaimen luomiseksi"; +"screen_create_new_recovery_key_list_item_5" = "Tallenna uusi palautusavaimesi salasanojen hallintaohjelmaan tai salattuun muistiinpanoon"; +"screen_create_new_recovery_key_title" = "Nollaa tilisi salaus toisella laitteella"; +"screen_create_poll_add_option_btn" = "Lisää vaihtoehto"; +"screen_create_poll_anonymous_desc" = "Näytä tulokset vasta kyselyn päätyttyä"; +"screen_create_poll_anonymous_headline" = "Piilota äänet"; +"screen_create_poll_answer_hint" = "Vaihtoehto %1$d"; +"screen_create_poll_cancel_confirmation_title_ios" = "Peruuta kysely"; +"screen_create_poll_question_desc" = "Kysymys tai aihe"; +"screen_create_poll_question_hint" = "Mistä kyselyssä on kyse?"; +"screen_create_poll_title" = "Luo kysely"; +"screen_create_room_action_create_room" = "Uusi huone"; +"screen_create_room_error_creating_room" = "Huoneen luomisessa tapahtui virhe"; +"screen_create_room_private_option_description" = "Vain kutsutut henkilöt pääsevät tähän huoneeseen. Kaikki viestit ovat päästä päähän salattuja."; +"screen_create_room_private_option_title" = "Yksityinen huone"; +"screen_create_room_public_option_description" = "Kuka tahansa voi löytää tämän huoneen.\nVoit muuttaa tämän milloin tahansa huoneen asetuksista."; +"screen_create_room_public_option_title" = "Julkinen huone"; +"screen_create_room_topic_label" = "Aihe (valinnainen)"; +"screen_deactivate_account_confirmation_dialog_content" = "Vahvista, että haluat deaktivoida tilisi. Tätä ei voi perua."; +"screen_deactivate_account_delete_all_messages" = "Poista kaikki viestini"; +"screen_deactivate_account_delete_all_messages_notice" = "Varoitus: Tulevaisuudessa muut voivat nähdä puutteellisia keskusteluja."; +"screen_deactivate_account_description" = "Tilisi deaktivointia %1$@. Jos teet sen:"; +"screen_deactivate_account_description_bold_part" = "ei voi peruuttaa"; +"screen_deactivate_account_list_item_1" = "Tilisi %1$@ (et voi kirjautua takaisin sisään, eikä tunnustasi voi käyttää uudelleen)."; +"screen_deactivate_account_list_item_1_bold_part" = "poistetaan käytöstä pysyvästi"; +"screen_deactivate_account_list_item_2" = "Sinut poistetaan kaikista keskusteluhuoneista."; +"screen_deactivate_account_list_item_3" = "Tilitietosi poistetaan identiteettipalvelimeltamme."; +"screen_deactivate_account_list_item_4" = "Viestisi näkyvät edelleen rekisteröityneille käyttäjille, mutta ne eivät ole uusien tai rekisteröimättömien käyttäjien saatavilla, jos päätät poistaa ne."; +"screen_deactivate_account_title" = "Deaktivoi tili"; +"screen_edit_poll_delete_confirmation" = "Haluatko varmasti poistaa tämän kyselyn?"; +"screen_edit_profile_display_name" = "Näyttönimi"; +"screen_edit_profile_display_name_placeholder" = "Näyttönimesi"; +"screen_edit_profile_error" = "Tuntematon virhe tapahtui, eikä tietoja voitu muuttaa."; +"screen_edit_profile_error_title" = "Profiilin muokkaaminen ei onnistunut"; +"screen_edit_profile_title" = "Muokkaa profiilia"; +"screen_edit_profile_updating_details" = "Muokataan profiilia..."; +"screen_encryption_reset_action_continue_reset" = "Jatka nollausta"; +"screen_encryption_reset_bullet_1" = "Tilitietosi, yhteystiedot, asetukset ja keskustelulista säilytetään"; +"screen_encryption_reset_bullet_2" = "Menetät kaiken viestihistorian, joka on tallella vain palvelimella"; +"screen_encryption_reset_bullet_3" = "Sinun on vahvistettava kaikki olemassa olevat laitteesi ja yhteystietosi uudelleen"; +"screen_encryption_reset_footer" = "Nollaa identiteettisi vain, jos et voi käyttää toista laitetta, johon olet kirjautunut, ja olet kadottanut palautusavaimesi."; +"screen_encryption_reset_title" = "Etkö voi vahvistaa? Sinun on nollattava identiteettisi."; +"screen_identity_confirmation_cannot_confirm" = "Etkö voi vahvistaa?"; +"screen_identity_confirmation_create_new_recovery_key" = "Luo uusi palautusavain"; +"screen_identity_confirmation_subtitle" = "Vahvista tämä laite suojattua viestintää varten."; +"screen_identity_confirmation_title" = "Vahvista identiteettisi"; +"screen_identity_confirmation_use_another_device" = "Käytä toista laitetta"; +"screen_identity_confirmation_use_recovery_key" = "Käytä palautusavainta"; +"screen_identity_confirmed_subtitle" = "Nyt voit lukea ja lähettää viestejä turvallisesti, ja kaikki, joiden kanssa keskustelet, voivat myös luottaa tähän laitteeseen."; +"screen_identity_confirmed_title" = "Laite vahvistettu"; +"screen_identity_waiting_on_other_device" = "Odotetaan toista laitetta…"; +"screen_invites_decline_chat_message" = "Haluatko varmasti hylätä kutsun liittyä %1$@ -huoneeseen?"; +"screen_invites_decline_chat_title" = "Hylkää kutsu"; +"screen_invites_decline_direct_chat_message" = "Haluatko varmasti hylätä kutsun yksityiseen keskusteluun käyttäjän %1$@ kanssa?"; +"screen_invites_decline_direct_chat_title" = "Hylkää keskustelu"; +"screen_invites_empty_list" = "Ei kutsuja"; +"screen_invites_invited_you" = "%1$@ (%2$@) kutsui sinut"; +"screen_join_room_join_action" = "Liity huoneeseen"; +"screen_join_room_knock_action" = "Lähetä liittymispyyntö"; +"screen_join_room_space_not_supported_description" = "%1$@ ei tue vielä tiloja. Voit käyttää tiloja selainversiolla."; +"screen_join_room_space_not_supported_title" = "Tiloja ei vielä tueta"; +"screen_join_room_subtitle_knock" = "Paina alla olevaa nappia ja huoneen ylläpitäjä saa ilmoituksen. Voit liittyä keskusteluun kun pyyntösi on hyväksytty."; +"screen_join_room_subtitle_no_preview" = "Sinun on oltava tämän huoneen jäsen, jotta voit nähdä viestihistorian."; +"screen_join_room_title_knock" = "Haluatko liittyä tähän huoneeseen?"; +"screen_join_room_title_no_preview" = "Esikatselu ei ole saatavilla"; +"screen_key_backup_disable_confirmation_action_turn_off" = "Poista käytöstä"; +"screen_key_backup_disable_confirmation_description" = "Menetät salatut viestisi, jos kirjaudut ulos kaikista laitteista."; +"screen_key_backup_disable_confirmation_title" = "Haluatko varmasti poistaa varmuuskopioinnin käytöstä?"; +"screen_key_backup_disable_description" = "Avainten säilytyksen poistaminen poistaa sinun kryptografisen identiteetin ja viestien avaimet palvelimeltasi ja poistaa seuraavat suojausominausuudet käytöstä:"; +"screen_key_backup_disable_description_point_1" = "Et saa salattua viestihistoriaa uusilla laitteilla"; +"screen_key_backup_disable_description_point_2" = "Menetät pääsyn salattuihin viestihisi, jos kirjaudut ulos %1$@ -sovelluksesta kaikkialla."; +"screen_key_backup_disable_title" = "Haluatko varmasti ottaa avainten säilytyksen pois käytöstä ja poistaa sen?"; +"screen_login_error_deactivated_account" = "Tämä tili on deaktivoitu."; +"screen_login_error_invalid_credentials" = "Väärä käyttäjänimi ja/tai salasana"; +"screen_login_error_invalid_user_id" = "Tämä ei ole kelvollinen käyttäjätunnus. Odotettu muoto: '@käyttäjä:kotipalvelin.fi'"; +"screen_login_error_refresh_tokens" = "Tämä palvelin on määritetty käyttämään refresh tokeneja. Näitä ei tueta salasanapohjaisen kirjautumisen kanssa."; +"screen_login_error_unsupported_authentication" = "Valitsemasi kotipalvelin ei tue salasana- tai OIDC-kirjautumista. Ota yhteyttä palvelimesi ylläpitäjään tai valitse toinen kotipalvelin."; +"screen_login_form_header" = "Syötä tietosi"; +"screen_login_title" = "Tervetuloa takaisin!"; +"screen_login_title_with_homeserver" = "Kirjaudu sisään %1$@ -palvelimelle"; +"screen_media_picker_error_failed_selection" = "Median valinta epäonnistui, yritä uudelleen."; +"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_migration_message" = "Tämä on kertaluonteinen prosessi, kiitos odottamisesta."; +"screen_migration_title" = "Tiliä määritetään."; +"screen_notification_optin_subtitle" = "Voit muuttaa asetuksia myöhemmin."; +"screen_notification_optin_title" = "Salli ilmoitukset ja älä koskaan missaa viestejä"; +"screen_notification_settings_additional_settings_section_title" = "Lisäasetukset"; +"screen_notification_settings_calls_label" = "Ääni- ja videopuheluista"; +"screen_notification_settings_configuration_mismatch" = "Konfiguraatio ei täsmää"; +"screen_notification_settings_configuration_mismatch_description" = "Olemme yksinkertaistaneet ilmoitusasetuksia, jotta vaihtoehdot olisi helpompi löytää. Joitakin aiemmin valitsemiasi asetuksia ei näytetä tässä, mutta ne ovat edelleen voimassa.\n\nJos jatkat, jotkin asetukset saattavat muuttua."; +"screen_notification_settings_direct_chats" = "Yksityiskeskusteluissa"; +"screen_notification_settings_edit_custom_settings_section_title" = "Keskustelukohtaiset asetukset"; +"screen_notification_settings_edit_failed_updating_default_mode" = "Ilmoitusasetusten muokkaamisessa tapahtui virhe."; +"screen_notification_settings_edit_mode_all_messages" = "Kaikista viesteistä"; +"screen_notification_settings_edit_mode_mentions_and_keywords" = "Vain maininnoista ja avainsanoista"; +"screen_notification_settings_edit_screen_direct_section_header" = "Yksityiskeskusteluissa, ilmoita minulle"; +"screen_notification_settings_edit_screen_group_section_header" = "Ryhmäkeskusteluissa, ilmoita minulle"; +"screen_notification_settings_enable_notifications" = "Ota ilmoitukset käyttöön tällä laitteella"; +"screen_notification_settings_failed_fixing_configuration" = "Määritystä ei ole korjattu, yritä uudelleen."; +"screen_notification_settings_group_chats" = "Ryhmäkeskusteluissa"; +"screen_notification_settings_invite_for_me_label" = "Kutsut"; +"screen_notification_settings_mentions_only_disclaimer" = "Kotipalvelimesi ei tue tätä vaihtoehtoa salatuissa huoneissa, joten et ehkä saa ilmoitusta joissakin huoneissa."; +"screen_notification_settings_mode_all" = "Kaikki"; +"screen_notification_settings_mode_mentions" = "Maininnat"; +"screen_notification_settings_notification_section_title" = "Ilmoita minulle"; +"screen_notification_settings_room_mention_label" = "Ilmoita minulle @room-maininnoista"; +"screen_notification_settings_system_notifications_action_required" = "Jos haluat saada ilmoituksia, vaihda %1$@."; +"screen_notification_settings_system_notifications_action_required_content_link" = "järjestelmäsi asetuksia"; +"screen_notification_settings_system_notifications_turned_off" = "Järjestelmän ilmoitukset on poissa päältä"; +"screen_notification_settings_title" = "Ilmoitukset"; +"screen_onboarding_sign_in_manually" = "Kirjaudu sisään manuaalisesti"; +"screen_onboarding_sign_in_with_qr_code" = "Kirjaudu sisään QR-koodilla"; +"screen_onboarding_sign_up" = "Luo tili"; +"screen_onboarding_welcome_message" = "Tervetuloa kaikkien aikojen nopeimpaan %1$@ -sovellukseen. Ahdettu nopeudella ja yksinkertaisuudella."; +"screen_onboarding_welcome_subtitle" = "Tervetuloa %1$@ -sovellukseen. Ahdettu nopeudella ja yksinkertaisuudella."; +"screen_onboarding_welcome_title" = "Ole elementissäsi"; +"screen_polls_history_empty_ongoing" = "Meneillään olevia kyselyjä ei löytynyt."; +"screen_polls_history_empty_past" = "Aiempia kyselyjä ei löytynyt."; +"screen_polls_history_filter_ongoing" = "Meneillään olevat"; +"screen_polls_history_filter_past" = "Aiemmat"; +"screen_polls_history_title" = "Kyselyt"; +"screen_qr_code_login_connecting_subtitle" = "Muodostetaan turvallista yhteyttä"; +"screen_qr_code_login_connection_note_secure_state_description" = "Turvallista yhteyttä uuteen laitteeseen ei voitu muodostaa. Olemassa olevat laitteesi ovat edelleen turvassa, eikä sinun tarvitse huolehtia niistä."; +"screen_qr_code_login_connection_note_secure_state_list_header" = "Mitä nyt?"; +"screen_qr_code_login_connection_note_secure_state_list_item_1" = "Yritä kirjautua sisään uudelleen QR-koodilla, jos kyseessä oli verkko-ongelma"; +"screen_qr_code_login_connection_note_secure_state_list_item_2" = "Jos kohtaat saman ongelman, kokeile toista wifi-verkkoa tai käytä mobiilidataa wifi-yhteyden sijaan"; +"screen_qr_code_login_connection_note_secure_state_list_item_3" = "Jos tämä ei auta, kirjaudu sisään manuaalisesti"; +"screen_qr_code_login_connection_note_secure_state_title" = "Yhteys ei ole turvallinen"; +"screen_qr_code_login_device_code_subtitle" = "Sinua pyydetään antamaan tässä laitteessa näkyvät kaksi numeroa."; +"screen_qr_code_login_device_code_title" = "Kirjoita alla oleva numero toisella laitteellasi"; +"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Kirjaudu sisään toisella laitteellasi ja yritä sitten uudelleen tai käytä toista laitetta, joka on jo kirjautunut sisään."; +"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Toinen laitteesi ei ole kirjautuneena"; +"screen_qr_code_login_error_cancelled_subtitle" = "Kirjautuminen peruutettiin toisella laitteella."; +"screen_qr_code_login_error_cancelled_title" = "Kirjautumispyyntö peruutettu"; +"screen_qr_code_login_error_declined_subtitle" = "Kirjautuminen hylättiin toisella laitteella."; +"screen_qr_code_login_error_declined_title" = "Kirjautuminen hylätty"; +"screen_qr_code_login_error_expired_subtitle" = "Kirjautuminen vanhentui. Yritä uudelleen."; +"screen_qr_code_login_error_expired_title" = "Kirjautumista ei suoritettu ajoissa"; +"screen_qr_code_login_error_linking_not_suported_subtitle" = "Toinen laitteesi ei tue kirjautumista %@ -sovellukseen QR-koodilla.\n\nYritä kirjautua sisään manuaalisesti tai skannaa QR-koodi toisella laitteella."; +"screen_qr_code_login_error_linking_not_suported_title" = "QR-koodia ei tueta"; +"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "Palveluntarjoajasi ei tue %1$@ -sovellusta"; +"screen_qr_code_login_error_sliding_sync_not_supported_title" = "%1$@ -sovellusta ei tueta"; +"screen_qr_code_login_initial_state_button_title" = "Valmis skannaamaan"; +"screen_qr_code_login_initial_state_item_1" = "Avaa %1$@ tietokoneella"; +"screen_qr_code_login_initial_state_item_2" = "Napsauta avatariasi"; +"screen_qr_code_login_initial_state_item_3" = "Valitse %1$@"; +"screen_qr_code_login_initial_state_item_3_action" = "“Yhdistä uusi laite”"; +"screen_qr_code_login_initial_state_item_4" = "Skannaa QR-koodi tällä laitteella"; +"screen_qr_code_login_initial_state_subtitle" = "Saatavilla vain, jos palveluntarjoajasi tukee sitä."; +"screen_qr_code_login_initial_state_title" = "Avaa %1$@ toisella laitteella saadaksesi QR-koodin"; +"screen_qr_code_login_invalid_scan_state_description" = "Käytä toisessa laitteessa näkyvää QR-koodia."; +"screen_qr_code_login_invalid_scan_state_subtitle" = "Väärä QR-koodi"; +"screen_qr_code_login_no_camera_permission_button" = "Siirry kameran asetuksiin"; +"screen_qr_code_login_no_camera_permission_state_description" = "Jatkaaksesi sinun on annettava lupa %1$@ -sovellukselle käyttää laitteesi kameraa."; +"screen_qr_code_login_no_camera_permission_state_title" = "Salli lupa kameraan QR-koodin skannaamiseksi"; +"screen_qr_code_login_scanning_state_title" = "Skannaa QR-koodi"; +"screen_qr_code_login_start_over_button" = "Aloita alusta"; +"screen_qr_code_login_unknown_error_description" = "Tapahtui odottamaton virhe. Yritä uudelleen."; +"screen_qr_code_login_verify_code_loading" = "Odotetaan toista laitettasi"; +"screen_qr_code_login_verify_code_subtitle" = "Palveluntarjoajasi saattaa kysyä seuraavaa koodia kirjautumisen vahvistamiseksi."; +"screen_qr_code_login_verify_code_title" = "Vahvistuskoodisi"; +"screen_recovery_key_change_description" = "Hanki uusi palautusavain, jos olet kadottanut nykyisen avaimen. Palautusavaimen vaihtamisen jälkeen vanha avaimesi ei enää toimi."; +"screen_recovery_key_change_generate_key" = "Luo uusi palautusavain"; +"screen_recovery_key_change_success" = "Palautusavain vaihdettu"; +"screen_recovery_key_change_title" = "Vaihda palautusavain?"; +"screen_recovery_key_confirm_create_new_recovery_key" = "Luo uusi palautusavain"; +"screen_recovery_key_confirm_description" = "Varmista, ettei kukaan näe tätä ruutua!"; +"screen_recovery_key_confirm_error_content" = "Yritä uudelleen vahvistaaksesi pääsyn avainten säilytykseen."; +"screen_recovery_key_confirm_error_title" = "Väärä palautusavain"; +"screen_recovery_key_confirm_key_description" = "Jos sinulla on turva-avain tai turvalause, sekin toimii."; +"screen_recovery_key_confirm_key_placeholder" = "Syötä..."; +"screen_recovery_key_confirm_lost_recovery_key" = "Hukkasitko palautusavaimesi?"; +"screen_recovery_key_confirm_success" = "Palautusavain vahvistettu"; +"screen_recovery_key_copied_to_clipboard" = "Palautusavain kopioitu"; +"screen_recovery_key_generating_key" = "Luodaan..."; +"screen_recovery_key_save_action" = "Tallenna palautusavain"; +"screen_recovery_key_save_description" = "Kirjoita tämä palautusavain turvalliseen paikkaan, kuten salasanojen hallintaohjelmaan, salattuun muistiinpanoon tai fyysiseen kassakaappiin."; +"screen_recovery_key_save_key_description" = "Kopioi palautusavain napauttamalla"; +"screen_recovery_key_save_title" = "Tallenna palautusavain turvalliseen paikkaan"; +"screen_recovery_key_setup_confirmation_description" = "Et voi palata katsomaan uutta palautusavaintasi uudelleen tämän vaiheen jälkeen."; +"screen_recovery_key_setup_confirmation_title" = "Oletko tallentanut palautusavaimesi?"; +"screen_recovery_key_setup_description" = "Avainten säilytys on suojattu palautusavaimella. Jos tarvitset uuden palautusavaimen tämän jälkeen, voit luoda uuden valitsemalla ‘Vaihda palautusavain’."; +"screen_recovery_key_setup_generate_key" = "Luo palautusavaimesi"; +"screen_recovery_key_setup_generate_key_description" = "Älä jaa tätä kenenkään kanssa!"; +"screen_recovery_key_setup_success" = "Palautuksen käyttöönotto onnistui"; +"screen_recovery_key_setup_title" = "Ota palautus käyttöön"; +"screen_report_content_block_user_hint" = "Valitse tämä, jos haluat piilottaa kaikki nykyiset ja tulevat viestit tältä käyttäjältä"; +"screen_report_content_explanation" = "Tämä viesti ilmoitetaan kotipalvelimesi ylläpitäjälle. Ylläpitäjä ei pysty lukemaan salattuja viestejä."; +"screen_report_content_hint" = "Syy tämän sisällön ilmoittamiseen"; +"screen_reset_encryption_confirmation_alert_action" = "Kyllä, nollaa nyt"; +"screen_reset_encryption_confirmation_alert_subtitle" = "Tätä prosessia ei voi peruuttaa."; +"screen_reset_encryption_confirmation_alert_title" = "Haluatko varmasti nollata identiteettisi?"; +"screen_reset_encryption_password_subtitle" = "Vahvista, että haluat nollata identiteettisi."; +"screen_reset_encryption_password_title" = "Kirjoita tilisi salasana jatkaaksesi"; +"screen_reset_identity_confirmation_subtitle" = "Olet siirtymässä %1$@ -tilillesi nollaamaan identiteettisi. Tämän jälkeen sinut ohjataan takaisin sovellukseen."; +"screen_reset_identity_confirmation_title" = "Etkö voi vahvistaa? Siirry tilillesi ja nollaa identiteettisi."; +"screen_room_alias_resolver_resolve_alias_failure" = "Huoneen aliaksen ratkaiseminen epäonnistui."; +"screen_room_attachment_source_camera" = "Kamera"; +"screen_room_attachment_source_camera_video" = "Nauhoita video"; +"screen_room_attachment_source_files" = "Liite"; +"screen_room_attachment_source_gallery" = "Kuva- ja videokirjasto"; +"screen_room_attachment_source_location" = "Sijainti"; +"screen_room_attachment_source_poll" = "Kysely"; +"screen_room_attachment_text_formatting" = "Tekstin muotoilu"; +"screen_room_change_permissions_administrators" = "Vain ylläpitäjät"; +"screen_room_change_permissions_ban_people" = "Porttikieltojen antaminen"; +"screen_room_change_permissions_delete_messages" = "Viestien poistaminen"; +"screen_room_change_permissions_invite_people" = "Kutsujen antaminen"; +"screen_room_change_permissions_moderators" = "Ylläpitäjät ja valvojat"; +"screen_room_change_permissions_remove_people" = "Henkilöiden poistaminen"; +"screen_room_change_permissions_room_avatar" = "Huoneen avatarin vaihtaminen"; +"screen_room_change_permissions_room_name" = "Huoneen nimen vaihtaminen"; +"screen_room_change_permissions_room_topic" = "Huoneen aiheen vaihtaminen"; +"screen_room_change_permissions_send_messages" = "Viestien lähettäminen"; +"screen_room_change_role_administrators_title" = "Muokkaa ylläpitäjiä"; +"screen_room_change_role_confirm_add_admin_description" = "Et voi peruuttaa tätä toimenpidettä. Ylennät käyttäjän samalle oikeustasolle kuin sinä."; +"screen_room_change_role_confirm_add_admin_title" = "Lisää ylläpitäjä?"; +"screen_room_change_role_confirm_demote_self_action" = "Alenna"; +"screen_room_change_role_confirm_demote_self_description" = "Et voi perua tätä muutosta, koska olet alentamassa itseäsi. Jos olet viimeinen oikeutettu henkilö tässä huoneessa, oikeuksia ei voi enää saada takaisin."; +"screen_room_change_role_confirm_demote_self_title" = "Alenna itsesi?"; +"screen_room_change_role_invited_member_name" = "%1$@ (Kutsuttu)"; +"screen_room_change_role_moderators_admin_section_footer" = "Ylläpitäjillä on automaattisesti valvojan oikeudet"; +"screen_room_change_role_moderators_title" = "Muokkaa valvojia"; +"screen_room_change_role_unsaved_changes_description" = "Sinulla on tallentamattomia muutoksia"; +"screen_room_details_add_topic_title" = "Lisää aihe"; +"screen_room_details_already_a_member" = "On jo jäsen"; +"screen_room_details_already_invited" = "On jo kutsuttu"; +"screen_room_details_badge_encrypted" = "Salattu"; +"screen_room_details_badge_not_encrypted" = "Ei salattu"; +"screen_room_details_badge_public" = "Julkinen huone"; +"screen_room_details_edit_room_title" = "Muokkaa huonetta"; +"screen_room_details_edition_error" = "Tuntematon virhe tapahtui, eikä tietoja voitu muuttaa."; +"screen_room_details_edition_error_title" = "Huoneen muokkaaminen ei onnistunut"; +"screen_room_details_encryption_enabled_subtitle" = "Viestisi suojataan lukoilla. Vain sinulla ja viesiten vastaanottajilla on uniikit avaimet niiden avaamiseen."; +"screen_room_details_encryption_enabled_title" = "Viestien salaus käytössä"; +"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_notification_mode_custom" = "Mukautettu"; +"screen_room_details_notification_mode_default" = "Oletus"; +"screen_room_details_share_room_title" = "Jaa huone"; +"screen_room_details_title" = "Huoneen tiedot"; +"screen_room_details_updating_room" = "Muokataan huonetta..."; +"screen_room_directory_search_loading_error" = "Lataus epäonnistui"; +"screen_room_directory_search_title" = "Huoneluettelo"; +"screen_room_encrypted_history_banner" = "Viestihistoria ei ole tällä hetkellä saatavilla"; +"screen_room_encrypted_history_banner_unverified" = "Viestihistoria ei ole käytettävissä tässä huoneessa. Vahvista tämä laite nähdäksesi viestihistoriasi."; +"screen_room_error_failed_retrieving_user_details" = "Käyttäjän tietojen hakeminen epäonnistui"; +"screen_room_invite_again_alert_message" = "Haluatko kutsua heidät takaisin?"; +"screen_room_invite_again_alert_title" = "Olet yksin tässä keskustelussa"; +"screen_room_member_details_block_alert_action" = "Estä"; +"screen_room_member_details_block_alert_description" = "Estetyt käyttäjät eivät voi lähettää sinulle viestejä ja kaikki heidän viestit piilotetaan. Voit poistaa eston milloin tahansa."; +"screen_room_member_details_block_user" = "Estä käyttäjä"; +"screen_room_member_details_title" = "Profiili"; +"screen_room_member_details_unblock_alert_action" = "Poista esto"; +"screen_room_member_details_unblock_alert_description" = "Näet jälleen kaikki heidän lähettämänsä viestit."; +"screen_room_member_details_unblock_user" = "Poista käyttäjän esto"; +"screen_room_member_details_verify_button_subtitle" = "Vahvista tämä käyttäjä verkkosovelluksen avulla."; +"screen_room_member_details_verify_button_title" = "Vahvista %1$@"; +"screen_room_member_list_ban_member_confirmation_action" = "Anna porttikielto"; +"screen_room_member_list_ban_member_confirmation_description" = "He eivät voi enää liittyä tähän huoneeseen, jos heidät kutsutaan."; +"screen_room_member_list_ban_member_confirmation_title" = "Haluatko varmasti antaa tälle jäsenelle porttikiellon?"; +"screen_room_member_list_banned_empty" = "Tässä huoneessa ei ole porttikieltoja"; +"screen_room_member_list_banning_user" = "Annetaan porttikieltoa käyttäjälle %1$@"; +"screen_room_member_list_manage_member_ban" = "Poista jäsen huoneesta ja anna porttikielto"; +"screen_room_member_list_manage_member_remove" = "Poista huoneesta"; +"screen_room_member_list_manage_member_remove_confirmation_kick" = "Poista vain jäsen huoneesta"; +"screen_room_member_list_manage_member_remove_confirmation_title" = "Poistetaanko jäsen huoneesta ja kielletäänkö heitä liittymästä tulevaisuudessa?"; +"screen_room_member_list_manage_member_unban_action" = "Poista porttikielto"; +"screen_room_member_list_manage_member_unban_message" = "He voivat liittyä tähän huoneeseen uudelleen, jos heidät kutsutaan."; +"screen_room_member_list_manage_member_unban_title" = "Poista käyttäjän porttikielto"; +"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_removing_user" = "Poistetaan käyttäjää %1$@ huoneesta..."; +"screen_room_member_list_role_administrator" = "Ylläpitäjä"; +"screen_room_member_list_role_moderator" = "Valvoja"; +"screen_room_member_list_room_members_header_title" = "Huoneen jäsenet"; +"screen_room_member_list_unbanning_user" = "Poistetaan käyttäjän %1$@ porttikieltoa"; +"screen_room_notification_settings_allow_custom" = "Salli mukautettu asetus"; +"screen_room_notification_settings_allow_custom_footnote" = "Tämän ottaminen käyttöön ohittaa oletusasetuksesi"; +"screen_room_notification_settings_custom_settings_title" = "Ilmoita minulle tässä keskustelussa"; +"screen_room_notification_settings_default_setting_footnote" = "Voit muuttaa sen %1$@."; +"screen_room_notification_settings_default_setting_footnote_content_link" = "yleisissä asetuksissa"; +"screen_room_notification_settings_default_setting_title" = "Oletusasetus"; +"screen_room_notification_settings_edit_remove_setting" = "Poista mukautettu asetus"; +"screen_room_notification_settings_error_loading_settings" = "Ilmoitusasetusten lataamisessa tapahtui virhe."; +"screen_room_notification_settings_error_restoring_default" = "Oletustilan palauttaminen epäonnistui, yritä uudelleen."; +"screen_room_notification_settings_error_setting_mode" = "Tilan asettaminen epäonnistui, yritä uudelleen."; +"screen_room_notification_settings_mentions_only_disclaimer" = "Kotipalvelimesi ei tue tätä vaihtoehtoa salatuissa huoneissa, joten et saa ilmoituksia tästä huoneesta."; +"screen_room_notification_settings_mode_all_messages" = "Kaikista viesteistä"; +"screen_room_notification_settings_room_custom_settings_title" = "Ilmoita minulle tässä huoneessa"; +"screen_room_retry_send_menu_send_again_action" = "Lähetä uudelleen"; +"screen_room_retry_send_menu_title" = "Viestisi lähettäminen epäonnistui"; +"screen_room_roles_and_permissions_admins" = "Ylläpitäjät"; +"screen_room_roles_and_permissions_change_my_role" = "Vaihda rooliani"; +"screen_room_roles_and_permissions_change_role_demote_to_member" = "Alenna jäseneksi"; +"screen_room_roles_and_permissions_change_role_demote_to_moderator" = "Alenna valvojaksi"; +"screen_room_roles_and_permissions_member_moderation" = "Jäsenten valvonta"; +"screen_room_roles_and_permissions_messages_and_content" = "Viestit ja sisältö"; +"screen_room_roles_and_permissions_moderators" = "Valvojat"; +"screen_room_roles_and_permissions_permissions_header" = "Oikeudet"; +"screen_room_roles_and_permissions_reset" = "Nollaa oikeudet"; +"screen_room_roles_and_permissions_reset_confirm_description" = "Kun nollaat käyttöoikeudet, menetät nykyiset asetukset."; +"screen_room_roles_and_permissions_reset_confirm_title" = "Nollataanko oikeudet?"; +"screen_room_roles_and_permissions_roles_header" = "Roolit"; +"screen_room_roles_and_permissions_room_details" = "Huoneen tiedot"; +"screen_room_roles_and_permissions_title" = "Roolit ja oikeudet"; +"screen_room_timeline_add_reaction" = "Lisää emoji"; +"screen_room_timeline_beginning_of_room" = "Tämä on huoneen %1$@ alku."; +"screen_room_timeline_beginning_of_room_no_name" = "Tämä on tämän keskustelun alku."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; +"screen_room_timeline_less_reactions" = "Näytä vähemmän"; +"screen_room_timeline_message_copied" = "Viesti kopioitu"; +"screen_room_timeline_no_permission_to_post" = "Sinulla ei ole oikeutta kirjoittaa tässä huoneessa"; +"screen_room_timeline_reactions_show_more" = "Näytä lisää"; +"screen_room_timeline_read_marker_title" = "Uusi"; +"screen_room_title" = "Keskustelu"; +"screen_room_typing_many_members_first_component_ios" = "%1$@, %2$@ ja "; +"screen_room_typing_notification_plural_ios" = " kirjoittavat..."; +"screen_room_typing_notification_singular_ios" = " kirjoittaa..."; +"screen_room_typing_two_members" = "%1$@ ja %2$@"; +"screen_room_voice_message_tooltip" = "Pidä pohjassa nauhoittaaksesi"; +"screen_roomlist_a11y_create_message" = "Luo uusi keskustelu tai huone"; +"screen_roomlist_empty_message" = "Aloita lähettämällä viesti jollekin."; +"screen_roomlist_empty_title" = "Sinulla ei ole vielä keskusteluja."; +"screen_roomlist_filter_favourites" = "Suosikit"; +"screen_roomlist_filter_favourites_empty_state_subtitle" = "Voit lisätä keskustelun suosikkeihisi keskustelun asetuksissa.\nToistaiseksi voit poistaa suodattimien valinnan, jotta näet muut keskustelut."; +"screen_roomlist_filter_favourites_empty_state_title" = "Sinulla ei ole vielä suosikkikeskusteluja"; +"screen_roomlist_filter_invites" = "Kutsut"; +"screen_roomlist_filter_invites_empty_state_title" = "Sinulla ei ole yhtään odottavaa kutsua."; +"screen_roomlist_filter_low_priority" = "Matala prioriteetti"; +"screen_roomlist_filter_mixed_empty_state_subtitle" = "Voit poistaa suodattimien valinnan nähdäksesi muut keskustelusi."; +"screen_roomlist_filter_mixed_empty_state_title" = "Sinulla ei ole sopivia keskusteluja tähän valintaan"; +"screen_roomlist_filter_people_empty_state_title" = "Sinulla ei ole vielä yhtään yksityisviestiä"; +"screen_roomlist_filter_rooms" = "Huoneet"; +"screen_roomlist_filter_rooms_empty_state_title" = "Et ole vielä missään huoneessa"; +"screen_roomlist_filter_unreads" = "Lukemattomat"; +"screen_roomlist_filter_unreads_empty_state_title" = "Onnittelut!\nSinulla ei ole lukemattomia viestejä!"; +"screen_roomlist_main_space_title" = "Keskustelut"; +"screen_roomlist_mark_as_read" = "Merkitse luetuksi"; +"screen_roomlist_mark_as_unread" = "Merkitse lukemattomaksi"; +"screen_roomlist_room_directory_button_title" = "Selaa kaikkia huoneita"; +"screen_server_confirmation_message_login_element_dot_io" = "Yksityinen palvelin Elementin työntekijöille."; +"screen_server_confirmation_message_login_matrix_dot_org" = "Matrix on avoin verkko turvallista, hajautettua viestintää varten."; +"screen_server_confirmation_message_register" = "Keskustelusi asuvat täällä — aivan kuten aivan kuten käyttäisit sähköpostipalveluntarjoajaa sähköpostiesi säilyttämiseen."; +"screen_server_confirmation_title_login" = "Olet kirjautumassa sisään %1$@-palvelimelle"; +"screen_server_confirmation_title_register" = "Olet luomassa tiliä %1$@-palvelimelle"; +"screen_session_verification_cancelled_subtitle" = "Jokin ei vaikuta oikealta. Joko pyyntö aikakatkaistiin tai hylättiin."; +"screen_session_verification_compare_emojis_subtitle" = "Vahvista, että alla olevat hymiöt vastaavat toisella laitteella näkyviä hymiöitä."; +"screen_session_verification_compare_emojis_title" = "Vertaa hymiöitä"; +"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_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"; +"screen_session_verification_positive_button_canceled" = "Yritä vahvistusta uudelleen"; +"screen_session_verification_positive_button_initial" = "Olen valmis"; +"screen_session_verification_positive_button_verifying_ongoing" = "Odotetaan vahvistusta..."; +"screen_session_verification_ready_subtitle" = "Vertaa emojisarjaa."; +"screen_session_verification_request_accepted_subtitle" = "Vertaa hymiöitä, varmistaen että ne ovat samassa järjestyksessä."; +"screen_session_verification_request_details_timestamp" = "Kirjautui sisään"; +"screen_session_verification_request_failure_title" = "Vahvistus epäonnistui"; +"screen_session_verification_request_footer" = "Jatka vain, jos sinä aloitit tämän vahvistuksen."; +"screen_session_verification_request_subtitle" = "Vahvista toinen laite pitääksesi viestihistoriasi turvassa."; +"screen_session_verification_request_success_subtitle" = "Nyt voit lukea tai lähettää viestejä turvallisesti toisella laitteellasi."; +"screen_session_verification_request_success_title" = "Laite vahvistettu"; +"screen_session_verification_request_title" = "Vahvistus pyydetty"; +"screen_session_verification_they_dont_match" = "Ne eivät täsmää"; +"screen_session_verification_they_match" = "Ne täsmäävät"; +"screen_session_verification_use_another_device_subtitle" = "Varmista, että sovellus on avoinna toisessa laitteessa, ennen kuin aloitat vahvistuksen tästä."; +"screen_session_verification_use_another_device_title" = "Avaa sovellus toisella vahvistetulla laitteella"; +"screen_session_verification_waiting_another_device_subtitle" = "Sinun pitäisi nähdä ponnahdusikkuna toisessa laitteessa. Aloita vahvistus nyt sieltä."; +"screen_session_verification_waiting_another_device_title" = "Aloita vahvistus toisella laitteella"; +"screen_session_verification_waiting_to_accept_subtitle" = "Hyväksy vahvistuspyyntö toisella laitteella jatkaaksesi."; +"screen_session_verification_waiting_to_accept_title" = "Odotetaan pyynnön hyväksymistä"; +"screen_share_location_title" = "Jaa sijainti"; +"screen_share_my_location_action" = "Jaa sijaintini"; +"screen_share_open_apple_maps" = "Avaa Apple Mapsissa"; +"screen_share_open_google_maps" = "Avaa Google Mapsissa"; +"screen_share_open_osm_maps" = "Avaa OpenStreetMapissa"; +"screen_share_this_location_action" = "Jaa tämä sijainti"; +"screen_signed_out_reason_1" = "Olet vaihtanut salasanasi toisessa istunnossa"; +"screen_signed_out_reason_2" = "Olet poistanut istunnon toisesta istunnosta"; +"screen_signed_out_reason_3" = "Palvelimesi ylläpitäjä on mitätöinyt käyttöoikeutesi"; +"screen_signed_out_subtitle" = "Sinut on saatettu kirjata ulos jostakin alla luetellusta syystä. Kirjaudu uudelleen sisään jatkaaksesi %@ -sovelluksen käyttöä."; +"screen_signed_out_title" = "Sinut on kirjattu ulos"; +"screen_signout_confirmation_dialog_content" = "Haluatko varmasti kirjautua ulos?"; +"screen_signout_in_progress_dialog_content" = "Kirjaudutaan ulos..."; +"screen_signout_key_backup_disabled_subtitle" = "Olet kirjautumassa ulos viimeisestä istunnostasi. Jos kirjaudut ulos nyt, menetät pääsyn salattuihin viesteihisi."; +"screen_signout_key_backup_disabled_title" = "Olet poistanut varmuuskopioinnin käytöstä"; +"screen_signout_key_backup_offline_subtitle" = "Avaimiasi varmuuskopioitiin vielä, kun menit offline-tilaan. Muodosta yhteys uudelleen, jotta avaimesi voidaan varmuuskopioida ennen uloskirjautumista."; +"screen_signout_key_backup_ongoing_subtitle" = "Odota, että tämä on valmis ennen uloskirjautumista."; +"screen_signout_key_backup_ongoing_title" = "Avaimiasi varmuuskopioidaan vielä"; +"screen_signout_recovery_disabled_subtitle" = "Olet kirjautumassa ulos viimeisestä istunnostasi. Jos kirjaudut ulos nyt, menetät pääsyn salattuihin viesteihisi."; +"screen_signout_recovery_disabled_title" = "Palautus ei ole käytössä"; +"screen_signout_save_recovery_key_subtitle" = "Olet kirjautumassa ulos viimeisestä istunnostasi. Jos kirjaudut ulos nyt, saatat menettää pääsyn salattuihin viesteihisi."; +"screen_start_chat_error_starting_chat" = "Keskustelun aloituksessa tapahtui virhe"; +"screen_view_location_title" = "Sijainti"; +"screen_welcome_bullet_1" = "Puhelut, kyselyt, haku ja paljon muuta lisätään myöhemmin tänä vuonna."; +"screen_welcome_bullet_2" = "Salattujen huoneiden viestihistoria ei ole vielä käytettävissä."; +"screen_welcome_bullet_3" = "Haluaisimme kuulla mielipiteesi, kerro mitä mieltä olet asetuksien kautta."; +"screen_welcome_button" = "Mennään!"; +"screen_welcome_subtitle" = "Tässä on mitä sinun tarvitsee tietää:"; +"screen_welcome_title" = "Tervetuloa %1$@ -sovellukseen!"; +"session_verification_banner_message" = "Vaikuttaisi siltä, että käytät uutta laitetta. Vahvista toisella laitteella nähdäksesi salatut viestit."; +"session_verification_banner_title" = "Vahvista, että se olet sinä"; +"settings_rageshake" = "Raivostunut ravistaminen"; +"settings_rageshake_detection_threshold" = "Havaitsemiskynnys"; +"settings_version_number" = "Versio: %1$@ (%2$@)"; +"state_event_avatar_changed_too" = "(myös avatar vaihdettiin)"; +"state_event_avatar_url_changed" = "%1$@ vaihtoi avatarinsa"; +"state_event_avatar_url_changed_by_you" = "Vaihdoit avatarisi"; +"state_event_demoted_to_member" = "%1$@ alennettiin jäseneksi"; +"state_event_demoted_to_moderator" = "%1$@ alennettiin valvojaksi"; +"state_event_display_name_changed_from" = "%1$@ vaihtoi näyttönimekseen %3$@ (se oli %2$@)"; +"state_event_display_name_changed_from_by_you" = "Vaihdoit näyttönimeksesi %2$@ (se oli %1$@)"; +"state_event_display_name_removed" = "%1$@ poisti näyttönimensä (se oli %2$@)"; +"state_event_display_name_removed_by_you" = "Poistit näyttönimesi (se oli %1$@)"; +"state_event_display_name_set" = "%1$@ asetti näyttönimekseen %2$@"; +"state_event_display_name_set_by_you" = "Asetit näyttönimeksesi %1$@"; +"state_event_promoted_to_administrator" = "%1$@ ylennettiin ylläpitäjäksi"; +"state_event_promoted_to_moderator" = "%1$@ ylennettiin valvojaksi"; +"state_event_room_avatar_changed" = "%1$@ vaihtoi huoneen avatarin"; +"state_event_room_avatar_changed_by_you" = "Vaihdoit huoneen avatarin"; +"state_event_room_avatar_removed" = "%1$@ poisti huoneen avatarin"; +"state_event_room_avatar_removed_by_you" = "Poistit huoneen avatarin"; +"state_event_room_ban" = "%1$@ antoi porttikiellon käyttäjälle %2$@"; +"state_event_room_ban_by_you" = "Annoit porttikiellon käyttäjälle %1$@"; +"state_event_room_created" = "%1$@ loi huoneen"; +"state_event_room_created_by_you" = "Loit huoneen"; +"state_event_room_invite" = "%1$@ kutsui käyttäjän %2$@"; +"state_event_room_invite_accepted" = "%1$@ hyväksyi kutsun"; +"state_event_room_invite_accepted_by_you" = "Hyväksyit kutsun"; +"state_event_room_invite_by_you" = "Kutsuit käyttäjän %1$@"; +"state_event_room_invite_you" = "%1$@ kutsui sinut"; +"state_event_room_join" = "%1$@ liittyi huoneeseen"; +"state_event_room_join_by_you" = "Liityit huoneeseen"; +"state_event_room_knock" = "%1$@ pyytää liittymistä"; +"state_event_room_knock_accepted" = "%1$@ myönsi pääsyn käyttäjälle %2$@"; +"state_event_room_knock_accepted_by_you" = "Sallit käyttäjän %1$@ liittyä"; +"state_event_room_knock_by_you" = "Pyysit liittymistä"; +"state_event_room_knock_denied" = "%1$@ hylkäsi käyttäjän %2$@ liittymispyynnön"; +"state_event_room_knock_denied_by_you" = "Hylkäsit käyttäjän %1$@ liittymispyynnön"; +"state_event_room_knock_denied_you" = "%1$@ hylkäsi liittymispyyntösi"; +"state_event_room_knock_retracted" = "%1$@ ei halua enää liittyä"; +"state_event_room_knock_retracted_by_you" = "Peruutit liittymispyyntösi"; +"state_event_room_leave" = "%1$@ poistui huoneesta"; +"state_event_room_leave_by_you" = "Poistuit huoneesta"; +"state_event_room_name_changed" = "%1$@ vaihtoi huoneen nimeksi: %2$@"; +"state_event_room_name_changed_by_you" = "Vaihdoit huoneen nimeksi: %1$@"; +"state_event_room_name_removed" = "%1$@ poisti huoneen nimen"; +"state_event_room_name_removed_by_you" = "Poistit huoneen nimen"; +"state_event_room_none" = "%1$@ ei tehnyt muutoksia"; +"state_event_room_none_by_you" = "Et tehnyt muutoksia"; +"state_event_room_pinned_events_changed" = "%1$@ muutti kiinnitettyjä viestejä"; +"state_event_room_pinned_events_changed_by_you" = "Muutit kiinnitettyjä viestejä"; +"state_event_room_pinned_events_pinned" = "%1$@ kiinnitti viestin"; +"state_event_room_pinned_events_pinned_by_you" = "Kiinnitit viestin"; +"state_event_room_pinned_events_unpinned" = "%1$@ poisti viestin kiinnityksen"; +"state_event_room_pinned_events_unpinned_by_you" = "Poistit viestin kiinnityksen"; +"state_event_room_reject" = "%1$@ hylkäsi kutsun"; +"state_event_room_reject_by_you" = "Hylkäsit kutsun"; +"state_event_room_remove" = "%1$@ poisti käyttäjän %2$@"; +"state_event_room_remove_by_you" = "Poistit käyttäjän %1$@"; +"state_event_room_third_party_invite" = "%1$@ kutsui käyttäjän %2$@ huoneeseen"; +"state_event_room_third_party_invite_by_you" = "Kutsuit käyttäjän %1$@ huoneeseen"; +"state_event_room_third_party_revoked_invite" = "%1$@ peruutti käyttäjän %2$@ kutsun huoneeseen"; +"state_event_room_third_party_revoked_invite_by_you" = "Peruutit käyttäjän %1$@ kutsun huoneeseen"; +"state_event_room_topic_changed" = "%1$@ vaihtoi aiheeksi: %2$@"; +"state_event_room_topic_changed_by_you" = "Vaihdoit aiheeksi: %1$@"; +"state_event_room_topic_removed" = "%1$@ poisti huoneen aiheen"; +"state_event_room_topic_removed_by_you" = "Poistit huoneen aiheen"; +"state_event_room_unban" = "%1$@ poisti käyttäjän %2$@ porttikiellon"; +"state_event_room_unban_by_you" = "Poistit käyttäjän %1$@ porttikiellon"; +"state_event_room_unknown_membership_change" = "%1$@ teki tuntemattoman muutoksen jäsenyyteensä"; +"test_language_identifier" = "fi"; +"test_untranslated_default_language_identifier" = "en"; +"troubleshoot_notifications_entry_point_section" = "Vianmääritys"; +"troubleshoot_notifications_screen_action" = "Suorita testit"; +"troubleshoot_notifications_screen_action_again" = "Suorita testit uudelleen"; +"troubleshoot_notifications_screen_failure" = "Osa testeistä epäonnistui. Tarkista tiedot."; +"troubleshoot_notifications_screen_notice" = "Suorita testit havaitaksesi konfiguraatiossasi olevat ongelmat, joiden vuoksi ilmoitukset eivät ehkä toimi odotetulla tavalla."; +"troubleshoot_notifications_screen_quick_fix_action" = "Yritä korjata"; +"troubleshoot_notifications_screen_success" = "Kaikki testit läpäistiin onnistuneesti."; +"troubleshoot_notifications_screen_title" = "Ilmoitusten vianmääritys"; +"troubleshoot_notifications_screen_waiting" = "Jotkin testit vaativat huomiotasi. Tarkista tiedot."; +"troubleshoot_notifications_test_check_permission_description" = "Tarkistaa, että sovellus voi näyttää ilmoituksia."; +"troubleshoot_notifications_test_check_permission_title" = "Lupien tarkistus"; +"troubleshoot_notifications_test_current_push_provider_description" = "Hakee nykyisen palveluntarjoajan nimen."; +"troubleshoot_notifications_test_current_push_provider_failure" = "Push-palveluntarjoajia ei ole valittu."; +"troubleshoot_notifications_test_current_push_provider_success" = "Nykyinen push-palveluntarjoaja: %1$@."; +"troubleshoot_notifications_test_current_push_provider_title" = "Nykyinen push-palveluntarjoaja"; +"troubleshoot_notifications_test_detect_push_provider_description" = "Varmistaa, että sovelluksella on vähintään yksi push-palveluntarjoaja."; +"troubleshoot_notifications_test_detect_push_provider_failure" = "Push-palveluntarjoajia ei löytynyt."; +"troubleshoot_notifications_test_detect_push_provider_title" = "Push-palveluntarjoajien havaitseminen"; +"troubleshoot_notifications_test_display_notification_description" = "Tarkistaa, että sovellus voi näyttää ilmoituksen."; +"troubleshoot_notifications_test_display_notification_failure" = "Ilmoitusta ei ole klikattu."; +"troubleshoot_notifications_test_display_notification_permission_failure" = "Ilmoitusta ei voida näyttää."; +"troubleshoot_notifications_test_display_notification_success" = "Ilmoitusta on klikattu!"; +"troubleshoot_notifications_test_display_notification_title" = "Ilmoituksen näyttäminen"; +"troubleshoot_notifications_test_display_notification_waiting" = "Klikkaa ilmoitusta jatkaaksesi testiä."; +"troubleshoot_notifications_test_firebase_availability_description" = "Varmistaa, että Firebase on käytettävissä."; +"troubleshoot_notifications_test_firebase_availability_failure" = "Firebase ei ole saatavilla."; +"troubleshoot_notifications_test_firebase_availability_success" = "Firebase on saatavilla."; +"troubleshoot_notifications_test_firebase_availability_title" = "Firebasen tarkistus"; +"troubleshoot_notifications_test_firebase_token_description" = "Varmistaa, että Firebase token on käytettävissä."; +"troubleshoot_notifications_test_firebase_token_failure" = "Firebase token ei ole tiedossa."; +"troubleshoot_notifications_test_firebase_token_success" = "Firebase token: %1$@."; +"troubleshoot_notifications_test_firebase_token_title" = "Firebase tokenin tarkistus"; +"troubleshoot_notifications_test_push_loop_back_description" = "Varmistaa, että sovellus vastaanottaa push-ilmoituksen."; +"troubleshoot_notifications_test_push_loop_back_failure_1" = "Virhe: pusher on hylännyt pyynnön."; +"troubleshoot_notifications_test_push_loop_back_failure_2" = "Virhe: %1$@."; +"troubleshoot_notifications_test_push_loop_back_failure_3" = "Virhe, push-ilmoitusta ei voi testata."; +"troubleshoot_notifications_test_push_loop_back_failure_4" = "Virhe, aikakatkaisu push-ilmoitusta odotellessa."; +"troubleshoot_notifications_test_push_loop_back_success" = "Push-ilmoituksella kesti %1$d ms palata takaisin."; +"troubleshoot_notifications_test_push_loop_back_title" = "Testaa push-ilmoituksen paluu"; +"troubleshoot_notifications_test_unified_push_description" = "Varmistas, että UnifiedPush-jakelijat ovat käytettävissä."; +"troubleshoot_notifications_test_unified_push_failure" = "Push-jakelijoita ei löytynyt."; +"troubleshoot_notifications_test_unified_push_title" = "UnifiedPushin tarkistus"; +"a11y_poll" = "Kysely"; +"banner_set_up_recovery_submit" = "Ota palautus käyttöön"; +"dialog_title_error" = "Virhe"; +"dialog_title_success" = "Onnistui"; +"notification_fallback_content" = "Ilmoitus"; +"notification_invitation_action_join" = "Liity"; +"notification_invitation_action_reject" = "Hylkää"; +"notification_room_action_mark_as_read" = "Merkitse luetuksi"; +"notification_room_action_quick_reply" = "Pikavastaus"; +"screen_pinned_timeline_screen_title_empty" = "Kiinnitetyt viestit"; +"screen_room_mentions_at_room_title" = "Kaikki"; +"screen_account_provider_change" = "Vaihda palveluntarjoajaa"; +"screen_account_provider_signin_subtitle" = "Keskustelusi asuvat täällä — aivan kuten aivan kuten käyttäisit sähköpostipalveluntarjoajaa sähköpostiesi säilyttämiseen."; +"screen_account_provider_signup_subtitle" = "Keskustelusi asuvat täällä — aivan kuten aivan kuten käyttäisit sähköpostipalveluntarjoajaa sähköpostiesi säilyttämiseen."; +"screen_analytics_settings_help_us_improve" = "Jaa anonyymejä käyttötietoja auttaaksesi meitä tunnistamaan ongelmat."; +"screen_analytics_settings_read_terms" = "Voit lukea kaikki ehtomme %1$@."; +"screen_analytics_settings_read_terms_content_link" = "täällä"; +"screen_blocked_users_unblock_alert_action" = "Poista esto"; +"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_setup" = "Ota palautus käyttöön"; +"screen_create_poll_cancel_confirmation_content_ios" = "Muutoksiasi ei tallenneta"; +"screen_create_room_add_people_title" = "Kutsu ihmisiä"; +"screen_create_room_room_name_label" = "Huoneen nimi"; +"screen_create_room_title" = "Luo huone"; +"screen_dm_details_block_alert_action" = "Estä"; +"screen_dm_details_block_alert_description" = "Estetyt käyttäjät eivät voi lähettää sinulle viestejä ja kaikki heidän viestit piilotetaan. Voit poistaa eston milloin tahansa."; +"screen_dm_details_block_user" = "Estä käyttäjä"; +"screen_dm_details_unblock_alert_action" = "Poista esto"; +"screen_dm_details_unblock_alert_description" = "Näet jälleen kaikki heidän lähettämänsä viestit."; +"screen_dm_details_unblock_user" = "Poista käyttäjän esto"; +"screen_edit_poll_delete_confirmation_title" = "Poista kysely"; +"screen_edit_poll_title" = "Muokkaa kyselyä"; +"screen_identity_use_another_device" = "Käytä toista laitetta"; +"screen_login_subtitle" = "Matrix on avoin verkko turvallista, hajautettua viestintää varten."; +"screen_notification_settings_mentions_section_title" = "Maininnat"; +"screen_qr_code_login_invalid_scan_state_retry_button" = "Yritä uudelleen"; +"screen_recovery_key_change_generate_key_description" = "Älä jaa tätä kenenkään kanssa!"; +"screen_recovery_key_confirm_title" = "Syötä palautusavaimesi"; +"screen_report_content_block_user" = "Estä käyttäjä"; +"screen_reset_encryption_password_placeholder" = "Syötä..."; +"screen_room_attachment_source_camera_photo" = "Ota kuva"; +"screen_room_change_permissions_everyone" = "Kaikki"; +"screen_room_change_permissions_member_moderation" = "Jäsenten valvonta"; +"screen_room_change_permissions_messages_and_content" = "Viestit ja sisältö"; +"screen_room_change_permissions_room_details" = "Huoneen tiedot"; +"screen_room_change_role_section_administrators" = "Ylläpitäjät"; +"screen_room_change_role_section_moderators" = "Valvojat"; +"screen_room_change_role_section_users" = "Jäsenet"; +"screen_room_change_role_unsaved_changes_title" = "Tallenna muutokset?"; +"screen_room_details_invite_people_title" = "Kutsu ihmisiä"; +"screen_room_details_leave_conversation_title" = "Poistu keskustelusta"; +"screen_room_details_leave_room_title" = "Poistu huoneesta"; +"screen_room_details_notification_title" = "Ilmoitukset"; +"screen_room_details_roles_and_permissions" = "Roolit ja oikeudet"; +"screen_room_details_room_name_label" = "Huoneen nimi"; +"screen_room_details_security_title" = "Turvallisuus"; +"screen_room_details_topic_title" = "Aihe"; +"screen_room_error_failed_processing_media" = "Median käsittely epäonnistui, yritä uudelleen."; +"screen_room_member_list_manage_member_remove_confirmation_ban" = "Poista jäsen huoneesta ja anna porttikielto"; +"screen_room_notification_settings_mode_mentions_and_keywords" = "Vain maininnoista ja avainsanoista"; +"screen_room_timeline_reactions_show_less" = "Näytä vähemmän"; +"screen_roomlist_filter_people" = "Ihmiset"; +"screen_server_confirmation_change_server" = "Vaihda palveluntarjoajaa"; +"screen_session_verification_request_failure_subtitle" = "Joko pyyntö aikakatkaistiin, pyyntö hylättiin tai vahvistus ei täsmännyt."; +"screen_signout_confirmation_dialog_submit" = "Kirjaudu ulos"; +"screen_signout_confirmation_dialog_title" = "Kirjaudu ulos"; +"screen_signout_key_backup_offline_title" = "Avaimiasi varmuuskopioidaan vielä"; +"screen_signout_preference_item" = "Kirjaudu ulos"; +"screen_signout_save_recovery_key_title" = "Oletko tallentanut palautusavaimesi?"; +"troubleshoot_notifications_entry_point_title" = "Ilmoitusten vianmääritys"; diff --git a/ElementX/Resources/Localizations/fi.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/fi.lproj/Localizable.stringsdict new file mode 100644 index 0000000000..2b6e31e2ea --- /dev/null +++ b/ElementX/Resources/Localizations/fi.lproj/Localizable.stringsdict @@ -0,0 +1,342 @@ + + + + + a11y_digits_entered + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d numero syötetty + other + %1$d numeroa syötetty + + + a11y_read_receipts_multiple_with_others + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ ja %2$d muu on lukenut viestin + other + %1$@ ja %2$d muuta on lukenut viestin + + + common_member_count + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d jäsen + other + %1$d jäsentä + + + common_poll_votes_count + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d ääni + other + %d ääntä + + + notification_compat_summary_line_for_room + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@: %2$d viesti + other + %1$@: %2$d viestiä + + + notification_compat_summary_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d ilmoitus + other + %d ilmoitusta + + + notification_invitations + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d kutsu + other + %d kutsua + + + notification_new_messages_for_room + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d uusi viesti + other + %d uutta viestiä + + + notification_unread_notified_messages + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d lukematon viesti + other + %d lukematonta viestiä + + + notification_unread_notified_messages_in_room_rooms + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d huoneessa + other + %d huoneessa + + + screen_app_lock_subtitle + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + Sinulla on %1$d yritys + other + Sinulla on %1$d yritystä + + + screen_app_lock_subtitle_wrong_pin + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + Väärä PIN-koodi. Sinulla on %1$d yritys jäljellä + other + Väärä PIN-koodi. Sinulla on %1$d yritystä jäljellä + + + screen_pinned_timeline_screen_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d kiinnitetty viesti + other + %1$d kiinnitettyä viestiä + + + screen_room_member_list_header_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d henkilö + other + %1$d henkilöä + + + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + + screen_room_timeline_state_changes + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d muutos huoneeseen + other + %1$d muutosta huoneeseen + + + screen_room_typing_many_members + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@, %2$@ ja %3$d muu + other + %1$@, %2$@ ja %3$d muuta + + + screen_room_typing_many_members_second_component_ios + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d muu + other + %d muuta + + + screen_room_typing_notification + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ kirjoittaa + other + %1$@ kirjoittavat + + + troubleshoot_notifications_test_detect_push_provider_success + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + Löytyi %1$d push-palveluntarjoaja: %2$@ + other + Löytyi %1$d push-palveluntarjoajaa: %2$@ + + + troubleshoot_notifications_test_unified_push_success + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d jakelija löytyi: %2$@. + other + %1$d jakelijaa löytyi: %2$@. + + + + \ No newline at end of file diff --git a/ElementX/Resources/Localizations/fi.lproj/SAS.strings b/ElementX/Resources/Localizations/fi.lproj/SAS.strings new file mode 100644 index 0000000000..572c9eaf97 --- /dev/null +++ b/ElementX/Resources/Localizations/fi.lproj/SAS.strings @@ -0,0 +1,64 @@ +"aeroplane" = "Lentokone"; +"anchor" = "Ankkuri"; +"apple" = "Omena"; +"ball" = "Pallo"; +"banana" = "Banaani"; +"bell" = "Soittokello"; +"bicycle" = "Polkupyörä"; +"book" = "Kirja"; +"butterfly" = "Perhonen"; +"cactus" = "Kaktus"; +"cake" = "Kakku"; +"cat" = "Kissa"; +"clock" = "Pöytäkello"; +"cloud" = "Pilvi"; +"corn" = "Maissi"; +"dog" = "Koira"; +"elephant" = "Norsu"; +"fire" = "Tuli"; +"fish" = "Kala"; +"flag" = "Lippu"; +"flower" = "Kukka"; +"folder" = "Kansio"; +"gift" = "Lahja"; +"glasses" = "Silmälasit"; +"globe" = "Maapallo"; +"guitar" = "Kitara"; +"hammer" = "Vasara"; +"hat" = "Hattu"; +"headphones" = "Kuulokkeet"; +"heart" = "Sydän"; +"horse" = "Hevonen"; +"hourglass" = "Tiimalasi"; +"key" = "Avain"; +"light_bulb" = "Hehkulamppu"; +"lion" = "Leijona"; +"lock" = "Lukko"; +"moon" = "Kuu"; +"mushroom" = "Sieni"; +"octopus" = "Tursas"; +"panda" = "Panda"; +"paperclip" = "Paperiliitin"; +"pencil" = "Lyijykynä"; +"penguin" = "Pingviini"; +"pig" = "Sika"; +"pin" = "Nuppineula"; +"pizza" = "Pizza"; +"rabbit" = "Kani"; +"robot" = "Robotti"; +"rocket" = "Raketti"; +"rooster" = "Kukko"; +"santa" = "Joulupukki"; +"scissors" = "Sakset"; +"smiley" = "Hymynaama"; +"spanner" = "Kiintoavain"; +"strawberry" = "Mansikka"; +"telephone" = "Puhelin"; +"thumbs_up" = "Peukalo ylös"; +"train" = "Juna"; +"tree" = "Puu"; +"trophy" = "Palkinto"; +"trumpet" = "Trumpetti"; +"turtle" = "Kilpikonna"; +"umbrella" = "Sateenvarjo"; +"unicorn" = "Yksisarvinen"; \ No newline at end of file diff --git a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings index 7cb63f2178..73f4c756eb 100644 --- a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Audio"; "common_blocked_users" = "Utilisateurs bloqués"; "common_bubbles" = "Bulles"; -"common_call_invite" = "Appel en cours (non supporté)"; "common_call_started" = "Appel démarré"; "common_chat_backup" = "Sauvegarde des discussions"; "common_copyright" = "Droits d’auteur"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Impossible d’envoyer une ou plusieurs invitations"; "common_unlock" = "Déverrouillage"; "common_unmute" = "Retirer la sourdine"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Événement non pris en charge"; "common_username" = "Nom d’utilisateur"; "common_verification_cancelled" = "Vérification annulée"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Cliquez (clic long) sur un message et choisissez « %1$@ » pour qu‘il apparaisse ici."; "screen_pinned_timeline_empty_state_headline" = "Épinglez les messages importants pour leur donner plus de visibilité"; "screen_reset_encryption_password_error" = "Une erreur s'est produite. Vérifiez que le mot de passe de votre compte est correct et réessayez."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Un ou plusieurs de vos appareils ne sont pas vérifiés. Vous pouvez quand même envoyer le message, ou vous pouvez annuler et réessayer plus tard après avoir vérifié tous vos appareils."; "screen_resolve_send_failure_you_unsigned_device_title" = "Votre message n'a pas été envoyé car vous n'avez pas vérifié tous vos appareils"; "screen_room_mentions_at_room_subtitle" = "Notifier tout le salon"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "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_view_all_button_title" = "Voir tout"; +"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_details_pinned_events_row_title" = "Messages épinglés"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Demande d'adhésion envoyée"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Ajouter un émoji"; "screen_room_timeline_beginning_of_room" = "Ceci est le début de %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Ceci est le début de cette conversation."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Afficher moins"; "screen_room_timeline_message_copied" = "Message copié"; "screen_room_timeline_no_permission_to_post" = "Vous n’êtes pas autorisé à publier dans ce salon"; diff --git a/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict index e456503941..c8a0ebe57e 100644 --- a/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d personnes + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings index 15f239bb9c..8a4a10e10a 100644 --- a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Hang"; "common_blocked_users" = "Letiltott felhasználók"; "common_bubbles" = "Buborékok"; -"common_call_invite" = "Folyamatban lévő hívás (nem támogatott)"; "common_call_started" = "A hívás elindult"; "common_chat_backup" = "Csevegés biztonsági mentése"; "common_copyright" = "Szerzői jogok"; @@ -226,6 +225,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_event" = "Nem támogatott esemény"; "common_username" = "Felhasználónév"; "common_verification_cancelled" = "Az ellenőrzés megszakítva"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Nyomjon hosszan az üzenetre, és válassza a „%1$@” lehetőséget, hogy itt szerepeljen."; "screen_pinned_timeline_empty_state_headline" = "Tűzze ki a fontos üzeneteket, hogy könnyen felfedezhetők legyenek"; "screen_reset_encryption_password_error" = "Ismeretlen hiba történt. Ellenőrizze, hogy a fiókja jelszava helyes-e, és próbálja meg újra."; @@ -377,11 +378,16 @@ "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_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_details_pinned_events_row_title" = "Kitűzött üzenetek"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Csatlakozási kérés elküldve"; "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."; @@ -789,6 +795,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_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"; diff --git a/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict index 8830225081..beebf83762 100644 --- a/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/hu.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d személy + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/id.lproj/Localizable.strings b/ElementX/Resources/Localizations/id.lproj/Localizable.strings index 5a5bde12f6..8625bc47b0 100644 --- a/ElementX/Resources/Localizations/id.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/id.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Audio"; "common_blocked_users" = "Pengguna yang diblokir"; "common_bubbles" = "Gelembung"; -"common_call_invite" = "Panggilan sedang berjalan (tidak didukung)"; "common_call_started" = "Panggilan dimulai"; "common_chat_backup" = "Pencadangan percakapan"; "common_copyright" = "Hak cipta"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Tidak dapat mengirim undangan"; "common_unlock" = "Buka kunci"; "common_unmute" = "Bunyikan"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Peristiwa tidak didukung"; "common_username" = "Nama pengguna"; "common_verification_cancelled" = "Verifikasi dibatalkan"; @@ -353,8 +353,8 @@ "screen_create_room_room_access_section_header" = "Akses Ruangan"; "screen_create_room_room_access_section_knocking_option_description" = "Siapa pun dapat meminta untuk bergabung dengan ruangan tetapi administrator atau moderator harus menerima permintaan tersebut"; "screen_create_room_room_access_section_knocking_option_title" = "Minta untuk bergabung"; -"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" = "Beberapa karakter tidak diperbolehkan. Hanya huruf, angka, dan simbol berikut didukung ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Alamat ruangan sudah ada, silakan coba sunting kolom alamat ruangan atau ubah nama ruangan"; "screen_create_room_room_address_section_footer" = "Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan."; "screen_create_room_room_address_section_title" = "Alamat ruangan"; "screen_create_room_room_visibility_section_title" = "Keterlihatan ruangan"; @@ -365,6 +365,7 @@ "screen_join_room_knock_message_description" = "Pesan (opsional)"; "screen_join_room_knock_sent_description" = "Anda akan menerima undangan untuk bergabung dengan ruangan jika permintaan Anda diterima."; "screen_join_room_knock_sent_title" = "Permintaan untuk bergabung dikirim"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Tekan pesan dan pilih “%1$@” untuk disertakan di sini."; "screen_pinned_timeline_empty_state_headline" = "Sematkan pesan penting agar mudah ditemukan"; "screen_reset_encryption_password_error" = "Terjadi kesalahan yang tidak diketahui. Harap periksa apakah kata sandi akun Anda sudah benar dan coba lagi."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Satu atau beberapa perangkat Anda tidak terverifikasi. Anda tetap dapat mengirim pesan, atau Anda dapat membatalkannya dan mencoba lagi nanti setelah Anda memverifikasi semua perangkat."; "screen_resolve_send_failure_you_unsigned_device_title" = "Pesan Anda tidak terkirim karena Anda belum memverifikasi satu atau beberapa perangkat Anda"; "screen_room_mentions_at_room_subtitle" = "Beri tahu seluruh ruangan"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ dari %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Pesan yang disematkan"; "screen_room_pinned_banner_loading_description" = "Memuat pesan…"; "screen_room_pinned_banner_view_all_button_title" = "Lihat Semua"; +"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_details_pinned_events_row_title" = "Pesan yang disematkan"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Permintaan untuk bergabung dikirim"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Tambahkan emoji"; "screen_room_timeline_beginning_of_room" = "Ini adalah awal dari %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Ini adalah awal dari percakapan ini."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Tampilkan lebih sedikit"; "screen_room_timeline_message_copied" = "Pesan disalin"; "screen_room_timeline_no_permission_to_post" = "Anda tidak memiliki izin untuk mengirim di ruangan ini"; @@ -849,10 +856,10 @@ "screen_session_verification_request_title" = "Verifikasi diminta"; "screen_session_verification_they_dont_match" = "Mereka tidak cocok"; "screen_session_verification_they_match" = "Mereka cocok"; -"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" = "Pastikan Anda membuka aplikasi di perangkat lain sebelum memulai verifikasi dari sini."; +"screen_session_verification_use_another_device_title" = "Buka aplikasi di perangkat terverifikasi lain"; +"screen_session_verification_waiting_another_device_subtitle" = "Anda akan melihat popup di perangkat lain. Mulai verifikasi dari sana sekarang."; +"screen_session_verification_waiting_another_device_title" = "Mulai verifikasi di perangkat lain"; "screen_session_verification_waiting_to_accept_subtitle" = "Terima permintaan untuk memulai proses verifikasi di sesi Anda yang lain untuk melanjutkan."; "screen_session_verification_waiting_to_accept_title" = "Menunggu untuk menerima permintaan"; "screen_share_location_title" = "Bagikan lokasi"; @@ -918,7 +925,7 @@ "state_event_room_join" = "%1$@ bergabung ke ruangan"; "state_event_room_join_by_you" = "Anda bergabung ke ruangan"; "state_event_room_knock" = "%1$@ meminta untuk bergabung"; -"state_event_room_knock_accepted" = "%1$@ memperbolehkan %2$@ untuk bergabung"; +"state_event_room_knock_accepted" = "%1$@ memberikan akses kepada %2$@"; "state_event_room_knock_accepted_by_you" = "Anda memperbolehkan %1$@ untuk bergabung"; "state_event_room_knock_by_you" = "Anda meminta untuk bergabung"; "state_event_room_knock_denied" = "%1$@ menolak permintaan %2$@ untuk bergabung"; diff --git a/ElementX/Resources/Localizations/id.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/id.lproj/Localizable.stringsdict index 2787aa3503..cfe76bd928 100644 --- a/ElementX/Resources/Localizations/id.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/id.lproj/Localizable.stringsdict @@ -198,6 +198,22 @@ %1$d orang + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/it.lproj/Localizable.strings b/ElementX/Resources/Localizations/it.lproj/Localizable.strings index 4f3d038ed2..29b162b895 100644 --- a/ElementX/Resources/Localizations/it.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/it.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Audio"; "common_blocked_users" = "Utenti bloccati"; "common_bubbles" = "Fumetti"; -"common_call_invite" = "Chiamata in corso (non supportata)"; "common_call_started" = "Chiamata avviata"; "common_chat_backup" = "Backup della chat"; "common_copyright" = "Copyright"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Impossibile inviare inviti"; "common_unlock" = "Sblocca"; "common_unmute" = "Annulla silenzioso"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Evento non supportato"; "common_username" = "Nome utente"; "common_verification_cancelled" = "Verifica annullata"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Premi su un messaggio e scegli “%1$@” per includerlo qui."; "screen_pinned_timeline_empty_state_headline" = "Fissa i messaggi importanti così che possano essere trovati facilmente"; "screen_reset_encryption_password_error" = "Si è verificato un errore sconosciuto. Controlla che la password del tuo account sia corretta e riprova."; @@ -377,11 +378,16 @@ "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_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_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_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."; @@ -789,6 +795,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_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"; diff --git a/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict index f144b6b3be..f84b37ef64 100644 --- a/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/it.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d persone + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings index 4fda4d6093..ac0243f611 100644 --- a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "აუდიო"; "common_blocked_users" = "Blocked users"; "common_bubbles" = "ბუშტები"; -"common_call_invite" = "Call in progress (unsupported)"; "common_call_started" = "Call started"; "common_chat_backup" = "ჩატის სარეზერვო ასლი"; "common_copyright" = "საავტორო უფლება"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "მოწვევის (ების) გაგზავნა შეუძლებელია"; "common_unlock" = "განბლოკვა"; "common_unmute" = "დადუმების გაუქმება"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "მხარდაუჭერელი მოვლენა"; "common_username" = "მომხმარებლის სახელი"; "common_verification_cancelled" = "დადასტურება გაუქმდა"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "მთელი ოთახისათვის შეტყობინება"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ of %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Pinned messages"; "screen_room_pinned_banner_loading_description" = "Loading message…"; "screen_room_pinned_banner_view_all_button_title" = "View All"; +"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_details_pinned_events_row_title" = "Pinned messages"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "ემოჯის დამატება"; "screen_room_timeline_beginning_of_room" = "ეს არის %1$@-ს დასაწყისი."; "screen_room_timeline_beginning_of_room_no_name" = "ეს არის ამ საუბრის დასაწყისი."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "ნაკლების ჩვენება"; "screen_room_timeline_message_copied" = "შეტყობინება დაკოპირდა"; "screen_room_timeline_no_permission_to_post" = "თქვენ არ გაქვთ ამ ოთახში გამოქვეყნების ნებართვა"; diff --git a/ElementX/Resources/Localizations/ka.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/ka.lproj/Localizable.stringsdict index e7051408c9..020466b968 100644 --- a/ElementX/Resources/Localizations/ka.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/ka.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d ადამიანი + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/nl.lproj/Localizable.strings b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings index db0bf30ad1..017f166710 100644 --- a/ElementX/Resources/Localizations/nl.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Geluid"; "common_blocked_users" = "Geblokkeerde gebruikers"; "common_bubbles" = "Bubbels"; -"common_call_invite" = "Gesprek bezig (niet ondersteund)"; "common_call_started" = "Oproep gestart"; "common_chat_backup" = "Chat back-up"; "common_copyright" = "Copyright"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Kan uitnodiging(en) niet verzenden"; "common_unlock" = "Ontgrendelen"; "common_unmute" = "Dempen opheffen"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Niet-ondersteunde gebeurtenis"; "common_username" = "Gebruikersnaam"; "common_verification_cancelled" = "Verificatie geannuleerd"; @@ -365,6 +365,7 @@ "screen_join_room_knock_message_description" = "Bericht (optioneel)"; "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" = "Verzoek om toe te treden verzonden"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Druk op een bericht en kies „%1$@” om het hier toe te voegen."; "screen_pinned_timeline_empty_state_headline" = "Zet belangrijke berichten vast zodat ze gemakkelijk te vinden zijn"; "screen_reset_encryption_password_error" = "Er is een onbekende fout opgetreden. Controleer of het wachtwoord van je account juist is en probeer het opnieuw."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Een of meer van je apparaten zijn niet geverifieerd. Je kunt het bericht toch verzenden, of je kunt het voorlopig annuleren en het later opnieuw proberen nadat je al je apparaten hebt geverifieerd."; "screen_resolve_send_failure_you_unsigned_device_title" = "Je bericht is niet verzonden omdat je een of meerdere apparaten niet geverifieerd hebt"; "screen_room_mentions_at_room_subtitle" = "Stuur een melding naar de hele kamer"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ van %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Vastgezette berichten"; "screen_room_pinned_banner_loading_description" = "Bericht laden..."; "screen_room_pinned_banner_view_all_button_title" = "Bekijk alles"; +"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_details_pinned_events_row_title" = "Vastgezette berichten"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Emoji toevoegen"; "screen_room_timeline_beginning_of_room" = "Dit is het begin van %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Dit is het begin van dit gesprek."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Toon minder"; "screen_room_timeline_message_copied" = "Bericht gekopieerd"; "screen_room_timeline_no_permission_to_post" = "Je hebt geen toestemming om berichten in deze kamer te plaatsen"; diff --git a/ElementX/Resources/Localizations/nl.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/nl.lproj/Localizable.stringsdict index a4b7f469a6..564de20b4f 100644 --- a/ElementX/Resources/Localizations/nl.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/nl.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d personen + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings index 6d8ec5744e..97fdc287a0 100644 --- a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Dźwięk"; "common_blocked_users" = "Zablokowani użytkownicy"; "common_bubbles" = "Bąbelki"; -"common_call_invite" = "Rozmowa w trakcie (niewspierane)"; "common_call_started" = "Rozpoczęto rozmowę"; "common_chat_backup" = "Backup czatu"; "common_copyright" = "Prawa autorskie"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Nie można wysłać zaproszeń"; "common_unlock" = "Odblokuj"; "common_unmute" = "Wyłącz wyciszenie"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Nieobsługiwane zdarzenie"; "common_username" = "Nazwa użytkownika"; "common_verification_cancelled" = "Weryfikacja anulowana"; @@ -365,6 +365,7 @@ "screen_join_room_knock_message_description" = "Wiadomość (opcjonalne)"; "screen_join_room_knock_sent_description" = "Otrzymasz zaproszenie dołączenia do pokoju, jeśli prośba zostanie zaakceptowana."; "screen_join_room_knock_sent_title" = "Wysłano prośbę o dołączenie"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Naciśnij wiadomość i wybierz “%1$@”, aby dołączyć tutaj."; "screen_pinned_timeline_empty_state_headline" = "Przypinaj ważne wiadomości, aby można było je łatwo znaleźć"; "screen_reset_encryption_password_error" = "Wystąpił nieznany błąd. Sprawdź, czy hasło jest poprawne i spróbuj ponownie."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Jedno lub więcej z Twoich urządzeń jest niezweryfikowanych. Wyślij wiadomość mimo to lub anuluj i spróbuj ponownie po zweryfikowaniu wszystkich swoich urządzeń."; "screen_resolve_send_failure_you_unsigned_device_title" = "Twoja wiadomość nie została wysłana, ponieważ nie zweryfikowałeś jednego lub więcej swoich urządzeń."; "screen_room_mentions_at_room_subtitle" = "Powiadom cały pokój"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ z %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ przypiętych wiadomości"; "screen_room_pinned_banner_loading_description" = "Wczytywanie wiadomości..."; "screen_room_pinned_banner_view_all_button_title" = "Wyświetl wszystkie"; +"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_details_pinned_events_row_title" = "Przypięte wiadomości"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Wysłano prośbę o dołączenie"; "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ń."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Dodaj emoji"; "screen_room_timeline_beginning_of_room" = "To jest początek %1$@"; "screen_room_timeline_beginning_of_room_no_name" = "To jest początek tej konwersacji"; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Pokaż mniej"; "screen_room_timeline_message_copied" = "Skopiowano wiadomość"; "screen_room_timeline_no_permission_to_post" = "Nie masz uprawnień, aby pisać w tym pokoju"; diff --git a/ElementX/Resources/Localizations/pl.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/pl.lproj/Localizable.stringsdict index 794f787cf5..c600ba88c6 100644 --- a/ElementX/Resources/Localizations/pl.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/pl.lproj/Localizable.stringsdict @@ -254,6 +254,22 @@ %1$d osób + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings index decda9de4c..cf0fdb3188 100644 --- a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Áudio"; "common_blocked_users" = "Usuários bloqueados"; "common_bubbles" = "Bolhas"; -"common_call_invite" = "Chamada em progresso (sem suporte)"; "common_call_started" = "Chamada iniciada"; "common_chat_backup" = "Backup de conversas"; "common_copyright" = "Direitos autorais"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Não foi possível enviar o(s) convite(s)"; "common_unlock" = "Desbloquear"; "common_unmute" = "Desmutar"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Evento não suportado"; "common_username" = "Nome do usuário"; "common_verification_cancelled" = "Verificação cancelada"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "Notificar a sala inteira"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ of %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Pinned messages"; "screen_room_pinned_banner_loading_description" = "Loading message…"; "screen_room_pinned_banner_view_all_button_title" = "View All"; +"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_details_pinned_events_row_title" = "Pinned messages"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Adicionar emoji"; "screen_room_timeline_beginning_of_room" = "Este é o início do %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Este é o início desta conversa."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Mostrar menos"; "screen_room_timeline_message_copied" = "Mensagem copiada"; "screen_room_timeline_no_permission_to_post" = "Você não tem permissão para postar nesta sala"; diff --git a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.stringsdict index 7c41ae03e3..18b1f01b16 100644 --- a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d pessoas + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings index 445ea610ca..58087838d3 100644 --- a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Áudio"; "common_blocked_users" = "Utilizadores bloqueados"; "common_bubbles" = "Bolhas"; -"common_call_invite" = "Chamada em curso (não suportada)"; "common_call_started" = "Chamada iniciada"; "common_chat_backup" = "Cópia de segurança das conversas"; "common_copyright" = "Direitos de autor"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Não foi possível enviar convite(s)"; "common_unlock" = "Desbloquear"; "common_unmute" = "Dessilenciar"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Evento não suportado"; "common_username" = "Nome de utilizador"; "common_verification_cancelled" = "Verificação cancelada"; @@ -365,6 +365,7 @@ "screen_join_room_knock_message_description" = "Mensagem (opcional)"; "screen_join_room_knock_sent_description" = "Irá receber um convite para participar na sala se seu pedido for aceite."; "screen_join_room_knock_sent_title" = "Pedido de adesão enviado"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Pressione uma mensagem e escolha \"%1$@\" para incluir aqui."; "screen_pinned_timeline_empty_state_headline" = "Fixa mensagens importantes para que possam ser facilmente descobertas"; "screen_reset_encryption_password_error" = "Um erro desconhecido aconteceu. Verifique se a senha da sua conta está correta e tente novamente."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Um ou mais dos teus dispositivos não foram verificados. Podes enviar a mensagem na mesma, ou podes cancelar por agora e tentar novamente mais tarde, depois de teres verificado todos os teus dispositivos."; "screen_resolve_send_failure_you_unsigned_device_title" = "A sua mensagem não foi enviada porque não verificou um ou mais dos seus dispositivos"; "screen_room_mentions_at_room_subtitle" = "Notificar toda a sala"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ de %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ mensagens afixadas"; "screen_room_pinned_banner_loading_description" = "A carregar mensagem..."; "screen_room_pinned_banner_view_all_button_title" = "Ver todas"; +"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_details_pinned_events_row_title" = "Mensagens afixadas"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Pedido de adesão enviado"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Adicionar emoji"; "screen_room_timeline_beginning_of_room" = "%1$@ começou aqui."; "screen_room_timeline_beginning_of_room_no_name" = "Esta conversa começou aqui."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Mostrar menos"; "screen_room_timeline_message_copied" = "Mensagem copiada"; "screen_room_timeline_no_permission_to_post" = "Não tens permissão para publicar nesta sala"; diff --git a/ElementX/Resources/Localizations/pt.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/pt.lproj/Localizable.stringsdict index eb8934967a..b3c5171d73 100644 --- a/ElementX/Resources/Localizations/pt.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/pt.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d pessoas + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings index b226a59516..727293079f 100644 --- a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Audio"; "common_blocked_users" = "Utilizatori blocați"; "common_bubbles" = "Baloane"; -"common_call_invite" = "Apel în curs (nesuportat)"; "common_call_started" = "A început un apel"; "common_chat_backup" = "Backup conversații"; "common_copyright" = "Drepturi de autor"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Nu s-a putut trimite invitația (invitațiile)"; "common_unlock" = "Deblocare"; "common_unmute" = "Activați sunetul"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Eveniment neacceptat"; "common_username" = "Utilizator"; "common_verification_cancelled" = "Verificare anulată"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "Notificați întreaga cameră"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ of %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Pinned messages"; "screen_room_pinned_banner_loading_description" = "Loading message…"; "screen_room_pinned_banner_view_all_button_title" = "View All"; +"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_details_pinned_events_row_title" = "Pinned messages"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Adăugați emoji"; "screen_room_timeline_beginning_of_room" = "Acesta este începutul conversației %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Acesta este începutul acestei conversații."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Afișați mai puțin"; "screen_room_timeline_message_copied" = "Mesaj copiat"; "screen_room_timeline_no_permission_to_post" = "Nu aveți permisiunea de a posta în această cameră"; diff --git a/ElementX/Resources/Localizations/ro.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/ro.lproj/Localizable.stringsdict index 18f7fe5b53..09720f2314 100644 --- a/ElementX/Resources/Localizations/ro.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/ro.lproj/Localizable.stringsdict @@ -238,6 +238,22 @@ %1$d persoane + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings index 9bc2f1d815..19a7d3735e 100644 --- a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Аудио"; "common_blocked_users" = "Заблокированные пользователи"; "common_bubbles" = "Пузыри"; -"common_call_invite" = "Выполняется звонок (не поддерживается)"; "common_call_started" = "Звонок начат"; "common_chat_backup" = "Резервная копия чатов"; "common_copyright" = "Авторское право"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Не удалось отправить приглашение(я)"; "common_unlock" = "Разблокировать"; "common_unmute" = "Вкл. звук"; +"common_unsupported_call" = "Неподдерживаемый вызов"; "common_unsupported_event" = "Неподдерживаемое событие"; "common_username" = "Имя пользователя"; "common_verification_cancelled" = "Подтверждение отменено"; @@ -365,6 +365,7 @@ "screen_join_room_knock_message_description" = "Сообщение (опционально)"; "screen_join_room_knock_sent_description" = "Вы получите приглашение присоединиться к комнате, как только ваш запрос будет принят."; "screen_join_room_knock_sent_title" = "Запрос на присоединение отправлен"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Отклонить и запретить"; "screen_pinned_timeline_empty_state_description" = "Нажмите на сообщение и выберите “%1$@”, чтобы добавить его сюда."; "screen_pinned_timeline_empty_state_headline" = "Закрепите важные сообщения, чтобы их можно было легко найти"; "screen_reset_encryption_password_error" = "Произошла неизвестная ошибка. Проверьте правильность пароля учетной записи и повторите попытку."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Одно или несколько ваших устройств не проверены. Вы можете отправить сообщение в любом случае или отменить его пока и повторить попытку позже, проверив все свои устройства."; "screen_resolve_send_failure_you_unsigned_device_title" = "Ваше сообщение не было отправлено, поскольку вы не подтвердили одно или несколько своих устройств."; "screen_room_mentions_at_room_subtitle" = "Уведомить всю комнату"; +"screen_room_multiple_knock_requests_view_all_button_title" = "Показать все"; "screen_room_pinned_banner_indicator" = "%1$@ из %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Закрепленные сообщения"; "screen_room_pinned_banner_loading_description" = "Загрузка сообщения..."; "screen_room_pinned_banner_view_all_button_title" = "Посмотреть все"; +"screen_room_single_knock_request_accept_button_title" = "Принять"; +"screen_room_single_knock_request_title" = "%1$@ хочет присоединиться к этой комнате"; +"screen_room_single_knock_request_view_button_title" = "Просмотр"; "screen_room_details_pinned_events_row_title" = "Закрепленные сообщения"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Запрос на присоединение отправлен"; "screen_timeline_item_menu_send_failure_changed_identity" = "Сообщение не отправлено, потому что верифицированная личность %1$@ изменилась."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Сообщение не отправлено, потому что %1$@ не проверил одно или несколько устройств."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Добавить эмодзи"; "screen_room_timeline_beginning_of_room" = "Это начало %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Это начало разговора."; +"screen_room_timeline_legacy_call" = "Неподдерживаемый вызов. уточните, может ли звонящий использовать новое приложение Element X."; "screen_room_timeline_less_reactions" = "Показать меньше"; "screen_room_timeline_message_copied" = "Сообщение скопировано"; "screen_room_timeline_no_permission_to_post" = "У вас нет разрешения публиковать сообщения в этой комнате"; diff --git a/ElementX/Resources/Localizations/ru.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/ru.lproj/Localizable.stringsdict index 71a17080b1..b56aa9e5b9 100644 --- a/ElementX/Resources/Localizations/ru.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/ru.lproj/Localizable.stringsdict @@ -254,6 +254,24 @@ %1$d пользователей + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d хочет присоединиться к этой комнате + few + %1$@ +%2$d хотят присоединиться к этой комнате + many + %1$@ +%2$d хотят присоединиться к этой комнате + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings index 3fd39dc069..45597d7dce 100644 --- a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Zvuk"; "common_blocked_users" = "Blokovaní používatelia"; "common_bubbles" = "Bubliny"; -"common_call_invite" = "Prebieha hovor (nepodporované)"; "common_call_started" = "Hovor sa začal"; "common_chat_backup" = "Záloha konverzácie"; "common_copyright" = "Autorské práva"; @@ -150,7 +149,7 @@ "common_favourited" = "Obľúbené"; "common_file" = "Súbor"; "common_forward_message" = "Preposlať správu"; -"common_frequently_used" = "Frequently used"; +"common_frequently_used" = "Často používané"; "common_gif" = "GIF"; "common_image" = "Obrázok"; "common_in_reply_to" = "V odpovedi na %1$@"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Nie je možné odoslať pozvánku/ky"; "common_unlock" = "Odomknúť"; "common_unmute" = "Zrušiť stlmenie zvuku"; +"common_unsupported_call" = "Nepodporovaný hovor"; "common_unsupported_event" = "Nepodporovaná udalosť"; "common_username" = "Používateľské meno"; "common_verification_cancelled" = "Overovanie zrušené"; @@ -233,7 +233,7 @@ "common_verification_failed" = "Overenie zlyhalo"; "common_verified" = "Overené"; "common_verify_device" = "Overiť zariadenie"; -"common_verify_identity" = "Verify identity"; +"common_verify_identity" = "Overiť totožnosť"; "common_video" = "Video"; "common_voice_message" = "Hlasová správa"; "common_waiting" = "Čaká sa…"; @@ -246,10 +246,10 @@ "common.you" = "Vy"; "common_unable_to_decrypt_insecure_device" = "Odoslané z nezabezpečeného zariadenia"; "common_unable_to_decrypt_verification_violation" = "Overená totožnosť odosielateľa sa zmenila"; -"confirm_recovery_key_banner_message" = "Vaša záloha konverzácie nie je momentálne synchronizovaná. Na zachovanie prístupu k zálohe konverzácie musíte potvrdiť svoj kľúč na obnovu."; -"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" = "Potvrďte svoj kľúč na obnovenie"; +"confirm_recovery_key_banner_message" = "Potvrďte svoj kľúč na obnovenie, aby ste zachovali prístup k úložisku kľúčov a histórii správ."; +"confirm_recovery_key_banner_primary_button_title" = "Zadajte kľúč na obnovenie"; +"confirm_recovery_key_banner_secondary_button_title" = "Zabudli ste svoj kľúč na obnovenie?"; +"confirm_recovery_key_banner_title" = "Vaše úložisko kľúčov nie je synchronizované"; "crash_detection_dialog_content" = "%1$@ zlyhal pri poslednom použití. Chcete zdieľať správu o páde s našim tímom?"; "crypto_identity_change_pin_violation" = "Zdá sa, že totožnosť používateľa %1$@ sa zmenila.%2$@"; "crypto_identity_change_pin_violation_new" = "Zdá sa, že identita %2$@ používateľa %1$@ sa zmenila. %3$@"; @@ -344,7 +344,7 @@ "rich_text_editor_unindent" = "Zrušiť odsadenie"; "rich_text_editor_url_placeholder" = "Odkaz"; "rich_text_editor_a11y_add_attachment" = "Pridať prílohu"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Voliteľný titulok…"; "screen_advanced_settings_element_call_base_url" = "Vlastná Element Call základná URL adresa"; "screen_advanced_settings_element_call_base_url_description" = "Nastaviť vlastnú základnú URL adresu pre Element Call."; "screen_advanced_settings_element_call_base_url_validation_error" = "Neplatná adresa URL, uistite sa, že ste uviedli protokol (http/https) a správnu adresu."; @@ -353,8 +353,8 @@ "screen_create_room_room_access_section_header" = "Prístup do miestnosti"; "screen_create_room_room_access_section_knocking_option_description" = "Ktokoľvek môže požiadať o pripojenie sa k miestnosti, ale administrátor alebo moderátor bude musieť žiadosť schváliť"; "screen_create_room_room_access_section_knocking_option_title" = "Požiadať o pripojenie"; -"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" = "Niektoré znaky nie sú povolené. Podporované sú iba písmená, číslice a nasledujúce symboly ! $ & '() * +/; =? @ [] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Táto adresa miestnosti už existuje, skúste upraviť pole adresy miestnosti alebo zmeňte názov miestnosti"; "screen_create_room_room_address_section_footer" = "Aby bola táto miestnosť viditeľná v adresári verejných miestností, budete potrebovať adresu miestnosti."; "screen_create_room_room_address_section_title" = "Adresa miestnosti"; "screen_create_room_room_visibility_section_title" = "Viditeľnosť miestnosti"; @@ -365,6 +365,7 @@ "screen_join_room_knock_message_description" = "Správa (voliteľné)"; "screen_join_room_knock_sent_description" = "Ak bude vaša žiadosť prijatá, dostanete pozvánku na vstup do miestnosti."; "screen_join_room_knock_sent_title" = "Žiadosť o pripojenie bola odoslaná"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Odmietnuť a zakázať"; "screen_pinned_timeline_empty_state_description" = "Stlačte správu a vyberte možnosť „%1$@“, ktorú chcete zahrnúť sem."; "screen_pinned_timeline_empty_state_headline" = "Pripnite dôležité správy, aby sa dali ľahko nájsť"; "screen_reset_encryption_password_error" = "Nastala neznáma chyba. Skontrolujte, či je heslo vášho účtu správne a skúste to znova."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Jedno alebo viac vašich zariadení nie je overených. Správu môžete odoslať aj tak, alebo môžete zatiaľ zrušiť a skúsiť to znova neskôr po overení všetkých svojich zariadení."; "screen_resolve_send_failure_you_unsigned_device_title" = "Vaša správa nebola odoslaná, pretože ste neoverili jedno alebo viac svojich zariadení"; "screen_room_mentions_at_room_subtitle" = "Informovať celú miestnosť"; +"screen_room_multiple_knock_requests_view_all_button_title" = "Zobraziť všetko"; "screen_room_pinned_banner_indicator" = "%1$@ z %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Pripnutých správ"; "screen_room_pinned_banner_loading_description" = "Načítava sa správa..."; "screen_room_pinned_banner_view_all_button_title" = "Zobraziť všetko"; +"screen_room_single_knock_request_accept_button_title" = "Prijať"; +"screen_room_single_knock_request_title" = "%1$@ chce vstúpiť do tejto miestnosti"; +"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_roomlist_knock_event_sent_description" = "Žiadosť o vstup odoslaná"; "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."; @@ -394,8 +400,8 @@ "screen_account_provider_signup_title" = "Chystáte sa vytvoriť účet na %@"; "screen_advanced_settings_developer_mode" = "Vývojársky režim"; "screen_advanced_settings_developer_mode_description" = "Umožniť prístup k možnostiam a funkciám pre vývojárov."; -"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" = "Nahrávajte fotografie a videá rýchlejšie a znížte spotrebu dát"; +"screen_advanced_settings_media_compression_title" = "Optimalizovať kvalitu médií"; "screen_advanced_settings_rich_text_editor_description" = "Vypnite rozšírený textový editor na ručné písanie Markdown."; "screen_advanced_settings_send_read_receipts" = "Potvrdenia o prečítaní"; "screen_advanced_settings_send_read_receipts_description" = "Ak je táto funkcia vypnutá, vaše potvrdenia o prečítaní sa nebudú nikomu odosielať. Stále budete dostávať potvrdenia o prečítaní od ostatných používateľov."; @@ -464,12 +470,12 @@ "screen_chat_backup_key_backup_action_enable" = "Zapnúť zálohovanie"; "screen_chat_backup_key_backup_description" = "Uložte svoju kryptografickú identitu a kľúče správ bezpečne na server. To vám umožní zobraziť históriu správ na všetkých nových zariadeniach. %1$@."; "screen_chat_backup_key_backup_title" = "Úložisko kľúčov"; -"screen_chat_backup_key_storage_disabled_error" = "Key storage must be turned on to set up recovery."; +"screen_chat_backup_key_storage_disabled_error" = "Úložisko kľúčov musí byť zapnuté, aby bolo možné nastaviť obnovenie."; "screen_chat_backup_key_storage_toggle_description" = "Nahrať kľúče z tohto zariadenia"; "screen_chat_backup_key_storage_toggle_title" = "Povoliť úložisko kľúčov"; "screen_chat_backup_recovery_action_change" = "Zmeniť kľúč na obnovenie"; "screen_chat_backup_recovery_action_change_description" = "Obnovte svoju kryptografickú totožnosť a históriu správ pomocou kľúča na obnovenie, ak ste stratili všetky svoje existujúce zariadenia."; -"screen_chat_backup_recovery_action_confirm_description" = "Vaša záloha konverzácie nie je momentálne synchronizovaná."; +"screen_chat_backup_recovery_action_confirm_description" = "Vaše úložisko kľúčov nie je momentálne synchronizované."; "screen_chat_backup_recovery_action_setup_description" = "Získajte prístup k vašim šifrovaným správam aj keď stratíte všetky svoje zariadenia alebo sa odhlásite zo všetkých %1$@ zariadení."; "screen_create_account_title" = "Vytvoriť účet"; "screen_create_new_recovery_key_list_item_1" = "Otvoriť %1$@ v stolnom počítači"; @@ -644,7 +650,7 @@ "screen_recovery_key_change_title" = "Zmeniť kľúč na obnovenie?"; "screen_recovery_key_confirm_create_new_recovery_key" = "Vytvoriť nový kľúč na obnovenie"; "screen_recovery_key_confirm_description" = "Uistite sa, že túto obrazovku nikto nevidí!"; -"screen_recovery_key_confirm_error_content" = "Skúste prosím znova potvrdiť prístup k vašej zálohe konverzácie."; +"screen_recovery_key_confirm_error_content" = "Skúste prosím znova potvrdiť prístup k úložisku kľúčov."; "screen_recovery_key_confirm_error_title" = "Nesprávny kľúč na obnovenie"; "screen_recovery_key_confirm_key_description" = "Ak máte bezpečnostný kľúč alebo bezpečnostnú frázu, bude to fungovať tiež."; "screen_recovery_key_confirm_key_placeholder" = "Zadať..."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Pridať emoji"; "screen_room_timeline_beginning_of_room" = "Toto je začiatok %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Toto je začiatok tejto konverzácie."; +"screen_room_timeline_legacy_call" = "Nepodporovaný hovor. Opýtajte sa, či volajúci môže použiť novú aplikáciu Element X."; "screen_room_timeline_less_reactions" = "Zobraziť menej"; "screen_room_timeline_message_copied" = "Správa skopírovaná"; "screen_room_timeline_no_permission_to_post" = "Nemáte povolenie uverejňovať príspevky v tejto miestnosti"; @@ -849,10 +856,10 @@ "screen_session_verification_request_title" = "Vyžadované overenie"; "screen_session_verification_they_dont_match" = "Nezhodujú sa"; "screen_session_verification_they_match" = "Zhodujú sa"; -"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" = "Pred začatím overovania odtiaľto sa uistite, že máte aplikáciu otvorenú v inom zariadení."; +"screen_session_verification_use_another_device_title" = "Otvorte aplikáciu na inom overenom zariadení"; +"screen_session_verification_waiting_another_device_subtitle" = "Na druhom zariadení by sa malo zobraziť vyskakovacie okno. Začnite teraz overovanie odtiaľ."; +"screen_session_verification_waiting_another_device_title" = "Spustiť overovanie na druhom zariadení"; "screen_session_verification_waiting_to_accept_subtitle" = "Ak chcete pokračovať, prijmite žiadosť o spustenie procesu overenia vo vašej druhej relácii."; "screen_session_verification_waiting_to_accept_title" = "Čaká sa na prijatie žiadosti"; "screen_share_location_title" = "Zdieľať polohu"; @@ -917,8 +924,8 @@ "state_event_room_invite_you" = "%1$@ vás pozval/a"; "state_event_room_join" = "%1$@ sa pripojil/a do miestnosti"; "state_event_room_join_by_you" = "Vstúpili ste do miestnosti"; -"state_event_room_knock" = "%1$@ požiadal o pripojenie"; -"state_event_room_knock_accepted" = "%1$@ umožnil/a používateľovi %2$@ pripojiť sa"; +"state_event_room_knock" = "%1$@ žiada o vstup"; +"state_event_room_knock_accepted" = "%1$@ umožnil/a vstup používateľovi %2$@"; "state_event_room_knock_accepted_by_you" = "Povolili ste používateľovi %1$@, aby sa pripojil"; "state_event_room_knock_by_you" = "Požiadali ste o pripojenie"; "state_event_room_knock_denied" = "%1$@ odmietol/a žiadosť používateľa %2$@ o vstup"; @@ -1039,7 +1046,7 @@ "screen_notification_settings_mentions_section_title" = "Zmienky"; "screen_qr_code_login_invalid_scan_state_retry_button" = "Skúste to znova"; "screen_recovery_key_change_generate_key_description" = "Nezdieľajte to s nikým!"; -"screen_recovery_key_confirm_title" = "Enter your recovery key"; +"screen_recovery_key_confirm_title" = "Zadajte kľúč na obnovenie"; "screen_report_content_block_user" = "Zablokovať používateľa"; "screen_reset_encryption_password_placeholder" = "Zadať..."; "screen_room_attachment_source_camera_photo" = "Urobiť fotku"; diff --git a/ElementX/Resources/Localizations/sk.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/sk.lproj/Localizable.stringsdict index acd716ce57..3cf16f0d90 100644 --- a/ElementX/Resources/Localizations/sk.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/sk.lproj/Localizable.stringsdict @@ -254,6 +254,24 @@ %1$d osôb + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d ďalší chcú vstúpiť do tejto miestnosti + few + %1$@ +%2$d ďalší chcú vstúpiť do tejto miestnosti + other + %1$@ +%2$d ďalších chce vstúpiť do tejto miestnosti + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings index f6fa8b9f5b..b7a28d19f1 100644 --- a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Ljud"; "common_blocked_users" = "Blockerade användare"; "common_bubbles" = "Bubblor"; -"common_call_invite" = "Samtal pågår (stöds inte)"; "common_call_started" = "Samtal startat"; "common_chat_backup" = "Chattsäkerhetskopia"; "common_copyright" = "Upphovsrätt"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Kunde inte skicka inbjudningar"; "common_unlock" = "Lås upp"; "common_unmute" = "Avtysta"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Händelse som inte stöds"; "common_username" = "Användarnamn"; "common_verification_cancelled" = "Verifiering avbruten"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Tryck på ett meddelande och välj ”%1$@” för att inkludera det här."; "screen_pinned_timeline_empty_state_headline" = "Fäst viktiga meddelanden så att de lätt kan upptäckas"; "screen_reset_encryption_password_error" = "Ett okänt fel inträffade. Kontrollera att ditt kontolösenord är korrekt och försök igen."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "Meddela hela rummet"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ av %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Fästa meddelanden"; "screen_room_pinned_banner_loading_description" = "Laddar meddelande …"; "screen_room_pinned_banner_view_all_button_title" = "Visa alla"; +"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_details_pinned_events_row_title" = "Fästa meddelanden"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Lägg till emoji"; "screen_room_timeline_beginning_of_room" = "Det här är början på %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Detta är början på det här samtalet."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Visa mindre"; "screen_room_timeline_message_copied" = "Meddelande kopierat"; "screen_room_timeline_no_permission_to_post" = "Du är inte behörig att göra inlägg i det här rummet"; diff --git a/ElementX/Resources/Localizations/sv.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/sv.lproj/Localizable.stringsdict index fe8c8bdc09..e23f92a5bc 100644 --- a/ElementX/Resources/Localizations/sv.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/sv.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$d personer + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/uk.lproj/InfoPlist.strings b/ElementX/Resources/Localizations/uk.lproj/InfoPlist.strings index bfb3c8a41b..6825b0489e 100644 --- a/ElementX/Resources/Localizations/uk.lproj/InfoPlist.strings +++ b/ElementX/Resources/Localizations/uk.lproj/InfoPlist.strings @@ -1,5 +1,5 @@ "NSCameraUsageDescription" = "Щоб зробити фото або відео і відправити їх як повідомлення, Element X потрібен доступ до камери."; "NSFaceIDUsageDescription" = "Face ID використовується для доступу до вашого застосунку."; -"NSLocationWhenInUseUsageDescription" = "Надайте доступ до місцезнаходження, щоб Element X міг поділитися вашим місцезнаходженням."; -"NSMicrophoneUsageDescription" = "Щоб записувати та надсилати повідомлення зі звуком, Element X потрібен доступ до мікрофону."; -"NSPhotoLibraryUsageDescription" = "Дозволяє зберігати фотографії та відео у вашій бібліотеці."; +"NSLocationWhenInUseUsageDescription" = "Надайте доступ до місцеперебування, щоб Element X міг поділитися ним."; +"NSMicrophoneUsageDescription" = "Щоб записувати та надсилати повідомлення зі звуком, Element X потрібен доступ до мікрофона."; +"NSPhotoLibraryUsageDescription" = "Дозволяє зберігати світлини та відео у вашій бібліотеці."; diff --git a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings index 09cd368c3e..d4ddc00a79 100644 --- a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings @@ -1,9 +1,9 @@ "Notification" = "Сповіщення"; "a11y_delete" = "Видалити"; -"a11y_hide_password" = "Приховати пароль"; -"a11y_jump_to_bottom" = "Перейти до низу"; +"a11y_hide_password" = "Cховати пароль"; +"a11y_jump_to_bottom" = "Перейти вниз"; "a11y_notifications_mentions_only" = "Тільки згадки"; -"a11y_notifications_muted" = "Приглушений"; +"a11y_notifications_muted" = "Звук вимкнено"; "a11y_page_n" = "Сторінка %1$d"; "a11y_pause" = "Пауза"; "a11y_pin_field" = "Поле PIN-коду"; @@ -17,7 +17,7 @@ "a11y_remove_reaction_with" = "Видалити реакцію з %1$@"; "a11y_send_files" = "Надіслати файли"; "a11y_show_password" = "Показати пароль"; -"a11y_start_call" = "Розпочати дзвінок"; +"a11y_start_call" = "Розпочати виклик"; "a11y_user_menu" = "Меню користувача"; "a11y_voice_message_record" = "Записати голосове повідомлення."; "a11y_voice_message_stop_recording" = "Припинити запис"; @@ -26,21 +26,21 @@ "action_back" = "Назад"; "action_call" = "Зателефонувати"; "action_cancel" = "Скасувати"; -"action_cancel_for_now" = "Cancel for now"; +"action_cancel_for_now" = "Скасувати наразі"; "action_choose_photo" = "Вибрати фото"; "action_clear" = "Очистити"; "action_close" = "Закрити"; "action_complete_verification" = "Верифікація завершена"; "action_confirm" = "Підтвердити"; -"action_confirm_password" = "Confirm password"; +"action_confirm_password" = "Підтвердіть пароль"; "action_continue" = "Продовжити"; "action_copy" = "Скопіювати"; "action_copy_link" = "Скопіювати посилання"; "action_copy_link_to_message" = "Скопіювати посилання на повідомлення"; "action_create" = "Створити"; "action_create_a_room" = "Створити кімнату"; -"action_deactivate" = "Deactivate"; -"action_deactivate_account" = "Deactivate account"; +"action_deactivate" = "Деактивувати"; +"action_deactivate_account" = "Деактивувати обліковий запис"; "action_decline" = "Відхилити"; "action_delete_poll" = "Видалити опитування"; "action_disable" = "Вимкнути"; @@ -54,14 +54,14 @@ "action_forgot_password" = "Забули пароль?"; "action_forward" = "Переслати"; "action_go_back" = "Повернутися"; -"action_ignore" = "Ignore"; +"action_ignore" = "Ігнорувати"; "action_invite" = "Запросити"; "action_invite_friends" = "Запросити людей"; "action_invite_friends_to_app" = "Запросити людей до %1$@"; "action_invite_people_to_app" = "Запросити людей в %1$@"; "action_invites_list" = "Запрошення"; "action_join" = "Доєднатися"; -"action_learn_more" = "Дізнатися більше"; +"action_learn_more" = "Докладніше"; "action_leave" = "Вийти"; "action_leave_conversation" = "Залишити розмову"; "action_leave_room" = "Вийти з кімнати"; @@ -94,29 +94,29 @@ "action_send" = "Надіслати"; "action_send_message" = "Надіслати повідомлення"; "action_share" = "Поділитися"; -"action_share_link" = "Поширити посилання"; -"action_show" = "Show"; +"action_share_link" = "Поділитися посиланням"; +"action_show" = "Показати"; "action_sign_in_again" = "Увійдіть знову"; "action_signout" = "Вийти"; "action_signout_anyway" = "Все одно вийти"; "action_skip" = "Пропустити"; "action_start" = "Розпочати"; -"action_start_chat" = "Почати чат"; +"action_start_chat" = "Розпочати бесіду"; "action_start_verification" = "Почати верифікацію"; "action_static_map_load" = "Натисніть, щоб завантажити мапу"; "action_take_photo" = "Зробити фото"; -"action_tap_for_options" = "Натисніть, щоб переглянути параметри"; +"action_tap_for_options" = "Торкніться, щоб переглянути параметри"; "action_try_again" = "Спробуйте ще раз"; "action_unpin" = "Відкріпити"; -"action_view_in_timeline" = "View in timeline"; +"action_view_in_timeline" = "Переглянути на шкалі часу"; "action_view_source" = "Переглянути джерело"; "action_yes" = "Так"; -"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."; -"banner_migrate_to_native_sliding_sync_title" = "Upgrade available"; -"banner_set_up_recovery_content" = "Recover your cryptographic identity and message history with a recovery key if you have lost all your existing devices."; -"banner_set_up_recovery_title" = "Set up recovery to protect your account"; +"banner_migrate_to_native_sliding_sync_action" = "Вийти та оновити"; +"banner_migrate_to_native_sliding_sync_description" = "Ваш сервер тепер підтримує новий, швидший протокол. Вийдіть із системи та увійдіть знову, щоб оновити систему зараз. Якщо ви зробите це зараз, це допоможе вам уникнути примусового виходу з системи, коли старий протокол буде видалено пізніше."; +"banner_migrate_to_native_sliding_sync_force_logout_title" = "Ваш домашній сервер більше не підтримує старий протокол. Будь ласка, вийдіть і увійдіть знову, щоб продовжити використання програми."; +"banner_migrate_to_native_sliding_sync_title" = "Доступне оновлення"; +"banner_set_up_recovery_content" = "Відновіть свою криптографічну ідентичність та історію повідомлень за допомогою ключа відновлення, якщо ви втратили всі наявні пристрої."; +"banner_set_up_recovery_title" = "Налаштуйте відновлення для захисту свого облікового запису"; "common_about" = "Відомості"; "common_acceptable_use_policy" = "Політика прийнятного використання"; "common_advanced_settings" = "Додаткові налаштування"; @@ -125,32 +125,31 @@ "common_audio" = "Аудіо"; "common_blocked_users" = "Заблоковані користувачі"; "common_bubbles" = "Бульбашки"; -"common_call_invite" = "Триває виклик (не підтримується)"; -"common_call_started" = "Дзвінок розпочато"; -"common_chat_backup" = "Резервне копіювання чату"; +"common_call_started" = "Виклик розпочато"; +"common_chat_backup" = "Резервне копіювання бесіди"; "common_copyright" = "Авторське право"; "common_creating_room" = "Створення кімнати..."; -"common_current_user_left_room" = "Вийшов (-ла) з кімнати"; +"common_current_user_left_room" = "Виходить з кімнати"; "common_dark" = "Темна"; -"common_decryption_error" = "Помилка розшифровки"; +"common_decryption_error" = "Помилка розшифрування"; "common_developer_options" = "Налаштування розробника"; -"common_device_id" = "Device ID"; -"common_direct_chat" = "Особистий чат"; +"common_device_id" = "Ідентифікатор пристрою"; +"common_direct_chat" = "Особиста бесіда"; "common_edited_suffix" = "(відредаговано)"; "common_editing" = "Редагування"; "common_emote" = "* %1$@ %2$@"; -"common_encryption" = "Encryption"; +"common_encryption" = "Шифрування"; "common_encryption_enabled" = "Шифрування ввімкнено"; "common_enter_your_pin" = "Введіть свій PIN-код"; "common_error" = "Помилка"; "common_everyone" = "Усі"; "common_face_id_ios" = "Face ID"; -"common_failed" = "Невдало"; -"common_favourite" = "Улюблений"; -"common_favourited" = "Вибране"; +"common_failed" = "Помилка"; +"common_favourite" = "Обране"; +"common_favourited" = "Обране"; "common_file" = "Файл"; "common_forward_message" = "Переслати повідомлення"; -"common_frequently_used" = "Frequently used"; +"common_frequently_used" = "Частовживані"; "common_gif" = "GIF"; "common_image" = "Зображення"; "common_in_reply_to" = "У відповідь на %1$@"; @@ -195,12 +194,12 @@ "common_saved_changes" = "Збережені зміни"; "common_saving" = "Збереження"; "common_screen_lock" = "Блокування екрану"; -"common_search_for_someone" = "Пошук когось"; +"common_search_for_someone" = "Шукати когось"; "common_search_results" = "Результати пошуку"; "common_security" = "Безпека"; -"common_seen_by" = "Побачили"; +"common_seen_by" = "Переглянули"; "common_sending" = "Надсилання…"; -"common_sending_failed" = "Не вдалося відправити"; +"common_sending_failed" = "Не вдалося надіслати"; "common_sent" = "Надіслано"; "common_server_not_supported" = "Сервер не підтримується"; "common_server_url" = "URL-адреса сервера"; @@ -208,7 +207,7 @@ "common_shared_location" = "Поширене розташування"; "common_signing_out" = "Вихід"; "common_something_went_wrong" = "Щось пішло не так"; -"common_starting_chat" = "Початок чату..."; +"common_starting_chat" = "Початок бесіди..."; "common_sticker" = "Наліпка"; "common_success" = "Успіх"; "common_suggestions" = "Пропозиції"; @@ -226,42 +225,43 @@ "common_unable_to_invite_title" = "Не вдалося надіслати запрошення"; "common_unlock" = "Розблокувати"; "common_unmute" = "Увімкнути звук"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Непідтримувана подія"; "common_username" = "Ім'я користувача"; "common_verification_cancelled" = "Верифікацію скасовано"; "common_verification_complete" = "Верифікацію завершено"; -"common_verification_failed" = "Verification failed"; -"common_verified" = "Verified"; -"common_verify_device" = "Перевірте пристрій"; -"common_verify_identity" = "Verify identity"; +"common_verification_failed" = "Перевірка не вдалася"; +"common_verified" = "Перевірено"; +"common_verify_device" = "Верифікувати пристрій"; +"common_verify_identity" = "Підтвердити особу"; "common_video" = "Відео"; "common_voice_message" = "Голосове повідомлення"; "common_waiting" = "Очікування..."; "common_waiting_for_decryption_key" = "Чекаємо на це повідомлення"; -"common.copied_to_clipboard" = "Copied to clipboard"; +"common.copied_to_clipboard" = "Скопійовано до буферу обміну"; "common.do_not_show_this_again" = "Не показувати це знову"; "common.open_source_licenses" = "Ліцензії відкритого коду"; -"common.pinned" = "Pinned"; +"common.pinned" = "Закріплено"; "common.send_to" = "Надіслати до"; -"common.you" = "You"; -"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" = "Ваша резервна копія чату наразі не синхронізована. Вам потрібно підтвердити ключ відновлення, щоб зберегти доступ до резервної копії чату."; -"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" = "Підтвердіть ключ відновлення"; -"crash_detection_dialog_content" = "%1$@ аварійно завершив роботу під час останнього використання. Бажаєте поділитися з нами звітом про збій?"; -"crypto_identity_change_pin_violation" = "%1$@'s identity appears to have changed. %2$@"; -"crypto_identity_change_pin_violation_new" = "%1$@’s %2$@ identity appears to have changed. %3$@"; +"common.you" = "Ви"; +"common_unable_to_decrypt_insecure_device" = "Надіслано з незахищеного пристрою"; +"common_unable_to_decrypt_verification_violation" = "Підтверджена особа відправника змінилася"; +"confirm_recovery_key_banner_message" = "Підтвердіть свій ключ відновлення, щоб мати доступ до сховища ключів та історії повідомлень."; +"confirm_recovery_key_banner_primary_button_title" = "Введіть ключ відновлення"; +"confirm_recovery_key_banner_secondary_button_title" = "Забули ключ відновлення?"; +"confirm_recovery_key_banner_title" = "Ваше сховище ключів не синхронізовано"; +"crash_detection_dialog_content" = "Стався збій %1$@ під час останнього користування. Хочете поділитися з нами звітом про збій?"; +"crypto_identity_change_pin_violation" = "Ідентичність %1$@, схоже, змінилася. %2$@"; +"crypto_identity_change_pin_violation_new" = "Ідентичність %1$@ %2$@ схоже, змінилася. %3$@"; "crypto_identity_change_pin_violation_new_user_id" = "(%1$@)"; -"dialog_permission_camera" = "Для того, щоб дозволити програмі використовувати камеру, надайте дозвіл у системних налаштуваннях."; -"dialog_permission_generic" = "Будь ласка, надайте дозвіл в системних налаштуваннях."; +"dialog_permission_camera" = "Щоб дозволити застосунку використовувати камеру, надайте дозвіл у системних налаштуваннях."; +"dialog_permission_generic" = "Надайте дозвіл в системних налаштуваннях."; "dialog_permission_location_description_ios" = "Надайте доступ в Налаштуваннях -> Місцезнаходження."; -"dialog_permission_location_title_ios" = "%1$@ не має доступу до вашого місцезнаходження."; -"dialog_permission_microphone" = "Для того, щоб дозволити програмі використовувати мікрофон, надайте дозвіл у налаштуваннях системи."; +"dialog_permission_location_title_ios" = "%1$@ не має доступу до вашого розташування."; +"dialog_permission_microphone" = "Щоб дозволити застосунку використовувати мікрофон, надайте дозвіл у налаштуваннях системи."; "dialog_permission_microphone_description_ios" = "Надайте доступ, щоб ви могли записувати та надсилати повідомлення з аудіо."; "dialog_permission_microphone_title_ios" = "%1$@ потрібен дозвіл на доступ до мікрофона."; -"dialog_permission_notification" = "Для того, щоб програма відображала сповіщення, надайте дозвіл у налаштуваннях системи."; +"dialog_permission_notification" = "Щоб застосунок показував сповіщення, надайте дозвіл у налаштуваннях системи."; "dialog_title_confirmation" = "Підтвердження"; "dialog_title_warning" = "Попередження"; "dialog_unsaved_changes_description_ios" = "Внесені зміни не буде збережено"; @@ -274,47 +274,47 @@ "emoji_picker_category_people" = "Смайлики та люди"; "emoji_picker_category_places" = "Подорожі та місця"; "emoji_picker_category_symbols" = "Символи"; -"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; +"error_account_creation_not_possible" = "Ваш домашній сервер потрібно оновити, щоб він підтримував службу автентифікації Matrix і створення облікових записів."; "error_failed_creating_the_permalink" = "Не вдалося створити постійне посилання"; -"error_failed_loading_map" = "%1$@ Не вдалося завантажити карту. Будь ласка, спробуйте ще раз пізніше."; +"error_failed_loading_map" = "%1$@ не може завантажити мапу. Повторіть спробу пізніше."; "error_failed_loading_messages" = "Не вдалося завантажити повідомлення"; -"error_failed_locating_user" = "%1$@ не вдалося отримати доступ до вашого місцезнаходження. Будь ласка, спробуйте ще раз пізніше."; +"error_failed_locating_user" = "%1$@ не вдалося отримати доступ до вашого розташування. Повторіть спробу пізніше."; "error_failed_uploading_voice_message" = "Не вдалося завантажити голосове повідомлення."; "error_message_not_found" = "Повідомлення не знайдено"; "error_no_compatible_app_found" = "Не знайдено сумісного застосунку для виконання цієї дії."; "error_some_messages_have_not_been_sent" = "Деякі повідомлення не були надіслані"; "error_unknown" = "Вибачте, сталася помилка"; "event_shield_reason_authenticity_not_guaranteed" = "Автентичність цього зашифрованого повідомлення не може бути гарантована на цьому пристрої."; -"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; -"event_shield_reason_sent_in_clear" = "Not encrypted."; -"event_shield_reason_unknown_device" = "Зашифрований невідомим або видаленим пристроєм."; -"event_shield_reason_unsigned_device" = "Зашифровано пристроєм, який не підтверджено його власником."; -"event_shield_reason_unverified_identity" = "Зашифровано неперевіреним користувачем."; -"full_screen_intent_banner_message" = "Щоб ніколи не пропустити важливий дзвінок, змініть налаштування, щоб увімкнути повноекранні сповіщення, коли телефон заблоковано."; -"full_screen_intent_banner_title" = "Enhance your call experience"; +"event_shield_reason_previously_verified" = "Зашифровано попередньо перевіреним користувачем."; +"event_shield_reason_sent_in_clear" = "Не зашифровано."; +"event_shield_reason_unknown_device" = "Зашифровано невідомим або видаленим пристроєм."; +"event_shield_reason_unsigned_device" = "Зашифровано пристроєм, який не верифіковано його власником."; +"event_shield_reason_unverified_identity" = "Зашифровано неверифікованим користувачем."; +"full_screen_intent_banner_message" = "Щоб ніколи не пропустити важливий виклик, змініть налаштування, щоб увімкнути повноекранні сповіщення, коли телефон заблоковано."; +"full_screen_intent_banner_title" = "Покращуйте досвід дзвінків"; "invite_friends_rich_title" = "🔐️ Приєднуйтеся до мене в %1$@"; -"invite_friends_text" = "Привіт, пишіть мені за адресою %1$@: %2$@"; -"leave_conversation_alert_subtitle" = "Ви впевнені, що хочете залишити цю розмову? Ця розмова не є загальнодоступною, і ви не зможете знову приєднатися без запрошення."; -"leave_room_alert_empty_subtitle" = "Ви впевнені, що хочете вийти з цієї кімнати? Ви тут єдина людина. Якщо Ви вийдете, ніхто в майбутньому не зможе приєднатися, у тому числі і Ви."; -"leave_room_alert_private_subtitle" = "Ви впевнені, що хочете вийти з цієї кімнати? Ця кімната не є публічною, і ви не зможете повернутися до неї без запрошення."; +"invite_friends_text" = "Вітаю, поспілкуйтеся зі мною в %1$@: %2$@"; +"leave_conversation_alert_subtitle" = "Ви впевнені, що хочете залишити цю розмову? Ця розмова не загальнодоступна, і ви не зможете знову приєднатися без запрошення."; +"leave_room_alert_empty_subtitle" = "Ви впевнені, що хочете вийти з цієї кімнати? Ви тут єдина людина. Якщо ви вийдете, ніхто в майбутньому не зможе приєднатися, у тому числі й ви."; +"leave_room_alert_private_subtitle" = "Ви впевнені, що хочете вийти з цієї кімнати? Ця кімната не загальнодоступна, і ви не зможете повернутися до неї без запрошення."; "leave_room_alert_subtitle" = "Ви впевнені, що хочете вийти з кімнати?"; "login_initial_device_name_ios" = "%1$@ iOS"; "notification_channel_call" = "Виклик"; "notification_channel_listening_for_events" = "Прослуховування подій"; "notification_channel_noisy" = "Гучні сповіщення"; -"notification_channel_ringing_calls" = "Дзвінки"; +"notification_channel_ringing_calls" = "Виклики"; "notification_channel_silent" = "Тихі сповіщення"; -"notification_incoming_call" = "Вхідний дзвінок"; -"notification_inline_reply_failed" = "** Не вдалося надіслати - будь ласка, відкрийте кімнату"; -"notification_invite_body" = "Запросив (-ла) Вас до чату"; -"notification_invite_body_with_sender" = "%1$@ invited you to chat"; -"notification_mentioned_you_body" = "Згадав(-ла) вас: %1$@"; +"notification_incoming_call" = "Вхідний виклик"; +"notification_inline_reply_failed" = "** Не вдалося надіслати - відкрийте кімнату"; +"notification_invite_body" = "Запрошує вас до бесіди"; +"notification_invite_body_with_sender" = "%1$@ запросив вас до чату"; +"notification_mentioned_you_body" = "Вас згадує: %1$@"; "notification_new_messages" = "Нові повідомлення"; -"notification_reaction_body" = "Відреагував (-ла) з %1$@"; -"notification_room_invite_body" = "Запросив (-ла) Вас приєднатися до кімнати"; -"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; +"notification_reaction_body" = "Реагує з %1$@"; +"notification_room_invite_body" = "Запрошує вас приєднатися до кімнати"; +"notification_room_invite_body_with_sender" = "%1$@ запросив вас приєднатися до кімнати"; "notification_sender_me" = "Я"; -"notification_sender_mention_reply" = "%1$@ mentioned or replied"; +"notification_sender_mention_reply" = "%1$@ згадували або відповідали"; "notification_test_push_notification_content" = "Ви переглядаєте сповіщення! Натисніть тут!"; "notification_ticker_text_dm" = "%1$@: %2$@"; "notification_ticker_text_group" = "%1$@: %2$@ %3$@"; @@ -344,48 +344,54 @@ "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" = "Необов'язковий підпис..."; "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" = "Неправильна URL-адреса, будь ласка, переконайтеся, що ви вказали протокол (http/https) та правильну адресу."; -"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_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; -"screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; -"screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; -"screen_resolve_send_failure_changed_identity_primary_button_title" = "Withdraw verification and send"; -"screen_resolve_send_failure_changed_identity_subtitle" = "You can withdraw your verification and send this message anyway, or you can cancel for now and try again later after reverifying %1$@."; -"screen_resolve_send_failure_changed_identity_title" = "Your message was not sent because %1$@’s verified identity has changed"; -"screen_resolve_send_failure_unsigned_device_primary_button_title" = "Send message anyway"; -"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$@ has verified all their devices."; -"screen_resolve_send_failure_unsigned_device_title" = "Your message was not sent because %1$@ has not verified all devices"; -"screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; -"screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; -"screen_room_mentions_at_room_subtitle" = "Сповістіть усю кімнату"; +"screen_advanced_settings_element_call_base_url_validation_error" = "Неправильна URL-адреса. Переконайтеся, що ви вказали протокол (http/https) та правильну адресу."; +"screen_create_room_room_access_section_anyone_option_description" = "Будь-хто може приєднатися до цієї кімнати"; +"screen_create_room_room_access_section_anyone_option_title" = "Кожний"; +"screen_create_room_room_access_section_header" = "Доступ до кімнати"; +"screen_create_room_room_access_section_knocking_option_description" = "Будь-хто може попросити приєднатися до кімнати, але адміністратор або модератор повинен буде прийняти запит"; +"screen_create_room_room_access_section_knocking_option_title" = "Запросити приєднатися"; +"screen_create_room_room_address_invalid_symbols_error_description" = "Деякі символи не допускаються. Підтримуються тільки букви, цифри і наступні символи! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Ця адреса кімнати вже існує, будь ласка, спробуйте відредагувати поле адреси кімнати або змінити назву кімнати"; +"screen_create_room_room_address_section_footer" = "Щоб цю кімнату було видно в каталозі загальнодоступних кімнат, вам знадобиться її адреса."; +"screen_create_room_room_address_section_title" = "Адреса кімнати"; +"screen_create_room_room_visibility_section_title" = "Видимість кімнати"; +"screen_join_room_cancel_knock_action" = "Скасувати запит"; +"screen_join_room_cancel_knock_alert_confirmation" = "Так, скасувати"; +"screen_join_room_cancel_knock_alert_description" = "Ви впевнені, що бажаєте скасувати свій запит на приєднання до цієї кімнати?"; +"screen_join_room_cancel_knock_alert_title" = "Скасувати запит на приєднання"; +"screen_join_room_knock_message_description" = "Повідомлення (необов'язково)"; +"screen_join_room_knock_sent_description" = "Ви отримаєте запрошення приєднатися до кімнати, якщо ваш запит буде прийнятий."; +"screen_join_room_knock_sent_title" = "Запит на приєднання надіслано"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_pinned_timeline_empty_state_description" = "Натисніть на повідомлення і виберіть \"%1$@\", щоб додати його сюди."; +"screen_pinned_timeline_empty_state_headline" = "Закріпіть важливі повідомлення, щоб їх можна було легко знайти"; +"screen_reset_encryption_password_error" = "Сталася невідома помилка. Будь ласка, перевірте правильність пароля свого облікового запису та повторіть спробу."; +"screen_resolve_send_failure_changed_identity_primary_button_title" = "Відкликати верифікацію та відправити"; +"screen_resolve_send_failure_changed_identity_subtitle" = "Ви все одно можете відкликати підтвердження та надіслати це повідомлення, або ви можете скасувати підписку на даний момент і спробувати пізніше після повторної перевірки %1$@."; +"screen_resolve_send_failure_changed_identity_title" = "Ваше повідомлення не було надіслано, оскільки підтверджена особистість %1$@ змінилася"; +"screen_resolve_send_failure_unsigned_device_primary_button_title" = "Надіслати повідомлення в будь-якому випадку"; +"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ використовує один або кілька неперевірених пристроїв. Ви можете відправити повідомлення в будь-якому випадку, або ж скасувати відправку і спробувати пізніше, коли %2$@ перевірить всі пристрої."; +"screen_resolve_send_failure_unsigned_device_title" = "Ваше повідомлення не було надіслано, тому що %1$@ не перевірив усі пристрої"; +"screen_resolve_send_failure_you_unsigned_device_subtitle" = "Один або кілька ваших пристроїв не підтверджено. Ви можете відправити повідомлення в будь-якому випадку, або ж скасувати відправку і спробувати пізніше, коли перевірите всі свої пристрої."; +"screen_resolve_send_failure_you_unsigned_device_title" = "Ваше повідомлення не було надіслано, оскільки ви не підтвердили один або декілька своїх пристроїв"; +"screen_room_mentions_at_room_subtitle" = "Сповістити всю кімнату"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ із %2$@"; -"screen_room_pinned_banner_indicator_description" = "%1$@ Закріплених повідомлень"; -"screen_room_pinned_banner_loading_description" = "Loading message…"; +"screen_room_pinned_banner_indicator_description" = "%1$@ закріплених повідомлень"; +"screen_room_pinned_banner_loading_description" = "Завантаження повідомлення…"; "screen_room_pinned_banner_view_all_button_title" = "Переглянути всі"; -"screen_room_details_pinned_events_row_title" = "Pinned messages"; -"screen_roomlist_knock_event_sent_description" = "Request to join sent"; -"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."; +"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_details_pinned_events_row_title" = "Закріплені повідомлення"; +"screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_roomlist_knock_event_sent_description" = "Запит на приєднання надіслано"; +"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" = "Повідомлення не надіслано, оскільки ви не підтвердили один або кілька своїх пристроїв."; "screen_account_provider_form_hint" = "Адреса домашнього сервера"; "screen_account_provider_form_notice" = "Уведіть пошуковий термін або адресу домену."; "screen_account_provider_form_subtitle" = "Пошук компанії, спільноти або приватного сервера."; @@ -394,25 +400,25 @@ "screen_account_provider_signup_title" = "Ви збираєтеся створити обліковий запис на %@"; "screen_advanced_settings_developer_mode" = "Режим розробника"; "screen_advanced_settings_developer_mode_description" = "Увімкніть доступ до функцій і можливостей для розробників."; -"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" = "Швидше завантажуйте фотографії та відео та зменшуйте використання даних"; +"screen_advanced_settings_media_compression_title" = "Оптимізуйте медіаякість"; "screen_advanced_settings_rich_text_editor_description" = "Вимкніть редактор розширеного тексту, щоб вводити Markdown вручну."; "screen_advanced_settings_send_read_receipts" = "Читати журнали"; "screen_advanced_settings_send_read_receipts_description" = "Якщо вимкнено, ваші сповіщення про прочитання нікому не надсилатимуться. Ви все одно отримуватимете сповіщення про прочитання від інших користувачів."; "screen_advanced_settings_share_presence" = "Поділіться присутністю"; -"screen_advanced_settings_share_presence_description" = "Якщо вимкнено, ви не зможете надсилати та отримувати сповіщення про прочитання або введення тексту"; +"screen_advanced_settings_share_presence_description" = "Якщо цей параметр вимкнено, ви не зможете надсилати й отримувати звіти про прочитання чи сповіщення про введення тексту."; "screen_advanced_settings_view_source_description" = "Увімкнути опцію для перегляду коду повідомлення в стрічці"; "screen_analytics_prompt_data_usage" = "Ми не записуватимемо та не профілюватимемо жодні персональні дані"; "screen_analytics_prompt_help_us_improve" = "Ділитися анонімними даними про використання, щоб допомогати нам виявляти проблеми."; "screen_analytics_prompt_read_terms" = "Ви можете прочитати всі наші умови %1$@."; "screen_analytics_prompt_read_terms_content_link" = "тут"; "screen_analytics_prompt_settings" = "Ви можете вимкнути цю функцію в будь-який час"; -"screen_analytics_prompt_third_party_sharing" = "Ми не передаватимемо Ваші дані третім особам"; -"screen_analytics_prompt_title" = "Допоможіть покращити %1$@"; +"screen_analytics_prompt_third_party_sharing" = "Ми не передаватимемо ваші дані третім особам"; +"screen_analytics_prompt_title" = "Допоможіть вдосконалити %1$@"; "screen_analytics_settings_share_data" = "Поділитися аналітичними даними"; -"screen_app_lock_biometric_authentication" = "біометрична аутентифікація"; +"screen_app_lock_biometric_authentication" = "біометрична автентифікація"; "screen_app_lock_biometric_unlock" = "біометричне розблокування"; -"screen_app_lock_biometric_unlock_reason_ios" = "Для доступу до застосунку потрібна аутентифікація"; +"screen_app_lock_biometric_unlock_reason_ios" = "Для доступу до застосунку потрібно автентифікуватися"; "screen_app_lock_forgot_pin" = "Забули PIN-код?"; "screen_app_lock_settings_change_pin" = "Змінити PIN-код"; "screen_app_lock_settings_enable_biometric_unlock" = "Дозволити біометричне розблокування"; @@ -423,55 +429,55 @@ "screen_app_lock_settings_remove_pin_alert_message" = "Ви впевнені, що хочете видалити PIN-код?"; "screen_app_lock_settings_remove_pin_alert_title" = "Видалити PIN-код?"; "screen_app_lock_setup_biometric_unlock_allow_title" = "Дозволити %1$@"; -"screen_app_lock_setup_biometric_unlock_skip" = "Я б краще використав PIN-код"; +"screen_app_lock_setup_biometric_unlock_skip" = "Мені краще використати PIN-код"; "screen_app_lock_setup_biometric_unlock_subtitle" = "Заощаджуйте час і використовуйте %1$@ для розблокування застосунку щоразу"; "screen_app_lock_setup_choose_pin" = "Виберіть PIN-код"; "screen_app_lock_setup_confirm_pin" = "Підтвердити PIN-код"; "screen_app_lock_setup_pin_context" = "Заблокуйте %1$@, щоб додати додаткову безпеку вашим чатам.\n\nВиберіть щось, що запам'ятовується. Але якщо ви забудете PIN-код, ви вийдете з застосунку."; -"screen_app_lock_setup_pin_forbidden_dialog_content" = "Ви не можете вибрати його як свій PIN-код з міркувань безпеки"; +"screen_app_lock_setup_pin_forbidden_dialog_content" = "Ви не можете вибрати його своїм PIN-кодом з міркувань безпеки"; "screen_app_lock_setup_pin_forbidden_dialog_title" = "Виберіть інший PIN-код"; "screen_app_lock_setup_pin_mismatch_dialog_content" = "Будь ласка, введіть один і той самий PIN-код двічі"; "screen_app_lock_setup_pin_mismatch_dialog_title" = "PIN-коди не збігаються"; -"screen_app_lock_signout_alert_message" = "Щоб продовжити, вам потрібно буде повторно увійти та створити новий PIN-код"; +"screen_app_lock_signout_alert_message" = "Щоб продовжити, вам потрібно повторно ввійти та створити новий PIN-код"; "screen_app_lock_signout_alert_title" = "Ви виходите з системи"; "screen_blocked_users_empty" = "У вас немає заблокованих користувачів."; "screen_blocked_users_unblocking" = "Розблокування…"; -"screen_bug_report_attach_screenshot" = "Прикріпити знімок екрану"; +"screen_bug_report_attach_screenshot" = "Прикріпити знімок екрана"; "screen_bug_report_contact_me" = "Ви можете зв'язатися зі мною, якщо у вас виникнуть додаткові запитання."; "screen_bug_report_contact_me_title" = "Звʼязатися зі мною"; -"screen_bug_report_edit_screenshot" = "Редагувати знімок екрану"; -"screen_bug_report_editor_description" = "Опишіть, будь ласка, проблему. Що Ви зробили? Чого Ви очікували? Що сталося? Будь ласка, опишіть якомога детальніше."; +"screen_bug_report_edit_screenshot" = "Редагувати знімок екрана"; +"screen_bug_report_editor_description" = "Будь ласка, опишіть проблему. Які дії ви виконали? Який очікуваний результат? Що сталося? Будь ласка, опишіть якомога детальніше."; "screen_bug_report_editor_placeholder" = "Опишіть проблему..."; "screen_bug_report_editor_supporting" = "Якщо можливо, будь ласка, напишіть опис англійською мовою."; -"screen_bug_report_error_description_too_short" = "Опис занадто короткий, будь ласка, надайте докладнішу інформацію про те, що сталося. Дякую!"; +"screen_bug_report_error_description_too_short" = "Опис закороткий, будь ласка, надайте докладнішу інформацію про те, що сталося. Дякуємо!"; "screen_bug_report_include_crash_logs" = "Надіслати журнали збоїв"; "screen_bug_report_include_logs" = "Дозволити журнали"; "screen_bug_report_include_screenshot" = "Надіслати знімок екрана"; "screen_bug_report_logs_description" = "Журнали будуть додані до вашого повідомлення, щоб переконатися, що все працює належним чином. Щоб надіслати повідомлення без журналів, вимкніть це налаштування."; "screen_bug_report_view_logs" = "Переглянути журнали"; -"screen_change_account_provider_matrix_org_subtitle" = "Matrix.org — це великий безплатний сервер у загальнодоступній мережі Matrix для безпечного децентралізованого зв’язку, яким керує Matrix.org Foundation."; +"screen_change_account_provider_matrix_org_subtitle" = "Matrix.org — це великий безплатний сервер у загальнодоступній мережі Matrix для безпечного децентралізованого спілкування, яким керує Matrix.org Foundation."; "screen_change_account_provider_other" = "Інше"; "screen_change_account_provider_subtitle" = "Використати іншого провайдера облікових записів, наприклад, власний приватний сервер або робочий обліковий запис."; "screen_change_account_provider_title" = "Змінити провайдера облікового запису"; -"screen_change_server_error_invalid_homeserver" = "Не вдалося підключитися до цього домашнього сервера. Будь ласка, перевірте, чи правильно Ви ввели URL-адресу домашнього сервера. Якщо URL-адреса правильна, зверніться за додатковою допомогою до адміністратора домашнього сервера."; -"screen_change_server_error_invalid_well_known" = "Sliding sync недоступний через проблему у well-known файлі:\n%1$@"; +"screen_change_server_error_invalid_homeserver" = "Не вдалося під'єднатися до цього домашнього сервера. Перевірте правильність введеної URL-адреси домашнього сервера. Якщо URL-адреса правильна, зверніться по додаткову допомогу до адміністратора домашнього сервера."; +"screen_change_server_error_invalid_well_known" = "Sliding sync недоступний через проблему у файлі well-known:\n%1$@"; "screen_change_server_error_no_sliding_sync_message" = "Наразі цей сервер не підтримує sliding sync."; "screen_change_server_form_header" = "URL-адреса домашнього сервера"; -"screen_change_server_form_notice" = "Ви можете підключитися лише до наявного сервера, який підтримує sliding sync. Ваш адміністратор домашнього сервера повинен буде налаштувати його. %1$@"; -"screen_change_server_subtitle" = "Яка адреса Вашого сервера?"; +"screen_change_server_form_notice" = "Ви можете під'єднатися лише до наявного сервера, який підтримує sliding sync. Адміністратор вашого домашнього сервера повинен буде налаштувати його. %1$@"; +"screen_change_server_subtitle" = "Яка адреса вашого сервера?"; "screen_change_server_title" = "Виберіть свій сервер"; "screen_chat_backup_key_backup_action_disable" = "Вимкнути резервне копіювання"; "screen_chat_backup_key_backup_action_enable" = "Увімкнути резервне копіювання"; -"screen_chat_backup_key_backup_description" = "Резервне копіювання гарантує, що ви не втратите історію повідомлень. %1$@."; +"screen_chat_backup_key_backup_description" = "Зберігайте свій криптографічний ідентифікатор і ключі повідомлень на сервері. Це дозволить вам переглядати історію повідомлень на будь-яких нових пристроях. %1$@."; "screen_chat_backup_key_backup_title" = "Резервне копіювання"; -"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_storage_disabled_error" = "Щоб налаштувати відновлення, потрібно ввімкнути зберігання ключів."; +"screen_chat_backup_key_storage_toggle_description" = "Завантажте ключі з цього пристрою"; +"screen_chat_backup_key_storage_toggle_title" = "Дозволити зберігання ключів"; "screen_chat_backup_recovery_action_change" = "Змінити ключ відновлення"; -"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" = "Ваша резервна копія чату наразі не синхронізована."; -"screen_chat_backup_recovery_action_setup_description" = "Отримайте доступ до своїх зашифрованих повідомлень, якщо ви втратите всі свої пристрої або вийшли з %1$@ системи."; -"screen_create_account_title" = "Create account"; +"screen_chat_backup_recovery_action_change_description" = "Відновіть криптографічну ідентичність та історію повідомлень за допомогою ключа відновлення, якщо ви втратили всі наявні пристрої."; +"screen_chat_backup_recovery_action_confirm_description" = "Сховище ключів наразі не синхронізовано."; +"screen_chat_backup_recovery_action_setup_description" = "Отримайте доступ до своїх зашифрованих повідомлень, якщо ви втратите всі свої пристрої або вийшли з %1$@ на всіх пристроях."; +"screen_create_account_title" = "Створити обліковий запис"; "screen_create_new_recovery_key_list_item_1" = "Відкрийте %1$@ на комп'ютері"; "screen_create_new_recovery_key_list_item_2" = "Увійдіть до вашого облікового запису знову"; "screen_create_new_recovery_key_list_item_3" = "Коли вас попросять підтвердити пристрій, виберіть %1$@"; @@ -489,53 +495,53 @@ "screen_create_poll_title" = "Створити опитування"; "screen_create_room_action_create_room" = "Нова кімната"; "screen_create_room_error_creating_room" = "Під час створення кімнати сталася помилка"; -"screen_create_room_private_option_description" = "Повідомлення в цій кімнаті зашифровані. Пізніше шифрування вимкнути не можна."; +"screen_create_room_private_option_description" = "Лише запрошені люди мають доступ до цієї кімнати. Усі повідомлення захищені наскрізним шифруванням."; "screen_create_room_private_option_title" = "Приватна кімната (тільки за запрошенням)"; -"screen_create_room_public_option_description" = "Повідомлення не шифруються, і будь-хто може їх прочитати. Шифрування можна ввімкнути пізніше."; -"screen_create_room_public_option_title" = "Загальна кімната (будь-хто)"; +"screen_create_room_public_option_description" = "Будь-хто може знайти цю кімнату. \nВи можете змінити це в будь-який час у налаштуваннях кімнати."; +"screen_create_room_public_option_title" = "Публічна кімната"; "screen_create_room_topic_label" = "Тема (необов'язково)"; -"screen_deactivate_account_confirmation_dialog_content" = "Please confirm that you want to deactivate your account. This action cannot be undone."; -"screen_deactivate_account_delete_all_messages" = "Delete all my messages"; -"screen_deactivate_account_delete_all_messages_notice" = "Warning: Future users may see incomplete conversations."; -"screen_deactivate_account_description" = "Deactivating your account is %1$@, it will:"; -"screen_deactivate_account_description_bold_part" = "irreversible"; -"screen_deactivate_account_list_item_1" = "%1$@ your account (you can't log back in, and your ID can't be reused)."; -"screen_deactivate_account_list_item_1_bold_part" = "Permanently disable"; -"screen_deactivate_account_list_item_2" = "Remove you from all chat rooms."; -"screen_deactivate_account_list_item_3" = "Delete your account information from our identity server."; -"screen_deactivate_account_list_item_4" = "Your messages will still be visible to registered users but won’t be available to new or unregistered users if you choose to delete them."; -"screen_deactivate_account_title" = "Deactivate account"; +"screen_deactivate_account_confirmation_dialog_content" = "Будь ласка, підтвердіть, що ви хочете деактивувати свій обліковий запис. Ця дія не може бути скасована."; +"screen_deactivate_account_delete_all_messages" = "Видалити всі мої повідомлення"; +"screen_deactivate_account_delete_all_messages_notice" = "Попередження: майбутні користувачі можуть бачити неповні розмови."; +"screen_deactivate_account_description" = "Деактивація вашого облікового запису%1$@ , це буде:"; +"screen_deactivate_account_description_bold_part" = "незворотні"; +"screen_deactivate_account_list_item_1" = "%1$@ваш обліковий запис (ви не можете знову увійти, а ваш ідентифікатор не може бути використаний повторно)."; +"screen_deactivate_account_list_item_1_bold_part" = "Назавжди відключити"; +"screen_deactivate_account_list_item_2" = "Видалити вас з усіх чатів."; +"screen_deactivate_account_list_item_3" = "Видаліть інформацію свого облікового запису з нашого сервера ідентифікації."; +"screen_deactivate_account_list_item_4" = "Ваші повідомлення залишатимуться видимими для зареєстрованих користувачів, але недоступними для нових або незареєстрованих користувачів, якщо ви вирішите їх видалити."; +"screen_deactivate_account_title" = "Відключити обліковий запис"; "screen_edit_poll_delete_confirmation" = "Ви впевнені, що хочете видалити це опитування?"; -"screen_edit_profile_display_name" = "Відображуване ім'я"; -"screen_edit_profile_display_name_placeholder" = "Ваше відображуване ім'я"; -"screen_edit_profile_error" = "Була виявлена невідома помилка, і інформацію не вдалося змінити."; +"screen_edit_profile_display_name" = "Показуване ім'я"; +"screen_edit_profile_display_name_placeholder" = "Ваше показуване ім'я"; +"screen_edit_profile_error" = "Виявлена невідома помилка, і не вдалося змінити інформацію."; "screen_edit_profile_error_title" = "Неможливо оновити профіль"; "screen_edit_profile_title" = "Редагувати профіль"; "screen_edit_profile_updating_details" = "Оновлення профілю..."; -"screen_encryption_reset_action_continue_reset" = "Continue reset"; -"screen_encryption_reset_bullet_1" = "Дані вашого облікового запису, контакти, налаштування й чати будуть збережені"; +"screen_encryption_reset_action_continue_reset" = "Продовжити скидання налаштувань"; +"screen_encryption_reset_bullet_1" = "Дані вашого облікового запису, контакти, налаштування й бесіди будуть збережені"; "screen_encryption_reset_bullet_2" = "Ви втратите свою наявну історію повідомлень"; -"screen_encryption_reset_bullet_3" = "Вам доведеться підтвердити всі наявні пристрої та контакти знову"; +"screen_encryption_reset_bullet_3" = "Вам доведеться верифікувати всі наявні пристрої та контакти повторно"; "screen_encryption_reset_footer" = "Скидайте ідентичність тільки якщо ви не маєте доступу до інших пристроїв в обліковому записі та втратили свій ключ відновлення."; -"screen_encryption_reset_title" = "Скиньте свою ідентичність, якщо не можете підтвердити іншим способом"; +"screen_encryption_reset_title" = "Не можете підтвердити? Вам доведеться скинути свою ідентичність."; "screen_identity_confirmation_cannot_confirm" = "Не можете підтвердити?"; "screen_identity_confirmation_create_new_recovery_key" = "Створити новий ключ відновлення"; -"screen_identity_confirmation_subtitle" = "Перевірте цей пристрій, щоб налаштувати безпечний обмін повідомленнями."; -"screen_identity_confirmation_title" = "Підтвердіть, що це ви"; -"screen_identity_confirmation_use_another_device" = "Use another device"; -"screen_identity_confirmation_use_recovery_key" = "Use recovery key"; +"screen_identity_confirmation_subtitle" = "Верифікуйте цей пристрій, щоб налаштувати безпечний обмін повідомленнями."; +"screen_identity_confirmation_title" = "Підтвердьте, що це ви"; +"screen_identity_confirmation_use_another_device" = "Використовуйте інший пристрій"; +"screen_identity_confirmation_use_recovery_key" = "Використовуйте ключ відновлення"; "screen_identity_confirmed_subtitle" = "Тепер ви можете безпечно читати або надсилати повідомлення, і кожен, з ким ви спілкуєтесь, також може довіряти цьому пристрою."; "screen_identity_confirmed_title" = "Пристрій перевірено"; "screen_identity_waiting_on_other_device" = "Чекає на інше пристрій…"; "screen_invites_decline_chat_message" = "Ви впевнені, що хочете відхилити запрошення приєднатися до %1$@?"; "screen_invites_decline_chat_title" = "Відхилити запрошення"; -"screen_invites_decline_direct_chat_message" = "Ви дійсно хочете відмовитися від приватного чату з %1$@?"; -"screen_invites_decline_direct_chat_title" = "Відхилити чат"; +"screen_invites_decline_direct_chat_message" = "Ви дійсно хочете відмовитися від приватної бесіди з %1$@?"; +"screen_invites_decline_direct_chat_title" = "Відхилити бесіду"; "screen_invites_empty_list" = "Немає запрошень"; -"screen_invites_invited_you" = "%1$@ (%2$@) запросив (-ла) Вас"; +"screen_invites_invited_you" = "%1$@ (%2$@) запрошує вас"; "screen_join_room_join_action" = "Приєднатися до кімнати"; "screen_join_room_knock_action" = "Постукати, щоб приєднатися"; -"screen_join_room_space_not_supported_description" = "%1$@ ще не підтримує простори. Ви можете отримати доступ до них в вебверсії."; +"screen_join_room_space_not_supported_description" = "%1$@ ще не підтримує простори. Ви можете отримати доступ до них у вебверсії."; "screen_join_room_space_not_supported_title" = "Простори поки що не підтримуються"; "screen_join_room_subtitle_knock" = "Натисніть кнопку нижче, і адміністратор кімнати отримає сповіщення. Ви зможете приєднатися до розмови після схвалення."; "screen_join_room_subtitle_no_preview" = "Ви мусите бути учасником цієї кімнати, щоб переглядати історію повідомлень."; @@ -551,7 +557,7 @@ "screen_login_error_deactivated_account" = "Цей обліковий запис було деактивовано."; "screen_login_error_invalid_credentials" = "Неправильне ім'я користувача та/або пароль"; "screen_login_error_invalid_user_id" = "Це недійсний ідентифікатор користувача. Очікуваний формат: '@user:homeserver.org'"; -"screen_login_error_refresh_tokens" = "Цей сервер налаштований на використання токенів оновлення. Вони не підтримуються при використанні входу на основі пароля."; +"screen_login_error_refresh_tokens" = "Цей сервер налаштований на використання оновлюваних токенів. Вони не підтримуються, якщо використовується вхід за допомогою основі пароля."; "screen_login_error_unsupported_authentication" = "Обраний домашній сервер не підтримує вхід за допомогою пароля або OIDC. Зверніться до адміністратора або виберіть інший домашній сервер."; "screen_login_form_header" = "Введіть свої дані"; "screen_login_title" = "З поверненням!"; @@ -567,23 +573,23 @@ "screen_notification_settings_calls_label" = "Аудіо та відеодзвінки"; "screen_notification_settings_configuration_mismatch" = "Невідповідність конфігурації"; "screen_notification_settings_configuration_mismatch_description" = "Ми спростили налаштування сповіщень, щоб полегшити пошук параметрів. Деякі користувацькі налаштування, які ви вибрали раніше, тут не відображаються, але вони все ще активні.\n\nЯкщо ви продовжите, деякі з ваших налаштувань можуть змінитися."; -"screen_notification_settings_direct_chats" = "Особисті чати"; -"screen_notification_settings_edit_custom_settings_section_title" = "Користувальницькі налаштування для чату"; +"screen_notification_settings_direct_chats" = "Особисті бесіди"; +"screen_notification_settings_edit_custom_settings_section_title" = "Користувальницькі налаштування бесід"; "screen_notification_settings_edit_failed_updating_default_mode" = "Під час оновлення налаштувань сповіщень сталася помилка."; "screen_notification_settings_edit_mode_all_messages" = "Всі повідомлення"; "screen_notification_settings_edit_mode_mentions_and_keywords" = "Тільки згадки та ключові слова"; -"screen_notification_settings_edit_screen_direct_section_header" = "В особистих чатах сповіщати про"; -"screen_notification_settings_edit_screen_group_section_header" = "У групових чатах повідомляти мене про"; +"screen_notification_settings_edit_screen_direct_section_header" = "В особистих бесідах сповіщати про"; +"screen_notification_settings_edit_screen_group_section_header" = "У групових бесідах сповіщати мене про"; "screen_notification_settings_enable_notifications" = "Увімкнути сповіщення на цьому пристрої"; "screen_notification_settings_failed_fixing_configuration" = "Конфігурацію не виправлено, спробуйте ще раз."; -"screen_notification_settings_group_chats" = "Групові чати"; +"screen_notification_settings_group_chats" = "Групові бесіди"; "screen_notification_settings_invite_for_me_label" = "Запрошення"; "screen_notification_settings_mentions_only_disclaimer" = "Ваш домашній сервер не підтримує цю опцію в зашифрованих кімнатах, ви можете не отримати сповіщення в деяких кімнатах."; "screen_notification_settings_mode_all" = "Усі"; "screen_notification_settings_mode_mentions" = "Згадки"; -"screen_notification_settings_notification_section_title" = "Повідомляти мене про"; +"screen_notification_settings_notification_section_title" = "Сповіщати мене про"; "screen_notification_settings_room_mention_label" = "Сповіщати про @room"; -"screen_notification_settings_system_notifications_action_required" = "Щоб отримувати сповіщення, будь ласка, змініть свої %1$@."; +"screen_notification_settings_system_notifications_action_required" = "Щоб отримувати сповіщення змініть свої %1$@."; "screen_notification_settings_system_notifications_action_required_content_link" = "системні налаштування"; "screen_notification_settings_system_notifications_turned_off" = "Системні сповіщення вимкнені"; "screen_notification_settings_title" = "Сповіщення"; @@ -593,22 +599,22 @@ "screen_onboarding_welcome_message" = "Ласкаво просимо до найшвидшого %1$@. Заряджений для швидкості та простоти."; "screen_onboarding_welcome_subtitle" = "Ласкаво просимо до %1$@. Заряджений, для швидкості та простоти."; "screen_onboarding_welcome_title" = "Будьте у своєму element"; -"screen_polls_history_empty_ongoing" = "Не можу знайти жодних поточних опитувань."; -"screen_polls_history_empty_past" = "Не можу знайти жодних минулих опитувань."; +"screen_polls_history_empty_ongoing" = "Не вдалося знайти жодних поточних опитувань."; +"screen_polls_history_empty_past" = "Не вдалося знайти жодних минулих опитувань."; "screen_polls_history_filter_ongoing" = "Поточні"; "screen_polls_history_filter_past" = "Минулі"; "screen_polls_history_title" = "Опитування"; "screen_qr_code_login_connecting_subtitle" = "Встановлення безпечного з'єднання"; -"screen_qr_code_login_connection_note_secure_state_description" = "Не вдалося встановити безпечне з'єднання з новим пристроєм. Ваші існуючі пристрої все ще в безпеці, і вам не потрібно про них турбуватися."; +"screen_qr_code_login_connection_note_secure_state_description" = "Не вдалося встановити безпечне з'єднання з новим пристроєм. Ваші наявні пристрої досі в безпеці, і вам не потрібно про них турбуватися."; "screen_qr_code_login_connection_note_secure_state_list_header" = "Що тепер?"; "screen_qr_code_login_connection_note_secure_state_list_item_1" = "Спробуйте увійти ще раз за допомогою QR-коду, якщо це була проблема з мережею"; "screen_qr_code_login_connection_note_secure_state_list_item_2" = "Якщо ви зіткнулися з тією ж проблемою, спробуйте іншу мережу Wi-Fi або використовуйте мобільний інтернет замість Wi-Fi"; "screen_qr_code_login_connection_note_secure_state_list_item_3" = "Якщо це не спрацює, увійдіть вручну"; -"screen_qr_code_login_connection_note_secure_state_title" = "З'єднання не є безпечним"; +"screen_qr_code_login_connection_note_secure_state_title" = "З'єднання не безпечне"; "screen_qr_code_login_device_code_subtitle" = "Вас попросять ввести дві цифри, показані на цьому пристрої."; "screen_qr_code_login_device_code_title" = "Введіть номер нижче на іншому пристрої"; -"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Увійдіть на іншому пристрої та спробуйте ще раз або скористайтеся іншим пристроєм, що вже в обліковому записі."; -"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Інший пристрій не ввійшов"; +"screen_qr_code_login_device_not_signed_in_scan_state_description" = "Увійдіть на іншому пристрої та спробуйте ще раз або скористайтеся іншим пристроєм, на якому ви вже ввійшли."; +"screen_qr_code_login_device_not_signed_in_scan_state_subtitle" = "Вхід на іншому пристрої не виконано"; "screen_qr_code_login_error_cancelled_subtitle" = "Вхід було скасовано на іншому пристрої."; "screen_qr_code_login_error_cancelled_title" = "Запит на вхід скасовано"; "screen_qr_code_login_error_declined_subtitle" = "Вхід був відхилений на іншому пристрої."; @@ -622,57 +628,57 @@ "screen_qr_code_login_initial_state_button_title" = "Готовий до сканування"; "screen_qr_code_login_initial_state_item_1" = "Відкрийте %1$@ на комп'ютері"; "screen_qr_code_login_initial_state_item_2" = "Натисніть на свою аватарку"; -"screen_qr_code_login_initial_state_item_3" = "Оберіть %1$@"; -"screen_qr_code_login_initial_state_item_3_action" = "“Підключити новий пристрій”"; -"screen_qr_code_login_initial_state_item_4" = "Відскануйте QR-код цим пристроєм"; -"screen_qr_code_login_initial_state_subtitle" = "Only available if your account provider supports it."; +"screen_qr_code_login_initial_state_item_3" = "Виберіть %1$@"; +"screen_qr_code_login_initial_state_item_3_action" = "“Під'єднати новий пристрій”"; +"screen_qr_code_login_initial_state_item_4" = "Зіскануйте QR-код цим пристроєм"; +"screen_qr_code_login_initial_state_subtitle" = "Доступно лише в тому випадку, якщо ваш постачальник облікового запису підтримує цю функцію."; "screen_qr_code_login_initial_state_title" = "Відкрийте %1$@ на іншому пристрої, щоб отримати QR-код"; "screen_qr_code_login_invalid_scan_state_description" = "Використовуйте QR-код, показаний на іншому пристрої."; "screen_qr_code_login_invalid_scan_state_subtitle" = "Неправильний QR-код"; "screen_qr_code_login_no_camera_permission_button" = "Перейти до налаштувань камери"; "screen_qr_code_login_no_camera_permission_state_description" = "Вам потрібно дати дозвіл %1$@ на використання камери вашого пристрою, щоб продовжити."; "screen_qr_code_login_no_camera_permission_state_title" = "Надайте доступ до камери, щоб сканувати QR-код"; -"screen_qr_code_login_scanning_state_title" = "Відскануйте QR-код"; +"screen_qr_code_login_scanning_state_title" = "Зіскануйте QR-код"; "screen_qr_code_login_start_over_button" = "Почати спочатку"; "screen_qr_code_login_unknown_error_description" = "Сталася несподівана помилка. Будь ласка, спробуйте ще раз."; "screen_qr_code_login_verify_code_loading" = "Чекаємо на ваш інший пристрій"; "screen_qr_code_login_verify_code_subtitle" = "Постачальник облікового запису може попросити вас ввести код нижче для підтвердження входу."; "screen_qr_code_login_verify_code_title" = "Ваш код підтвердження"; -"screen_recovery_key_change_description" = "Отримайте новий ключ відновлення, якщо ви втратили існуючий ключ. Після зміни ключа відновлення ваш старий більше не буде працювати."; +"screen_recovery_key_change_description" = "Отримайте новий ключ відновлення, якщо ви втратили наявний ключ. Після зміни ключа відновлення ваш попередній більше не працюватиме."; "screen_recovery_key_change_generate_key" = "Згенерувати новий ключ відновлення"; "screen_recovery_key_change_success" = "Ключ відновлення змінено"; "screen_recovery_key_change_title" = "Змінити ключ відновлення?"; "screen_recovery_key_confirm_create_new_recovery_key" = "Створити новий ключ відновлення"; "screen_recovery_key_confirm_description" = "Впевніться, що ніхто не дивиться!"; -"screen_recovery_key_confirm_error_content" = "Будь ласка, спробуйте ще раз, щоб підтвердити доступ до резервної копії чату."; +"screen_recovery_key_confirm_error_content" = "Будь ласка, спробуйте ще раз, щоб підтвердити доступ до сховища ключів."; "screen_recovery_key_confirm_error_title" = "Неправильний ключ відновлення"; "screen_recovery_key_confirm_key_description" = "Якщо у вас є ключ безпеки або фраза безпеки, це теж спрацює."; -"screen_recovery_key_confirm_key_placeholder" = "Ввести..."; +"screen_recovery_key_confirm_key_placeholder" = "Входимо..."; "screen_recovery_key_confirm_lost_recovery_key" = "Загубили ключ відновлення?"; "screen_recovery_key_confirm_success" = "Ключ відновлення підтверджено"; "screen_recovery_key_copied_to_clipboard" = "Скопійовано ключ відновлення"; "screen_recovery_key_generating_key" = "Створення…"; "screen_recovery_key_save_action" = "Зберегти ключ відновлення"; -"screen_recovery_key_save_description" = "Запишіть свій ключ відновлення в безпечному місці або збережіть його в диспетчері паролів."; +"screen_recovery_key_save_description" = "Запишіть цей ключ відновлення в безпечне місце, наприклад, у менеджер паролей, зашифровану записку або власноруч у фізично безпечному місці."; "screen_recovery_key_save_key_description" = "Торкніться, щоб скопіювати ключ відновлення"; "screen_recovery_key_save_title" = "Збережіть ключ відновлення"; "screen_recovery_key_setup_confirmation_description" = "Після цього кроку ви не зможете отримати доступ до нового ключа відновлення."; "screen_recovery_key_setup_confirmation_title" = "Ви зберегли ключ відновлення?"; "screen_recovery_key_setup_description" = "Ваша резервна копія чату захищена ключем відновлення. Якщо вам потрібен новий ключ відновлення після налаштування, ви можете відтворити, вибравши «Змінити ключ відновлення»."; -"screen_recovery_key_setup_generate_key" = "Створіть свій ключ відновлення"; -"screen_recovery_key_setup_generate_key_description" = "Переконайтеся, що ви можете зберігати ключ відновлення в безпечному місці"; +"screen_recovery_key_setup_generate_key" = "Згенеруйте ключ відновлення"; +"screen_recovery_key_setup_generate_key_description" = "Не діліться цим ні з ким!"; "screen_recovery_key_setup_success" = "Налаштування відновлення виконано успішно"; "screen_recovery_key_setup_title" = "Налаштувати відновлення"; -"screen_report_content_block_user_hint" = "Перевірте, чи хочете Ви приховати всі поточні та майбутні повідомлення від цього користувача"; -"screen_report_content_explanation" = "Це повідомлення буде надіслано адміністратору вашого домашнього сервера. Він (вона) не зможе прочитати жодні зашифровані повідомлення."; +"screen_report_content_block_user_hint" = "Перевірте, чи хочете ви приховати всі поточні та майбутні повідомлення від цього користувача"; +"screen_report_content_explanation" = "Це повідомлення буде надіслано адміністраторам вашого домашнього сервера. Вони не зможуть прочитати зашифровані повідомлення."; "screen_report_content_hint" = "Причина скарги на цей вміст"; "screen_reset_encryption_confirmation_alert_action" = "Так, скинути зараз"; "screen_reset_encryption_confirmation_alert_subtitle" = "Цей процес незворотний."; "screen_reset_encryption_confirmation_alert_title" = "Ви впевнені, що хочете скинути шифрування?"; "screen_reset_encryption_password_subtitle" = "Підтвердьте, що ви хочете скинути шифрування."; "screen_reset_encryption_password_title" = "Введіть пароль облікового запису, щоб продовжити"; -"screen_reset_identity_confirmation_subtitle" = "You're about to go to your %1$@ account to reset your identity. Afterwards you'll be taken back to the app."; -"screen_reset_identity_confirmation_title" = "Can't confirm? Go to your account to reset your identity."; +"screen_reset_identity_confirmation_subtitle" = "Ви збираєтеся перейти до свого облікового запису %1$@, щоб скинути свій обліковий запис. Після цього ви повернетесь до програми."; +"screen_reset_identity_confirmation_title" = "Не можете підтвердити? Перейдіть до свого облікового запису, щоб скинути облікові дані."; "screen_room_alias_resolver_resolve_alias_failure" = "Не вдалося розв'язати псевдонім кімнати."; "screen_room_attachment_source_camera" = "Камера"; "screen_room_attachment_source_camera_video" = "Записати відео"; @@ -695,10 +701,10 @@ "screen_room_change_role_confirm_add_admin_description" = "Ви не зможете скасувати цю дію. Ви просуваєте користувача, щоб він мав такий же рівень прав, як і ви."; "screen_room_change_role_confirm_add_admin_title" = "Додати адміністратора?"; "screen_room_change_role_confirm_demote_self_action" = "Понизити"; -"screen_room_change_role_confirm_demote_self_description" = "Ви не зможете скасувати цю зміну, оскільки ви знижуєте себе, якщо ви останній привілейований користувач у кімнаті, відновити привілеї буде неможливо."; +"screen_room_change_role_confirm_demote_self_description" = "Ви не зможете скасувати цю зміну, оскільки ви понижуєте себе, якщо ви останній привілейований користувач у кімнаті, відновити повноваження буде неможливо."; "screen_room_change_role_confirm_demote_self_title" = "Понизити себе?"; "screen_room_change_role_invited_member_name" = "%1$@ (Очікується)"; -"screen_room_change_role_moderators_admin_section_footer" = "Адміністратори автоматично мають права модератора"; +"screen_room_change_role_moderators_admin_section_footer" = "Адміністратори автоматично мають повноваження модератора"; "screen_room_change_role_moderators_title" = "Керувати модераторами"; "screen_room_change_role_unsaved_changes_description" = "У вас є не збережені зміни."; "screen_room_details_add_topic_title" = "Додати тему"; @@ -706,17 +712,17 @@ "screen_room_details_already_invited" = "Уже запрошені"; "screen_room_details_badge_encrypted" = "Зашифровано"; "screen_room_details_badge_not_encrypted" = "Не зашифровано"; -"screen_room_details_badge_public" = "Публічна кімната"; +"screen_room_details_badge_public" = "Загальнодоступна кімната"; "screen_room_details_edit_room_title" = "Редагувати кімнату"; "screen_room_details_edition_error" = "Сталася невідома помилка, й інформацію не вдалося змінити."; "screen_room_details_edition_error_title" = "Не вдалося оновити кімнату"; -"screen_room_details_encryption_enabled_subtitle" = "Повідомлення захищені замками. Тільки Ви та одержувачі маєте унікальні ключі для їх розблокування."; +"screen_room_details_encryption_enabled_subtitle" = "Повідомлення захищені замками. Тільки ви та одержувачі маєте унікальні ключі для їх розблокування."; "screen_room_details_encryption_enabled_title" = "Шифрування повідомлень увімкнено"; "screen_room_details_error_loading_notification_settings" = "Виникла помилка при завантаженні налаштувань сповіщень."; "screen_room_details_error_muting" = "Не вдалося вимкнути цю кімнату. Будь ласка, спробуйте ще раз."; "screen_room_details_error_unmuting" = "Не вдалося ввімкнути звук цієї кімнати. Повторіть спробу."; "screen_room_details_notification_mode_custom" = "Власні"; -"screen_room_details_notification_mode_default" = "За замовчуванням"; +"screen_room_details_notification_mode_default" = "Типово"; "screen_room_details_share_room_title" = "Поділитися кімнатою"; "screen_room_details_title" = "Інформація про кімнату"; "screen_room_details_updating_room" = "Оновлення кімнати..."; @@ -725,17 +731,17 @@ "screen_room_encrypted_history_banner" = "Історія повідомлень наразі недоступна."; "screen_room_encrypted_history_banner_unverified" = "Історія повідомлень недоступна в цій кімнаті. Перевірте цей пристрій, щоб побачити історію повідомлень."; "screen_room_error_failed_retrieving_user_details" = "Не вдалося отримати дані користувача"; -"screen_room_invite_again_alert_message" = "Чи хотіли б Ви запросити їх знову?"; -"screen_room_invite_again_alert_title" = "Ви одні в цьому чаті"; +"screen_room_invite_again_alert_message" = "Чи хотіли б ви запросити їх знову?"; +"screen_room_invite_again_alert_title" = "Ви одні в цій бесіді"; "screen_room_member_details_block_alert_action" = "Заблокувати"; -"screen_room_member_details_block_alert_description" = "Заблоковані користувачі не зможуть надсилати Вам повідомлення, і всі їхні повідомлення будуть приховані. Ви можете розблокувати їх у будь-який час."; +"screen_room_member_details_block_alert_description" = "Заблоковані користувачі не зможуть надсилати вам повідомлення, і всі їхні повідомлення будуть приховані. Ви можете розблокувати їх у будь-який час."; "screen_room_member_details_block_user" = "Заблокувати користувача"; "screen_room_member_details_title" = "Профіль"; "screen_room_member_details_unblock_alert_action" = "Розблокувати"; "screen_room_member_details_unblock_alert_description" = "Ви знову зможете бачити всі повідомлення від них."; "screen_room_member_details_unblock_user" = "Розблокувати користувача"; -"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" = "Використовуйте веб-додаток, щоб верифікувати цього користувача."; +"screen_room_member_details_verify_button_title" = "Перевірте %1$@"; "screen_room_member_list_ban_member_confirmation_action" = "Заблокувати"; "screen_room_member_list_ban_member_confirmation_description" = "Він не зможе приєднатися до цієї кімнати знову, якщо його запросять."; "screen_room_member_list_ban_member_confirmation_title" = "Ви точно хочете заблокувати цього користувача?"; @@ -743,8 +749,8 @@ "screen_room_member_list_banning_user" = "Блокування %1$@"; "screen_room_member_list_manage_member_ban" = "Вилучити й заблокувати учасника"; "screen_room_member_list_manage_member_remove" = "Вилучити з кімнати"; -"screen_room_member_list_manage_member_remove_confirmation_kick" = "Лише видалити учасника"; -"screen_room_member_list_manage_member_remove_confirmation_title" = "Видалити учасника та заборонити приєднання в майбутньому?"; +"screen_room_member_list_manage_member_remove_confirmation_kick" = "Лише вилучити учасника"; +"screen_room_member_list_manage_member_remove_confirmation_title" = "Вилучити учасника та заборонити приєднання в майбутньому?"; "screen_room_member_list_manage_member_unban_action" = "Розблокувати"; "screen_room_member_list_manage_member_unban_message" = "Вони зможуть знову приєднатися до цієї кімнати, якщо їх запросять."; "screen_room_member_list_manage_member_unban_title" = "Розблокувати користувача"; @@ -752,26 +758,26 @@ "screen_room_member_list_mode_banned" = "Заблоковані"; "screen_room_member_list_mode_members" = "Учасники"; "screen_room_member_list_pending_header_title" = "На розгляді"; -"screen_room_member_list_removing_user" = "Вилучаємо %1$@…"; +"screen_room_member_list_removing_user" = "Вилучення %1$@…"; "screen_room_member_list_role_administrator" = "Адміністратор"; "screen_room_member_list_role_moderator" = "Модератор"; "screen_room_member_list_room_members_header_title" = "Учасники кімнати"; "screen_room_member_list_unbanning_user" = "Розблокування %1$@"; "screen_room_notification_settings_allow_custom" = "Дозволити користувальницькі налаштування"; -"screen_room_notification_settings_allow_custom_footnote" = "Увімкнення цього параметра змінить налаштування за замовчуванням"; -"screen_room_notification_settings_custom_settings_title" = "Повідомте мене в цьому чаті для"; +"screen_room_notification_settings_allow_custom_footnote" = "Увімкнення цього параметра змінить типові налаштування"; +"screen_room_notification_settings_custom_settings_title" = "Сповіщати мене в цій бесіді про"; "screen_room_notification_settings_default_setting_footnote" = "Ви можете змінити це у своїх %1$@."; "screen_room_notification_settings_default_setting_footnote_content_link" = "глобальних налаштуваннях"; -"screen_room_notification_settings_default_setting_title" = "Налаштування за замовчуванням"; +"screen_room_notification_settings_default_setting_title" = "Типові налаштування"; "screen_room_notification_settings_edit_remove_setting" = "Вилучити користувальницькі налаштування"; "screen_room_notification_settings_error_loading_settings" = "Під час завантаження налаштувань сповіщень сталася помилка."; -"screen_room_notification_settings_error_restoring_default" = "Не вдалося відновити режим за замовчуванням, спробуйте ще раз."; +"screen_room_notification_settings_error_restoring_default" = "Не вдалося відновити типовий режим, спробуйте ще раз."; "screen_room_notification_settings_error_setting_mode" = "Не вдалося встановити режим, спробуйте ще раз."; "screen_room_notification_settings_mentions_only_disclaimer" = "Ваш домашній сервер не підтримує цю опцію в зашифрованих кімнатах, ви не отримаєте сповіщення в цій кімнаті."; "screen_room_notification_settings_mode_all_messages" = "Всі повідомлення"; -"screen_room_notification_settings_room_custom_settings_title" = "У цій кімнаті повідомляти мене про"; +"screen_room_notification_settings_room_custom_settings_title" = "У цій кімнаті сповіщати мене про"; "screen_room_retry_send_menu_send_again_action" = "Надіслати знову"; -"screen_room_retry_send_menu_title" = "Ваше повідомлення не вдалося надіслати"; +"screen_room_retry_send_menu_title" = "Не вдалося надіслати ваше повідомлення"; "screen_room_roles_and_permissions_admins" = "Адміністратори"; "screen_room_roles_and_permissions_change_my_role" = "Змінити мою роль"; "screen_room_roles_and_permissions_change_role_demote_to_member" = "Понизити до учасника"; @@ -789,40 +795,41 @@ "screen_room_timeline_add_reaction" = "Додати смайлики"; "screen_room_timeline_beginning_of_room" = "Це початок %1$@"; "screen_room_timeline_beginning_of_room_no_name" = "Це початок цієї розмови."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Показувати менше"; "screen_room_timeline_message_copied" = "Повідомлення скопійовано"; -"screen_room_timeline_no_permission_to_post" = "У Вас немає дозволу на публікацію в цій кімнаті"; +"screen_room_timeline_no_permission_to_post" = "У вас немає дозволу на публікацію в цій кімнаті"; "screen_room_timeline_reactions_show_more" = "Показати більше"; "screen_room_timeline_read_marker_title" = "Нове"; -"screen_room_title" = "Чат"; +"screen_room_title" = "Бесіда"; "screen_room_typing_many_members_first_component_ios" = "%1$@, %2$@ та "; "screen_room_typing_notification_plural_ios" = " пишуть…"; "screen_room_typing_notification_singular_ios" = " пише…"; "screen_room_typing_two_members" = "%1$@ та %2$@"; -"screen_room_voice_message_tooltip" = "Тримати, щоб записати"; +"screen_room_voice_message_tooltip" = "Затисніть, щоб записати"; "screen_roomlist_a11y_create_message" = "Створити нову розмову або кімнату"; "screen_roomlist_empty_message" = "Почніть з обміну повідомленнями з кимось."; -"screen_roomlist_empty_title" = "Ще немає чатів."; -"screen_roomlist_filter_favourites" = "Улюблені"; -"screen_roomlist_filter_favourites_empty_state_subtitle" = "Ви можете додати чат до улюблених у налаштуваннях чату.\nНаразі ви можете зняти фільтри, щоб побачити інші ваші чати"; -"screen_roomlist_filter_favourites_empty_state_title" = "Ви ще не маєте улюблених чатів"; +"screen_roomlist_empty_title" = "Ще немає бесід."; +"screen_roomlist_filter_favourites" = "Обране"; +"screen_roomlist_filter_favourites_empty_state_subtitle" = "Ви можете додати бесіду до обраних у налаштуваннях бесіди.\nНаразі ви можете зняти фільтри, щоб побачити інші ваші бесіди"; +"screen_roomlist_filter_favourites_empty_state_title" = "Ви ще не маєте обраних бесід"; "screen_roomlist_filter_invites" = "Запрошення"; "screen_roomlist_filter_invites_empty_state_title" = "У вас немає запрошень, що очікують на розгляд."; "screen_roomlist_filter_low_priority" = "Низький пріоритет"; -"screen_roomlist_filter_mixed_empty_state_subtitle" = "Ви можете зняти фільтри, щоб побачити інші ваші чати"; -"screen_roomlist_filter_mixed_empty_state_title" = "Ви не маєте чатів для цієї категорії"; -"screen_roomlist_filter_people_empty_state_title" = "Ви ще не маєте жодного особистого чату"; +"screen_roomlist_filter_mixed_empty_state_subtitle" = "Ви можете зняти фільтри, щоб побачити інші ваші бесіди"; +"screen_roomlist_filter_mixed_empty_state_title" = "Ви не маєте бесід для цієї категорії"; +"screen_roomlist_filter_people_empty_state_title" = "Ви ще не маєте жодної особистої бесіди"; "screen_roomlist_filter_rooms" = "Кімнати"; "screen_roomlist_filter_rooms_empty_state_title" = "Ви ще не учасник жодної кімнати"; "screen_roomlist_filter_unreads" = "Непрочитані"; "screen_roomlist_filter_unreads_empty_state_title" = "Вітаємо!\nУ вас немає непрочитаних повідомлень!"; -"screen_roomlist_main_space_title" = "Усі чати"; +"screen_roomlist_main_space_title" = "Бесіди"; "screen_roomlist_mark_as_read" = "Позначити прочитаним"; "screen_roomlist_mark_as_unread" = "Позначити непрочитаним"; "screen_roomlist_room_directory_button_title" = "Переглянути всі кімнати"; "screen_server_confirmation_message_login_element_dot_io" = "Приватний сервер для співробітників Element."; "screen_server_confirmation_message_login_matrix_dot_org" = "Matrix — це відкрита мережа для безпечної, децентралізованої комунікації."; -"screen_server_confirmation_message_register" = "Тут будуть зберігатися Ваші розмови - так само, як Ви використовуєте поштову скриньку для зберігання своїх електронних листів."; +"screen_server_confirmation_message_register" = "Тут розміщуватимуться ваші розмови — так само як у поштовій скриньці для зберігання своїх електронних листів."; "screen_server_confirmation_title_login" = "Ви збираєтесь увійти в %1$@"; "screen_server_confirmation_title_register" = "Ви збираєтеся створити обліковий запис на %1$@"; "screen_session_verification_cancelled_subtitle" = "Щось не так. Або час очікування запиту минув, або в запиті було відмовлено."; @@ -832,155 +839,155 @@ "screen_session_verification_compare_numbers_title" = "Порівняйте цифри"; "screen_session_verification_complete_subtitle" = "Ваш новий сеанс підтверджено. Він матиме доступ до ваших зашифрованих повідомлень, й інші користувачі вважатимуть його надійним."; "screen_session_verification_enter_recovery_key" = "Введіть ключ відновлення"; -"screen_session_verification_failed_subtitle" = "Either the request timed out, the request was denied, or there was a verification mismatch."; -"screen_session_verification_open_existing_session_subtitle" = "Доведіть, що це Ви, щоб отримати доступ до історії зашифрованих повідомлень."; -"screen_session_verification_open_existing_session_title" = "Відкрийте існуючий сеанс"; -"screen_session_verification_positive_button_canceled" = "Повторити перевірку"; -"screen_session_verification_positive_button_initial" = "Я готовий"; +"screen_session_verification_failed_subtitle" = "Або час очікування запиту минув, або запит було відхилено, або виникла розбіжність у верифікації."; +"screen_session_verification_open_existing_session_subtitle" = "Доведіть, що це ви, щоб отримати доступ до історії зашифрованих повідомлень."; +"screen_session_verification_open_existing_session_title" = "Відкрийте активний сеанс"; +"screen_session_verification_positive_button_canceled" = "Повторити верифікацію"; +"screen_session_verification_positive_button_initial" = "У мене все готово"; "screen_session_verification_positive_button_verifying_ongoing" = "Очікування збігу"; -"screen_session_verification_ready_subtitle" = "Порівняйте унікальний набір емоджи."; -"screen_session_verification_request_accepted_subtitle" = "Порівняйте унікальні емодзі, переконавшись, що вони відображаються в однаковому порядку."; -"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_ready_subtitle" = "Порівняйте унікальний набір емоджі."; +"screen_session_verification_request_accepted_subtitle" = "Порівняйте унікальні емодзі, переконавшись, що вони показані в однаковому порядку."; +"screen_session_verification_request_details_timestamp" = "Увійшов"; +"screen_session_verification_request_failure_title" = "Не вдалося перевірити"; +"screen_session_verification_request_footer" = "Продовжуйте, лише якщо ви ініціювали цю перевірку."; +"screen_session_verification_request_subtitle" = "Перевірте інший пристрій, щоб захистити історію повідомлень."; +"screen_session_verification_request_success_subtitle" = "Тепер ви можете безпечно читати або надсилати повідомлення на іншому пристрої."; +"screen_session_verification_request_success_title" = "Пристрій перевірено"; +"screen_session_verification_request_title" = "Запитано на верифікацію"; "screen_session_verification_they_dont_match" = "Вони не збігаються"; "screen_session_verification_they_match" = "Вони збігаються"; -"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_waiting_to_accept_subtitle" = "Щоб продовжити, прийміть запит на початок процесу перевірки в іншому сеансі."; +"screen_session_verification_use_another_device_subtitle" = "Перш ніж починати перевірку звідси, переконайтеся, що програму відкрито на іншому пристрої."; +"screen_session_verification_use_another_device_title" = "Відкрийте додаток на іншому перевіреному пристрої"; +"screen_session_verification_waiting_another_device_subtitle" = "Ви повинні побачити спливаюче вікно на іншому пристрої. Почніть перевірку звідти."; +"screen_session_verification_waiting_another_device_title" = "Почніть перевірку на іншому пристрої"; +"screen_session_verification_waiting_to_accept_subtitle" = "Щоб продовжити, прийміть запит на початок процесу верифікації в іншому сеансі."; "screen_session_verification_waiting_to_accept_title" = "Очікування на прийняття запиту"; "screen_share_location_title" = "Поділитися розташуванням"; "screen_share_my_location_action" = "Поділитися моїм розташуванням"; "screen_share_open_apple_maps" = "Відкрити в Apple Maps"; -"screen_share_open_google_maps" = "Відкрити в Google Maps"; +"screen_share_open_google_maps" = "Відкрити в Картах Google"; "screen_share_open_osm_maps" = "Відкрити в OpenStreetMap"; -"screen_share_this_location_action" = "Поділитися цим місцезнаходженням"; +"screen_share_this_location_action" = "Поділитися цим місцем перебування"; "screen_signed_out_reason_1" = "Ви змінили пароль під час іншого сеансу"; "screen_signed_out_reason_2" = "Ви видалили сеанс з іншого сеансу"; -"screen_signed_out_reason_3" = "Адміністратор вашого сервера визнав недійсним ваш доступ"; +"screen_signed_out_reason_3" = "Адміністратор вашого сервера визнав ваш доступ недійсним"; "screen_signed_out_subtitle" = "Можливо, ви вийшли з системи з однієї з причин, наведених нижче. Будь ласка, увійдіть знову, щоб продовжити використання %@."; "screen_signed_out_title" = "Ви вийшли з системи"; "screen_signout_confirmation_dialog_content" = "Ви впевнені, що бажаєте вийти?"; "screen_signout_in_progress_dialog_content" = "Вихід…"; "screen_signout_key_backup_disabled_subtitle" = "Ви збираєтеся вийти зі свого останнього сеансу. Якщо ви вийдете зараз, ви втратите доступ до своїх зашифрованих повідомлень."; "screen_signout_key_backup_disabled_title" = "Ви вимкнули резервне копіювання"; -"screen_signout_key_backup_offline_subtitle" = "Коли ви вийшли з мережі, резервна копія ваших ключів все ще створювалася. Повторно підключіться, щоб зберегти резервну копію ключів перед виходом з системи."; -"screen_signout_key_backup_ongoing_subtitle" = "Зачекайте, поки це завершиться, перш ніж вийти."; +"screen_signout_key_backup_offline_subtitle" = "Коли ви вийшли з мережі, резервна копія ваших ключів все ще створювалася. Повторно під'єднайтеся, щоб зберегти резервну копію ключів перед виходом."; +"screen_signout_key_backup_ongoing_subtitle" = "Дочекайтеся завершення процесу, перш ніж вийти."; "screen_signout_key_backup_ongoing_title" = "Резервне копіювання ваших ключів ще триває"; "screen_signout_recovery_disabled_subtitle" = "Ви збираєтеся вийти зі свого останнього сеансу. Якщо ви вийдете зараз, ви втратите доступ до своїх зашифрованих повідомлень."; "screen_signout_recovery_disabled_title" = "Відновлення не налаштовано"; "screen_signout_save_recovery_key_subtitle" = "Ви збираєтеся вийти зі свого останнього сеансу. Якщо вийти зараз, ви можете втратити доступ до зашифрованих повідомлень."; -"screen_start_chat_error_starting_chat" = "Під час спроби почати чат сталася помилка"; -"screen_view_location_title" = "Місцезнаходження"; -"screen_welcome_bullet_1" = "Дзвінки, опитування, пошук тощо будуть додані пізніше цього року."; +"screen_start_chat_error_starting_chat" = "Під час спроби почати бесіду сталася помилка"; +"screen_view_location_title" = "Розташування"; +"screen_welcome_bullet_1" = "Виклики, опитування, пошук тощо будуть додані пізніше цього року."; "screen_welcome_bullet_2" = "Історія повідомлень для зашифрованих кімнат ще недоступна."; "screen_welcome_bullet_3" = "Ми хотіли б почути вас, розкажіть нам ваші враження та ідеї щодо застосунку на сторінці налаштувань."; -"screen_welcome_button" = "Пішли!"; +"screen_welcome_button" = "Уперед!"; "screen_welcome_subtitle" = "Ось що вам потрібно знати:"; "screen_welcome_title" = "Ласкаво просимо до %1$@!"; -"session_verification_banner_message" = "Схоже, Ви використовуєте новий пристрій. Щоб отримати доступ до зашифрованих повідомлень, підтвердьте особу за допомогою іншого пристрою."; -"session_verification_banner_title" = "Підтвердьте, що це Ви"; -"settings_rageshake" = "Rageshake"; +"session_verification_banner_message" = "Схоже, ви використовуєте новий пристрій. Щоб отримати доступ до зашифрованих повідомлень, підтвердьте особу за допомогою іншого пристрою."; +"session_verification_banner_title" = "Підтвердьте, що це ви"; +"settings_rageshake" = "Лютострус"; "settings_rageshake_detection_threshold" = "Поріг виявлення"; "settings_version_number" = "Версія: %1$@ (%2$@)"; "state_event_avatar_changed_too" = "(аватар теж було змінено)"; -"state_event_avatar_url_changed" = "%1$@ змінив (-ла) свій аватар"; +"state_event_avatar_url_changed" = "%1$@ змінює свій аватар"; "state_event_avatar_url_changed_by_you" = "Ви змінили свій аватар"; "state_event_demoted_to_member" = "%1$@ понижено до учасника"; "state_event_demoted_to_moderator" = "%1$@ понижено до модератора"; -"state_event_display_name_changed_from" = "%1$@ змінив (-ла) своє імʼя з %2$@ на %3$@"; +"state_event_display_name_changed_from" = "%1$@ змінює своє імʼя з %2$@ на %3$@"; "state_event_display_name_changed_from_by_you" = "Ви змінили своє ім'я з %1$@ на %2$@"; -"state_event_display_name_removed" = "%1$@ видалив (-ла) своє ім'я (було %2$@)"; +"state_event_display_name_removed" = "%1$@ вилучає своє ім'я (було %2$@)"; "state_event_display_name_removed_by_you" = "Ви видалили своє ім'я (було%1$@)"; -"state_event_display_name_set" = "%1$@ змінив (-ла) своє ім'я на %2$@"; +"state_event_display_name_set" = "%1$@ змінює своє ім'я на %2$@"; "state_event_display_name_set_by_you" = "Ви змінили своє імʼя на %1$@"; "state_event_promoted_to_administrator" = "%1$@ підвищено до адміністратора"; "state_event_promoted_to_moderator" = "%1$@ підвищено до модератора"; -"state_event_room_avatar_changed" = "%1$@ змінив (-ла) аватар кімнати"; +"state_event_room_avatar_changed" = "%1$@ змінює аватар кімнати"; "state_event_room_avatar_changed_by_you" = "Ви змінили аватар кімнати"; -"state_event_room_avatar_removed" = "%1$@ видалив (-ла) аватар кімнати"; +"state_event_room_avatar_removed" = "%1$@ видаляє аватар кімнати"; "state_event_room_avatar_removed_by_you" = "Ви видалили аватар кімнати"; -"state_event_room_ban" = "%1$@ заблокував (-ла) %2$@"; +"state_event_room_ban" = "%1$@ блокує %2$@"; "state_event_room_ban_by_you" = "Ви заблокували %1$@"; -"state_event_room_created" = "%1$@ створив (-ла) кімнату"; +"state_event_room_created" = "%1$@ створює кімнату"; "state_event_room_created_by_you" = "Ви створили кімнату"; -"state_event_room_invite" = "%1$@ запросив (-ла) %2$@"; -"state_event_room_invite_accepted" = "%1$@ прийняв (-ла) запрошення"; +"state_event_room_invite" = "%1$@ запрошує %2$@"; +"state_event_room_invite_accepted" = "%1$@ приймає запрошення"; "state_event_room_invite_accepted_by_you" = "Ви прийняли запрошення"; "state_event_room_invite_by_you" = "Ви запросили %1$@"; -"state_event_room_invite_you" = "%1$@ запросив (-ла) Вас"; -"state_event_room_join" = "%1$@ приєднався (-лася) до кімнати"; +"state_event_room_invite_you" = "Вас запрошує %1$@"; +"state_event_room_join" = "%1$@ приєднується до кімнати"; "state_event_room_join_by_you" = "Ви приєдналися до кімнати"; "state_event_room_knock" = "%1$@ подав (-ла) запит на приєднання"; "state_event_room_knock_accepted" = "%1$@ дозволив (-ла) %2$@ приєднатися"; "state_event_room_knock_accepted_by_you" = "Ви дозволили %1$@ приєднатися"; "state_event_room_knock_by_you" = "Ви подали запит на приєднання"; -"state_event_room_knock_denied" = "%1$@ відхилив (-ла) запит %2$@ на приєднання"; -"state_event_room_knock_denied_by_you" = "Ви відхилили запит %1$@ на приєднання"; -"state_event_room_knock_denied_you" = "%1$@ відхилив (-ла) Ваш запит на приєднання"; -"state_event_room_knock_retracted" = "%1$@ більше не зацікавлений у приєднанні"; +"state_event_room_knock_denied" = "%1$@ відхиляє запит %2$@ на приєднання"; +"state_event_room_knock_denied_by_you" = "Ви відхилили запит на приєднання від %1$@"; +"state_event_room_knock_denied_you" = "%1$@ відхиляє ваш запит на приєднання"; +"state_event_room_knock_retracted" = "%1$@ більше не хоче приєднуватися"; "state_event_room_knock_retracted_by_you" = "Ви відкликали свій запит на приєднання"; -"state_event_room_leave" = "%1$@ вийшов (-ла) з кімнати"; +"state_event_room_leave" = "%1$@ виходить з кімнати"; "state_event_room_leave_by_you" = "Ви вийшли з кімнати"; -"state_event_room_name_changed" = "%1$@ змінив (-ла) назву кімнати на: %2$@"; +"state_event_room_name_changed" = "%1$@ змінює назву кімнати на: %2$@"; "state_event_room_name_changed_by_you" = "Ви змінили назву кімнати на: %1$@"; -"state_event_room_name_removed" = "%1$@ видалив (-ла) назву кімнати"; +"state_event_room_name_removed" = "%1$@ вилучає назву кімнати"; "state_event_room_name_removed_by_you" = "Ви видалили назву кімнати"; -"state_event_room_none" = "%1$@ не внесено жодних змін"; +"state_event_room_none" = "%1$@ нічого не змінює"; "state_event_room_none_by_you" = "Ви не внесли жодних змін"; -"state_event_room_pinned_events_changed" = "%1$@ змінив(-ла) закріплені повідомлення"; +"state_event_room_pinned_events_changed" = "%1$@ змінює закріплені повідомлення"; "state_event_room_pinned_events_changed_by_you" = "Ви змінили закріплені повідомлення"; -"state_event_room_pinned_events_pinned" = "%1$@ закріпив(-ла) повідомлення"; +"state_event_room_pinned_events_pinned" = "%1$@ закріплює повідомлення"; "state_event_room_pinned_events_pinned_by_you" = "Ви закріпили повідомлення"; -"state_event_room_pinned_events_unpinned" = "%1$@ відкріпив(-ла) повідомлення"; +"state_event_room_pinned_events_unpinned" = "%1$@ відкріплює повідомлення"; "state_event_room_pinned_events_unpinned_by_you" = "Ви відкріпили повідомлення"; -"state_event_room_reject" = "%1$@ відхилив (-ла) запрошення"; +"state_event_room_reject" = "%1$@ відхиляє запрошення"; "state_event_room_reject_by_you" = "Ви відхилили запрошення"; -"state_event_room_remove" = "%1$@ вилучив (-ла) %2$@"; +"state_event_room_remove" = "%1$@ вилучає %2$@"; "state_event_room_remove_by_you" = "Ви видалили %1$@"; -"state_event_room_third_party_invite" = "%1$@ запросив (-ла) %2$@ приєднатися до кімнати"; +"state_event_room_third_party_invite" = "%1$@ запрошує %2$@ приєднатися до кімнати"; "state_event_room_third_party_invite_by_you" = "Ви запросили %1$@ приєднатися до кімнати"; -"state_event_room_third_party_revoked_invite" = "%1$@ відкликав (-ла) запрошення для %2$@ на приєднання до кімнати"; -"state_event_room_third_party_revoked_invite_by_you" = "Ви відкликали запрошення для %1$@ на приєднання до кімнати"; -"state_event_room_topic_changed" = "%1$@ змінив (-ла) тему на: %2$@"; +"state_event_room_third_party_revoked_invite" = "%1$@ відкликає запрошення приєднатися до кімнати для %2$@"; +"state_event_room_third_party_revoked_invite_by_you" = "Ви відкликали запрошення приєднатися до кімнати для %1$@"; +"state_event_room_topic_changed" = "%1$@ змінює тему на: %2$@"; "state_event_room_topic_changed_by_you" = "Ви змінили тему на: %1$@"; -"state_event_room_topic_removed" = "%1$@ видалив (-ла) тему кімнати"; -"state_event_room_topic_removed_by_you" = "Ви видалили тему кімнати"; -"state_event_room_unban" = "%1$@ розблокував (-ла) %2$@"; +"state_event_room_topic_removed" = "%1$@ вилучає тему кімнати"; +"state_event_room_topic_removed_by_you" = "Ви вилучили тему кімнати"; +"state_event_room_unban" = "%1$@ розблоковує %2$@"; "state_event_room_unban_by_you" = "Ви розблокували %1$@"; -"state_event_room_unknown_membership_change" = "%1$@ вніс (внесла) невідомі зміни щодо свого членства"; +"state_event_room_unknown_membership_change" = "%1$@ вносить невідомі зміни щодо свого членства"; "test_language_identifier" = "uk"; "test_untranslated_default_language_identifier" = "en"; "troubleshoot_notifications_entry_point_section" = "Усунення несправностей"; "troubleshoot_notifications_screen_action" = "Запустити тести"; "troubleshoot_notifications_screen_action_again" = "Запустити тести знову"; -"troubleshoot_notifications_screen_failure" = "Деякі тести не пройшли. Будь ласка, перегляньте деталі."; +"troubleshoot_notifications_screen_failure" = "Деякі тести не пройдено. Перегляньте подробиці."; "troubleshoot_notifications_screen_notice" = "Запустіть тести, щоб виявити будь-яку проблему у вашій конфігурації, через яку сповіщення можуть не працювати належним чином."; "troubleshoot_notifications_screen_quick_fix_action" = "Спробувати виправити"; -"troubleshoot_notifications_screen_success" = "Всі тести пройшли успішно."; +"troubleshoot_notifications_screen_success" = "Всі тести успішно пройдено."; "troubleshoot_notifications_screen_title" = "Усунення неполадок сповіщень"; -"troubleshoot_notifications_screen_waiting" = "Деякі тести вимагають вашої уваги. Будь ласка, перегляньте деталі."; -"troubleshoot_notifications_test_check_permission_description" = "Перевірте, чи програма може показувати сповіщення."; +"troubleshoot_notifications_screen_waiting" = "Деякі тести вимагають вашої уваги. Перегляньте подробиці."; +"troubleshoot_notifications_test_check_permission_description" = "Перевірте, чи може застосунок показувати сповіщення."; "troubleshoot_notifications_test_check_permission_title" = "Перевірте дозволи"; "troubleshoot_notifications_test_current_push_provider_description" = "Отримує назву поточного постачальника."; -"troubleshoot_notifications_test_current_push_provider_failure" = "Постачальників push-сповіщень не обрано."; +"troubleshoot_notifications_test_current_push_provider_failure" = "Постачальників push-сповіщень не вибрано."; "troubleshoot_notifications_test_current_push_provider_success" = "Поточний постачальник: %1$@."; -"troubleshoot_notifications_test_current_push_provider_title" = "Поточний провайдер push"; -"troubleshoot_notifications_test_detect_push_provider_description" = "Переконайтеся, що програма має принаймні один push провайдер."; -"troubleshoot_notifications_test_detect_push_provider_failure" = "Не знайдено постачальників push-повідомлень."; -"troubleshoot_notifications_test_detect_push_provider_title" = "Виявлення push-провайдерів"; -"troubleshoot_notifications_test_display_notification_description" = "Перевірте, чи може програма відображати сповіщення."; +"troubleshoot_notifications_test_current_push_provider_title" = "Поточний постачальник push-сповіщень"; +"troubleshoot_notifications_test_detect_push_provider_description" = "Переконайтеся, що застосунок має принаймні одного постачальника push-сповіщень."; +"troubleshoot_notifications_test_detect_push_provider_failure" = "Не знайдено постачальників push-сповіщень."; +"troubleshoot_notifications_test_detect_push_provider_title" = "Виявлення постачальників push-сповіщень"; +"troubleshoot_notifications_test_display_notification_description" = "Перевірте, чи може застосунок показувати сповіщення."; "troubleshoot_notifications_test_display_notification_failure" = "Ви не натиснули на сповіщення."; -"troubleshoot_notifications_test_display_notification_permission_failure" = "Не вдається відобразити сповіщення."; +"troubleshoot_notifications_test_display_notification_permission_failure" = "Не вдається показати сповіщення."; "troubleshoot_notifications_test_display_notification_success" = "Ви натиснули на сповіщення!"; -"troubleshoot_notifications_test_display_notification_title" = "Відображення сповіщення"; -"troubleshoot_notifications_test_display_notification_waiting" = "Будь ласка, натисніть на сповіщення, щоб продовжити тест."; +"troubleshoot_notifications_test_display_notification_title" = "Показ сповіщення"; +"troubleshoot_notifications_test_display_notification_waiting" = "Натисніть на сповіщення, щоб продовжити тест."; "troubleshoot_notifications_test_firebase_availability_description" = "Переконується, що Firebase доступний."; "troubleshoot_notifications_test_firebase_availability_failure" = "Firebase недоступний."; "troubleshoot_notifications_test_firebase_availability_success" = "Firebase доступний."; @@ -993,8 +1000,8 @@ "troubleshoot_notifications_test_push_loop_back_failure_1" = "Помилка: постачальник push-сповіщень відхилив запит."; "troubleshoot_notifications_test_push_loop_back_failure_2" = "Помилка: %1$@."; "troubleshoot_notifications_test_push_loop_back_failure_3" = "Помилка, неможливо перевірити push."; -"troubleshoot_notifications_test_push_loop_back_failure_4" = "Error, timeout waiting for push."; -"troubleshoot_notifications_test_push_loop_back_success" = "Push loop back took %1$d ms."; +"troubleshoot_notifications_test_push_loop_back_failure_4" = "Помилка, час очікування вийшов на push-повідомлення."; +"troubleshoot_notifications_test_push_loop_back_success" = "Зворотнє відправлення push-повідомлення, зайняло %1$d мс."; "troubleshoot_notifications_test_push_loop_back_title" = "Перевірка зворотного надсилання"; "troubleshoot_notifications_test_unified_push_description" = "Переконується, що дистриб'ютори UnifiedPush доступні."; "troubleshoot_notifications_test_unified_push_failure" = "Дистриб'юторів не знайдено."; @@ -1008,18 +1015,18 @@ "notification_invitation_action_reject" = "Відхилити"; "notification_room_action_mark_as_read" = "Позначити прочитаним"; "notification_room_action_quick_reply" = "Швидка відповідь"; -"screen_pinned_timeline_screen_title_empty" = "Pinned messages"; +"screen_pinned_timeline_screen_title_empty" = "Закріплені повідомлення"; "screen_room_mentions_at_room_title" = "Усі"; "screen_account_provider_change" = "Змінити провайдера облікового запису"; -"screen_account_provider_signin_subtitle" = "Тут будуть зберігатися Ваші розмови - так само, як Ви використовуєте поштову скриньку для зберігання своїх електронних листів."; -"screen_account_provider_signup_subtitle" = "Тут будуть зберігатися Ваші розмови - так само, як Ви використовуєте поштову скриньку для зберігання своїх електронних листів."; +"screen_account_provider_signin_subtitle" = "Тут розміщуватимуться ваші розмови — так само як у поштовій скриньці для зберігання своїх електронних листів."; +"screen_account_provider_signup_subtitle" = "Тут розміщуватимуться ваші розмови — так само як у поштовій скриньці для зберігання своїх електронних листів."; "screen_analytics_settings_help_us_improve" = "Ділитися анонімними даними про використання, щоб допомогати нам виявляти проблеми."; "screen_analytics_settings_read_terms" = "Ви можете прочитати всі наші умови %1$@."; "screen_analytics_settings_read_terms_content_link" = "тут"; "screen_blocked_users_unblock_alert_action" = "Розблокувати"; "screen_blocked_users_unblock_alert_description" = "Ви знову зможете бачити всі повідомлення від них."; "screen_blocked_users_unblock_alert_title" = "Розблокувати користувача"; -"screen_bug_report_rash_logs_alert_title" = "%1$@ аварійно завершив роботу під час останнього використання. Бажаєте поділитися з нами звітом про збій?"; +"screen_bug_report_rash_logs_alert_title" = "Стався збій %1$@ під час останнього користування. Хочете поділитися з нами звітом про збій?"; "screen_chat_backup_recovery_action_confirm" = "Введіть ключ відновлення"; "screen_chat_backup_recovery_action_setup" = "Налаштувати відновлення"; "screen_create_poll_cancel_confirmation_content_ios" = "Внесені зміни не буде збережено"; @@ -1027,21 +1034,21 @@ "screen_create_room_room_name_label" = "Назва кімнати"; "screen_create_room_title" = "Створити кімнату"; "screen_dm_details_block_alert_action" = "Заблокувати"; -"screen_dm_details_block_alert_description" = "Заблоковані користувачі не зможуть надсилати Вам повідомлення, і всі їхні повідомлення будуть приховані. Ви можете розблокувати їх у будь-який час."; +"screen_dm_details_block_alert_description" = "Заблоковані користувачі не зможуть надсилати вам повідомлення, і всі їхні повідомлення будуть приховані. Ви можете розблокувати їх у будь-який час."; "screen_dm_details_block_user" = "Заблокувати користувача"; "screen_dm_details_unblock_alert_action" = "Розблокувати"; "screen_dm_details_unblock_alert_description" = "Ви знову зможете бачити всі повідомлення від них."; "screen_dm_details_unblock_user" = "Розблокувати користувача"; "screen_edit_poll_delete_confirmation_title" = "Видалити опитування"; "screen_edit_poll_title" = "Редагувати опитування"; -"screen_identity_use_another_device" = "Use another device"; +"screen_identity_use_another_device" = "Використовуйте інший пристрій"; "screen_login_subtitle" = "Matrix — це відкрита мережа для безпечної, децентралізованої комунікації."; "screen_notification_settings_mentions_section_title" = "Згадки"; "screen_qr_code_login_invalid_scan_state_retry_button" = "Спробуйте ще раз"; -"screen_recovery_key_change_generate_key_description" = "Переконайтеся, що ви можете зберігати ключ відновлення в безпечному місці"; -"screen_recovery_key_confirm_title" = "Enter your recovery key"; +"screen_recovery_key_change_generate_key_description" = "Не діліться цим ні з ким!"; +"screen_recovery_key_confirm_title" = "Введіть ключ відновлення"; "screen_report_content_block_user" = "Заблокувати користувача"; -"screen_reset_encryption_password_placeholder" = "Ввести..."; +"screen_reset_encryption_password_placeholder" = "Входимо..."; "screen_room_attachment_source_camera_photo" = "Зробити фото"; "screen_room_change_permissions_everyone" = "Усі"; "screen_room_change_permissions_member_moderation" = "Модерація учасників"; @@ -1065,7 +1072,7 @@ "screen_room_timeline_reactions_show_less" = "Показувати менше"; "screen_roomlist_filter_people" = "Люди"; "screen_server_confirmation_change_server" = "Змінити провайдера облікового запису"; -"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" = "Або час очікування запиту минув, або запит було відхилено, або виникла розбіжність у верифікації."; "screen_signout_confirmation_dialog_submit" = "Вийти"; "screen_signout_confirmation_dialog_title" = "Вийти"; "screen_signout_key_backup_offline_title" = "Резервне копіювання ваших ключів ще триває"; diff --git a/ElementX/Resources/Localizations/uk.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/uk.lproj/Localizable.stringsdict index a9a812c7bb..03fd8b15ad 100644 --- a/ElementX/Resources/Localizations/uk.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/uk.lproj/Localizable.stringsdict @@ -13,11 +13,11 @@ NSStringFormatValueTypeKey d one - %1$d введена цифра + Введена %1$d цифра few - %1$d введено цифри + Введено %1$d цифри many - %1$d введено цифри + Введено %1$d цифр a11y_read_receipts_multiple_with_others @@ -141,7 +141,7 @@ one %d нове повідомлення few - %d нових повідомлень + %d нові повідомлення many %d нових повідомлень @@ -159,7 +159,7 @@ one %d непрочитане сповіщення few - %d непрочитаних сповіщень + %d непрочитані сповіщення many %d непрочитаних сповіщень @@ -229,9 +229,11 @@ NSStringFormatValueTypeKey d one - %1$d Pinned message - other - %1$d Pinned messages + %1$d Закріплене повідомлення + few + %1$d Закріплених повідомлення + many + %1$d Закріплених повідомлення screen_room_member_list_header_title @@ -252,6 +254,22 @@ %1$d осіб + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey @@ -285,7 +303,7 @@ few %1$@%2$@ та %3$d інші many - %1$@%2$@ та %3$d інші + %1$@%2$@ та %3$d інших screen_room_typing_many_members_second_component_ios @@ -337,7 +355,7 @@ one Виявлено %1$d постачальника: %2$@ few - Виявлено %1$d постачальників: %2$@ + Виявлено %1$d постачальники: %2$@ many Виявлено %1$d постачальників: %2$@ @@ -353,11 +371,11 @@ NSStringFormatValueTypeKey d one - %1$d дистриб'ютора знайдено: %2$@. + Знайдений %1$d дистриб'ютор: %2$@. few - %1$d дистриб'юторів знайдено: %2$@. + Знайдено %1$d дистриб'ютори: %2$@. many - %1$d дистриб'юторів знайдено: %2$@. + Знайдено %1$d дистриб'юторів: %2$@. diff --git a/ElementX/Resources/Localizations/uz.lproj/Localizable.strings b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings index 04cb4691a0..48db2eb1e1 100644 --- a/ElementX/Resources/Localizations/uz.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "Audio"; "common_blocked_users" = "Blocked users"; "common_bubbles" = "Pufakchalar"; -"common_call_invite" = "Call in progress (unsupported)"; "common_call_started" = "Call started"; "common_chat_backup" = "Chatning zaxira nusxasi"; "common_copyright" = "Mualliflik huquqi"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "Taklif(lar)ni yuborib bo‘lmadi"; "common_unlock" = "Unlock"; "common_unmute" = "Ovozni yoqish"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "Qo'llab-quvvatlanmagan hodisa"; "common_username" = "Foydalanuvchi nomi"; "common_verification_cancelled" = "Tasdiqlash bekor qilindi"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "Notify the whole room"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ of %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Pinned messages"; "screen_room_pinned_banner_loading_description" = "Loading message…"; "screen_room_pinned_banner_view_all_button_title" = "View All"; +"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_details_pinned_events_row_title" = "Pinned messages"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "Emoji qo'shmoq"; "screen_room_timeline_beginning_of_room" = "Bu %1$@ni boshlanishi"; "screen_room_timeline_beginning_of_room_no_name" = "Bu suhbatning boshlanishi."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "Kamroq ko'rsatish"; "screen_room_timeline_message_copied" = "Xabar nusxalandi"; "screen_room_timeline_no_permission_to_post" = "Sizda bu xonaga post yozishga ruxsat yo‘q"; diff --git a/ElementX/Resources/Localizations/uz.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/uz.lproj/Localizable.stringsdict index d7c1c72156..1f8d3d8868 100644 --- a/ElementX/Resources/Localizations/uz.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/uz.lproj/Localizable.stringsdict @@ -226,6 +226,22 @@ %1$dodamlar + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings index 7454457022..202cafb0cb 100644 --- a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings @@ -3,7 +3,7 @@ "a11y_hide_password" = "隐藏密码"; "a11y_jump_to_bottom" = "跳转到底部"; "a11y_notifications_mentions_only" = "仅提及"; -"a11y_notifications_muted" = "关闭通知"; +"a11y_notifications_muted" = "通知已关闭"; "a11y_page_n" = "第 %1$d 页"; "a11y_pause" = "暂停"; "a11y_pin_field" = "PIN 字段"; @@ -32,18 +32,18 @@ "action_close" = "关闭"; "action_complete_verification" = "完成验证"; "action_confirm" = "确认"; -"action_confirm_password" = "Confirm password"; +"action_confirm_password" = "确认密码"; "action_continue" = "继续"; "action_copy" = "复制"; "action_copy_link" = "复制链接"; "action_copy_link_to_message" = "复制消息链接"; "action_create" = "创建"; -"action_create_a_room" = "创建房间"; -"action_deactivate" = "Deactivate"; -"action_deactivate_account" = "Deactivate account"; +"action_create_a_room" = "创建聊天室"; +"action_deactivate" = "停用"; +"action_deactivate_account" = "停用账户"; "action_decline" = "拒绝"; "action_delete_poll" = "删除投票"; -"action_disable" = "停用"; +"action_disable" = "禁用"; "action_discard" = "丢弃"; "action_done" = "完成"; "action_edit" = "编辑"; @@ -54,7 +54,7 @@ "action_forgot_password" = "忘记密码?"; "action_forward" = "转发"; "action_go_back" = "返回"; -"action_ignore" = "Ignore"; +"action_ignore" = "忽略"; "action_invite" = "邀请"; "action_invite_friends" = "邀请朋友"; "action_invite_friends_to_app" = "邀请朋友加入 %1$@"; @@ -64,7 +64,7 @@ "action_learn_more" = "了解更多"; "action_leave" = "离开"; "action_leave_conversation" = "离开聊天"; -"action_leave_room" = "离开房间"; +"action_leave_room" = "离开聊天室"; "action_load_more" = "载入更多"; "action_manage_account" = "管理账户"; "action_manage_devices" = "管理设备"; @@ -95,7 +95,7 @@ "action_send_message" = "发送消息"; "action_share" = "分享"; "action_share_link" = "分享链接"; -"action_show" = "Show"; +"action_show" = "显示"; "action_sign_in_again" = "再次登录"; "action_signout" = "登出"; "action_signout_anyway" = "仍然登出"; @@ -125,21 +125,20 @@ "common_audio" = "音频"; "common_blocked_users" = "已屏蔽用户"; "common_bubbles" = "气泡"; -"common_call_invite" = "通话进行中(不支持)"; "common_call_started" = "通话已开始"; "common_chat_backup" = "聊天记录备份"; "common_copyright" = "版权"; -"common_creating_room" = "正在创建房间..."; -"common_current_user_left_room" = "离开房间"; -"common_dark" = "暗色"; +"common_creating_room" = "正在创建聊天室..."; +"common_current_user_left_room" = "离开聊天室"; +"common_dark" = "深色"; "common_decryption_error" = "解密错误"; "common_developer_options" = "开发者选项"; -"common_device_id" = "Device ID"; +"common_device_id" = "设备 ID"; "common_direct_chat" = "私聊"; "common_edited_suffix" = "(已编辑)"; "common_editing" = "编辑中"; "common_emote" = "* %1$@ %2$@"; -"common_encryption" = "Encryption"; +"common_encryption" = "加密"; "common_encryption_enabled" = "已启用加密"; "common_enter_your_pin" = "输入 PIN 码"; "common_error" = "错误"; @@ -150,12 +149,12 @@ "common_favourited" = "已收藏"; "common_file" = "文件"; "common_forward_message" = "转发消息"; -"common_frequently_used" = "Frequently used"; +"common_frequently_used" = "常用"; "common_gif" = "GIF"; "common_image" = "图片"; "common_in_reply_to" = "回复 %1$@"; "common_invite_unknown_profile" = "找不到此 Matrix ID,因此可能无法收到邀请。"; -"common_leaving_room" = "正在离开房间"; +"common_leaving_room" = "正在离开聊天室"; "common_light" = "浅色"; "common_link_copied_to_clipboard" = "链接已复制到剪贴板"; "common_loading" = "正在加载..."; @@ -166,7 +165,7 @@ "common_modern" = "现代"; "common_mute" = "静音"; "common_no_results" = "没有结果"; -"common_no_room_name" = "无房间名"; +"common_no_room_name" = "无聊天室名"; "common_offline" = "离线"; "common_optic_id_ios" = "光学 ID"; "common_or" = "或"; @@ -189,8 +188,8 @@ "common_report_a_problem" = "报告问题"; "common_report_submitted" = "报告已提交"; "common_rich_text_editor" = "富文本编辑器"; -"common_room" = "房间"; -"common_room_name" = "房间名称"; +"common_room" = "聊天室"; +"common_room_name" = "聊天室名称"; "common_room_name_placeholder" = "例如:项目名称"; "common_saved_changes" = "保存的更改"; "common_saving" = "正在保存"; @@ -218,41 +217,42 @@ "common_third_party_notices" = "第三方通知"; "common_thread" = "消息列"; "common_topic" = "话题"; -"common_topic_placeholder" = "这个房间是关于什么的?"; +"common_topic_placeholder" = "这个聊天室是关于什么的?"; "common_touch_id_ios" = "触控 ID"; "common_unable_to_decrypt" = "无法解密"; "common_unable_to_decrypt_no_access" = "无权访问此消息"; -"common_unable_to_invite_message" = "无法向一个或多个用户发送邀请。"; +"common_unable_to_invite_message" = "无法向部分用户发送邀请。"; "common_unable_to_invite_title" = "无法发送邀请"; "common_unlock" = "解锁"; "common_unmute" = "解除静音"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "不支持的事件"; "common_username" = "用户名"; "common_verification_cancelled" = "验证已取消"; "common_verification_complete" = "验证完成"; -"common_verification_failed" = "Verification failed"; -"common_verified" = "Verified"; +"common_verification_failed" = "验证失败"; +"common_verified" = "已验证"; "common_verify_device" = "验证设备"; -"common_verify_identity" = "Verify identity"; +"common_verify_identity" = "验证身份"; "common_video" = "视频"; "common_voice_message" = "语音消息"; "common_waiting" = "等待..."; "common_waiting_for_decryption_key" = "正在等待解密密钥"; -"common.copied_to_clipboard" = "Copied to clipboard"; +"common.copied_to_clipboard" = "已复制到剪贴板"; "common.do_not_show_this_again" = "不再显示此内容"; "common.open_source_licenses" = "开源许可证"; -"common.pinned" = "Pinned"; +"common.pinned" = "已置顶"; "common.send_to" = "发送至"; -"common.you" = "You"; -"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" = "聊天备份目前不同步,需要输入恢复密钥才能访问聊天备份。"; -"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" = "输入恢复密钥"; +"common.you" = "您"; +"common_unable_to_decrypt_insecure_device" = "从不安全的设备发送"; +"common_unable_to_decrypt_verification_violation" = "发送者的已验证身份已改变"; +"confirm_recovery_key_banner_message" = "确认恢复密钥,以保持对密钥存储和消息历史的访问。"; +"confirm_recovery_key_banner_primary_button_title" = "输入恢复密钥"; +"confirm_recovery_key_banner_secondary_button_title" = "忘记了恢复密钥?"; +"confirm_recovery_key_banner_title" = "你的密钥存储已不同步"; "crash_detection_dialog_content" = "%1$@ 上次使用时崩溃了。想和我们分享崩溃报告吗?"; -"crypto_identity_change_pin_violation" = "%1$@'s identity appears to have changed. %2$@"; -"crypto_identity_change_pin_violation_new" = "%1$@’s %2$@ identity appears to have changed. %3$@"; +"crypto_identity_change_pin_violation" = "%1$@ 的身份似乎已经改变。%2$@"; +"crypto_identity_change_pin_violation_new" = "%1$@ 的 %2$@ 身份似乎已经改变。%3$@"; "crypto_identity_change_pin_violation_new_user_id" = "(%1$@)"; "dialog_permission_camera" = "为了让应用程序使用相机,请在系统设置中授予权限。"; "dialog_permission_generic" = "请在系统设置中授予权限。"; @@ -274,7 +274,7 @@ "emoji_picker_category_people" = "表情和人物"; "emoji_picker_category_places" = "旅行和地点"; "emoji_picker_category_symbols" = "符号"; -"error_account_creation_not_possible" = "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation."; +"error_account_creation_not_possible" = "您的服务器需要升级,以支持 Matrix 鉴权服务和账户创建。"; "error_failed_creating_the_permalink" = "创建固定链接失败"; "error_failed_loading_map" = "%1$@ 无法加载地图,请稍后再试。"; "error_failed_loading_messages" = "加载消息失败"; @@ -285,7 +285,7 @@ "error_some_messages_have_not_been_sent" = "某些信息尚未发送"; "error_unknown" = "抱歉,发生了错误"; "event_shield_reason_authenticity_not_guaranteed" = "此加密消息的真实性无法在此设备上保证。"; -"event_shield_reason_previously_verified" = "Encrypted by a previously-verified user."; +"event_shield_reason_previously_verified" = "由先前验证过的用户加密。"; "event_shield_reason_sent_in_clear" = "未加密。"; "event_shield_reason_unknown_device" = "由未知或已删除的设备加密。"; "event_shield_reason_unsigned_device" = "由未经其所有者验证的设备加密。"; @@ -295,9 +295,9 @@ "invite_friends_rich_title" = "🔐️ 加入我 %1$@"; "invite_friends_text" = "嗨!请通过 %1$@ 与我联系:%2$@"; "leave_conversation_alert_subtitle" = "您确定要离开此对话吗?此对话不公开,未经邀请您将无法重新加入。"; -"leave_room_alert_empty_subtitle" = "确定要离开这个房间吗?这里只有你一个人。如果你离开此房间,包括你在内的所有人都将无法进入。"; -"leave_room_alert_private_subtitle" = "确定要离开这个房间吗?此房间不公开,没有邀请你将无法重新加入。"; -"leave_room_alert_subtitle" = "确定要离开房间吗?"; +"leave_room_alert_empty_subtitle" = "确定要离开此聊天室吗?此处只有你一个人。如果离开此聊天室,包括你在内的所有人都将无法进入。"; +"leave_room_alert_private_subtitle" = "确定要离开此聊天室吗?此聊天室不公开,没有邀请你将无法重新加入。"; +"leave_room_alert_subtitle" = "确定要离开聊天室吗?"; "login_initial_device_name_ios" = "%1$@ iOS"; "notification_channel_call" = "通话"; "notification_channel_listening_for_events" = "监听事件"; @@ -305,14 +305,14 @@ "notification_channel_ringing_calls" = "来电振铃"; "notification_channel_silent" = "静默通知"; "notification_incoming_call" = "来电"; -"notification_inline_reply_failed" = "** 无法发送——请打开房间"; +"notification_inline_reply_failed" = "** 无法发送——请打开聊天室"; "notification_invite_body" = "邀请您聊天"; -"notification_invite_body_with_sender" = "%1$@ invited you to chat"; +"notification_invite_body_with_sender" = "%1$@ 邀您聊天"; "notification_mentioned_you_body" = "提到了你:%1$@"; "notification_new_messages" = "新消息"; "notification_reaction_body" = "使用 %1$@ 回应"; -"notification_room_invite_body" = "邀请你加入房间"; -"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; +"notification_room_invite_body" = "邀请你加入聊天室"; +"notification_room_invite_body_with_sender" = "%1$@ 邀请您加入房间"; "notification_sender_me" = "我"; "notification_sender_mention_reply" = "%1$@提及或回复"; "notification_test_push_notification_content" = "您正在查看通知!点击我!"; @@ -344,63 +344,69 @@ "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" = "可选的标题……"; "screen_advanced_settings_element_call_base_url" = "自定义 Element Call URL"; "screen_advanced_settings_element_call_base_url_description" = "为 Element 通话设置根 URL。"; "screen_advanced_settings_element_call_base_url_validation_error" = "URL 无效,请确保包含协议(http/https)和正确的地址。"; -"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_access_section_anyone_option_description" = "任何人都可以加入此房间"; +"screen_create_room_room_access_section_anyone_option_title" = "任何人"; +"screen_create_room_room_access_section_header" = "房间访问权限"; +"screen_create_room_room_access_section_knocking_option_description" = "任何人都可以请求加入房间,但必须由管理员或审核人接受"; +"screen_create_room_room_access_section_knocking_option_title" = "请求加入"; "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_create_room_room_address_section_footer" = "要使该房间在公开房间目录中可见,您需要一个房间地址。"; +"screen_create_room_room_address_section_title" = "房间地址"; +"screen_create_room_room_visibility_section_title" = "房间可见性"; +"screen_join_room_cancel_knock_action" = "取消请求"; +"screen_join_room_cancel_knock_alert_confirmation" = "是的,取消"; +"screen_join_room_cancel_knock_alert_description" = "您确定要取消加入此房间的请求吗?"; +"screen_join_room_cancel_knock_alert_title" = "取消加入申请"; +"screen_join_room_knock_message_description" = "消息(可选)"; +"screen_join_room_knock_sent_description" = "如果您的请求被接受,您将收到加入房间的邀请。"; +"screen_join_room_knock_sent_title" = "加入请求已发送"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "按下消息并选择 “%1$@” 将其包含在此处。"; "screen_pinned_timeline_empty_state_headline" = "固定重要消息,以便轻松发现它们"; "screen_reset_encryption_password_error" = "发生未知错误。请检查您的帐户密码是否正确,然后重试。"; -"screen_resolve_send_failure_changed_identity_primary_button_title" = "Withdraw verification and send"; -"screen_resolve_send_failure_changed_identity_subtitle" = "You can withdraw your verification and send this message anyway, or you can cancel for now and try again later after reverifying %1$@."; -"screen_resolve_send_failure_changed_identity_title" = "Your message was not sent because %1$@’s verified identity has changed"; -"screen_resolve_send_failure_unsigned_device_primary_button_title" = "Send message anyway"; -"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$@ has verified all their devices."; +"screen_resolve_send_failure_changed_identity_primary_button_title" = "撤回验证并发送"; +"screen_resolve_send_failure_changed_identity_subtitle" = "您可以撤回验证并仍然发送此消息;也可以暂时取消验证,在重新验证 %1$@ 后重试。"; +"screen_resolve_send_failure_changed_identity_title" = "您的消息未发送,因为 %1$@ 的已验证身份已发生改变"; +"screen_resolve_send_failure_unsigned_device_primary_button_title" = "仍然发送消息"; +"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ 正在使用一个或多个未经验证的设备。您还是可以继续发送信息;也可以暂时取消,等 %2$@ 验证了所有设备后重试。"; "screen_resolve_send_failure_unsigned_device_title" = "您的消息未发送,因为%1$@尚未验证所有设备"; -"screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; -"screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; -"screen_room_mentions_at_room_subtitle" = "通知整个房间"; +"screen_resolve_send_failure_you_unsigned_device_subtitle" = "您有未验证的设备。您仍然可以发送消息;也可以暂时取消,并在验证所有设备后稍后重试。"; +"screen_resolve_send_failure_you_unsigned_device_title" = "您的消息未发送,因为您有尚未验证的设备。"; +"screen_room_mentions_at_room_subtitle" = "通知整个聊天室"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ / %2$@"; "screen_room_pinned_banner_indicator_description" = "置顶消息 %1$@"; "screen_room_pinned_banner_loading_description" = "正在加载消息..."; "screen_room_pinned_banner_view_all_button_title" = "查看全部"; +"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_details_pinned_events_row_title" = "置顶消息"; -"screen_roomlist_knock_event_sent_description" = "Request to join sent"; -"screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed."; +"screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_roomlist_knock_event_sent_description" = "加入请求已发送"; +"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" = "Message not sent because you have not verified one or more of your devices."; +"screen_timeline_item_menu_send_failure_you_unsigned_device" = "消息未发送,因为您有尚未验证的设备。"; "screen_account_provider_form_hint" = "服务器地址"; "screen_account_provider_form_notice" = "输入搜索词或域名地址。"; "screen_account_provider_form_subtitle" = "搜索公司、社区或私人服务器。"; -"screen_account_provider_form_title" = "查找账户提供者"; -"screen_account_provider_signin_title" = "您即将登录%@"; +"screen_account_provider_form_title" = "寻找账户提供方"; +"screen_account_provider_signin_title" = "您即将登录 %@"; "screen_account_provider_signup_title" = "您即将在 %@ 上创建一个帐户"; "screen_advanced_settings_developer_mode" = "开发者模式"; "screen_advanced_settings_developer_mode_description" = "允许开发人员访问特性和功能。"; -"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" = "针对上传进行优化"; +"screen_advanced_settings_media_compression_title" = "媒体"; "screen_advanced_settings_rich_text_editor_description" = "禁用富文本编辑器,手动输入 Markdown。"; "screen_advanced_settings_send_read_receipts" = "已读回执"; -"screen_advanced_settings_send_read_receipts_description" = "如果关闭,您的已读回执将不会发送给别人。您仍能收到别人的已读回执。"; +"screen_advanced_settings_send_read_receipts_description" = "关闭后已读回执将不会发送给他人,但仍能收到他人的已读回执。"; "screen_advanced_settings_share_presence" = "分享在线状态"; -"screen_advanced_settings_share_presence_description" = "如果关闭,您将无法发送或接收已读回执、输入通知"; +"screen_advanced_settings_share_presence_description" = "关闭后将无法发送或接收已读回执、输入通知"; "screen_advanced_settings_view_source_description" = "启用在时间轴中查看消息源码的选项。"; "screen_analytics_prompt_data_usage" = "我们不会记录或分析任何个人数据"; "screen_analytics_prompt_help_us_improve" = "共享匿名使用数据以帮助我们排查问题。"; @@ -451,8 +457,8 @@ "screen_bug_report_view_logs" = "查看日志"; "screen_change_account_provider_matrix_org_subtitle" = "Matrix.org 由 Matrix.org 基金会运营,是用于安全、去中心化的通信的公共 Matrix 网络上的大型免费服务器。"; "screen_change_account_provider_other" = "其他"; -"screen_change_account_provider_subtitle" = "使用其他帐户提供者,例如您自己的私人服务器或工作帐户。"; -"screen_change_account_provider_title" = "更改账户提供者"; +"screen_change_account_provider_subtitle" = "使用其他账户提供商,例如您自己的私人服务器或工作账户。"; +"screen_change_account_provider_title" = "更改账户提供方"; "screen_change_server_error_invalid_homeserver" = "我们无法访问此服务器。请检查您输入的服务器网址是否正确。如果 URL 正确,请联系您的服务器管理员寻求进一步帮助。"; "screen_change_server_error_invalid_well_known" = "由于 Well Known 文件中的问题,Sliding Sync 不可用:\n%1$@"; "screen_change_server_error_no_sliding_sync_message" = "该服务器目前不支持 Sliding Sync。"; @@ -462,16 +468,16 @@ "screen_change_server_title" = "选择服务器"; "screen_chat_backup_key_backup_action_disable" = "关闭备份"; "screen_chat_backup_key_backup_action_enable" = "开启备份"; -"screen_chat_backup_key_backup_description" = "备份可确保你不会丢失消息历史记录。%1$@。"; -"screen_chat_backup_key_backup_title" = "备份"; -"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" = "将您的密码学身份和消息密钥安全地存储在服务器上。这样您就可以在任何新设备上查看您的消息历史记录。%1$@。"; +"screen_chat_backup_key_backup_title" = "密钥存储"; +"screen_chat_backup_key_storage_disabled_error" = "必须打开密钥存储才能设置恢复。"; +"screen_chat_backup_key_storage_toggle_description" = "从此设备上传密钥"; +"screen_chat_backup_key_storage_toggle_title" = "允许密钥存储"; "screen_chat_backup_recovery_action_change" = "更改恢复密钥"; -"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" = "您的聊天备份当前不同步。"; +"screen_chat_backup_recovery_action_change_description" = "如果您丢失了所有现有设备,使用恢复密钥恢复您的密码学身份和消息历史记录。"; +"screen_chat_backup_recovery_action_confirm_description" = "您的密钥存储当前不同步。"; "screen_chat_backup_recovery_action_setup_description" = "在丢失或从 %1$@ 登出所有设备的情况下访问加密消息。"; -"screen_create_account_title" = "Create account"; +"screen_create_account_title" = "创建账户"; "screen_create_new_recovery_key_list_item_1" = "在桌面设备中打开 %1$@"; "screen_create_new_recovery_key_list_item_2" = "再次登录您的账户"; "screen_create_new_recovery_key_list_item_3" = "当要求验证您的设备时,选择 %1$@"; @@ -488,23 +494,23 @@ "screen_create_poll_question_hint" = "投票的内容是什么?"; "screen_create_poll_title" = "创建投票"; "screen_create_room_action_create_room" = "新聊天室"; -"screen_create_room_error_creating_room" = "创建房间时出错"; -"screen_create_room_private_option_description" = "此聊天室中的消息已加密。加密无法禁用。"; -"screen_create_room_private_option_title" = "私人房间(仅限受邀者)"; -"screen_create_room_public_option_description" = "消息未加密,任何人都可以查看。可以稍后启用加密。"; -"screen_create_room_public_option_title" = "公共房间(任何人)"; +"screen_create_room_error_creating_room" = "创建聊天室时出错"; +"screen_create_room_private_option_description" = "只有受邀用户才能访问此房间。所有消息均经过端到端加密。"; +"screen_create_room_private_option_title" = "私有房间"; +"screen_create_room_public_option_description" = "任何人都能找到此房间。\n你可以随时在房间设置中更改。"; +"screen_create_room_public_option_title" = "公开房间"; "screen_create_room_topic_label" = "主题(可选)"; -"screen_deactivate_account_confirmation_dialog_content" = "Please confirm that you want to deactivate your account. This action cannot be undone."; -"screen_deactivate_account_delete_all_messages" = "Delete all my messages"; -"screen_deactivate_account_delete_all_messages_notice" = "Warning: Future users may see incomplete conversations."; -"screen_deactivate_account_description" = "Deactivating your account is %1$@, it will:"; -"screen_deactivate_account_description_bold_part" = "irreversible"; -"screen_deactivate_account_list_item_1" = "%1$@ your account (you can't log back in, and your ID can't be reused)."; -"screen_deactivate_account_list_item_1_bold_part" = "Permanently disable"; -"screen_deactivate_account_list_item_2" = "Remove you from all chat rooms."; -"screen_deactivate_account_list_item_3" = "Delete your account information from our identity server."; -"screen_deactivate_account_list_item_4" = "Your messages will still be visible to registered users but won’t be available to new or unregistered users if you choose to delete them."; -"screen_deactivate_account_title" = "Deactivate account"; +"screen_deactivate_account_confirmation_dialog_content" = "请确认您要停用您的账户。此操作无法撤消。"; +"screen_deactivate_account_delete_all_messages" = "删除我的所有消息"; +"screen_deactivate_account_delete_all_messages_notice" = "警告:未来的用户可能会看到不完整的对话。"; +"screen_deactivate_account_description" = "停用您的帐户是%1$@,它将:"; +"screen_deactivate_account_description_bold_part" = "不可逆转的"; +"screen_deactivate_account_list_item_1" = "%1$@您的账户(您无法登录回来,并且您的ID无法重复使用)。"; +"screen_deactivate_account_list_item_1_bold_part" = "永久禁用"; +"screen_deactivate_account_list_item_2" = "将您从所有聊天房间中移除。"; +"screen_deactivate_account_list_item_3" = "从我们的身份服务器中删除您的账户信息。"; +"screen_deactivate_account_list_item_4" = "注册用户仍可看到您的消息,但如果您选择删除它们,新用户或未注册用户将无法看到您的消息。"; +"screen_deactivate_account_title" = "停用账户"; "screen_edit_poll_delete_confirmation" = "您确定要删除此投票吗?"; "screen_edit_profile_display_name" = "显示名称"; "screen_edit_profile_display_name_placeholder" = "你的显示名称"; @@ -534,12 +540,12 @@ "screen_invites_empty_list" = "没有邀请"; "screen_invites_invited_you" = "%1$@ (%2$@)邀请了你"; "screen_join_room_join_action" = "加入聊天室"; -"screen_join_room_knock_action" = "加入房间"; +"screen_join_room_knock_action" = "加入聊天室"; "screen_join_room_space_not_supported_description" = "%1$@ 尚不支持空间。您可以通过 Web 端访问空间"; "screen_join_room_space_not_supported_title" = "空间尚不支持"; -"screen_join_room_subtitle_knock" = "点击下面的按钮,系统将通知房间管理员。获得批准后,您将能够加入对话。"; +"screen_join_room_subtitle_knock" = "点击下面的按钮,系统将通知聊天室管理员。获得批准后将能够加入对话。"; "screen_join_room_subtitle_no_preview" = "只有聊天室成员才能查看消息历史记录。"; -"screen_join_room_title_knock" = "想加入这个房间吗?"; +"screen_join_room_title_knock" = "想加入这个聊天室吗?"; "screen_join_room_title_no_preview" = "预览不可用"; "screen_key_backup_disable_confirmation_action_turn_off" = "关闭"; "screen_key_backup_disable_confirmation_description" = "如果您登出所有设备,您的加密消息将丢失。"; @@ -567,7 +573,7 @@ "screen_notification_settings_calls_label" = "音视频通话"; "screen_notification_settings_configuration_mismatch" = "配置不匹配"; "screen_notification_settings_configuration_mismatch_description" = "我们简化了通知设置,使选项更易于查找。您过去选择的某些自定义设置未在此处显示,但它们仍然有效。\n\n如果继续,您的某些设置可能会更改。"; -"screen_notification_settings_direct_chats" = "直接聊天"; +"screen_notification_settings_direct_chats" = "私聊"; "screen_notification_settings_edit_custom_settings_section_title" = "各聊天室的独立设置"; "screen_notification_settings_edit_failed_updating_default_mode" = "更新通知设置时出错。"; "screen_notification_settings_edit_mode_all_messages" = "全部消息"; @@ -578,11 +584,11 @@ "screen_notification_settings_failed_fixing_configuration" = "配置尚未更正,请重试。"; "screen_notification_settings_group_chats" = "群聊"; "screen_notification_settings_invite_for_me_label" = "邀请"; -"screen_notification_settings_mentions_only_disclaimer" = "您的服务器在加密房间中不支持此选项,因此在某些房间您可能无法收到通知。"; +"screen_notification_settings_mentions_only_disclaimer" = "服务器在加密聊天室中不支持此选项,因此在某些聊天室可能无法收到通知。"; "screen_notification_settings_mode_all" = "全部"; "screen_notification_settings_mode_mentions" = "提及"; "screen_notification_settings_notification_section_title" = "请通知我:"; -"screen_notification_settings_room_mention_label" = "在 @room 通知我"; +"screen_notification_settings_room_mention_label" = "@room 时通知我"; "screen_notification_settings_system_notifications_action_required" = "要接收通知,请更改您的 %1$@。"; "screen_notification_settings_system_notifications_action_required_content_link" = "系统设置"; "screen_notification_settings_system_notifications_turned_off" = "系统通知已关闭"; @@ -617,7 +623,7 @@ "screen_qr_code_login_error_expired_title" = "登录未及时完成"; "screen_qr_code_login_error_linking_not_suported_subtitle" = "另一个设备不支持使用二维码登录 %@.\n\n尝试手动或使用另一个设备扫描二维码."; "screen_qr_code_login_error_linking_not_suported_title" = "不支持二维码"; -"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "账户提供者不支持 %1$@."; +"screen_qr_code_login_error_sliding_sync_not_supported_subtitle" = "账户提供方不支持 %1$@."; "screen_qr_code_login_error_sliding_sync_not_supported_title" = "不支持 %1$@."; "screen_qr_code_login_initial_state_button_title" = "准备进行扫描"; "screen_qr_code_login_initial_state_item_1" = "在桌面设备上打开 %1$@"; @@ -625,7 +631,7 @@ "screen_qr_code_login_initial_state_item_3" = "选择 %1$@"; "screen_qr_code_login_initial_state_item_3_action" = "「连接新设备」"; "screen_qr_code_login_initial_state_item_4" = "使用此设备扫描二维码"; -"screen_qr_code_login_initial_state_subtitle" = "Only available if your account provider supports it."; +"screen_qr_code_login_initial_state_subtitle" = "仅在您的账户提供方支持时才可用。"; "screen_qr_code_login_initial_state_title" = "在另一台设备上打开 %1$@ 以获取二维码"; "screen_qr_code_login_invalid_scan_state_description" = "使用其他设备上显示的二维码。"; "screen_qr_code_login_invalid_scan_state_subtitle" = "二维码错误"; @@ -636,7 +642,7 @@ "screen_qr_code_login_start_over_button" = "重新开始"; "screen_qr_code_login_unknown_error_description" = "发生了意外错误。请再试一次。"; "screen_qr_code_login_verify_code_loading" = "等着您的其他设备"; -"screen_qr_code_login_verify_code_subtitle" = "您的账户提供商可能会要求您提供以下代码来验证登录。"; +"screen_qr_code_login_verify_code_subtitle" = "您的账户提供方可能会要求您提供以下代码来验证登录。"; "screen_qr_code_login_verify_code_title" = "您的验证码"; "screen_recovery_key_change_description" = "如果您丢失了现有的恢复密钥,请获取新的恢复密钥。更改恢复密钥后,您的旧密钥将不再起作用。"; "screen_recovery_key_change_generate_key" = "生成新的恢复密钥"; @@ -644,7 +650,7 @@ "screen_recovery_key_change_title" = "更改恢复密钥?"; "screen_recovery_key_confirm_create_new_recovery_key" = "创建新的恢复密钥"; "screen_recovery_key_confirm_description" = "确保没有人能看到这个界面!"; -"screen_recovery_key_confirm_error_content" = "请重试以访问您的聊天备份。"; +"screen_recovery_key_confirm_error_content" = "请重试以确认访问您的密钥存储。"; "screen_recovery_key_confirm_error_title" = "恢复密钥不正确"; "screen_recovery_key_confirm_key_description" = "如果您有安全密钥或安全短语,也可以用。"; "screen_recovery_key_confirm_key_placeholder" = "输入……"; @@ -653,14 +659,14 @@ "screen_recovery_key_copied_to_clipboard" = "恢复密钥已复制"; "screen_recovery_key_generating_key" = "正在生成……"; "screen_recovery_key_save_action" = "保存恢复密钥"; -"screen_recovery_key_save_description" = "在安全的地方写下恢复密钥或将其保存在密码管理器中。"; +"screen_recovery_key_save_description" = "将此恢复密钥保存在安全的地方,例如密码管理器、加密笔记或物理保险箱。"; "screen_recovery_key_save_key_description" = "点击复制恢复密钥"; "screen_recovery_key_save_title" = "保存您的恢复密钥"; "screen_recovery_key_setup_confirmation_description" = "完成此步骤后,您将无法访问新的恢复密钥。"; "screen_recovery_key_setup_confirmation_title" = "您保存了恢复密钥吗?"; "screen_recovery_key_setup_description" = "您的聊天备份受恢复密钥保护。如果您在安装后需要新的恢复密钥,则可以通过选择「更改恢复密钥」来重新创建。"; "screen_recovery_key_setup_generate_key" = "生成恢复密钥"; -"screen_recovery_key_setup_generate_key_description" = "确保将恢复密钥存储在安全的地方"; +"screen_recovery_key_setup_generate_key_description" = "不要告诉任何人!"; "screen_recovery_key_setup_success" = "恢复设置成功"; "screen_recovery_key_setup_title" = "设置恢复"; "screen_report_content_block_user_hint" = "请确认是否要隐藏该用户当前和未来的所有信息"; @@ -673,7 +679,7 @@ "screen_reset_encryption_password_title" = "输入您的账户密码以继续"; "screen_reset_identity_confirmation_subtitle" = "您将要转到您的%1$@帐户来重置您的身份信息。之后,您将被带回该应用。"; "screen_reset_identity_confirmation_title" = "无法确认?请前往您的帐户重置您的身份。"; -"screen_room_alias_resolver_resolve_alias_failure" = "无法解析房间别名。"; +"screen_room_alias_resolver_resolve_alias_failure" = "无法解析聊天室别名。"; "screen_room_attachment_source_camera" = "相机"; "screen_room_attachment_source_camera_video" = "录制视频"; "screen_room_attachment_source_files" = "附件"; @@ -695,7 +701,7 @@ "screen_room_change_role_confirm_add_admin_description" = "您将无法撤消此操作。您正在提升用户的权限,使其拥有与您平权。"; "screen_room_change_role_confirm_add_admin_title" = "添加管理员?"; "screen_room_change_role_confirm_demote_self_action" = "降级"; -"screen_room_change_role_confirm_demote_self_description" = "由于您正在降级,您将无法撤消此更改。如果您是房间中的最后一个特权用户,则无法重新获得权限。"; +"screen_room_change_role_confirm_demote_self_description" = "您正在降级,此更改将无法撤消。如果您是聊天室中的最后一个特权用户,则无法重新获得权限。"; "screen_room_change_role_confirm_demote_self_title" = "降级自己?"; "screen_room_change_role_invited_member_name" = "%1$@(待处理)"; "screen_room_change_role_moderators_admin_section_footer" = "管理员自动拥有协管员权限"; @@ -706,22 +712,22 @@ "screen_room_details_already_invited" = "已邀请"; "screen_room_details_badge_encrypted" = "加密的"; "screen_room_details_badge_not_encrypted" = "未加密的"; -"screen_room_details_badge_public" = "公开房间"; +"screen_room_details_badge_public" = "公共聊天室"; "screen_room_details_edit_room_title" = "编辑聊天室"; "screen_room_details_edition_error" = "出现未知错误,无法更改信息。"; "screen_room_details_edition_error_title" = "无法更新聊天室"; "screen_room_details_encryption_enabled_subtitle" = "消息已加密,只有你和消息接收者拥有唯一解密密钥。"; "screen_room_details_encryption_enabled_title" = "消息加密已启用"; "screen_room_details_error_loading_notification_settings" = "加载通知设置时出错。"; -"screen_room_details_error_muting" = "无法将此房间静音,请重试。"; -"screen_room_details_error_unmuting" = "无法取消此房间的静音,请重试。"; +"screen_room_details_error_muting" = "无法将此聊天室静音,请重试。"; +"screen_room_details_error_unmuting" = "无法取消此聊天室的静音,请重试。"; "screen_room_details_notification_mode_custom" = "自定义"; "screen_room_details_notification_mode_default" = "默认"; -"screen_room_details_share_room_title" = "分享房间"; +"screen_room_details_share_room_title" = "分享聊天室"; "screen_room_details_title" = "聊天室信息"; -"screen_room_details_updating_room" = "正在更新房间……"; +"screen_room_details_updating_room" = "正在更新聊天室……"; "screen_room_directory_search_loading_error" = "加载失败"; -"screen_room_directory_search_title" = "房间目录"; +"screen_room_directory_search_title" = "聊天室目录"; "screen_room_encrypted_history_banner" = "消息历史记录当前不可用。"; "screen_room_encrypted_history_banner_unverified" = "此聊天室无法查看消息历史记录。请验证此设备以查看之。"; "screen_room_error_failed_retrieving_user_details" = "无法获取用户信息"; @@ -734,19 +740,19 @@ "screen_room_member_details_unblock_alert_action" = "解封"; "screen_room_member_details_unblock_alert_description" = "可以重新接收他们的消息。"; "screen_room_member_details_unblock_user" = "解封用户"; -"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" = "使用 Web 应用程序验证此用户。"; +"screen_room_member_details_verify_button_title" = "验证 %1$@"; "screen_room_member_list_ban_member_confirmation_action" = "封禁"; -"screen_room_member_list_ban_member_confirmation_description" = "即使受到邀请,他们也无法再次加入房间。"; +"screen_room_member_list_ban_member_confirmation_description" = "即使受到邀请,他们也无法再次加入聊天室。"; "screen_room_member_list_ban_member_confirmation_title" = "您确定要封禁该成员吗?"; -"screen_room_member_list_banned_empty" = "这个房间里没有被封禁的用户。"; +"screen_room_member_list_banned_empty" = "此聊天室里没有被封禁的用户。"; "screen_room_member_list_banning_user" = "封禁 %1$@"; "screen_room_member_list_manage_member_ban" = "移除并封禁成员"; -"screen_room_member_list_manage_member_remove" = "从房间移除"; +"screen_room_member_list_manage_member_remove" = "从聊天室移除"; "screen_room_member_list_manage_member_remove_confirmation_kick" = "仅移除成员"; "screen_room_member_list_manage_member_remove_confirmation_title" = "删除成员并禁止重新加入?"; "screen_room_member_list_manage_member_unban_action" = "取消封禁"; -"screen_room_member_list_manage_member_unban_message" = "如果受到邀请,他们可以重新加入房间。"; +"screen_room_member_list_manage_member_unban_message" = "如果受到邀请,他们可以重新加入聊天室。"; "screen_room_member_list_manage_member_unban_title" = "解封用户"; "screen_room_member_list_manage_member_user_info" = "查看个人资料"; "screen_room_member_list_mode_banned" = "已封禁用户"; @@ -767,7 +773,7 @@ "screen_room_notification_settings_error_loading_settings" = "加载通知设置时出错。"; "screen_room_notification_settings_error_restoring_default" = "恢复默认模式失败,请重试。"; "screen_room_notification_settings_error_setting_mode" = "设置模式失败,请重试。"; -"screen_room_notification_settings_mentions_only_disclaimer" = "您的服务器在加密房间中不支持此选项,您无法在此房间收到通知。"; +"screen_room_notification_settings_mentions_only_disclaimer" = "服务器在加密聊天室中不支持此选项,无法在此聊天室收到通知。"; "screen_room_notification_settings_mode_all_messages" = "所有消息"; "screen_room_notification_settings_room_custom_settings_title" = "在这个聊天室,通知我:"; "screen_room_retry_send_menu_send_again_action" = "再次发送"; @@ -789,9 +795,10 @@ "screen_room_timeline_add_reaction" = "添加表情符号"; "screen_room_timeline_beginning_of_room" = "这是 %1$@ 聊天室的开始。"; "screen_room_timeline_beginning_of_room_no_name" = "这是本对话的开始。"; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "折叠"; "screen_room_timeline_message_copied" = "消息已复制"; -"screen_room_timeline_no_permission_to_post" = "您无权在此房间发言"; +"screen_room_timeline_no_permission_to_post" = "您无权在此聊天室发言"; "screen_room_timeline_reactions_show_more" = "展开"; "screen_room_timeline_read_marker_title" = "新消息"; "screen_room_title" = "聊天"; @@ -819,10 +826,10 @@ "screen_roomlist_main_space_title" = "全部聊天"; "screen_roomlist_mark_as_read" = "标记为已读"; "screen_roomlist_mark_as_unread" = "标记为未读"; -"screen_roomlist_room_directory_button_title" = "浏览所有房间"; +"screen_roomlist_room_directory_button_title" = "浏览所有聊天室"; "screen_server_confirmation_message_login_element_dot_io" = "专为 Element 员工提供的私人服务器。"; "screen_server_confirmation_message_login_matrix_dot_org" = "Matrix 是一个用于安全、去中心化通信的开放网络。"; -"screen_server_confirmation_message_register" = "这是您的对话将进行的地方,就像您使用电子邮件提供商来保存电子邮件一样。"; +"screen_server_confirmation_message_register" = "这是您的对话将存在的地方,就像您使用电子邮件提供方来保存电子邮件一样。"; "screen_server_confirmation_title_login" = "即将登录 %1$@"; "screen_server_confirmation_title_register" = "即将在 %1$@ 上创建一个账户"; "screen_session_verification_cancelled_subtitle" = "发生了一些错误。网络请求超时,或者被服务器拒绝。"; @@ -832,27 +839,27 @@ "screen_session_verification_compare_numbers_title" = "比较数字"; "screen_session_verification_complete_subtitle" = "新设备已经成功验证。现在新设备可以访问加密信息,其他用户也会信任这个设备。"; "screen_session_verification_enter_recovery_key" = "输入恢复密钥"; -"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" = "要么请求超时,要么请求被拒绝,要么验证不匹配。"; "screen_session_verification_open_existing_session_subtitle" = "证明自己的身份以访问加密历史消息。"; "screen_session_verification_open_existing_session_title" = "打开已有会话"; "screen_session_verification_positive_button_canceled" = "重试验证"; "screen_session_verification_positive_button_initial" = "准备就绪"; -"screen_session_verification_positive_button_verifying_ongoing" = "等待比对"; +"screen_session_verification_positive_button_verifying_ongoing" = "等待比对……"; "screen_session_verification_ready_subtitle" = "比较一组表情符号。"; "screen_session_verification_request_accepted_subtitle" = "比较表情符号,确保它们以相同顺序排列。"; -"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" = "已登录"; +"screen_session_verification_request_failure_title" = "验证失败"; +"screen_session_verification_request_footer" = "仅在你发起此验证后才继续。"; +"screen_session_verification_request_subtitle" = "验证另一台设备以确保您的消息历史记录保密。"; +"screen_session_verification_request_success_subtitle" = "现在,您可以在其他设备上安全地阅读或发送消息。"; +"screen_session_verification_request_success_title" = "设备已验证"; +"screen_session_verification_request_title" = "已请求验证"; "screen_session_verification_they_dont_match" = "不匹配"; "screen_session_verification_they_match" = "匹配"; "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_use_another_device_title" = "在另一台验证的设备上打开应用"; "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_another_device_title" = "在另一台设备上开始验证"; "screen_session_verification_waiting_to_accept_subtitle" = "请在其他会话中接受验证请求。"; "screen_session_verification_waiting_to_accept_title" = "等待接受请求"; "screen_share_location_title" = "分享位置"; @@ -879,7 +886,7 @@ "screen_start_chat_error_starting_chat" = "在开始聊天时发生了错误"; "screen_view_location_title" = "位置"; "screen_welcome_bullet_1" = "今年晚些时候将增加通话、投票、搜索等功能。"; -"screen_welcome_bullet_2" = "加密房间的消息历史记录尚不可用。"; +"screen_welcome_bullet_2" = "加密聊天室的消息历史记录尚不可用。"; "screen_welcome_bullet_3" = "我们很乐意听取您的意见,请通过设置页面告诉我们您的想法。"; "screen_welcome_button" = "开始吧!"; "screen_welcome_subtitle" = "以下是您需要了解的内容:"; @@ -902,21 +909,21 @@ "state_event_display_name_set_by_you" = "你将显示名称设置为 %1$@"; "state_event_promoted_to_administrator" = "%1$@ 晋升为管理员"; "state_event_promoted_to_moderator" = "%1$@ 晋升为协管员"; -"state_event_room_avatar_changed" = "%1$@ 更换了房间头像"; -"state_event_room_avatar_changed_by_you" = "你更换了房间头像"; -"state_event_room_avatar_removed" = "%1$@ 移除了房间头像"; -"state_event_room_avatar_removed_by_you" = "你移除了房间头像"; +"state_event_room_avatar_changed" = "%1$@ 更换了聊天室头像"; +"state_event_room_avatar_changed_by_you" = "你更换了聊天室头像"; +"state_event_room_avatar_removed" = "%1$@ 移除了聊天室头像"; +"state_event_room_avatar_removed_by_you" = "你移除了聊天室头像"; "state_event_room_ban" = "%1$@ 封禁了 %2$@"; "state_event_room_ban_by_you" = "你封禁了 %1$@"; -"state_event_room_created" = "%1$@ 创建了房间"; -"state_event_room_created_by_you" = "你创建了房间"; +"state_event_room_created" = "%1$@ 创建了聊天室"; +"state_event_room_created_by_you" = "你创建了聊天室"; "state_event_room_invite" = "%1$@ 邀请了 %2$@"; "state_event_room_invite_accepted" = "%1$@ 接受了邀请"; "state_event_room_invite_accepted_by_you" = "你接受了邀请"; "state_event_room_invite_by_you" = "你邀请了 %1$@"; "state_event_room_invite_you" = "%1$@ 邀请了你"; -"state_event_room_join" = "%1$@ 加入了房间"; -"state_event_room_join_by_you" = "你加入了房间"; +"state_event_room_join" = "%1$@ 加入了聊天室"; +"state_event_room_join_by_you" = "你加入了聊天室"; "state_event_room_knock" = "%1$@ 请求加入"; "state_event_room_knock_accepted" = "%1$@ 允许 %2$@ 加入"; "state_event_room_knock_accepted_by_you" = "您已允许 %1$@ 加入"; @@ -926,12 +933,12 @@ "state_event_room_knock_denied_you" = "%1$@ 拒绝了你的加入请求"; "state_event_room_knock_retracted" = "%1$@ 已不再想加入"; "state_event_room_knock_retracted_by_you" = "你取消了加入申请"; -"state_event_room_leave" = "%1$@ 离开了房间"; -"state_event_room_leave_by_you" = "你离开了房间"; -"state_event_room_name_changed" = "%1$@ 将房间名称改为 %2$@"; -"state_event_room_name_changed_by_you" = "你把房间名称改为 %1$@"; -"state_event_room_name_removed" = "%1$@ 移除了房间名称"; -"state_event_room_name_removed_by_you" = "你移除了房间名称"; +"state_event_room_leave" = "%1$@ 离开了聊天室"; +"state_event_room_leave_by_you" = "你离开了聊天室"; +"state_event_room_name_changed" = "%1$@ 将聊天室名称改为 %2$@"; +"state_event_room_name_changed_by_you" = "你把聊天室名称改为 %1$@"; +"state_event_room_name_removed" = "%1$@ 移除了聊天室名称"; +"state_event_room_name_removed_by_you" = "你移除了聊天室名称"; "state_event_room_none" = "%1$@ 没有任何更改"; "state_event_room_none_by_you" = "您未进行任何更改"; "state_event_room_pinned_events_changed" = "%1$@ 更改了置顶消息"; @@ -944,14 +951,14 @@ "state_event_room_reject_by_you" = "你拒绝了邀请"; "state_event_room_remove" = "%1$@ 移除了 %2$@"; "state_event_room_remove_by_you" = "你移除了 %1$@"; -"state_event_room_third_party_invite" = "%1$@向%2$@发送了加入房间的邀请"; -"state_event_room_third_party_invite_by_you" = "你邀请 %1$@ 加入房间"; -"state_event_room_third_party_revoked_invite" = "%1$@ 撤销了 %2$@ 加入房间的邀请"; -"state_event_room_third_party_revoked_invite_by_you" = "你撤销了 %1$@ 加入房间的邀请"; +"state_event_room_third_party_invite" = "%1$@ 向 %2$@ 发送了加入聊天室的邀请"; +"state_event_room_third_party_invite_by_you" = "你邀请 %1$@ 加入聊天室"; +"state_event_room_third_party_revoked_invite" = "%1$@ 撤销了 %2$@ 加入聊天室的邀请"; +"state_event_room_third_party_revoked_invite_by_you" = "你撤销了 %1$@ 加入聊天室的邀请"; "state_event_room_topic_changed" = "%1$@ 将主题改为:%2$@"; "state_event_room_topic_changed_by_you" = "你将主题改为:%1$@"; -"state_event_room_topic_removed" = "%1$@ 移除了房间主题"; -"state_event_room_topic_removed_by_you" = "你移除了房间主题"; +"state_event_room_topic_removed" = "%1$@ 移除了聊天室主题"; +"state_event_room_topic_removed_by_you" = "你移除了聊天室主题"; "state_event_room_unban" = "%1$@ 解禁了 %2$@"; "state_event_room_unban_by_you" = "你解禁了 %1$@"; "state_event_room_unknown_membership_change" = "%1$@ 对其成员资格进行了未知更改"; @@ -1010,9 +1017,9 @@ "notification_room_action_quick_reply" = "快速回复"; "screen_pinned_timeline_screen_title_empty" = "置顶消息"; "screen_room_mentions_at_room_title" = "所有人"; -"screen_account_provider_change" = "更改账户提供者"; -"screen_account_provider_signin_subtitle" = "这是您的对话将进行的地方,就像您使用电子邮件提供商来保存电子邮件一样。"; -"screen_account_provider_signup_subtitle" = "这是您的对话将进行的地方,就像您使用电子邮件提供商来保存电子邮件一样。"; +"screen_account_provider_change" = "更改账户提供方"; +"screen_account_provider_signin_subtitle" = "这是您的对话将存在的地方,就像您使用电子邮件提供方来保存电子邮件一样。"; +"screen_account_provider_signup_subtitle" = "这是您的对话将存在的地方,就像您使用电子邮件提供方来保存电子邮件一样。"; "screen_analytics_settings_help_us_improve" = "共享匿名使用数据以帮助我们排查问题。"; "screen_analytics_settings_read_terms" = "您可以阅读我们的所有条款 %1$@。"; "screen_analytics_settings_read_terms_content_link" = "此处"; @@ -1024,8 +1031,8 @@ "screen_chat_backup_recovery_action_setup" = "设置恢复"; "screen_create_poll_cancel_confirmation_content_ios" = "更改不会保存"; "screen_create_room_add_people_title" = "邀请朋友"; -"screen_create_room_room_name_label" = "房间名称"; -"screen_create_room_title" = "创建房间"; +"screen_create_room_room_name_label" = "聊天室名称"; +"screen_create_room_title" = "创建聊天室"; "screen_dm_details_block_alert_action" = "封禁"; "screen_dm_details_block_alert_description" = "被封禁的用户无法给你发消息,并且他们的消息会被隐藏。你可以随时解封。"; "screen_dm_details_block_user" = "封禁用户"; @@ -1038,8 +1045,8 @@ "screen_login_subtitle" = "Matrix 是一个用于安全、去中心化通信的开放网络。"; "screen_notification_settings_mentions_section_title" = "提及"; "screen_qr_code_login_invalid_scan_state_retry_button" = "再试一次"; -"screen_recovery_key_change_generate_key_description" = "确保将恢复密钥存储在安全的地方"; -"screen_recovery_key_confirm_title" = "Enter your recovery key"; +"screen_recovery_key_change_generate_key_description" = "不要告诉任何人!"; +"screen_recovery_key_confirm_title" = "输入恢复密钥"; "screen_report_content_block_user" = "封禁用户"; "screen_reset_encryption_password_placeholder" = "输入……"; "screen_room_attachment_source_camera_photo" = "拍摄照片"; @@ -1053,10 +1060,10 @@ "screen_room_change_role_unsaved_changes_title" = "保存更改?"; "screen_room_details_invite_people_title" = "邀请朋友"; "screen_room_details_leave_conversation_title" = "离开聊天"; -"screen_room_details_leave_room_title" = "离开房间"; +"screen_room_details_leave_room_title" = "离开聊天室"; "screen_room_details_notification_title" = "通知"; "screen_room_details_roles_and_permissions" = "角色与权限"; -"screen_room_details_room_name_label" = "房间名称"; +"screen_room_details_room_name_label" = "聊天室名称"; "screen_room_details_security_title" = "安全"; "screen_room_details_topic_title" = "话题"; "screen_room_error_failed_processing_media" = "处理要上传的媒体失败,请重试。"; @@ -1064,8 +1071,8 @@ "screen_room_notification_settings_mode_mentions_and_keywords" = "仅限提及和关键词"; "screen_room_timeline_reactions_show_less" = "折叠"; "screen_roomlist_filter_people" = "用户"; -"screen_server_confirmation_change_server" = "更改账户提供者"; -"screen_session_verification_request_failure_subtitle" = "Either the request timed out, the request was denied, or there was a verification mismatch."; +"screen_server_confirmation_change_server" = "更改账户提供方"; +"screen_session_verification_request_failure_subtitle" = "要么请求超时,要么请求被拒绝,要么验证不匹配。"; "screen_signout_confirmation_dialog_submit" = "登出"; "screen_signout_confirmation_dialog_title" = "登出"; "screen_signout_key_backup_offline_title" = "您的密钥仍在备份中"; diff --git a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.stringsdict index dd12b72dad..8fcb14b35d 100644 --- a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.stringsdict @@ -139,7 +139,7 @@ NSStringFormatValueTypeKey d other - %d 个房间 + %d 个聊天室 screen_app_lock_subtitle @@ -198,6 +198,22 @@ %1$d 人 + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey @@ -209,7 +225,7 @@ NSStringFormatValueTypeKey d other - %1$d 聊天室变更 + %1$d 个聊天室变化 screen_room_typing_many_members diff --git a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings index 315ae5eefc..cd3b91b6b8 100644 --- a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings @@ -125,7 +125,6 @@ "common_audio" = "音訊"; "common_blocked_users" = "封鎖的使用者"; "common_bubbles" = "泡泡"; -"common_call_invite" = "Call in progress (unsupported)"; "common_call_started" = "Call started"; "common_chat_backup" = "聊天室備份"; "common_copyright" = "著作權"; @@ -226,6 +225,7 @@ "common_unable_to_invite_title" = "無法發送邀請"; "common_unlock" = "解鎖"; "common_unmute" = "開啟通知"; +"common_unsupported_call" = "Unsupported call"; "common_unsupported_event" = "不支援的事件"; "common_username" = "使用者名稱"; "common_verification_cancelled" = "驗證已取消"; @@ -365,6 +365,7 @@ "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_decline_and_ban_action_title" = "Decline and ban"; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -377,11 +378,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; "screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; "screen_room_mentions_at_room_subtitle" = "通知整個聊天室"; +"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; "screen_room_pinned_banner_indicator" = "%1$@ of %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Pinned messages"; "screen_room_pinned_banner_loading_description" = "Loading message…"; "screen_room_pinned_banner_view_all_button_title" = "View All"; +"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_details_pinned_events_row_title" = "Pinned messages"; +"screen_room_details_requests_to_join_title" = "Requests to join"; "screen_roomlist_knock_event_sent_description" = "Request to join sent"; "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."; @@ -789,6 +795,7 @@ "screen_room_timeline_add_reaction" = "新增表情符號"; "screen_room_timeline_beginning_of_room" = "This is the beginning of %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "This is the beginning of this conversation."; +"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; "screen_room_timeline_less_reactions" = "較少"; "screen_room_timeline_message_copied" = "訊息已複製"; "screen_room_timeline_no_permission_to_post" = "您沒有權限在此聊天室傳送訊息"; diff --git a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.stringsdict index f580e973f2..f38cd938da 100644 --- a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.stringsdict @@ -202,6 +202,22 @@ %1$d 位夥伴 + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this room + other + %1$@ +%2$d others want to join this room + + screen_room_timeline_state_changes NSStringLocalizedFormatKey diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 012eec9e9a..5eab6c3017 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -1738,6 +1738,8 @@ internal enum L10n { internal static var screenRoomDetailsNotificationTitle: String { return L10n.tr("Localizable", "screen_room_details_notification_title") } /// Pinned messages internal static var screenRoomDetailsPinnedEventsRowTitle: String { return L10n.tr("Localizable", "screen_room_details_pinned_events_row_title") } + /// Requests to join + internal static var screenRoomDetailsRequestsToJoinTitle: String { return L10n.tr("Localizable", "screen_room_details_requests_to_join_title") } /// Roles and permissions internal static var screenRoomDetailsRolesAndPermissions: String { return L10n.tr("Localizable", "screen_room_details_roles_and_permissions") } /// Room name diff --git a/ElementX/Sources/UITests/UITestsNotificationCenter.swift b/ElementX/Sources/UITests/UITestsNotificationCenter.swift index 32c2d8dde4..8e2c594a38 100644 --- a/ElementX/Sources/UITests/UITestsNotificationCenter.swift +++ b/ElementX/Sources/UITests/UITestsNotificationCenter.swift @@ -8,14 +8,14 @@ import Combine import SwiftUI -@MainActor /// A notification center that can be injected in the app to post notifications /// that are sent from the UI tests runner. Usage: /// - Create an instance of the center in the screen you want to test and call `startListening`. /// - Create a `UITestSignalling.Client` in the `.tests` mode in your tests. /// - Start the app from the tests and call `client.waitForApp()` to establish communication. /// - Send the notification from the tests you would like posted in the app. -class UITestsNotificationCenter: NotificationCenter { +@MainActor +class UITestsNotificationCenter: NotificationCenter, @unchecked Sendable { // periphery:ignore - retaining purpose private var client: UITestsSignalling.Client? private var signalCancellable: AnyCancellable? diff --git a/UITests/Sources/Application.swift b/UITests/Sources/Application.swift index 861dc17519..2c208450d6 100644 --- a/UITests/Sources/Application.swift +++ b/UITests/Sources/Application.swift @@ -53,11 +53,11 @@ enum Application { extension XCUIApplication { static var recordMode: SnapshotTestingConfiguration.Record = .missing - @MainActor /// Assert screenshot for a screen with the given identifier. Does not fail if a screenshot is newly created. /// - Parameter identifier: Identifier of the UI test screen /// - Parameter step: An optional integer that can be used to take multiple snapshots per test identifier. /// - Parameter insets: Optional insets with which to crop the image by. + @MainActor func assertScreenshot(_ identifier: UITestsScreenIdentifier, step: Int? = nil, insets: UIEdgeInsets? = nil, delay: Duration = .seconds(1), precision: Float = 0.99) async throws { var snapshotName = identifier.rawValue if let step { From c91a9bd9c94e51d9b5ef968c6942870244301f3b Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Mon, 18 Nov 2024 11:36:37 +0000 Subject: [PATCH 29/74] Update the SDK. (#3524) --- ElementX.xcodeproj/project.pbxproj | 84 +++++++------ .../xcshareddata/swiftpm/Package.resolved | 4 +- .../Mocks/Generated/SDKGeneratedMocks.swift | 113 ++++++++++++++---- .../Services/Timeline/TimelineProxy.swift | 2 + project.yml | 2 +- 5 files changed, 140 insertions(+), 65 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 3d48cc4cb9..20ef13eee7 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -187,6 +187,7 @@ 26252AA9AED64010788F4C26 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A3E8741D199CD1A37F4CBF /* UIView.swift */; }; 2689D22EF1D10D22B0A4DAEA /* NotificationContentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7BB243B26D54EF1A0C422C0 /* NotificationContentBuilder.swift */; }; 273AB64B9A26B61C51858867 /* AsyncSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = A73A07BAEDD74C48795A996A /* AsyncSequence.swift */; }; + 2748E5574A1031DD05E54FDA /* KnockRequestCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44B71F6D9062E8EB8929BB97 /* KnockRequestCell.swift */; }; 274CE3C986841D15FD530BF5 /* ShimmerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97CE98208321C4D66E363612 /* ShimmerModifier.swift */; }; 275EDE8849A2AC1D9309ED7C /* TemplateScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43456E73F8A2D52B69B9FB9 /* TemplateScreenViewModel.swift */; }; 2797C9D9BA642370F1C85D78 /* Untranslated.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = F75DF9500D69A3AAF8339E69 /* Untranslated.stringsdict */; }; @@ -800,7 +801,6 @@ A6F345328CCC5C9B0DAE2257 /* LogViewerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB05221D7D941CC82DC8480 /* LogViewerScreenViewModel.swift */; }; A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; }; A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; }; - A7A369F22CE62AF800819CCB /* KnockRequestCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A369F12CE62AE900819CCB /* KnockRequestCell.swift */; }; A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; A808DC3F72D15C6C5A52317E /* TimelineItemDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCDA016D05107DED3B9495CB /* TimelineItemDebugView.swift */; }; A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; }; @@ -1266,13 +1266,13 @@ 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; 0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = ""; }; - 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = ""; }; + 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = ""; }; 044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = ""; }; 045253F9967A535EE5B16691 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; 046C0D3F53B0B5EF0A1F5BEA /* RoomSummaryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryTests.swift; sourceTree = ""; }; - 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.swift; sourceTree = ""; }; 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = ""; }; 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxyProtocol.swift; sourceTree = ""; }; @@ -1338,7 +1338,7 @@ 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 = ""; }; - 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = IntegrationTests.xctestplan; 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 = ""; }; @@ -1432,7 +1432,7 @@ 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = ""; }; 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenCoordinator.swift; sourceTree = ""; }; 260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = ""; }; - 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = PreviewTests.xctestplan; sourceTree = ""; }; + 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; path = PreviewTests.xctestplan; sourceTree = ""; }; 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorder.swift; sourceTree = ""; }; 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceProtocol.swift; sourceTree = ""; }; 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1503,7 +1503,7 @@ 3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = ""; }; 35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; 35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = ""; }; - 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = ""; }; 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerURLBuildersTests.swift; sourceTree = ""; }; 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = ""; }; @@ -1570,6 +1570,7 @@ 43C2067FF58B4996323EB40C /* SessionDirectories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDirectories.swift; sourceTree = ""; }; 4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareToMapsAppActivity.swift; sourceTree = ""; }; 44ABA63DBE7F76C58260B43B /* EmoteRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineView.swift; sourceTree = ""; }; + 44B71F6D9062E8EB8929BB97 /* KnockRequestCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestCell.swift; sourceTree = ""; }; 44C314C00533E2C297796B60 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = ""; }; 44ECC9D66400727DFFEE12E8 /* TimelineStartRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStartRoomTimelineView.swift; sourceTree = ""; }; 450E04B2A976CC4C8CC1807C /* EmoteRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItem.swift; sourceTree = ""; }; @@ -1614,7 +1615,7 @@ 4B41FABA2B0AEF4389986495 /* LoginMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMode.swift; sourceTree = ""; }; 4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenCoordinator.swift; sourceTree = ""; }; 4C8D988E82A8DFA13BE46F7C /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pl; path = pl.lproj/Localizable.stringsdict; sourceTree = ""; }; - 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreen.swift; sourceTree = ""; }; 4D3A7375AB22721C436EB056 /* ComposerToolbarModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarModels.swift; sourceTree = ""; }; 4E2245243369B99216C7D84E /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = ""; }; @@ -1885,7 +1886,7 @@ 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 8DA1E8F287680C8ED25EDBAC /* NetworkMonitorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitorMock.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = ""; }; + 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 = ""; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = ""; }; @@ -1992,7 +1993,6 @@ A6EA0D8B0BBD8805F7D5A133 /* TextBasedRoomTimelineViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineViewProtocol.swift; sourceTree = ""; }; A73A07BAEDD74C48795A996A /* AsyncSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncSequence.swift; sourceTree = ""; }; A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationTokenTests.swift; sourceTree = ""; }; - A7A369F12CE62AE900819CCB /* KnockRequestCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestCell.swift; sourceTree = ""; }; A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = ""; }; A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModelProtocol.swift; sourceTree = ""; }; A7E37072597F67C4DD8CC2DB /* ComposerDraftServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerDraftServiceProtocol.swift; sourceTree = ""; }; @@ -2067,7 +2067,7 @@ B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyProtocol.swift; sourceTree = ""; }; B53AC78E49A297AC1D72A7CF /* AppMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediator.swift; sourceTree = ""; }; B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = ""; }; - B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = ""; }; + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; 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 = ""; }; @@ -2185,7 +2185,7 @@ CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = ""; }; CDE3F3911FF7CC639BDE5844 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = ""; }; - CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = ""; }; D01FD1171FF40E34D707FD00 /* BigIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigIcon.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 = ""; }; @@ -2318,7 +2318,7 @@ ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = ""; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = ""; }; ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModel.swift; sourceTree = ""; }; - ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = ""; }; ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = ""; }; EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = ""; }; @@ -2341,7 +2341,7 @@ F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = ""; }; - F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = ""; }; + F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = ""; }; F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = ""; }; F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = ""; }; @@ -2359,7 +2359,7 @@ F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineBubbleLayout.swift; sourceTree = ""; }; F5E23D8EE6CBACF32F1EC874 /* MediaPlayerProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProviderProtocol.swift; sourceTree = ""; }; F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModel.swift; sourceTree = ""; }; - F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_apple_image.heic; sourceTree = ""; }; + F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; path = test_apple_image.heic; sourceTree = ""; }; F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = ""; }; F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockUITests.swift; sourceTree = ""; }; F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderMock.swift; sourceTree = ""; }; @@ -4803,22 +4803,6 @@ path = Application; sourceTree = ""; }; - A7A369EF2CE62AB300819CCB /* KnockRequestsListScreen */ = { - isa = PBXGroup; - children = ( - A7A369F02CE62AC900819CCB /* View */, - ); - path = KnockRequestsListScreen; - sourceTree = ""; - }; - A7A369F02CE62AC900819CCB /* View */ = { - isa = PBXGroup; - children = ( - A7A369F12CE62AE900819CCB /* KnockRequestCell.swift */, - ); - path = View; - sourceTree = ""; - }; A7F3784CAF9F4CF654BC52CD /* View */ = { isa = PBXGroup; children = ( @@ -5023,6 +5007,14 @@ path = View; sourceTree = ""; }; + BF0415BE807CA2BCFC210008 /* KnockRequestsListScreen */ = { + isa = PBXGroup; + children = ( + F2BBD71E8BF13D2DD2A19064 /* View */, + ); + path = KnockRequestsListScreen; + sourceTree = ""; + }; C0937E3B06A8F0E2DB7C8241 /* Other */ = { isa = PBXGroup; children = ( @@ -5386,7 +5378,6 @@ E59565F441830B19DBAE567C /* Screens */ = { isa = PBXGroup; children = ( - A7A369EF2CE62AB300819CCB /* KnockRequestsListScreen */, 13263FFEA7749D822B51AA90 /* AppLock */, E74CD7681375AD2EAA34D66B /* Authentication */, 295BCC81AB45927F5F2033B1 /* AuthenticationStartScreen */, @@ -5403,6 +5394,7 @@ B53CA9BECD3F97805E1432D0 /* HomeScreen */, F12966DF3DA87FEF21348D60 /* InviteUsersScreen */, FFD7C58CA6A7D6BBC2F584B5 /* JoinRoomScreen */, + BF0415BE807CA2BCFC210008 /* KnockRequestsListScreen */, 948DD12A5533BE1BC260E437 /* LocationSharing */, 73E032ADD008D63812791D97 /* LogViewerScreen */, 87E2774157D9C4894BCFF3F8 /* MediaPickerScreen */, @@ -5579,6 +5571,14 @@ path = InviteUsersScreen; sourceTree = ""; }; + F2BBD71E8BF13D2DD2A19064 /* View */ = { + isa = PBXGroup; + children = ( + 44B71F6D9062E8EB8929BB97 /* KnockRequestCell.swift */, + ); + path = View; + sourceTree = ""; + }; F3F90EBF3341F1FB47579B77 /* View */ = { isa = PBXGroup; children = ( @@ -6787,6 +6787,7 @@ 1FE593ECEC40A43789105D80 /* KeychainController.swift in Sources */, FD29471C72872F8B7580E3E1 /* KeychainControllerMock.swift in Sources */, CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */, + 2748E5574A1031DD05E54FDA /* KnockRequestCell.swift in Sources */, D5E8EE8A288EFCCF646860EA /* KnockRequestsBannerView.swift in Sources */, C969A62F3D9F14318481A33B /* KnockedRoomProxy.swift in Sources */, 6681D6D3ADF69EBD2625F29A /* KnockedRoomProxyMock.swift in Sources */, @@ -6957,7 +6958,6 @@ C8C7AF33AADF88B306CD2695 /* QRCodeLoginService.swift in Sources */, BB04B1D8E7401C90506D401E /* QRCodeLoginServiceProtocol.swift in Sources */, FDD5B4B616D9FF4DE3E9A418 /* QRCodeScannerView.swift in Sources */, - A7A369F22CE62AF800819CCB /* KnockRequestCell.swift in Sources */, C9A631FD968249B4BA0B7B3C /* ReactionsSummaryView.swift in Sources */, 743790BF6A5B0577EA74AF14 /* ReadMarkerRoomTimelineItem.swift in Sources */, 2BBC0EB1E07963810A5D7423 /* ReadMarkerRoomTimelineView.swift in Sources */, @@ -7557,7 +7557,9 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_NSE"; + OTHER_SWIFT_FLAGS = ( + "-DIS_NSE", + ); PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -7606,7 +7608,9 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; + OTHER_SWIFT_FLAGS = ( + "-DIS_MAIN_APP", + ); PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7632,7 +7636,9 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; + OTHER_SWIFT_FLAGS = ( + "-DIS_MAIN_APP", + ); PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7898,7 +7904,9 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_NSE"; + OTHER_SWIFT_FLAGS = ( + "-DIS_NSE", + ); PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -8129,7 +8137,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.67; + version = 1.0.68; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index fe9b061d23..85a96075b9 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "5f23a9b8e210aa9962b420bcd7065d5f9cf142c9", - "version" : "1.0.67" + "revision" : "4e0924228b177720b67df1843ea7a4377d073900", + "version" : "1.0.68" } }, { diff --git a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift index 689ef2fdee..eb7722fe12 100644 --- a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift @@ -16851,6 +16851,71 @@ open class RoomPreviewSDKMock: MatrixRustSDK.RoomPreview { } } + //MARK: - inviter + + var inviterUnderlyingCallsCount = 0 + open var inviterCallsCount: Int { + get { + if Thread.isMainThread { + return inviterUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = inviterUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + inviterUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + inviterUnderlyingCallsCount = newValue + } + } + } + } + open var inviterCalled: Bool { + return inviterCallsCount > 0 + } + + var inviterUnderlyingReturnValue: RoomMember? + open var inviterReturnValue: RoomMember? { + get { + if Thread.isMainThread { + return inviterUnderlyingReturnValue + } else { + var returnValue: RoomMember?? = nil + DispatchQueue.main.sync { + returnValue = inviterUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + inviterUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + inviterUnderlyingReturnValue = newValue + } + } + } + } + open var inviterClosure: (() async -> RoomMember?)? + + open override func inviter() async -> RoomMember? { + inviterCallsCount += 1 + if let inviterClosure = inviterClosure { + return await inviterClosure() + } else { + return inviterReturnValue + } + } + //MARK: - leave open var leaveThrowableError: Error? @@ -19432,15 +19497,15 @@ open class TimelineSDKMock: MatrixRustSDK.Timeline { //MARK: - sendFile - var sendFileUrlFileInfoProgressWatcherUseSendQueueUnderlyingCallsCount = 0 - open var sendFileUrlFileInfoProgressWatcherUseSendQueueCallsCount: Int { + var sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueUnderlyingCallsCount = 0 + open var sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueCallsCount: Int { get { if Thread.isMainThread { - return sendFileUrlFileInfoProgressWatcherUseSendQueueUnderlyingCallsCount + return sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendFileUrlFileInfoProgressWatcherUseSendQueueUnderlyingCallsCount + returnValue = sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueUnderlyingCallsCount } return returnValue! @@ -19448,29 +19513,29 @@ open class TimelineSDKMock: MatrixRustSDK.Timeline { } set { if Thread.isMainThread { - sendFileUrlFileInfoProgressWatcherUseSendQueueUnderlyingCallsCount = newValue + sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendFileUrlFileInfoProgressWatcherUseSendQueueUnderlyingCallsCount = newValue + sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueUnderlyingCallsCount = newValue } } } } - open var sendFileUrlFileInfoProgressWatcherUseSendQueueCalled: Bool { - return sendFileUrlFileInfoProgressWatcherUseSendQueueCallsCount > 0 + open var sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueCalled: Bool { + return sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueCallsCount > 0 } - open var sendFileUrlFileInfoProgressWatcherUseSendQueueReceivedArguments: (url: String, fileInfo: FileInfo, progressWatcher: ProgressWatcher?, useSendQueue: Bool)? - open var sendFileUrlFileInfoProgressWatcherUseSendQueueReceivedInvocations: [(url: String, fileInfo: FileInfo, progressWatcher: ProgressWatcher?, useSendQueue: Bool)] = [] + open var sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueReceivedArguments: (url: String, fileInfo: FileInfo, caption: String?, formattedCaption: FormattedBody?, progressWatcher: ProgressWatcher?, useSendQueue: Bool)? + open var sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueReceivedInvocations: [(url: String, fileInfo: FileInfo, caption: String?, formattedCaption: FormattedBody?, progressWatcher: ProgressWatcher?, useSendQueue: Bool)] = [] - var sendFileUrlFileInfoProgressWatcherUseSendQueueUnderlyingReturnValue: SendAttachmentJoinHandle! - open var sendFileUrlFileInfoProgressWatcherUseSendQueueReturnValue: SendAttachmentJoinHandle! { + var sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueUnderlyingReturnValue: SendAttachmentJoinHandle! + open var sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueReturnValue: SendAttachmentJoinHandle! { get { if Thread.isMainThread { - return sendFileUrlFileInfoProgressWatcherUseSendQueueUnderlyingReturnValue + return sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueUnderlyingReturnValue } else { var returnValue: SendAttachmentJoinHandle? = nil DispatchQueue.main.sync { - returnValue = sendFileUrlFileInfoProgressWatcherUseSendQueueUnderlyingReturnValue + returnValue = sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueUnderlyingReturnValue } return returnValue! @@ -19478,26 +19543,26 @@ open class TimelineSDKMock: MatrixRustSDK.Timeline { } set { if Thread.isMainThread { - sendFileUrlFileInfoProgressWatcherUseSendQueueUnderlyingReturnValue = newValue + sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendFileUrlFileInfoProgressWatcherUseSendQueueUnderlyingReturnValue = newValue + sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueUnderlyingReturnValue = newValue } } } } - open var sendFileUrlFileInfoProgressWatcherUseSendQueueClosure: ((String, FileInfo, ProgressWatcher?, Bool) -> SendAttachmentJoinHandle)? + open var sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueClosure: ((String, FileInfo, String?, FormattedBody?, ProgressWatcher?, Bool) -> SendAttachmentJoinHandle)? - open override func sendFile(url: String, fileInfo: FileInfo, progressWatcher: ProgressWatcher?, useSendQueue: Bool) -> SendAttachmentJoinHandle { - sendFileUrlFileInfoProgressWatcherUseSendQueueCallsCount += 1 - sendFileUrlFileInfoProgressWatcherUseSendQueueReceivedArguments = (url: url, fileInfo: fileInfo, progressWatcher: progressWatcher, useSendQueue: useSendQueue) + open override func sendFile(url: String, fileInfo: FileInfo, caption: String?, formattedCaption: FormattedBody?, progressWatcher: ProgressWatcher?, useSendQueue: Bool) -> SendAttachmentJoinHandle { + sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueCallsCount += 1 + sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueReceivedArguments = (url: url, fileInfo: fileInfo, caption: caption, formattedCaption: formattedCaption, progressWatcher: progressWatcher, useSendQueue: useSendQueue) DispatchQueue.main.async { - self.sendFileUrlFileInfoProgressWatcherUseSendQueueReceivedInvocations.append((url: url, fileInfo: fileInfo, progressWatcher: progressWatcher, useSendQueue: useSendQueue)) + self.sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueReceivedInvocations.append((url: url, fileInfo: fileInfo, caption: caption, formattedCaption: formattedCaption, progressWatcher: progressWatcher, useSendQueue: useSendQueue)) } - if let sendFileUrlFileInfoProgressWatcherUseSendQueueClosure = sendFileUrlFileInfoProgressWatcherUseSendQueueClosure { - return sendFileUrlFileInfoProgressWatcherUseSendQueueClosure(url, fileInfo, progressWatcher, useSendQueue) + if let sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueClosure = sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueClosure { + return sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueClosure(url, fileInfo, caption, formattedCaption, progressWatcher, useSendQueue) } else { - return sendFileUrlFileInfoProgressWatcherUseSendQueueReturnValue + return sendFileUrlFileInfoCaptionFormattedCaptionProgressWatcherUseSendQueueReturnValue } } diff --git a/ElementX/Sources/Services/Timeline/TimelineProxy.swift b/ElementX/Sources/Services/Timeline/TimelineProxy.swift index 798ee7f4eb..4309d206cb 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxy.swift @@ -257,6 +257,8 @@ final class TimelineProxy: TimelineProxyProtocol { let handle = timeline.sendFile(url: url.path(percentEncoded: false), fileInfo: fileInfo, + caption: nil, + formattedCaption: nil, progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) }, diff --git a/project.yml b/project.yml index 1151ce093a..5cc1bb8ed4 100644 --- a/project.yml +++ b/project.yml @@ -61,7 +61,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.67 + exactVersion: 1.0.68 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From bef1eda533f8131404ffb394837b8af5dc003842 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Mon, 18 Nov 2024 11:38:20 +0000 Subject: [PATCH 30/74] Fix a bug where the security banner has the wrong state when out of sync. (#3511) --- .../Screens/HomeScreen/HomeScreenModels.swift | 26 ++++- .../HomeScreen/HomeScreenViewModel.swift | 15 ++- .../HomeScreen/View/HomeScreenContent.swift | 6 +- ...eScreenRecoveryKeyConfirmationBanner.swift | 42 +++++-- .../Sources/HomeScreenViewModelTests.swift | 110 ++++++++++++++++-- 5 files changed, 168 insertions(+), 31 deletions(-) diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift index 2e58c17ae7..7671b37748 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift @@ -66,10 +66,28 @@ enum HomeScreenRoomListMode: CustomStringConvertible { } } -enum HomeScreenBannerMode { +enum HomeScreenSecurityBannerMode: Equatable { case none case dismissed - case show + case show(HomeScreenRecoveryKeyConfirmationBanner.State) + + var isDismissed: Bool { + switch self { + case .dismissed: true + default: false + } + } + + var isShown: Bool { + switch self { + case .show: true + default: false + } + } +} + +enum HomeScreenMigrationBannerMode { + case none, show, dismissed } struct HomeScreenViewState: BindableState { @@ -77,8 +95,8 @@ struct HomeScreenViewState: BindableState { var userDisplayName: String? var userAvatarURL: URL? - var securityBannerMode = HomeScreenBannerMode.none - var slidingSyncMigrationBannerMode = HomeScreenBannerMode.none + var securityBannerMode = HomeScreenSecurityBannerMode.none + var slidingSyncMigrationBannerMode = HomeScreenMigrationBannerMode.none var requiresExtraAccountSetup = false diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index c1b21cf4f2..9bd00e2b29 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -55,16 +55,15 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol .sink { [weak self] securityState in guard let self else { return } - switch (securityState.verificationState, securityState.recoveryState) { - case (.verified, .disabled): + switch securityState.recoveryState { + case .disabled: state.requiresExtraAccountSetup = true - state.securityBannerMode = .show - case (.verified, .incomplete): - state.requiresExtraAccountSetup = true - - if state.securityBannerMode != .dismissed { - state.securityBannerMode = .show + if !state.securityBannerMode.isDismissed { + state.securityBannerMode = .show(.setUpRecovery) } + case .incomplete: + state.requiresExtraAccountSetup = true + state.securityBannerMode = .show(.recoveryOutOfSync) default: state.securityBannerMode = .none state.requiresExtraAccountSetup = false diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenContent.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenContent.swift index 68c7408b9c..969d1882a6 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenContent.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenContent.swift @@ -120,7 +120,7 @@ struct HomeScreenContent: View { private var topSection: some View { // An empty VStack causes glitches within the room list if context.viewState.shouldShowFilters || - context.viewState.securityBannerMode == .show || + context.viewState.securityBannerMode.isShown || context.viewState.slidingSyncMigrationBannerMode == .show { VStack(spacing: 0) { if context.viewState.shouldShowFilters { @@ -129,8 +129,8 @@ struct HomeScreenContent: View { if context.viewState.slidingSyncMigrationBannerMode == .show { HomeScreenSlidingSyncMigrationBanner(context: context) - } else if context.viewState.securityBannerMode == .show { - HomeScreenRecoveryKeyConfirmationBanner(requiresExtraAccountSetup: context.viewState.requiresExtraAccountSetup, context: context) + } else if case let .show(state) = context.viewState.securityBannerMode { + HomeScreenRecoveryKeyConfirmationBanner(state: state, context: context) } } .background(Color.compound.bgCanvasDefault) diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRecoveryKeyConfirmationBanner.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRecoveryKeyConfirmationBanner.swift index 1adf1fac7b..3442762890 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRecoveryKeyConfirmationBanner.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRecoveryKeyConfirmationBanner.swift @@ -10,13 +10,37 @@ import Compound import SwiftUI struct HomeScreenRecoveryKeyConfirmationBanner: View { - let requiresExtraAccountSetup: Bool + enum State { case setUpRecovery, recoveryOutOfSync } + let state: State var context: HomeScreenViewModel.Context - var title: String { requiresExtraAccountSetup ? L10n.bannerSetUpRecoveryTitle : L10n.confirmRecoveryKeyBannerTitle } - var message: String { requiresExtraAccountSetup ? L10n.bannerSetUpRecoveryContent : L10n.confirmRecoveryKeyBannerMessage } - var actionTitle: String { requiresExtraAccountSetup ? L10n.bannerSetUpRecoverySubmit : L10n.confirmRecoveryKeyBannerPrimaryButtonTitle } - var primaryAction: HomeScreenViewAction { requiresExtraAccountSetup ? .setupRecovery : .confirmRecoveryKey } + var title: String { + switch state { + case .setUpRecovery: L10n.bannerSetUpRecoveryTitle + case .recoveryOutOfSync: L10n.confirmRecoveryKeyBannerTitle + } + } + + var message: String { + switch state { + case .setUpRecovery: L10n.bannerSetUpRecoveryContent + case .recoveryOutOfSync: L10n.confirmRecoveryKeyBannerMessage + } + } + + var actionTitle: String { + switch state { + case .setUpRecovery: L10n.bannerSetUpRecoverySubmit + case .recoveryOutOfSync: L10n.confirmRecoveryKeyBannerPrimaryButtonTitle + } + } + + var primaryAction: HomeScreenViewAction { + switch state { + case .setUpRecovery: .setupRecovery + case .recoveryOutOfSync: .confirmRecoveryKey + } + } var body: some View { VStack(spacing: 16) { @@ -37,7 +61,7 @@ struct HomeScreenRecoveryKeyConfirmationBanner: View { .foregroundColor(.compound.textPrimary) .frame(maxWidth: .infinity, alignment: .leading) - if requiresExtraAccountSetup { + if state == .setUpRecovery { Button { context.send(viewAction: .skipRecoveryKeyConfirmation) } label: { @@ -63,7 +87,7 @@ struct HomeScreenRecoveryKeyConfirmationBanner: View { .buttonStyle(.compound(.primary, size: .medium)) .accessibilityIdentifier(A11yIdentifiers.homeScreen.recoveryKeyConfirmationBannerContinue) - if !requiresExtraAccountSetup { + if state == .recoveryOutOfSync { Button { context.send(viewAction: .resetEncryption) } label: { @@ -81,10 +105,10 @@ struct HomeScreenRecoveryKeyConfirmationBanner_Previews: PreviewProvider, Testab static let viewModel = buildViewModel() static var previews: some View { - HomeScreenRecoveryKeyConfirmationBanner(requiresExtraAccountSetup: true, + HomeScreenRecoveryKeyConfirmationBanner(state: .setUpRecovery, context: viewModel.context) .previewDisplayName("Set up recovery") - HomeScreenRecoveryKeyConfirmationBanner(requiresExtraAccountSetup: false, + HomeScreenRecoveryKeyConfirmationBanner(state: .recoveryOutOfSync, context: viewModel.context) .previewDisplayName("Out of sync") } diff --git a/UnitTests/Sources/HomeScreenViewModelTests.swift b/UnitTests/Sources/HomeScreenViewModelTests.swift index e485844793..1361b8303e 100644 --- a/UnitTests/Sources/HomeScreenViewModelTests.swift +++ b/UnitTests/Sources/HomeScreenViewModelTests.swift @@ -20,13 +20,6 @@ class HomeScreenViewModelTests: XCTestCase { override func setUpWithError() throws { cancellables.removeAll() - roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))) - clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", roomSummaryProvider: roomSummaryProvider)) - viewModel = HomeScreenViewModel(userSession: UserSessionMock(.init(clientProxy: clientProxy)), - analyticsService: ServiceLocator.shared.analytics, - appSettings: ServiceLocator.shared.settings, - selectedRoomPublisher: CurrentValueSubject(nil).asCurrentValuePublisher(), - userIndicatorController: ServiceLocator.shared.userIndicatorController) } override func tearDown() { @@ -34,6 +27,8 @@ class HomeScreenViewModelTests: XCTestCase { } func testSelectRoom() async throws { + setupViewModel() + let mockRoomId = "mock_room_id" var correctResult = false var selectedRoomId = "" @@ -57,6 +52,8 @@ class HomeScreenViewModelTests: XCTestCase { } func testTapUserAvatar() async throws { + setupViewModel() + var correctResult = false viewModel.actions @@ -76,6 +73,8 @@ class HomeScreenViewModelTests: XCTestCase { } func testLeaveRoomAlert() async throws { + setupViewModel() + let mockRoomId = "1" clientProxy.roomForIdentifierClosure = { _ in .joined(JoinedRoomProxyMock(.init(id: mockRoomId, name: "Some room"))) } @@ -92,6 +91,8 @@ class HomeScreenViewModelTests: XCTestCase { } func testLeaveRoomError() async throws { + setupViewModel() + let mockRoomId = "1" let room = JoinedRoomProxyMock(.init(id: mockRoomId, name: "Some room")) room.leaveRoomClosure = { .failure(.sdkError(ClientProxyMockError.generic)) } @@ -110,6 +111,8 @@ class HomeScreenViewModelTests: XCTestCase { } func testLeaveRoomSuccess() async throws { + setupViewModel() + let mockRoomId = "1" var correctResult = false let expectation = expectation(description: #function) @@ -136,6 +139,8 @@ class HomeScreenViewModelTests: XCTestCase { } func testShowRoomDetails() async throws { + setupViewModel() + let mockRoomId = "1" var correctResult = false viewModel.actions @@ -155,6 +160,8 @@ class HomeScreenViewModelTests: XCTestCase { } func testFilters() async throws { + setupViewModel() + context.filtersState.activateFilter(.people) try await Task.sleep(for: .milliseconds(100)) XCTAssertEqual(roomSummaryProvider.roomListPublisher.value.count, 2) @@ -162,6 +169,8 @@ class HomeScreenViewModelTests: XCTestCase { } func testSearch() async throws { + setupViewModel() + context.isSearchFieldFocused = true context.searchQuery = "lude to Found" try await Task.sleep(for: .milliseconds(100)) @@ -170,6 +179,8 @@ class HomeScreenViewModelTests: XCTestCase { } func testFiltersEmptyState() async throws { + setupViewModel() + context.filtersState.activateFilter(.people) context.filtersState.activateFilter(.favourites) try await Task.sleep(for: .milliseconds(100)) @@ -177,4 +188,89 @@ class HomeScreenViewModelTests: XCTestCase { context.isSearchFieldFocused = true XCTAssertFalse(context.viewState.shouldShowEmptyFilterState) } + + func testSetUpRecoveryBannerState() async throws { + // Given a view model without a visible security banner. + let securityStateStateSubject = CurrentValueSubject(.init(verificationState: .verified, recoveryState: .unknown)) + setupViewModel(securityStatePublisher: securityStateStateSubject.asCurrentValuePublisher()) + XCTAssertEqual(context.viewState.securityBannerMode, .none) + + // When the recovery state comes through as disabled. + var deferred = deferFulfillment(context.$viewState) { $0.requiresExtraAccountSetup == true } + securityStateStateSubject.send(.init(verificationState: .verified, recoveryState: .disabled)) + try await deferred.fulfill() + + // Then the banner should be shown to set up recovery. + XCTAssertEqual(context.viewState.securityBannerMode, .show(.setUpRecovery)) + + // When the recovery is enabled. + deferred = deferFulfillment(context.$viewState) { $0.requiresExtraAccountSetup == false } + securityStateStateSubject.send(.init(verificationState: .verified, recoveryState: .enabled)) + try await deferred.fulfill() + + // Then the banner should no longer be shown. + XCTAssertEqual(context.viewState.securityBannerMode, .none) + } + + func testDismissSetUpRecoveryBannerState() async throws { + // Given a view model with the setup recovery banner shown. + let securityStateStateSubject = CurrentValueSubject(.init(verificationState: .verified, recoveryState: .unknown)) + setupViewModel(securityStatePublisher: securityStateStateSubject.asCurrentValuePublisher()) + var deferred = deferFulfillment(context.$viewState) { $0.securityBannerMode == .show(.setUpRecovery) } + securityStateStateSubject.send(.init(verificationState: .verified, recoveryState: .disabled)) + try await deferred.fulfill() + + // When the banner is dismissed. + deferred = deferFulfillment(context.$viewState) { $0.securityBannerMode == .dismissed } + context.send(viewAction: .skipRecoveryKeyConfirmation) + + // Then the banner should no longer be shown. + try await deferred.fulfill() + + // And when the recovery state comes through a second time the banner should still not be shown. + let failure = deferFailure(context.$viewState, timeout: 1) { $0.securityBannerMode != .dismissed } + securityStateStateSubject.send(.init(verificationState: .verified, recoveryState: .disabled)) + try await failure.fulfill() + } + + func testOutOfSyncRecoveryBannerState() async throws { + // Given a view model without a visible security banner. + let securityStateStateSubject = CurrentValueSubject(.init(verificationState: .verified, recoveryState: .unknown)) + setupViewModel(securityStatePublisher: securityStateStateSubject.asCurrentValuePublisher()) + XCTAssertEqual(context.viewState.securityBannerMode, .none) + + // When the recovery state comes through as incomplete. + var deferred = deferFulfillment(context.$viewState) { $0.requiresExtraAccountSetup == true } + securityStateStateSubject.send(.init(verificationState: .verified, recoveryState: .incomplete)) + try await deferred.fulfill() + + // Then the banner should be shown for out of sync recovery. + XCTAssertEqual(context.viewState.securityBannerMode, .show(.recoveryOutOfSync)) + + // When the recovery is enabled. + deferred = deferFulfillment(context.$viewState) { $0.requiresExtraAccountSetup == false } + securityStateStateSubject.send(.init(verificationState: .verified, recoveryState: .enabled)) + try await deferred.fulfill() + + // Then the banner should no longer be shown. + XCTAssertEqual(context.viewState.securityBannerMode, .none) + } + + // MARK: - Helpers + + private func setupViewModel(securityStatePublisher: CurrentValuePublisher? = nil) { + roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))) + clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", + roomSummaryProvider: roomSummaryProvider)) + let userSession = UserSessionMock(.init(clientProxy: clientProxy)) + if let securityStatePublisher { + userSession.sessionSecurityStatePublisher = securityStatePublisher + } + + viewModel = HomeScreenViewModel(userSession: userSession, + analyticsService: ServiceLocator.shared.analytics, + appSettings: ServiceLocator.shared.settings, + selectedRoomPublisher: CurrentValueSubject(nil).asCurrentValuePublisher(), + userIndicatorController: ServiceLocator.shared.userIndicatorController) + } } From dc0563764dfde9036d34487e39ff92e48fcfb5ed Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Mon, 18 Nov 2024 14:34:18 +0200 Subject: [PATCH 31/74] Fix image animations / remove fading when switching between local and remote echoes. --- .../Other/SwiftUI/Views/LoadableImage.swift | 32 ++++++++++++------- .../ImageRoomTimelineView.swift | 4 +-- .../StickerRoomTimelineView.swift | 2 +- .../VideoRoomTimelineView.swift | 2 +- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift index 1f909688bb..ad3a4fb75c 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift @@ -11,11 +11,11 @@ import Kingfisher import SwiftUI /// Used to configure animations -enum LoadableImageMediaType { +enum LoadableImageMediaType: Equatable { /// An avatar (can be displayed anywhere within the app). case avatar /// An image displayed in the timeline. - case timelineItem + case timelineItem(uniqueID: String) /// Any other media (can be displayed anywhere within the app). case generic } @@ -77,9 +77,19 @@ struct LoadableImage: View { mediaProvider: mediaProvider, transformer: transformer, placeholder: placeholder) + .id(stableMediaIdentifier) + } + + private var stableMediaIdentifier: String { + switch mediaType { + case .timelineItem(let uniqueID): + // Consider media for the same item to be the same view + uniqueID + default: // Binds the lifecycle of the LoadableImage to the associated URL. // This fixes the problem of the cache returning old values after a change in the URL. - .id(mediaSource.url) + mediaSource.url.absoluteString + } } } @@ -309,33 +319,33 @@ struct LoadableImage_Previews: PreviewProvider, TestablePreview { static var previews: some View { LazyVGrid(columns: [.init(.adaptive(minimum: 110, maximum: 110))], spacing: 24) { LoadableImage(url: "mxc://wherever/1234", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), mediaProvider: mediaProvider, placeholder: placeholder) .layout(title: "Loaded") LoadableImage(url: "mxc://wherever/2345", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), blurhash: "KpE4oyayR5|GbHb];3j@of", mediaProvider: mediaProvider, placeholder: placeholder) .layout(title: "Hidden (blurhash)", hideTimelineMedia: true) LoadableImage(url: "mxc://wherever/3456", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), mediaProvider: mediaProvider, placeholder: placeholder) .layout(title: "Hidden (placeholder)", hideTimelineMedia: true) LoadableImage(url: "mxc://wherever/4567", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), blurhash: "KbLM^j]q$jT|EfR-3rtjXk", mediaProvider: loadingMediaProvider, placeholder: placeholder) .layout(title: "Loading (blurhash)") LoadableImage(url: "mxc://wherever/5678", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), mediaProvider: loadingMediaProvider, placeholder: placeholder) .layout(title: "Loading (placeholder)") @@ -347,7 +357,7 @@ struct LoadableImage_Previews: PreviewProvider, TestablePreview { .layout(title: "Loading (avatar)") LoadableImage(url: "mxc://wherever/345", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), blurhash: "KbLM^j]q$jT|EfR-3rtjXk", mediaProvider: mediaProvider, transformer: transformer, @@ -355,7 +365,7 @@ struct LoadableImage_Previews: PreviewProvider, TestablePreview { .layout(title: "Loaded (transformer)") LoadableImage(url: "mxc://wherever/345", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), blurhash: "KbLM^j]q$jT|EfR-3rtjXk", mediaProvider: loadingMediaProvider, transformer: transformer, @@ -363,7 +373,7 @@ struct LoadableImage_Previews: PreviewProvider, TestablePreview { .layout(title: "Loading (transformer)") LoadableImage(url: "mxc://wherever/234", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), blurhash: "KbLM^j]q$jT|EfR-3rtjXk", mediaProvider: mediaProvider, transformer: transformer, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift index beb06037db..53bd61704b 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift @@ -41,7 +41,7 @@ struct ImageRoomTimelineView: View { private var loadableImage: some View { if timelineItem.content.contentType == .gif { LoadableImage(mediaSource: timelineItem.content.imageInfo.source, - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.content.blurhash, size: timelineItem.content.imageInfo.size, mediaProvider: context.mediaProvider) { @@ -50,7 +50,7 @@ struct ImageRoomTimelineView: View { .timelineMediaFrame(imageInfo: timelineItem.content.imageInfo) } else { LoadableImage(mediaSource: timelineItem.content.thumbnailInfo?.source ?? timelineItem.content.imageInfo.source, - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.content.blurhash, size: timelineItem.content.thumbnailInfo?.size ?? timelineItem.content.imageInfo.size, mediaProvider: context.mediaProvider) { diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift index 2763bb1313..b411148670 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift @@ -15,7 +15,7 @@ struct StickerRoomTimelineView: View { var body: some View { TimelineStyler(timelineItem: timelineItem) { LoadableImage(mediaSource: timelineItem.imageInfo.source, - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.blurhash, size: timelineItem.imageInfo.size, mediaProvider: context.mediaProvider) { diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift index d64d93c284..030b584998 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift @@ -42,7 +42,7 @@ struct VideoRoomTimelineView: View { var thumbnail: some View { if let thumbnailSource = timelineItem.content.thumbnailInfo?.source { LoadableImage(mediaSource: thumbnailSource, - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.content.blurhash, size: timelineItem.content.thumbnailInfo?.size, mediaProvider: context.mediaProvider) { imageView in From 18cbbe4d4a5c1917e2f388c850687eec100ee8b9 Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:40:27 +0100 Subject: [PATCH 32/74] Update compound iOS (#3532) * update * removed functions that have been migrated in compound --- ElementX.xcodeproj/project.pbxproj | 65 ++++++++----------- .../xcshareddata/swiftpm/Package.resolved | 6 +- .../SwiftUI/Layout/ScaledFrameModifier.swift | 34 ---------- .../SwiftUI/Layout/ScaledOffsetModifier.swift | 28 -------- .../Layout/ScaledPaddingModifier.swift | 32 --------- project.yml | 2 +- 6 files changed, 31 insertions(+), 136 deletions(-) delete mode 100644 ElementX/Sources/Other/SwiftUI/Layout/ScaledFrameModifier.swift delete mode 100644 ElementX/Sources/Other/SwiftUI/Layout/ScaledOffsetModifier.swift delete mode 100644 ElementX/Sources/Other/SwiftUI/Layout/ScaledPaddingModifier.swift diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 20ef13eee7..c56153a222 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 56; objects = { /* Begin PBXAggregateTarget section */ @@ -140,7 +140,6 @@ 1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */; }; 1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */; }; 1B2F9F368619FFF8C63C87CC /* BugReportScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EECE8B331CD169790EF284F /* BugReportScreenViewModelTests.swift */; }; - 1B67DE519285647C98812723 /* ScaledOffsetModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC5D7DA665E1F5F509C994C7 /* ScaledOffsetModifier.swift */; }; 1B88BB631F7FC45A213BB554 /* TimelineItemSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */; }; 1B8E30B35BF8F541C1318F19 /* SecureBackupScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40316EFFEAC7B206EE9A55AE /* SecureBackupScreenViewModelTests.swift */; }; 1BA04D05EBC6646958B1BE60 /* PlaceholderScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF34A2FD6797535C95AC918D /* PlaceholderScreenCoordinator.swift */; }; @@ -462,7 +461,6 @@ 63780F9DA06573E38A471ECA /* GenericCallLinkWidgetDriver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C202C1C7E330F124981A31 /* GenericCallLinkWidgetDriver.swift */; }; 63CDC201A5980F304F6D0A1C /* WaveformInteractionModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFEE91FB8ABB5F5884B6D940 /* WaveformInteractionModifier.swift */; }; 63E46D18B91D08E15FC04125 /* ExpiringTaskRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B25F959A434BB9923A3223F /* ExpiringTaskRunner.swift */; }; - 6409CE10CFF4DCB68C4C3872 /* ScaledPaddingModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E26C69EC1157D71CC61ADAE4 /* ScaledPaddingModifier.swift */; }; 642DF13C49ED4121C148230E /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E227F34BE43B08E098796E /* TestablePreview.swift */; }; 6448F8D1D3CA4CD27BB4CADD /* RoomMemberProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */; }; 64AB99285DC4437C0DDE9585 /* MenuSheetLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49ABAB186CF00B15C5521D04 /* MenuSheetLabelStyle.swift */; }; @@ -1133,7 +1131,6 @@ F3F38062C6CA21CF403C5C90 /* AudioConverterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2757B1BE23DF8AA239937243 /* AudioConverterProtocol.swift */; }; F3F9D61C53C348043D3D6F51 /* EncryptionResetScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 811E8BF34E931D51552C9C13 /* EncryptionResetScreen.swift */; }; F40B097470D3110DFDB1FAAA /* LegalInformationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */; }; - F4971845B5C4F270F6BC5745 /* ScaledFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D82F234B3576BD6268C7950 /* ScaledFrameModifier.swift */; }; F4996C82A4B3A5FF0C8EDD03 /* RoomListFilterModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */; }; F4C005F006FC3657B9F0A31D /* BugReportHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25586C0ADB814FEE9897DCAA /* BugReportHook.swift */; }; F519DE17A3A0F760307B2E6D /* InviteUsersScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D155E09BF961BBA8F85263 /* InviteUsersScreenViewModel.swift */; }; @@ -1266,13 +1263,13 @@ 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; 0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = ""; }; - 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; + 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = ""; }; 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = ""; }; 044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = ""; }; 045253F9967A535EE5B16691 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; 046C0D3F53B0B5EF0A1F5BEA /* RoomSummaryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryTests.swift; sourceTree = ""; }; - 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.swift; sourceTree = ""; }; 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = ""; }; 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxyProtocol.swift; sourceTree = ""; }; @@ -1281,6 +1278,7 @@ 05512FB13987D221B7205DE0 /* HomeScreenRecoveryKeyConfirmationBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRecoveryKeyConfirmationBanner.swift; sourceTree = ""; }; 0554FEA301486A8CFA475D5A /* AuthenticationClientBuilderFactoryMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationClientBuilderFactoryMock.swift; sourceTree = ""; }; 05596E4A11A8C9346E9E54AE /* SoftLogoutScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenCoordinator.swift; sourceTree = ""; }; + 057B747CF045D3C6C30EAB2C /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = fi; path = fi.lproj/Localizable.stringsdict; sourceTree = ""; }; 05A3E8741D199CD1A37F4CBF /* UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = ""; }; 05AF58372CA884A789EB9C5A /* AppMediatorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediatorProtocol.swift; sourceTree = ""; }; 05F598B1B346DAF223651C91 /* LoginScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenCoordinator.swift; sourceTree = ""; }; @@ -1338,7 +1336,7 @@ 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 = ""; }; - 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = ""; }; + 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; 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 = ""; }; @@ -1422,6 +1420,7 @@ 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationControllerProxyMock.swift; sourceTree = ""; }; 24B8177BD2AF45A286F5DA31 /* GlobalSearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchScreen.swift; sourceTree = ""; }; 24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModel.swift; sourceTree = ""; }; + 24E637CF570711FB5FD63DEA /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/InfoPlist.strings; sourceTree = ""; }; 24E8C8817F59BEC7E358EB78 /* AuthenticationStartScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreen.swift; sourceTree = ""; }; 24EC819497BB5F8C4998D760 /* RoomListFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFilterView.swift; sourceTree = ""; }; 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1432,7 +1431,7 @@ 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = ""; }; 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenCoordinator.swift; sourceTree = ""; }; 260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = ""; }; - 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; path = PreviewTests.xctestplan; sourceTree = ""; }; + 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = PreviewTests.xctestplan; sourceTree = ""; }; 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorder.swift; sourceTree = ""; }; 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceProtocol.swift; sourceTree = ""; }; 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1503,7 +1502,7 @@ 3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = ""; }; 35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; 35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = ""; }; - 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = ""; }; 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerURLBuildersTests.swift; sourceTree = ""; }; 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = ""; }; @@ -1565,6 +1564,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 = ""; }; + 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 = ""; }; 43C2067FF58B4996323EB40C /* SessionDirectories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDirectories.swift; sourceTree = ""; }; @@ -1615,7 +1615,7 @@ 4B41FABA2B0AEF4389986495 /* LoginMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMode.swift; sourceTree = ""; }; 4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenCoordinator.swift; sourceTree = ""; }; 4C8D988E82A8DFA13BE46F7C /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pl; path = pl.lproj/Localizable.stringsdict; sourceTree = ""; }; - 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreen.swift; sourceTree = ""; }; 4D3A7375AB22721C436EB056 /* ComposerToolbarModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarModels.swift; sourceTree = ""; }; 4E2245243369B99216C7D84E /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = ""; }; @@ -1684,7 +1684,6 @@ 5CEEAE1BFAACD6C96B6DB731 /* PHGPostHogProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogProtocol.swift; sourceTree = ""; }; 5D26A086A8278D39B5756D6F /* project.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = project.yml; sourceTree = ""; }; 5D53754227CEBD06358956D7 /* PinnedEventsTimelineScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineScreenCoordinator.swift; sourceTree = ""; }; - 5D82F234B3576BD6268C7950 /* ScaledFrameModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScaledFrameModifier.swift; sourceTree = ""; }; 5D99730313BEBF08CDE81EE3 /* EmojiDetection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiDetection.swift; sourceTree = ""; }; 5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProperties.swift; sourceTree = ""; }; 5E33FD32BBC44D703C7AE4F9 /* TextBasedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineItem.swift; sourceTree = ""; }; @@ -1886,7 +1885,7 @@ 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 8DA1E8F287680C8ED25EDBAC /* NetworkMonitorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitorMock.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = ""; }; + 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; 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 = ""; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = ""; }; @@ -2003,6 +2002,7 @@ A9873374E72AA53260AE90A2 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = ""; }; A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationFlowCoordinator.swift; sourceTree = ""; }; A9E6065FC6BC4A1B4C629E08 /* TimelineItemMenuActionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenuActionProvider.swift; sourceTree = ""; }; + 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 = ""; }; AAC9344689121887B74877AF /* UnitTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2067,7 +2067,7 @@ B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyProtocol.swift; sourceTree = ""; }; B53AC78E49A297AC1D72A7CF /* AppMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediator.swift; sourceTree = ""; }; B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = ""; }; - B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = ""; }; 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 = ""; }; @@ -2185,7 +2185,7 @@ CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = ""; }; CDE3F3911FF7CC639BDE5844 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; 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 = ""; }; + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; D01FD1171FF40E34D707FD00 /* BigIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigIcon.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 = ""; }; @@ -2258,7 +2258,6 @@ E1A5FEF17ED7E6176D922D4F /* RoomDetailsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreen.swift; sourceTree = ""; }; E1E0B4A34E69BD2132BEC521 /* MessageText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageText.swift; sourceTree = ""; }; E1ED17433ADC77287F8904F9 /* CallNotificationRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallNotificationRoomTimelineItem.swift; sourceTree = ""; }; - E26C69EC1157D71CC61ADAE4 /* ScaledPaddingModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScaledPaddingModifier.swift; sourceTree = ""; }; E2B1CC9AA154F4D5435BF60A /* Comparable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comparable.swift; sourceTree = ""; }; E2F96CCBEAAA7F2185BFA354 /* ClientProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxyMock.swift; sourceTree = ""; }; E3059CFA00C67D8787273B20 /* ServerSelectionScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenViewModel.swift; sourceTree = ""; }; @@ -2309,7 +2308,6 @@ EB76A9AFC6CCAD4998D9B045 /* IdentityConfirmationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenViewModel.swift; sourceTree = ""; }; EBEB8D9F4940E161B18FE4BC /* UITestsNotificationCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsNotificationCenter.swift; sourceTree = ""; }; EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsViewModelTests.swift; sourceTree = ""; }; - EC5D7DA665E1F5F509C994C7 /* ScaledOffsetModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScaledOffsetModifier.swift; sourceTree = ""; }; ECB836DD8BE31931F51B8AC9 /* EncryptionSettingsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionSettingsFlowCoordinator.swift; sourceTree = ""; }; ECD5FCBA169B6A82F501CA1B /* AnalyticsSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; ECF79FB25E2D4BD6F50CE7C9 /* RoomMembersListScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModel.swift; sourceTree = ""; }; @@ -2318,7 +2316,7 @@ ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = ""; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = ""; }; ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModel.swift; sourceTree = ""; }; - ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = ""; }; ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = ""; }; EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = ""; }; @@ -2341,7 +2339,7 @@ F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = ""; }; - F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; + F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = ""; }; F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = ""; }; F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = ""; }; F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = ""; }; @@ -2359,7 +2357,7 @@ F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineBubbleLayout.swift; sourceTree = ""; }; F5E23D8EE6CBACF32F1EC874 /* MediaPlayerProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProviderProtocol.swift; sourceTree = ""; }; F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModel.swift; sourceTree = ""; }; - F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; path = test_apple_image.heic; sourceTree = ""; }; + F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_apple_image.heic; sourceTree = ""; }; F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = ""; }; F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockUITests.swift; sourceTree = ""; }; F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderMock.swift; sourceTree = ""; }; @@ -5208,9 +5206,6 @@ 565F1B2B300597C616B37888 /* FullscreenDialog.swift */, 49ABAB186CF00B15C5521D04 /* MenuSheetLabelStyle.swift */, 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */, - 5D82F234B3576BD6268C7950 /* ScaledFrameModifier.swift */, - EC5D7DA665E1F5F509C994C7 /* ScaledOffsetModifier.swift */, - E26C69EC1157D71CC61ADAE4 /* ScaledPaddingModifier.swift */, 933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */, EFF7BF82A950B91BC5469E91 /* ViewFrameReader.swift */, ); @@ -5985,6 +5980,7 @@ es, et, fa, + fi, fr, hu, id, @@ -7100,9 +7096,6 @@ 50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */, D43F0503EF2CBC55272538FE /* SDKGeneratedMocks.swift in Sources */, 88CBF1595E39CE697928DE48 /* SFNumberedListView.swift in Sources */, - F4971845B5C4F270F6BC5745 /* ScaledFrameModifier.swift in Sources */, - 1B67DE519285647C98812723 /* ScaledOffsetModifier.swift in Sources */, - 6409CE10CFF4DCB68C4C3872 /* ScaledPaddingModifier.swift in Sources */, FB595EC9C00AB32F39034055 /* SceneDelegate.swift in Sources */, 0437765FF480249486893CC7 /* ScreenTrackerViewModifier.swift in Sources */, 0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */, @@ -7414,6 +7407,7 @@ 6722709BD6178E10B70C9641 /* es */, F3C7252B3461D06175D975A4 /* et */, C715CFE00686DACA59D836EA /* fa */, + A9E88667D393612FD5D84718 /* fi */, CEE20623EB4A9B88FB29F2BA /* fr */, D196116D2DD3F2757D45FCB7 /* hu */, 330AF4D121C3396F7A14B21D /* id */, @@ -7442,6 +7436,7 @@ AACE9B8E1A4AE79A7E2914F6 /* es */, 4F5F0662483ED69791D63B16 /* et */, 48CE6BF18E542B32FA52CE06 /* fa */, + 057B747CF045D3C6C30EAB2C /* fi */, 653610CB5F9776EAAAB98155 /* fr */, C95ADE8D9527523572532219 /* hu */, 475D47D0BFE961B02BAC5D49 /* id */, @@ -7475,6 +7470,7 @@ CBBCC6E74774E79B599625D0 /* es */, A443FAE2EE820A5790C35C8D /* et */, A9873374E72AA53260AE90A2 /* fa */, + 434522ED2BDED08759048077 /* fi */, CC680E0E79D818706CB28CF8 /* fr */, 624244C398804ADC885239AA /* hu */, EF98A02DED04075F7CF0C721 /* id */, @@ -7507,6 +7503,7 @@ 1215A4FC53D2319E81AE8970 /* en */, 2525D78FEA7E7B132ED85C58 /* es */, 2C39D91A31409775B0F4268F /* et */, + 24E637CF570711FB5FD63DEA /* fi */, ACD7BD6BEE21264F6677904A /* fr */, 1D652E78832289CD9EB64488 /* hu */, 7199693797B66245EF97BCF5 /* id */, @@ -7557,9 +7554,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_NSE", - ); + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -7608,9 +7603,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_MAIN_APP", - ); + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7636,9 +7629,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_MAIN_APP", - ); + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7904,9 +7895,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_NSE", - ); + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -8257,7 +8246,7 @@ repositoryURL = "https://github.com/element-hq/compound-ios"; requirement = { kind = revision; - revision = 4af41551fb7a7b9da0fd95171f2dec554726fadd; + revision = 80edb8829b4ca00c0a52a39b7d9024e3ebdc1acb; }; }; 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 85a96075b9..513fc50f06 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" : "6190515a2af1eb1cb02114270fd536f1b6daa518", - "version" : "2.0.1" + "revision" : "d81c1aa03fed8662cf85702310542bdc9e5b3d93", + "version" : "2.0.2" } }, { @@ -15,7 +15,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/compound-ios", "state" : { - "revision" : "4af41551fb7a7b9da0fd95171f2dec554726fadd" + "revision" : "80edb8829b4ca00c0a52a39b7d9024e3ebdc1acb" } }, { diff --git a/ElementX/Sources/Other/SwiftUI/Layout/ScaledFrameModifier.swift b/ElementX/Sources/Other/SwiftUI/Layout/ScaledFrameModifier.swift deleted file mode 100644 index 84de64af9b..0000000000 --- a/ElementX/Sources/Other/SwiftUI/Layout/ScaledFrameModifier.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright 2023, 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 { - func scaledFrame(size: CGFloat, alignment: Alignment = .center, relativeTo textStyle: Font.TextStyle = .body) -> some View { - scaledFrame(width: size, height: size, alignment: alignment, relativeTo: textStyle) - } - - func scaledFrame(width: CGFloat, height: CGFloat, alignment: Alignment = .center, relativeTo textStyle: Font.TextStyle = .body) -> some View { - modifier(ScaledFrameModifier(width: width, height: height, alignment: alignment, relativeTo: textStyle)) - } -} - -private struct ScaledFrameModifier: ViewModifier { - @ScaledMetric var width: CGFloat - @ScaledMetric var height: CGFloat - let alignment: Alignment - - init(width: CGFloat, height: CGFloat, alignment: Alignment, relativeTo textStyle: Font.TextStyle) { - _width = ScaledMetric(wrappedValue: width, relativeTo: textStyle) - _height = ScaledMetric(wrappedValue: height, relativeTo: textStyle) - self.alignment = alignment - } - - func body(content: Content) -> some View { - content.frame(width: width, height: height, alignment: alignment) - } -} diff --git a/ElementX/Sources/Other/SwiftUI/Layout/ScaledOffsetModifier.swift b/ElementX/Sources/Other/SwiftUI/Layout/ScaledOffsetModifier.swift deleted file mode 100644 index 550e470f4b..0000000000 --- a/ElementX/Sources/Other/SwiftUI/Layout/ScaledOffsetModifier.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// 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 { - func scaledOffset(x: CGFloat = 0, y: CGFloat = 0, relativeTo textStyle: Font.TextStyle = .body) -> some View { - modifier(ScaledOffsetModifier(x: x, y: y, relativeTo: textStyle)) - } -} - -private struct ScaledOffsetModifier: ViewModifier { - @ScaledMetric var x: CGFloat - @ScaledMetric var y: CGFloat - - init(x: CGFloat, y: CGFloat, relativeTo textStyle: Font.TextStyle) { - _x = ScaledMetric(wrappedValue: x, relativeTo: textStyle) - _y = ScaledMetric(wrappedValue: y, relativeTo: textStyle) - } - - func body(content: Content) -> some View { - content.offset(x: x, y: y) - } -} diff --git a/ElementX/Sources/Other/SwiftUI/Layout/ScaledPaddingModifier.swift b/ElementX/Sources/Other/SwiftUI/Layout/ScaledPaddingModifier.swift deleted file mode 100644 index c2e5e86136..0000000000 --- a/ElementX/Sources/Other/SwiftUI/Layout/ScaledPaddingModifier.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright 2023, 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 { - func scaledPadding(_ length: CGFloat, relativeTo textStyle: Font.TextStyle = .body) -> some View { - scaledPadding(.all, length, relativeTo: textStyle) - } - - func scaledPadding(_ edges: Edge.Set, _ length: CGFloat, relativeTo textStyle: Font.TextStyle = .body) -> some View { - modifier(ScaledPaddingModifier(edges: edges, length: length, textStyle: textStyle)) - } -} - -private struct ScaledPaddingModifier: ViewModifier { - let edges: Edge.Set - @ScaledMetric var length: CGFloat - - init(edges: Edge.Set, length: CGFloat, textStyle: Font.TextStyle) { - self.edges = edges - _length = ScaledMetric(wrappedValue: length, relativeTo: textStyle) - } - - func body(content: Content) -> some View { - content.padding(edges, length) - } -} diff --git a/project.yml b/project.yml index 5cc1bb8ed4..3e07914aa1 100644 --- a/project.yml +++ b/project.yml @@ -65,7 +65,7 @@ packages: # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios - revision: 4af41551fb7a7b9da0fd95171f2dec554726fadd + revision: 80edb8829b4ca00c0a52a39b7d9024e3ebdc1acb # path: ../compound-ios AnalyticsEvents: url: https://github.com/matrix-org/matrix-analytics-events From 6b6420a2297c78cfc2626c8e23bf8d66d40c3a37 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Mon, 18 Nov 2024 15:18:20 +0200 Subject: [PATCH 33/74] Expose the public search feature flag in the developer settings and disable it by default. --- ElementX/Sources/Application/AppSettings.swift | 2 +- .../DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift | 1 + .../DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ElementX/Sources/Application/AppSettings.swift b/ElementX/Sources/Application/AppSettings.swift index 40b0d76bfe..5949761ec5 100644 --- a/ElementX/Sources/Application/AppSettings.swift +++ b/ElementX/Sources/Application/AppSettings.swift @@ -268,7 +268,7 @@ final class AppSettings { // MARK: - Feature Flags - @UserPreference(key: UserDefaultsKeys.publicSearchEnabled, defaultValue: isDevelopmentBuild, storageType: .volatile) + @UserPreference(key: UserDefaultsKeys.publicSearchEnabled, defaultValue: false, storageType: .userDefaults(store)) var publicSearchEnabled @UserPreference(key: UserDefaultsKeys.fuzzyRoomListSearchEnabled, defaultValue: false, storageType: .userDefaults(store)) diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift index f8523ff3c1..1024600448 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift @@ -43,6 +43,7 @@ enum DeveloperOptionsScreenViewAction { protocol DeveloperOptionsProtocol: AnyObject { var logLevel: TracingConfiguration.LogLevel { get set } var slidingSyncDiscovery: AppSettings.SlidingSyncDiscovery { get set } + var publicSearchEnabled: Bool { get set } var hideUnreadMessagesBadge: Bool { get set } var fuzzyRoomListSearchEnabled: Bool { get set } var hideTimelineMedia: Bool { get set } diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift index d9e6f2a6cd..08b06c6e82 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift @@ -36,6 +36,10 @@ struct DeveloperOptionsScreen: View { } Section("Room List") { + Toggle(isOn: $context.publicSearchEnabled) { + Text("Public search") + } + Toggle(isOn: $context.hideUnreadMessagesBadge) { Text("Hide grey dots") } From 1901749c1723f920381e7bee6263d2edea1cfeab Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:58:29 +0000 Subject: [PATCH 34/74] Update the SDK. (#3535) --- ElementX.xcodeproj/project.pbxproj | 44 +++++++++++-------- .../xcshareddata/swiftpm/Package.resolved | 4 +- project.yml | 2 +- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index c56153a222..12f40d1d8f 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -1263,13 +1263,13 @@ 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; 0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = ""; }; - 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = ""; }; + 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = ""; }; 044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = ""; }; 045253F9967A535EE5B16691 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; 046C0D3F53B0B5EF0A1F5BEA /* RoomSummaryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryTests.swift; sourceTree = ""; }; - 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.swift; sourceTree = ""; }; 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = ""; }; 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxyProtocol.swift; sourceTree = ""; }; @@ -1336,7 +1336,7 @@ 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 = ""; }; - 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = IntegrationTests.xctestplan; 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 = ""; }; @@ -1431,7 +1431,7 @@ 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = ""; }; 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenCoordinator.swift; sourceTree = ""; }; 260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = ""; }; - 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = PreviewTests.xctestplan; sourceTree = ""; }; + 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; path = PreviewTests.xctestplan; sourceTree = ""; }; 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorder.swift; sourceTree = ""; }; 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceProtocol.swift; sourceTree = ""; }; 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1502,7 +1502,7 @@ 3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = ""; }; 35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; 35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = ""; }; - 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = ""; }; 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerURLBuildersTests.swift; sourceTree = ""; }; 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = ""; }; @@ -1615,7 +1615,7 @@ 4B41FABA2B0AEF4389986495 /* LoginMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMode.swift; sourceTree = ""; }; 4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenCoordinator.swift; sourceTree = ""; }; 4C8D988E82A8DFA13BE46F7C /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pl; path = pl.lproj/Localizable.stringsdict; sourceTree = ""; }; - 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreen.swift; sourceTree = ""; }; 4D3A7375AB22721C436EB056 /* ComposerToolbarModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarModels.swift; sourceTree = ""; }; 4E2245243369B99216C7D84E /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = ""; }; @@ -1885,7 +1885,7 @@ 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 8DA1E8F287680C8ED25EDBAC /* NetworkMonitorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitorMock.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = ""; }; + 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 = ""; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = ""; }; @@ -2067,7 +2067,7 @@ B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyProtocol.swift; sourceTree = ""; }; B53AC78E49A297AC1D72A7CF /* AppMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediator.swift; sourceTree = ""; }; B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = ""; }; - B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = ""; }; + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; 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 = ""; }; @@ -2185,7 +2185,7 @@ CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = ""; }; CDE3F3911FF7CC639BDE5844 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = ""; }; - CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = ""; }; D01FD1171FF40E34D707FD00 /* BigIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigIcon.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 = ""; }; @@ -2316,7 +2316,7 @@ ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = ""; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = ""; }; ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModel.swift; sourceTree = ""; }; - ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = ""; }; ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = ""; }; EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = ""; }; @@ -2339,7 +2339,7 @@ F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = ""; }; - F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = ""; }; + F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = ""; }; F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = ""; }; F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = ""; }; @@ -2357,7 +2357,7 @@ F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineBubbleLayout.swift; sourceTree = ""; }; F5E23D8EE6CBACF32F1EC874 /* MediaPlayerProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProviderProtocol.swift; sourceTree = ""; }; F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModel.swift; sourceTree = ""; }; - F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_apple_image.heic; sourceTree = ""; }; + F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; path = test_apple_image.heic; sourceTree = ""; }; F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = ""; }; F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockUITests.swift; sourceTree = ""; }; F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderMock.swift; sourceTree = ""; }; @@ -7554,7 +7554,9 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_NSE"; + OTHER_SWIFT_FLAGS = ( + "-DIS_NSE", + ); PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -7603,7 +7605,9 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; + OTHER_SWIFT_FLAGS = ( + "-DIS_MAIN_APP", + ); PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7629,7 +7633,9 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; + OTHER_SWIFT_FLAGS = ( + "-DIS_MAIN_APP", + ); PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7895,7 +7901,9 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = "-DIS_NSE"; + OTHER_SWIFT_FLAGS = ( + "-DIS_NSE", + ); PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -8126,7 +8134,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.68; + version = 1.0.69; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 513fc50f06..29b2dfc754 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "4e0924228b177720b67df1843ea7a4377d073900", - "version" : "1.0.68" + "revision" : "7f6beb6a5aceca7d573c3370ece96cfd8589b94a", + "version" : "1.0.69" } }, { diff --git a/project.yml b/project.yml index 3e07914aa1..9c7432d92a 100644 --- a/project.yml +++ b/project.yml @@ -61,7 +61,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.68 + exactVersion: 1.0.69 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From 352bb577ad047b819f5e19948d4471b14fff071b Mon Sep 17 00:00:00 2001 From: Element CI Date: Tue, 19 Nov 2024 08:19:20 -0800 Subject: [PATCH 35/74] Prepare next release --- CHANGES.md | 44 ++++++++++++++++++++++++++++++ ElementX.xcodeproj/project.pbxproj | 4 +-- project.yml | 2 +- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ef61cce70d..5399deba5e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,47 @@ +## Changes in 1.9.6 (2024-11-19) + +### What's Changed + +✨ Features +* Share extension by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3506 +* Enable local echoes for media uploads on development builds. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3514 + +🙌 Improvements +* Stacked Avatars View by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3504 + +🐛 Bugfixes +* Regenerate thumbnails to see if it helps with phantom avatar switching. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3503 +* Fix #1947 - Check expected files are still present before restoring a session. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3507 +* Fix Rooms that user has knocked not displaying the request sent screen by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3513 +* Fix share extension app group so it works for nightlies too by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3520 +* Fix toolbar icons disappearing on the iPad after backgrounding the app by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3521 +* Fix a bug where the security banner has the wrong state when out of sync. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3511 +* Fix image animations / remove fading when switching between local and remote echoes. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3525 + +🗣 Translations +* Translations update by @RiotRobot in https://github.com/element-hq/element-x-ios/pull/3523 + +🧱 Build +* Update the project to use Xcode 16.1 by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3505 + +🚧 In development 🚧 +* Knock requests banner by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3510 +* Knocking Request Cell by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3516 + +Others +* Update the strings for unsupported calls. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3502 +* Bump the RustSDK to v1.0.67 by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3512 +* UI test fixes by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3515 +* Group image and video metadata in specialised structs by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3518 +* Update compound by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3519 +* Update the SDK. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3524 +* Update compound iOS by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3532 +* Expose the public search feature flag in the developer settings and disable it by default. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3528 +* Update the SDK. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3535 + + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.9.5...1.9.6 + ## Changes in 1.9.5 (2024-11-11) ### What's Changed diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 12f40d1d8f..b88ded62c8 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -7743,7 +7743,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 17.6; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; MACOSX_DEPLOYMENT_TARGET = 14.6; - MARKETING_VERSION = 1.9.6; + MARKETING_VERSION = 1.9.7; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCTION_APP_NAME = Element; @@ -7820,7 +7820,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 17.6; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; MACOSX_DEPLOYMENT_TARGET = 14.6; - MARKETING_VERSION = 1.9.6; + MARKETING_VERSION = 1.9.7; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; diff --git a/project.yml b/project.yml index 9c7432d92a..d80b046579 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.6 + MARKETING_VERSION: 1.9.7 CURRENT_PROJECT_VERSION: 1 SUPPORTS_MACCATALYST: false From b75ad6a5aaf27ab605ccc89ead7e7267f6a0215d Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:35:01 +0000 Subject: [PATCH 36/74] Support adding a caption to media uploads. (#3531) * Add a composer to the MediaUploadPreviewScreen. And send it's content to the media upload's caption. * Use the new compound SendButton (updating relative padding in the toolbar). * Update snapshots. * Add unit tests for sending a caption. --- ElementX.xcodeproj/project.pbxproj | 4 + .../xcshareddata/swiftpm/Package.resolved | 4 +- .../Mocks/Generated/GeneratedMocks.swift | 160 +++++++++--------- .../Sources/Mocks/JoinedRoomProxyMock.swift | 18 +- .../Sources/Mocks/TimelineProxyMock.swift | 35 ++++ .../Sources/Other/SwiftUI/Views/BigIcon.swift | 6 +- .../MediaUploadPreviewScreenModels.swift | 7 + .../MediaUploadPreviewScreenViewModel.swift | 40 ++++- .../View/MediaUploadPreviewScreen.swift | 70 +++++--- .../View/ComposerToolbar.swift | 38 +++-- .../View/MessageComposer.swift | 98 ++++++----- .../View/RoomAttachmentPicker.swift | 4 +- .../View/VoiceMessageRecordingButton.swift | 15 +- .../Services/Timeline/TimelineProxy.swift | 14 +- .../Timeline/TimelineProxyProtocol.swift | 6 + .../test_composerToolbar-iPad-en-GB.1.png | 4 +- .../test_composerToolbar-iPad-en-GB.Reply.png | 4 +- ...mposerToolbar-iPad-en-GB.Voice-Message.png | 4 +- ...serToolbar-iPad-en-GB.With-Suggestions.png | 4 +- .../test_composerToolbar-iPad-pseudo.1.png | 4 +- ...test_composerToolbar-iPad-pseudo.Reply.png | 4 +- ...poserToolbar-iPad-pseudo.Voice-Message.png | 4 +- ...erToolbar-iPad-pseudo.With-Suggestions.png | 4 +- ...test_composerToolbar-iPhone-16-en-GB.1.png | 4 +- ..._composerToolbar-iPhone-16-en-GB.Reply.png | 4 +- ...rToolbar-iPhone-16-en-GB.Voice-Message.png | 4 +- ...olbar-iPhone-16-en-GB.With-Suggestions.png | 4 +- ...est_composerToolbar-iPhone-16-pseudo.1.png | 4 +- ...composerToolbar-iPhone-16-pseudo.Reply.png | 4 +- ...Toolbar-iPhone-16-pseudo.Voice-Message.png | 4 +- ...lbar-iPhone-16-pseudo.With-Suggestions.png | 4 +- ..._mediaUploadPreviewScreen-iPad-en-GB.1.png | 4 +- ...mediaUploadPreviewScreen-iPad-pseudo.1.png | 4 +- ...aUploadPreviewScreen-iPhone-16-en-GB.1.png | 4 +- ...UploadPreviewScreen-iPhone-16-pseudo.1.png | 4 +- .../test_messageComposer-iPad-en-GB.1.png | 4 +- ...Composer-iPad-en-GB.Replying-in-thread.png | 4 +- ...st_messageComposer-iPad-en-GB.Replying.png | 4 +- .../test_messageComposer-iPad-pseudo.1.png | 4 +- ...omposer-iPad-pseudo.Replying-in-thread.png | 4 +- ...t_messageComposer-iPad-pseudo.Replying.png | 4 +- ...test_messageComposer-iPhone-16-en-GB.1.png | 4 +- ...ser-iPhone-16-en-GB.Replying-in-thread.png | 4 +- ...ssageComposer-iPhone-16-en-GB.Replying.png | 4 +- ...est_messageComposer-iPhone-16-pseudo.1.png | 4 +- ...er-iPhone-16-pseudo.Replying-in-thread.png | 4 +- ...sageComposer-iPhone-16-pseudo.Replying.png | 4 +- .../test_roomScreen-iPad-en-GB.1.png | 4 +- .../test_roomScreen-iPad-pseudo.1.png | 4 +- .../test_roomScreen-iPhone-16-en-GB.1.png | 4 +- .../test_roomScreen-iPhone-16-pseudo.1.png | 4 +- .../test_timelineView-iPad-en-GB.1.png | 4 +- .../test_timelineView-iPad-pseudo.1.png | 4 +- .../test_timelineView-iPhone-16-en-GB.1.png | 4 +- .../test_timelineView-iPhone-16-pseudo.1.png | 4 +- ...diaUploadPreviewScreenViewModelTests.swift | 133 ++++++++++++++- 56 files changed, 529 insertions(+), 283 deletions(-) create mode 100644 ElementX/Sources/Mocks/TimelineProxyMock.swift diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index b88ded62c8..e58469ce84 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -689,6 +689,7 @@ 90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; 914BDF61447C723F104BCE33 /* SessionDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C2067FF58B4996323EB40C /* SessionDirectories.swift */; }; 915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */; }; + 919BAE492CECA981009F6A5B /* TimelineProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */; }; 91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; }; 91C6AC0E9D2B9C0C76CC6AD4 /* RoomDirectorySearchScreenScreenModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3984C93B8E9B10C92DADF9EE /* RoomDirectorySearchScreenScreenModelProtocol.swift */; }; 91D1A46A733EC24C081DD353 /* SessionVerificationRequestDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A1265FAF2C0AF1C30605BE7 /* SessionVerificationRequestDetailsView.swift */; }; @@ -1900,6 +1901,7 @@ 90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemView.swift; sourceTree = ""; }; 913C8E13B8B602C7B6C0C4AE /* PillTextAttachmentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillTextAttachmentData.swift; sourceTree = ""; }; 91868EB98818044E6FEBE532 /* NotificationPermissionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenCoordinator.swift; sourceTree = ""; }; + 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyMock.swift; sourceTree = ""; }; 91C8BD78F7B9247AC57FA1A3 /* RedactedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineView.swift; sourceTree = ""; }; 91CF6F7D08228D16BA69B63B /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.strings"; sourceTree = ""; }; 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenu.swift; sourceTree = ""; }; @@ -3032,6 +3034,7 @@ 9EB9BA2F30EB8C33226D8FF1 /* UserSessionStoreMock.swift */, B23135B06B044CB811139D2F /* Generated */, E5E545F92D01588360A9BAC5 /* SDK */, + 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */, ); path = Mocks; sourceTree = ""; @@ -7096,6 +7099,7 @@ 50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */, D43F0503EF2CBC55272538FE /* SDKGeneratedMocks.swift in Sources */, 88CBF1595E39CE697928DE48 /* SFNumberedListView.swift in Sources */, + 919BAE492CECA981009F6A5B /* TimelineProxyMock.swift in Sources */, FB595EC9C00AB32F39034055 /* SceneDelegate.swift in Sources */, 0437765FF480249486893CC7 /* ScreenTrackerViewModifier.swift in Sources */, 0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */, diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 29b2dfc754..8b26c4c617 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -248,8 +248,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-snapshot-testing", "state" : { - "revision" : "7b0bbbae90c41f848f90ac7b4df6c4f50068256d", - "version" : "1.17.5" + "revision" : "42a086182681cf661f5c47c9b7dc3931de18c6d7", + "version" : "1.17.6" } }, { diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index c6361567d1..db4da917b7 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -14449,15 +14449,15 @@ class TimelineProxyMock: TimelineProxyProtocol { } //MARK: - sendAudio - var sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendAudioUrlAudioInfoProgressSubjectRequestHandleCallsCount: Int { + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingCallsCount + return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } return returnValue! @@ -14465,27 +14465,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } } } } - var sendAudioUrlAudioInfoProgressSubjectRequestHandleCalled: Bool { - return sendAudioUrlAudioInfoProgressSubjectRequestHandleCallsCount > 0 + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCalled: Bool { + return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCallsCount > 0 } - var sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendAudioUrlAudioInfoProgressSubjectRequestHandleReturnValue: Result! { + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingReturnValue + return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } return returnValue! @@ -14493,35 +14493,35 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } } } } - var sendAudioUrlAudioInfoProgressSubjectRequestHandleClosure: ((URL, AudioInfo, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure: ((URL, AudioInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendAudio(url: URL, audioInfo: AudioInfo, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendAudioUrlAudioInfoProgressSubjectRequestHandleCallsCount += 1 - if let sendAudioUrlAudioInfoProgressSubjectRequestHandleClosure = sendAudioUrlAudioInfoProgressSubjectRequestHandleClosure { - return await sendAudioUrlAudioInfoProgressSubjectRequestHandleClosure(url, audioInfo, progressSubject, requestHandle) + func sendAudio(url: URL, audioInfo: AudioInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCallsCount += 1 + if let sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure = sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure { + return await sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure(url, audioInfo, caption, progressSubject, requestHandle) } else { - return sendAudioUrlAudioInfoProgressSubjectRequestHandleReturnValue + return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleReturnValue } } //MARK: - sendFile - var sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendFileUrlFileInfoProgressSubjectRequestHandleCallsCount: Int { + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingCallsCount + return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } return returnValue! @@ -14529,27 +14529,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } } } } - var sendFileUrlFileInfoProgressSubjectRequestHandleCalled: Bool { - return sendFileUrlFileInfoProgressSubjectRequestHandleCallsCount > 0 + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCalled: Bool { + return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCallsCount > 0 } - var sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendFileUrlFileInfoProgressSubjectRequestHandleReturnValue: Result! { + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingReturnValue + return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } return returnValue! @@ -14557,35 +14557,35 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } } } } - var sendFileUrlFileInfoProgressSubjectRequestHandleClosure: ((URL, FileInfo, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure: ((URL, FileInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendFile(url: URL, fileInfo: FileInfo, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendFileUrlFileInfoProgressSubjectRequestHandleCallsCount += 1 - if let sendFileUrlFileInfoProgressSubjectRequestHandleClosure = sendFileUrlFileInfoProgressSubjectRequestHandleClosure { - return await sendFileUrlFileInfoProgressSubjectRequestHandleClosure(url, fileInfo, progressSubject, requestHandle) + func sendFile(url: URL, fileInfo: FileInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCallsCount += 1 + if let sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure = sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure { + return await sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure(url, fileInfo, caption, progressSubject, requestHandle) } else { - return sendFileUrlFileInfoProgressSubjectRequestHandleReturnValue + return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleReturnValue } } //MARK: - sendImage - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleCallsCount: Int { + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingCallsCount + return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } return returnValue! @@ -14593,27 +14593,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } } } } - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleCalled: Bool { - return sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleCallsCount > 0 + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCalled: Bool { + return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCallsCount > 0 } - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleReturnValue: Result! { + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingReturnValue + return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } return returnValue! @@ -14621,22 +14621,22 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } } } } - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleClosure: ((URL, URL, ImageInfo, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure: ((URL, URL, ImageInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleCallsCount += 1 - if let sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleClosure = sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleClosure { - return await sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleClosure(url, thumbnailURL, imageInfo, progressSubject, requestHandle) + func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCallsCount += 1 + if let sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure = sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure { + return await sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure(url, thumbnailURL, imageInfo, caption, progressSubject, requestHandle) } else { - return sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleReturnValue + return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleReturnValue } } //MARK: - sendLocation @@ -14711,15 +14711,15 @@ class TimelineProxyMock: TimelineProxyProtocol { } //MARK: - sendVideo - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleCallsCount: Int { + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingCallsCount + return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } return returnValue! @@ -14727,27 +14727,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } } } } - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleCalled: Bool { - return sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleCallsCount > 0 + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCalled: Bool { + return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCallsCount > 0 } - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleReturnValue: Result! { + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingReturnValue + return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } return returnValue! @@ -14755,22 +14755,22 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } } } } - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleClosure: ((URL, URL, VideoInfo, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure: ((URL, URL, VideoInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleCallsCount += 1 - if let sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleClosure = sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleClosure { - return await sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleClosure(url, thumbnailURL, videoInfo, progressSubject, requestHandle) + func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCallsCount += 1 + if let sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure = sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure { + return await sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure(url, thumbnailURL, videoInfo, caption, progressSubject, requestHandle) } else { - return sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleReturnValue + return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleReturnValue } } //MARK: - sendVoiceMessage diff --git a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift index 75a1a5c373..ff385d9121 100644 --- a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift @@ -49,22 +49,8 @@ extension JoinedRoomProxyMock { id = configuration.id isEncrypted = configuration.isEncrypted - let timeline = TimelineProxyMock() - timeline.sendMessageEventContentReturnValue = .success(()) - timeline.paginateBackwardsRequestSizeReturnValue = .success(()) - timeline.paginateForwardsRequestSizeReturnValue = .success(()) - timeline.sendReadReceiptForTypeReturnValue = .success(()) - - if configuration.shouldUseAutoUpdatingTimeline { - timeline.underlyingTimelineProvider = AutoUpdatingRoomTimelineProviderMock() - } else { - let timelineProvider = RoomTimelineProviderMock() - timelineProvider.paginationState = .init(backward: configuration.timelineStartReached ? .timelineEndReached : .idle, forward: .timelineEndReached) - timelineProvider.underlyingMembershipChangePublisher = PassthroughSubject().eraseToAnyPublisher() - timeline.underlyingTimelineProvider = timelineProvider - } - - self.timeline = timeline + timeline = TimelineProxyMock(.init(isAutoUpdating: configuration.shouldUseAutoUpdatingTimeline, + timelineStartReached: configuration.timelineStartReached)) ownUserID = configuration.ownUserID diff --git a/ElementX/Sources/Mocks/TimelineProxyMock.swift b/ElementX/Sources/Mocks/TimelineProxyMock.swift new file mode 100644 index 0000000000..13147820e6 --- /dev/null +++ b/ElementX/Sources/Mocks/TimelineProxyMock.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 Combine +import Foundation + +extension TimelineProxyMock { + struct Configuration { + var isAutoUpdating = false + var timelineStartReached = false + } + + @MainActor + convenience init(_ configuration: Configuration) { + self.init() + + sendMessageEventContentReturnValue = .success(()) + paginateBackwardsRequestSizeReturnValue = .success(()) + paginateForwardsRequestSizeReturnValue = .success(()) + sendReadReceiptForTypeReturnValue = .success(()) + + if configuration.isAutoUpdating { + underlyingTimelineProvider = AutoUpdatingRoomTimelineProviderMock() + } else { + let timelineProvider = RoomTimelineProviderMock() + timelineProvider.paginationState = .init(backward: configuration.timelineStartReached ? .timelineEndReached : .idle, forward: .timelineEndReached) + timelineProvider.underlyingMembershipChangePublisher = PassthroughSubject().eraseToAnyPublisher() + underlyingTimelineProvider = timelineProvider + } + } +} diff --git a/ElementX/Sources/Other/SwiftUI/Views/BigIcon.swift b/ElementX/Sources/Other/SwiftUI/Views/BigIcon.swift index 2551c02ca1..a32482f47e 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/BigIcon.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/BigIcon.swift @@ -50,7 +50,7 @@ struct BigIcon: View { var style: Style = .defaultSolid var body: some View { - CompoundIcon(icon, size: .custom(32), relativeTo: .title) + CompoundIcon(icon, size: .custom(32), relativeTo: .compound.headingLG) .modifier(BigIconModifier(style: style)) } } @@ -62,7 +62,7 @@ extension Image { resizable() .renderingMode(.template) .aspectRatio(contentMode: .fit) - .scaledPadding(insets, relativeTo: .title) + .scaledPadding(insets, relativeTo: .compound.headingLG) .modifier(BigIconModifier(style: style)) } } @@ -72,7 +72,7 @@ private struct BigIconModifier: ViewModifier { func body(content: Content) -> some View { content - .scaledFrame(size: 64, relativeTo: .title) + .scaledFrame(size: 64, relativeTo: .compound.headingLG) .foregroundColor(style.foregroundColor) .background { RoundedRectangle(cornerRadius: 14) diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift index c471ab42a1..f9c1eb178e 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift @@ -15,6 +15,13 @@ struct MediaUploadPreviewScreenViewState: BindableState { let url: URL let title: String? var shouldDisableInteraction = false + + var bindings = MediaUploadPreviewScreenBindings() +} + +struct MediaUploadPreviewScreenBindings: BindableState { + var caption = NSAttributedString() + var presendCallback: (() -> Void)? } enum MediaUploadPreviewScreenViewAction { diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift index cca94f2cc3..c7f2164db3 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift @@ -42,6 +42,9 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, } override func process(viewAction: MediaUploadPreviewScreenViewAction) { + // Get the current caption before all the processing starts. + let caption = state.bindings.caption.nonBlankString + switch viewAction { case .send: Task { @@ -51,7 +54,7 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, switch await mediaUploadingPreprocessor.processMedia(at: url) { case .success(let mediaInfo): - switch await sendAttachment(mediaInfo: mediaInfo, progressSubject: progressSubject) { + switch await sendAttachment(mediaInfo: mediaInfo, caption: caption, progressSubject: progressSubject) { case .success: actionsSubject.send(.dismiss) case .failure(let error): @@ -75,20 +78,38 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, // MARK: - Private - private func sendAttachment(mediaInfo: MediaInfo, progressSubject: CurrentValueSubject?) async -> Result { + private func sendAttachment(mediaInfo: MediaInfo, caption: String?, progressSubject: CurrentValueSubject?) async -> Result { let requestHandle: ((SendAttachmentJoinHandleProtocol) -> Void) = { [weak self] handle in self?.requestHandle = handle } switch mediaInfo { case let .image(imageURL, thumbnailURL, imageInfo): - return await roomProxy.timeline.sendImage(url: imageURL, thumbnailURL: thumbnailURL, imageInfo: imageInfo, progressSubject: progressSubject, requestHandle: requestHandle) + return await roomProxy.timeline.sendImage(url: imageURL, + thumbnailURL: thumbnailURL, + imageInfo: imageInfo, + caption: caption, + progressSubject: progressSubject, + requestHandle: requestHandle) case let .video(videoURL, thumbnailURL, videoInfo): - return await roomProxy.timeline.sendVideo(url: videoURL, thumbnailURL: thumbnailURL, videoInfo: videoInfo, progressSubject: progressSubject, requestHandle: requestHandle) + return await roomProxy.timeline.sendVideo(url: videoURL, + thumbnailURL: thumbnailURL, + videoInfo: videoInfo, + caption: caption, + progressSubject: progressSubject, + requestHandle: requestHandle) case let .audio(audioURL, audioInfo): - return await roomProxy.timeline.sendAudio(url: audioURL, audioInfo: audioInfo, progressSubject: progressSubject, requestHandle: requestHandle) + return await roomProxy.timeline.sendAudio(url: audioURL, + audioInfo: audioInfo, + caption: caption, + progressSubject: progressSubject, + requestHandle: requestHandle) case let .file(fileURL, fileInfo): - return await roomProxy.timeline.sendFile(url: fileURL, fileInfo: fileInfo, progressSubject: progressSubject, requestHandle: requestHandle) + return await roomProxy.timeline.sendFile(url: fileURL, + fileInfo: fileInfo, + caption: caption, + progressSubject: progressSubject, + requestHandle: requestHandle) } } @@ -118,3 +139,10 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, userIndicatorController.submitIndicator(UserIndicator(title: label)) } } + +extension NSAttributedString { + var nonBlankString: String? { + guard !string.isBlank else { return nil } + return string + } +} diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift index 30db52e56c..6da34ba5ed 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift @@ -5,6 +5,7 @@ // Please see LICENSE in the repository root for full details. // +import Compound import QuickLook import SwiftUI @@ -17,13 +18,20 @@ struct MediaUploadPreviewScreen: View { var body: some View { mainContent - .id(UUID()) + .id(context.viewState.url) + .ignoresSafeArea(edges: [.horizontal]) + .safeAreaInset(edge: .bottom, spacing: 0) { + composer + .padding(.horizontal, 12) + .padding(.vertical, 16) + .background() // Don't use compound so we match the QLPreviewController. + } .navigationTitle(title) .navigationBarTitleDisplayMode(.inline) - .disabled(context.viewState.shouldDisableInteraction) - .ignoresSafeArea(edges: [.horizontal, .bottom]) .toolbar { toolbar } + .disabled(context.viewState.shouldDisableInteraction) .interactiveDismissDisabled() + .preferredColorScheme(.dark) } @ViewBuilder @@ -38,18 +46,31 @@ struct MediaUploadPreviewScreen: View { } } + private var composer: some View { + HStack(spacing: 12) { + MessageComposerTextField(placeholder: L10n.richTextEditorComposerCaptionPlaceholder, + text: $context.caption, + presendCallback: $context.presendCallback, + maxHeight: ComposerConstant.maxHeight, + keyHandler: { _ in }, + pasteHandler: { _ in }) + .messageComposerStyle() + + SendButton { + context.send(viewAction: .send) + } + } + } + @ToolbarContentBuilder private var toolbar: some ToolbarContent { ToolbarItem(placement: .cancellationAction) { Button { context.send(viewAction: .cancel) } label: { Text(L10n.actionCancel) } - } - ToolbarItem(placement: .confirmationAction) { - Button { context.send(viewAction: .send) } label: { - Text(L10n.actionSend) - } - .disabled(context.viewState.shouldDisableInteraction) + // Fix a bug with the preferredColorScheme on iOS 18 where the button doesn't + // follow the dark colour scheme on devices running with dark mode disabled. + .tint(.compound.textActionPrimary) } } } @@ -111,29 +132,32 @@ private class PreviewItem: NSObject, QLPreviewItem { } } +private class PreviewViewController: QLPreviewController { + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + + // Remove top file details bar + navigationController?.navigationBar.isHidden = true + + // Hide toolbar share button + toolbarItems?.first?.isHidden = true + } +} + // MARK: - Previews struct MediaUploadPreviewScreen_Previews: PreviewProvider, TestablePreview { + static let snapshotURL = URL.picturesDirectory + static let testURL = Bundle.main.url(forResource: "AppIcon60x60@2x", withExtension: "png") + static let viewModel = MediaUploadPreviewScreenViewModel(userIndicatorController: UserIndicatorControllerMock.default, roomProxy: JoinedRoomProxyMock(), mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings), - title: "some random file name", - url: URL.picturesDirectory) + title: "App Icon.png", + url: snapshotURL) static var previews: some View { NavigationStack { MediaUploadPreviewScreen(context: viewModel.context) } } } - -private class PreviewViewController: QLPreviewController { - override func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() - - // Remove top file details bar - navigationController?.navigationBar.isHidden = true - - // Hide toolbar share button - toolbarItems?.first?.isHidden = true - } -} diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift index 0cb580d0ab..aa6c14db2f 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift @@ -62,7 +62,7 @@ struct ComposerToolbar: View { if !context.composerFormattingEnabled { if context.viewState.isUploading { ProgressView() - .scaledFrame(size: 44, relativeTo: .title) + .scaledFrame(size: 44, relativeTo: .compound.headingLG) .padding(.leading, 3) } else if context.viewState.showSendButton { sendButton @@ -119,27 +119,29 @@ struct ComposerToolbar: View { Image(Asset.Images.closeRte.name) .resizable() .scaledToFit() - .scaledFrame(size: 30, relativeTo: .title) - .scaledPadding(7, relativeTo: .title) + .scaledFrame(size: 30, relativeTo: .compound.headingLG) + .scaledPadding(7, relativeTo: .compound.headingLG) } .accessibilityLabel(L10n.actionClose) .accessibilityIdentifier(A11yIdentifiers.roomScreen.composerToolbar.closeFormattingOptions) } private var sendButton: some View { - Button { - sendMessage() - } label: { - CompoundIcon(context.viewState.composerMode.isEdit ? \.check : \.sendSolid) - .scaledPadding(6, relativeTo: .title) - .accessibilityLabel(context.viewState.composerMode.isEdit ? L10n.actionConfirm : L10n.actionSend) - .foregroundColor(context.viewState.sendButtonDisabled ? .compound.iconDisabled : .white) - .background { - Circle() - .foregroundColor(context.viewState.sendButtonDisabled ? .clear : .compound.iconAccentTertiary) + Group { + if context.viewState.composerMode.isEdit { + Button(action: sendMessage) { + CompoundIcon(\.check, size: .medium, relativeTo: .compound.headingLG) + .foregroundColor(.white) + .scaledPadding(6, relativeTo: .compound.headingLG) + .background(.compound.iconAccentTertiary, in: Circle()) + .accessibilityLabel(L10n.actionConfirm) } - .scaledPadding(4, relativeTo: .title) + } else { + SendButton(action: sendMessage) + .accessibilityLabel(L10n.actionSend) + } } + .scaledPadding(4, relativeTo: .compound.headingLG) .disabled(context.viewState.sendButtonDisabled) .animation(.linear(duration: 0.1).disabledDuringTests(), value: context.viewState.sendButtonDisabled) .keyboardShortcut(.return, modifiers: [.command]) @@ -271,8 +273,8 @@ struct ComposerToolbar: View { } label: { CompoundIcon(\.delete) .scaledToFit() - .scaledFrame(size: 30, relativeTo: .title) - .scaledPadding(7, relativeTo: .title) + .scaledFrame(size: 30, relativeTo: .compound.headingLG) + .scaledPadding(7, relativeTo: .compound.headingLG) } .buttonStyle(.compound(.plain)) .accessibilityLabel(L10n.a11yDelete) @@ -291,6 +293,8 @@ struct ComposerToolbar: View { } } +// MARK: - Previews + struct ComposerToolbar_Previews: PreviewProvider, TestablePreview { static let wysiwygViewModel = WysiwygComposerViewModel() static let composerViewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel, @@ -330,8 +334,6 @@ struct ComposerToolbar_Previews: PreviewProvider, TestablePreview { } } -// MARK: - Mock - extension ComposerToolbar { static func mock(focused: Bool = true) -> ComposerToolbar { let wysiwygViewModel = WysiwygComposerViewModel() diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift index 809c80279f..89f8903d07 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift @@ -35,17 +35,8 @@ struct MessageComposer: View { resizeGrabber } - mainContent - .padding(.horizontal, 12.0) - .clipShape(composerShape) - .background { - ZStack { - composerShape - .fill(Color.compound.bgSubtleSecondary) - composerShape - .stroke(Color.compound._borderTextFieldFocused, lineWidth: 0.5) - } - } + composerTextField + .messageComposerStyle(header: header) // Explicitly disable all animations to fix weirdness with the header immediately // appearing whilst the text field and keyboard are still animating up to it. .animation(.noAnimation, value: mode) @@ -57,34 +48,27 @@ struct MessageComposer: View { @State private var composerFrame = CGRect.zero - private var mainContent: some View { - VStack(alignment: .leading, spacing: -6) { - header - - if composerFormattingEnabled { - Color.clear - .overlay(alignment: .top) { - composerView - .clipped() - .readFrame($composerFrame) - } - .frame(minHeight: ComposerConstant.minHeight, maxHeight: max(composerHeight, composerFrame.height), - alignment: .top) - .tint(.compound.iconAccentTertiary) - .padding(.vertical, 10) - .onAppear { - onAppearAction() - } - } else { - MessageComposerTextField(placeholder: L10n.richTextEditorComposerPlaceholder, - text: $plainComposerText, - presendCallback: $presendCallback, - maxHeight: ComposerConstant.maxHeight, - keyHandler: { handleKeyPress($0) }, - pasteHandler: pasteAction) - .tint(.compound.iconAccentTertiary) - .padding(.vertical, 10) - } + @ViewBuilder + private var composerTextField: some View { + if composerFormattingEnabled { + Color.clear + .overlay(alignment: .top) { + composerView + .clipped() + .readFrame($composerFrame) + } + .frame(minHeight: ComposerConstant.minHeight, maxHeight: max(composerHeight, composerFrame.height), + alignment: .top) + .onAppear { + onAppearAction() + } + } else { + MessageComposerTextField(placeholder: L10n.richTextEditorComposerPlaceholder, + text: $plainComposerText, + presendCallback: $presendCallback, + maxHeight: ComposerConstant.maxHeight, + keyHandler: { handleKeyPress($0) }, + pasteHandler: pasteAction) } } @@ -200,6 +184,42 @@ private struct MessageComposerHeaderLabelStyle: LabelStyle { } } +// MARK: - Style + +extension View { + func messageComposerStyle(header: some View = EmptyView()) -> some View { + modifier(MessageComposerStyleModifier(header: header)) + } +} + +private struct MessageComposerStyleModifier: ViewModifier { + private let composerShape = RoundedRectangle(cornerRadius: 21, style: .circular) + + let header: Header + + func body(content: Content) -> some View { + VStack(alignment: .leading, spacing: -6) { + header + + content + .tint(.compound.iconAccentTertiary) + .padding(.vertical, 10) + } + .padding(.horizontal, 12.0) + .clipShape(composerShape) + .background { + ZStack { + composerShape + .fill(Color.compound.bgSubtleSecondary) + composerShape + .stroke(Color.compound.borderInteractiveSecondary, lineWidth: 0.5) + } + } + } +} + +// MARK: - Previews + struct MessageComposer_Previews: PreviewProvider, TestablePreview { static let viewModel = TimelineViewModel.mock diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift index 791ee8d548..0732bd15f8 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift @@ -18,8 +18,8 @@ struct RoomAttachmentPicker: View { Menu { menuContent } label: { - CompoundIcon(asset: Asset.Images.composerAttachment, size: .custom(30), relativeTo: .title) - .scaledPadding(7, relativeTo: .title) + CompoundIcon(asset: Asset.Images.composerAttachment, size: .custom(30), relativeTo: .compound.headingLG) + .scaledPadding(7, relativeTo: .compound.headingLG) } .buttonStyle(RoomAttachmentPickerButtonStyle()) .accessibilityLabel(L10n.actionAddToTimeline) diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift index 8688f0f6cf..c998209e53 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift @@ -32,18 +32,15 @@ struct VoiceMessageRecordingButton: View { } label: { switch mode { case .idle: - CompoundIcon(\.micOn, size: .medium, relativeTo: .title) + CompoundIcon(\.micOn, size: .medium, relativeTo: .compound.headingLG) .foregroundColor(.compound.iconSecondary) - .scaledPadding(10, relativeTo: .title) + .scaledPadding(10, relativeTo: .compound.headingLG) case .recording: - CompoundIcon(asset: Asset.Images.stopRecording, size: .medium, relativeTo: .title) + CompoundIcon(asset: Asset.Images.stopRecording, size: .medium, relativeTo: .compound.headingLG) .foregroundColor(.compound.iconOnSolidPrimary) - .scaledPadding(6, relativeTo: .title) - .background( - Circle() - .foregroundColor(.compound.bgActionPrimaryRest) - ) - .scaledPadding(4, relativeTo: .title) + .scaledPadding(6, relativeTo: .compound.headingLG) + .background(.compound.bgActionPrimaryRest, in: Circle()) + .scaledPadding(4, relativeTo: .compound.headingLG) } } .buttonStyle(VoiceMessageRecordingButtonStyle()) diff --git a/ElementX/Sources/Services/Timeline/TimelineProxy.swift b/ElementX/Sources/Services/Timeline/TimelineProxy.swift index 4309d206cb..0a7a1b1dca 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxy.swift @@ -223,13 +223,14 @@ final class TimelineProxy: TimelineProxyProtocol { func sendAudio(url: URL, audioInfo: AudioInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending audio") let handle = timeline.sendAudio(url: url.path(percentEncoded: false), audioInfo: audioInfo, - caption: nil, + caption: caption, formattedCaption: nil, progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) @@ -251,13 +252,14 @@ final class TimelineProxy: TimelineProxyProtocol { func sendFile(url: URL, fileInfo: FileInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending file") let handle = timeline.sendFile(url: url.path(percentEncoded: false), fileInfo: fileInfo, - caption: nil, + caption: caption, formattedCaption: nil, progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) @@ -277,9 +279,11 @@ final class TimelineProxy: TimelineProxyProtocol { return .success(()) } + // swiftlint:disable:next function_parameter_count func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending image") @@ -287,7 +291,7 @@ final class TimelineProxy: TimelineProxyProtocol { let handle = timeline.sendImage(url: url.path(percentEncoded: false), thumbnailUrl: thumbnailURL.path(percentEncoded: false), imageInfo: imageInfo, - caption: nil, + caption: caption, formattedCaption: nil, progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) @@ -325,9 +329,11 @@ final class TimelineProxy: TimelineProxyProtocol { return .success(()) } + // swiftlint:disable:next function_parameter_count func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending video") @@ -335,7 +341,7 @@ final class TimelineProxy: TimelineProxyProtocol { let handle = timeline.sendVideo(url: url.path(percentEncoded: false), thumbnailUrl: thumbnailURL.path(percentEncoded: false), videoInfo: videoInfo, - caption: nil, + caption: caption, formattedCaption: nil, progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) diff --git a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift index e1c8b5f6fe..d0d5285fb2 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift @@ -51,17 +51,21 @@ protocol TimelineProxyProtocol { func sendAudio(url: URL, audioInfo: AudioInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result func sendFile(url: URL, fileInfo: FileInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result + // swiftlint:disable:next function_parameter_count func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result @@ -71,9 +75,11 @@ protocol TimelineProxyProtocol { zoomLevel: UInt8?, assetType: AssetType?) async -> Result + // swiftlint:disable:next function_parameter_count func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png index 0d9570e808..49a9a32877 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed83944ed745ce8ba0d41ee0ccc0e343b917875cb190fb83f869ca5200df8555 -size 75517 +oid sha256:888932f08b86692e4ed6d35aa438a1fa4839a0247ef4d4e8109f9f4d2902a2a7 +size 75306 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png index 24ca0f3d3f..d7f9d22c76 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:474774d07c69a9652245a6f2e31b57fc29325592cd98f9455ddb53fca0d3c047 -size 93517 +oid sha256:3005df9a148c026be35620606d64fd479601439bf2bdda4d3d56113d121464d7 +size 93485 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 6d783efa97..51071b6860 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:649cf6ecbb5506ff2d3d88932950bb965f5ce21529f97d10c0bf065f51931f23 -size 95810 +oid sha256:a8a8066e41d3d84e7aedc675e7991b0dd57fc1f93f363312353bf43a236e3f6a +size 101416 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 2ee57674c0..e594e1dd0b 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:e4fd5cfb6d8191e632c5a5b0d2a9f89b50b36d1547d903971a9498ce6c6cb32a -size 98356 +oid sha256:1b8ef13343f827c0dc3e9aaf74ce28f8a3e96bb0f4b9aa457e6a9ff40b3ad632 +size 98059 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png index 1651742e07..cc67cd4148 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fd2db090826802de3831227fbb81614deea2ecd62c1e3cff9488d0e4c4c113f -size 75899 +oid sha256:d546bdab2d2ff0d1f674bc5f5d7583f7a60c338a8ee6e94041ed4ed07a106a31 +size 75724 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png index fe8714849f..deb7d63737 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a716604e488f96f610770f9b550e36ba5caf6cafaf7c1e24155cd3ff498b1a98 -size 94344 +oid sha256:b9c15c54c93c21400eb263cbc0575f86d1c47377d2f73a2fe59ec8d7886914e3 +size 94359 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 d93d75328a..f293f957b1 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:ab78db432612172ab37dae1e1c2972d7ec1e8398034df87f32d97e5ccef19c5d -size 96540 +oid sha256:8fcc46292a1139dab8462e81a1f91bc177e9a05cbcf8ff6ef5ddbe15707cfdf8 +size 102213 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 489b79684d..0deed32f47 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:9ed7b4e33493a6206a97101e5f241cb331afd24b39d60e60af8d577a30aa1cc0 -size 98738 +oid sha256:516b16553d506445d965c708a5f56e5b9c53b23488809a2513a56c2368a2d633 +size 98477 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.1.png index 09364f55ac..4edb595846 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29c7624de3004d0a17828fd97c74b516cd420781c2c7a7c96d6383d8befcc9c5 -size 34590 +oid sha256:d4a497fc8cb28e5187c80bf8caec98e69c9faec1ed153b1c2beaa52aa8cd8ae1 +size 34435 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Reply.png index 1acfcc6c5a..f0b7d423ad 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Reply.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Reply.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34126123e98e38598b990f5a0e5c7a4f80d58b336131dcbd0646e2dbe4e8c754 -size 51216 +oid sha256:942b0ff59359bbfe7a1ae88f7acf44b856f763d91688bac8ad173a7eda405972 +size 50565 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 827b509aaa..029173618c 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:c18ac30d254a8ab48fd16bdd213b4000944ead4e634a69cc6a808e1408805c65 -size 52052 +oid sha256:6ffa98f5f715b47251f816c0fcab5c4ff62d51d60270f8a41a34ca3835c3e0f6 +size 58631 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 a4224c5d3d..b4ce7760f4 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:b1c8b56332155977848329ca750ac240b304210abef5587519f8e2e222435a42 -size 53760 +oid sha256:b4bc7dbfbb1c7c58641f7d19bcb648e792220c19919b9001b09bdc8ccda0c86f +size 53599 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.1.png index a50fe3f0ef..b93a576a43 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:69c9c7a7368afc683ed8ee311038cea74c1305dc96c2594e3ef1e089a5044353 -size 35006 +oid sha256:67d481416b45627802785280c9dd03bc5f634902b64a4beacd567b42fd0a444c +size 34849 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Reply.png index 1f2018dfcf..1074662e1e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Reply.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Reply.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:463bece34b226141be90906cc7aeb56f55e217034f25befa0eee5ab7fc9a9cde -size 52029 +oid sha256:9c9ed32588b6de5c4c2c87c14a54a4d436648518cf6b7807a16a39be20332778 +size 51436 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 efb7b232dd..2dfa3ceba8 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:938c55d264a5ec64d9f982482b93c0a1f15b3454b19f7ea61b6a91a82f56fccc -size 52835 +oid sha256:b411f75a2ce4d925ee0170cb0956129fd26b1c2d8b64b0741b82699bc058e6b6 +size 59463 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 f5722c5796..0c9096622a 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:88408dc1dd51e53dec8a4d476c4a42b7d2bdea768430be9002e48ce554ed753c -size 54176 +oid sha256:fd4bca95fba0ed2e11a1212c1ac3d1a638815274c370a1bdb4a3dd825c89de6d +size 54013 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 c36548dd78..a218dc80e7 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:142460487dd7b40c347faeb4ce229bc900cee12d358288edec544fa7f74f26b8 -size 78954 +oid sha256:885fb08cfe301dd996fa6f1b276afa7a74f6534d692ab313ec7d64bfcb970981 +size 91980 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 da0b314e65..687ed48841 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:740a28f97bf1d14670f314d0030a013e2aa6349551dbdc7c11e95334c05c4ac6 -size 79591 +oid sha256:ab99e9ac3233f55705f96cc0c8f1480351f0765b7b36d1e90e3262758b2ede9a +size 93223 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 2d9b3cd6a3..748902c2b8 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:7b48e09d6a5605dd6e21141b176b17f7637c59be6bdee67d3650c1d61fd06493 -size 39052 +oid sha256:3cd02932f70d0c1336b295d94ca31694f569fea56b36b8cc29c448284406e8dd +size 50622 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 b6ea52d1ee..960476010a 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:d24d5f89ef4e437525e82bd0aa0ab52f9f6c7463bbec799c8d5de724294d0f9c -size 39482 +oid sha256:26109f9334be8c7452fd98c15158bea787df6b87f560f8ee6b6aea46dc6a1647 +size 51627 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png index 00c09a774e..aee9e9b7d3 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:620197da87f254260dca5e965abc6e6cbd9f7743c01a236c58b8642437b92047 -size 98722 +oid sha256:1a5e7e651f73e10b1b7c5fad0a3eb631d9f50f5f42286f1faaed852316dd287d +size 98836 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 2773e12577..e7368f76cd 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:6a034b807916e062e25c5fb59ecd09a47d0e1c7c822534b35e992fd9c839ab07 -size 196481 +oid sha256:71cb80dc579a03031aa4de25bf2af339ddd8670651c0e3a5b4fb5d0423592455 +size 196910 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 2773e12577..e7368f76cd 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:6a034b807916e062e25c5fb59ecd09a47d0e1c7c822534b35e992fd9c839ab07 -size 196481 +oid sha256:71cb80dc579a03031aa4de25bf2af339ddd8670651c0e3a5b4fb5d0423592455 +size 196910 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png index 39f60f5f62..61a955e37b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a632e640aefa28698b33f87eb8a8576db9021ea3e0f6cbbddcf3d7c61f71c35 -size 99789 +oid sha256:4914f7dc335cc0333584c2ad34034ce5a28e6fb3bb52d05f27734ed2dae5e7a6 +size 99876 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 26e53c7a36..f76ef12797 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:ffe1ceda422b0bccc1e587036ea047bebb4ee4643f54bdf25ff2b3b530b6f7e2 -size 199662 +oid sha256:218956837978d0f8f16b8744a064f5ed78be91a8be0a712cae7536f54867319c +size 200002 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 26e53c7a36..f76ef12797 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:ffe1ceda422b0bccc1e587036ea047bebb4ee4643f54bdf25ff2b3b530b6f7e2 -size 199662 +oid sha256:218956837978d0f8f16b8744a064f5ed78be91a8be0a712cae7536f54867319c +size 200002 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png index b0eb8e49aa..a28707e06c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bbfd12737413020fd7c0ff01c1b276f57ced10e33be2ea41977d3faf79050857 -size 54984 +oid sha256:9951096cb1ddc3050415353192108a4489908d8355b30189845a7da5fa2b5d83 +size 55103 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 e58f1c116b..69aeadc93e 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:91bef32e5248f8084995b237b671cea005ce0eb9253a325165dd066a43934bfa -size 135848 +oid sha256:19d120c20ff2a374d05884e6599032a4a3d4982dd9e2d19bc4e28e95f79cb4e0 +size 136286 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 e58f1c116b..69aeadc93e 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:91bef32e5248f8084995b237b671cea005ce0eb9253a325165dd066a43934bfa -size 135848 +oid sha256:19d120c20ff2a374d05884e6599032a4a3d4982dd9e2d19bc4e28e95f79cb4e0 +size 136286 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png index b237a68c61..bda11829e5 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:702ac84c437121bd0c7370fc5de6928cf60894554c00dcb721924f349db4c991 -size 57150 +oid sha256:745116e5588711197b37e391b2f2ca6359c9a4cb8b3dd718ec55dd29c33d72a1 +size 57224 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 39ebe44626..990235129f 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:c5fd3ee0cc6bb3cf124cc66877d87cde800a3da7c10f8e26d6e19d884f4ca40e -size 139138 +oid sha256:da4f3b1174b24ae18c931db745a788e01793f73693fe132cb29836728db76172 +size 139540 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 39ebe44626..990235129f 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:c5fd3ee0cc6bb3cf124cc66877d87cde800a3da7c10f8e26d6e19d884f4ca40e -size 139138 +oid sha256:da4f3b1174b24ae18c931db745a788e01793f73693fe132cb29836728db76172 +size 139540 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 ff3b7d7e6d..742befb2f7 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:033f43d5be47abd91cd5f36b93a8b32b0f9800e7a8a947e0c2cd4debd8b4c694 -size 295633 +oid sha256:906409795a47057b2da67dc7a50221b6a9be839309cf434899d3ee7c19735c83 +size 295656 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 65b5872de5..76fe17dfea 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:bc959ac1d5a22da8ca928d891e9f0a649dfa28b1cdfa7a91b0a74d2189cc38a3 -size 297711 +oid sha256:38a6eea96f81ab5acd88b75823745cc7bb71c237ff0ca181e05e0263abc487d9 +size 297761 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 bd01dd63c7..037e6f2eee 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:26de643c28b47f7fd0631c0c754d979c43fc51bc274e863fdb6acaf0ed299960 -size 180507 +oid sha256:6b8ab1d9311c44e85d8e145a9290e97aa2b37070a3104402332479ec8c2fd739 +size 180530 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 10b37a11f3..d1aac8e161 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:58ae4f390371ef48aca7b5faeb4c75ba7bdfad4294797fd422c0d102036ee4a8 -size 178571 +oid sha256:f5843af5ad8774b2d73bc57b18caacb79cfa46abc54c797b5c17948f961ded06 +size 178598 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 ff3b7d7e6d..742befb2f7 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:033f43d5be47abd91cd5f36b93a8b32b0f9800e7a8a947e0c2cd4debd8b4c694 -size 295633 +oid sha256:906409795a47057b2da67dc7a50221b6a9be839309cf434899d3ee7c19735c83 +size 295656 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 65b5872de5..76fe17dfea 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:bc959ac1d5a22da8ca928d891e9f0a649dfa28b1cdfa7a91b0a74d2189cc38a3 -size 297711 +oid sha256:38a6eea96f81ab5acd88b75823745cc7bb71c237ff0ca181e05e0263abc487d9 +size 297761 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 bd01dd63c7..037e6f2eee 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:26de643c28b47f7fd0631c0c754d979c43fc51bc274e863fdb6acaf0ed299960 -size 180507 +oid sha256:6b8ab1d9311c44e85d8e145a9290e97aa2b37070a3104402332479ec8c2fd739 +size 180530 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 10b37a11f3..d1aac8e161 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:58ae4f390371ef48aca7b5faeb4c75ba7bdfad4294797fd422c0d102036ee4a8 -size 178571 +oid sha256:f5843af5ad8774b2d73bc57b18caacb79cfa46abc54c797b5c17948f961ded06 +size 178598 diff --git a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift index 880f27acbb..c74ec03185 100644 --- a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift +++ b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift @@ -10,4 +10,135 @@ import XCTest @testable import ElementX @MainActor -class MediaUploadPreviewScreenViewModelTests: XCTestCase { } +class MediaUploadPreviewScreenViewModelTests: XCTestCase { + var timelineProxy: TimelineProxyMock! + var viewModel: MediaUploadPreviewScreenViewModel! + var context: MediaUploadPreviewScreenViewModel.Context { viewModel.context } + + enum TestError: Swift.Error { + case unexpectedParameter + case unknown + } + + override func setUp() { + AppSettings.resetAllSettings() + let appSettings = AppSettings() + appSettings.optimizeMediaUploads = false + ServiceLocator.shared.register(appSettings: appSettings) + } + + deinit { + AppSettings.resetAllSettings() + } + + func testImageUploadWithoutCaption() async throws { + setUpViewModel(url: imageURL, expectedCaption: nil) + context.caption = .init("") + try await send() + } + + func testImageUploadWithBlankCaption() async throws { + setUpViewModel(url: imageURL, expectedCaption: nil) + context.caption = .init(" ") + try await send() + } + + func testImageUploadWithCaption() async throws { + let caption = "This is a really great image!" + setUpViewModel(url: imageURL, expectedCaption: caption) + context.caption = .init(string: caption) + try await send() + } + + func testVideoUploadWithoutCaption() async throws { + setUpViewModel(url: videoURL, expectedCaption: nil) + context.caption = .init("") + try await send() + } + + func testVideoUploadWithCaption() async throws { + let caption = "Check out this video!" + setUpViewModel(url: videoURL, expectedCaption: caption) + context.caption = .init(string: caption) + try await send() + } + + func testAudioUploadWithoutCaption() async throws { + setUpViewModel(url: audioURL, expectedCaption: nil) + context.caption = .init("") + try await send() + } + + func testAudioUploadWithCaption() async throws { + let caption = "Listen to this!" + setUpViewModel(url: audioURL, expectedCaption: caption) + context.caption = .init(string: caption) + try await send() + } + + func testFileUploadWithoutCaption() async throws { + setUpViewModel(url: fileURL, expectedCaption: nil) + context.caption = .init("") + try await send() + } + + func testFileUploadWithCaption() async throws { + let caption = "Please will you check my article." + setUpViewModel(url: fileURL, expectedCaption: caption) + context.caption = .init(string: caption) + try await send() + } + + // MARK: - Helpers + + private var audioURL: URL { assertResourceURL(filename: "test_audio.mp3") } + private var fileURL: URL { assertResourceURL(filename: "test_pdf.pdf") } + private var imageURL: URL { assertResourceURL(filename: "test_animated_image.gif") } + private var videoURL: URL { assertResourceURL(filename: "landscape_test_video.mov") } + + private func assertResourceURL(filename: String) -> URL { + guard let url = Bundle(for: Self.self).url(forResource: filename, withExtension: nil) else { + XCTFail("Failed retrieving test asset") + return .picturesDirectory + } + return url + } + + private func setUpViewModel(url: URL, expectedCaption: String?) { + timelineProxy = TimelineProxyMock(.init()) + timelineProxy.sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, caption, _, _ in + self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) + } + timelineProxy.sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, caption, _, _ in + self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) + } + timelineProxy.sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, _, caption, _, _ in + self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) + } + timelineProxy.sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, _, caption, _, _ in + self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) + } + + let roomProxy = JoinedRoomProxyMock(.init()) + roomProxy.timeline = timelineProxy + viewModel = MediaUploadPreviewScreenViewModel(userIndicatorController: UserIndicatorControllerMock(), + roomProxy: roomProxy, + mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings), + title: "Some File", + url: url) + } + + private func verifyCaption(_ caption: String?, expectedCaption: String?) -> Result { + guard caption == expectedCaption else { + XCTFail("The sent caption '\(caption ?? "nil")' does not match the expected value '\(expectedCaption ?? "nil")'").self + return .failure(.sdkError(TestError.unexpectedParameter)) + } + return .success(()) + } + + private func send() async throws { + let deferred = deferFulfillment(viewModel.actions) { $0 == .dismiss } + context.send(viewAction: .send) + try await deferred.fulfill() + } +} From bce3b3a3851b556a89ade7f2ef6bea60598946e3 Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Tue, 19 Nov 2024 20:23:06 +0100 Subject: [PATCH 37/74] using `roomPreview` API for invited rooms (#3530) * using roomPreview for invited rooms * Update ElementX/Sources/Services/Room/RoomInfoProxy.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * improved code * fix, but requires a SDK PR * update sdk * package resolved * fixed the tests --------- Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> --- ElementX.xcodeproj/project.pbxproj | 10 +-- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../Mocks/Generated/GeneratedMocks.swift | 69 +------------------ .../Sources/Mocks/InvitedRoomProxyMock.swift | 1 + .../HomeScreen/HomeScreenViewModel.swift | 2 +- .../JoinRoomScreenViewModel.swift | 2 +- .../Sources/Services/Client/ClientProxy.swift | 7 +- .../Services/Room/InvitedRoomProxy.swift | 34 ++++----- .../Services/Room/KnockedRoomProxy.swift | 7 +- .../Sources/Services/Room/RoomInfoProxy.swift | 22 ++++-- .../Services/Room/RoomProxyProtocol.swift | 4 +- project.yml | 2 +- 12 files changed, 52 insertions(+), 112 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index e58469ce84..5403ca071d 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -117,6 +117,7 @@ 1621BF6316FFFEF5AE067C77 /* Avatars.swift in Sources */ = {isa = PBXBuildFile; fileRef = C142248014E08E885E323E56 /* Avatars.swift */; }; 1653275750CE11F5CE94DDFD /* ReadReceiptsSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8063E65441E771200108C558 /* ReadReceiptsSummaryView.swift */; }; 167D00CAA13FAFB822298021 /* MediaProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */; }; + 16A1F6C703305FCAF4E14EC6 /* TimelineProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17A8AA0DFA06012A9DAB951E /* TimelineProxyMock.swift */; }; 16CBD087038DE3815CDA512C /* PollMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D38391154120264910D19528 /* PollMock.swift */; }; 16E4F1B8B9BFE1367F96DDA7 /* CompletionSuggestionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 989FC684408B31A677F5538B /* CompletionSuggestionView.swift */; }; 1702981A8085BE4FB0EC001B /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = D33116993D54FADC0C721C1F /* Application.swift */; }; @@ -689,7 +690,6 @@ 90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; 914BDF61447C723F104BCE33 /* SessionDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C2067FF58B4996323EB40C /* SessionDirectories.swift */; }; 915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */; }; - 919BAE492CECA981009F6A5B /* TimelineProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */; }; 91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; }; 91C6AC0E9D2B9C0C76CC6AD4 /* RoomDirectorySearchScreenScreenModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3984C93B8E9B10C92DADF9EE /* RoomDirectorySearchScreenScreenModelProtocol.swift */; }; 91D1A46A733EC24C081DD353 /* SessionVerificationRequestDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A1265FAF2C0AF1C30605BE7 /* SessionVerificationRequestDetailsView.swift */; }; @@ -1353,6 +1353,7 @@ 16D09C79746BDCD9173EB3A7 /* RoomDetailsEditScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenModels.swift; sourceTree = ""; }; 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 = ""; }; 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 = ""; }; @@ -1901,7 +1902,6 @@ 90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemView.swift; sourceTree = ""; }; 913C8E13B8B602C7B6C0C4AE /* PillTextAttachmentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillTextAttachmentData.swift; sourceTree = ""; }; 91868EB98818044E6FEBE532 /* NotificationPermissionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenCoordinator.swift; sourceTree = ""; }; - 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyMock.swift; sourceTree = ""; }; 91C8BD78F7B9247AC57FA1A3 /* RedactedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineView.swift; sourceTree = ""; }; 91CF6F7D08228D16BA69B63B /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.strings"; sourceTree = ""; }; 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenu.swift; sourceTree = ""; }; @@ -3028,13 +3028,13 @@ F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */, 4AB29A2D95D3469B5F016655 /* SecureBackupControllerMock.swift */, 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */, + 17A8AA0DFA06012A9DAB951E /* TimelineProxyMock.swift */, 7893780A1FD6E3F38B3E9049 /* UserIndicatorControllerMock.swift */, AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */, F4469F6AE311BDC439B3A5EC /* UserSessionMock.swift */, 9EB9BA2F30EB8C33226D8FF1 /* UserSessionStoreMock.swift */, B23135B06B044CB811139D2F /* Generated */, E5E545F92D01588360A9BAC5 /* SDK */, - 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */, ); path = Mocks; sourceTree = ""; @@ -7099,7 +7099,6 @@ 50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */, D43F0503EF2CBC55272538FE /* SDKGeneratedMocks.swift in Sources */, 88CBF1595E39CE697928DE48 /* SFNumberedListView.swift in Sources */, - 919BAE492CECA981009F6A5B /* TimelineProxyMock.swift in Sources */, FB595EC9C00AB32F39034055 /* SceneDelegate.swift in Sources */, 0437765FF480249486893CC7 /* ScreenTrackerViewModifier.swift in Sources */, 0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */, @@ -7222,6 +7221,7 @@ 562EFB9AB62B38830D9AA778 /* TimelineMediaFrame.swift in Sources */, B818580464CFB5400A3EF6AE /* TimelineModels.swift in Sources */, E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */, + 16A1F6C703305FCAF4E14EC6 /* TimelineProxyMock.swift in Sources */, 2FEC6652055984389CE1BBEC /* TimelineProxyProtocol.swift in Sources */, 8446C2A7ECEFDA79F622725F /* TimelineReactionsView.swift in Sources */, 4DAEE2468669848B6C9F55B4 /* TimelineReadReceiptsView.swift in Sources */, @@ -8138,7 +8138,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.69; + version = 1.0.70; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 8b26c4c617..af01bfc351 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "7f6beb6a5aceca7d573c3370ece96cfd8589b94a", - "version" : "1.0.69" + "revision" : "e1651193fa976d2184526a0ca4699535e410d94d", + "version" : "1.0.70" } }, { diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index db4da917b7..a8def51e01 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -5831,11 +5831,12 @@ class ElementCallWidgetDriverMock: ElementCallWidgetDriverProtocol { } } class InvitedRoomProxyMock: InvitedRoomProxyProtocol { - var info: RoomInfoProxy { + var info: BaseRoomInfoProxyProtocol { get { return underlyingInfo } set(value) { underlyingInfo = value } } - var underlyingInfo: RoomInfoProxy! + var underlyingInfo: BaseRoomInfoProxyProtocol! + var inviter: RoomMemberProxyProtocol? var id: String { get { return underlyingId } set(value) { underlyingId = value } @@ -5911,70 +5912,6 @@ class InvitedRoomProxyMock: InvitedRoomProxyProtocol { return rejectInvitationReturnValue } } - //MARK: - acceptInvitation - - var acceptInvitationUnderlyingCallsCount = 0 - var acceptInvitationCallsCount: Int { - get { - if Thread.isMainThread { - return acceptInvitationUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = acceptInvitationUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - acceptInvitationUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - acceptInvitationUnderlyingCallsCount = newValue - } - } - } - } - var acceptInvitationCalled: Bool { - return acceptInvitationCallsCount > 0 - } - - var acceptInvitationUnderlyingReturnValue: Result! - var acceptInvitationReturnValue: Result! { - get { - if Thread.isMainThread { - return acceptInvitationUnderlyingReturnValue - } else { - var returnValue: Result? = nil - DispatchQueue.main.sync { - returnValue = acceptInvitationUnderlyingReturnValue - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - acceptInvitationUnderlyingReturnValue = newValue - } else { - DispatchQueue.main.sync { - acceptInvitationUnderlyingReturnValue = newValue - } - } - } - } - var acceptInvitationClosure: (() async -> Result)? - - func acceptInvitation() async -> Result { - acceptInvitationCallsCount += 1 - if let acceptInvitationClosure = acceptInvitationClosure { - return await acceptInvitationClosure() - } else { - return acceptInvitationReturnValue - } - } } class JoinedRoomProxyMock: JoinedRoomProxyProtocol { var isEncrypted: Bool { diff --git a/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift b/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift index 66bc9a93f2..65c71d8ea1 100644 --- a/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift @@ -23,6 +23,7 @@ extension InvitedRoomProxyMock { convenience init(_ configuration: InvitedRoomProxyMockConfiguration) { self.init() id = configuration.id + inviter = configuration.inviter info = RoomInfoProxy(roomInfo: .init(configuration)) } } diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index 9bd00e2b29..12313779a4 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -408,7 +408,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol return } - switch await roomProxy.acceptInvitation() { + switch await userSession.clientProxy.joinRoom(roomID, via: []) { case .success: actionsSubject.send(.presentRoom(roomIdentifier: roomID)) analyticsService.trackJoinedRoom(isDM: roomProxy.info.isDirect, diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift index 828d1a28cd..6312924698 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift @@ -109,7 +109,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo case .joined(let joinedRoomProxy): roomPreviewInfo = joinedRoomProxy.infoPublisher.value case .invited(let invitedRoomProxy): - inviter = invitedRoomProxy.info.inviter.flatMap(RoomInviterDetails.init) + inviter = invitedRoomProxy.inviter.map(RoomInviterDetails.init) roomPreviewInfo = invitedRoomProxy.info case .knocked(let knockedRoomProxy): roomPreviewInfo = knockedRoomProxy.info diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index f36ff6d7bb..61c0aa4888 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -930,16 +930,15 @@ class ClientProxy: ClientProxyProtocol { switch roomListItem.membership() { case .invited: return try await .invited(InvitedRoomProxy(roomListItem: roomListItem, - room: roomListItem.invitedRoom())) + roomPreview: roomListItem.previewRoom(via: []), + ownUserID: userID)) case .knocked: if appSettings.knockingEnabled { return try await .knocked(KnockedRoomProxy(roomListItem: roomListItem, roomPreview: roomListItem.previewRoom(via: []), ownUserID: userID)) - } else { - return try await .invited(InvitedRoomProxy(roomListItem: roomListItem, - room: roomListItem.invitedRoom())) } + return nil case .joined: if roomListItem.isTimelineInitialized() == false { try await roomListItem.initTimeline(eventTypeFilter: eventFilters, internalIdPrefix: nil) diff --git a/ElementX/Sources/Services/Room/InvitedRoomProxy.swift b/ElementX/Sources/Services/Room/InvitedRoomProxy.swift index 4e2be76cc0..33bf851da8 100644 --- a/ElementX/Sources/Services/Room/InvitedRoomProxy.swift +++ b/ElementX/Sources/Services/Room/InvitedRoomProxy.swift @@ -11,36 +11,28 @@ import UIKit class InvitedRoomProxy: InvitedRoomProxyProtocol { private let roomListItem: RoomListItemProtocol - private let room: RoomProtocol + private let roomPreview: RoomPreviewProtocol + let info: BaseRoomInfoProxyProtocol + let ownUserID: String + let inviter: RoomMemberProxyProtocol? // A room identifier is constant and lazy stops it from being fetched // multiple times over FFI - lazy var id: String = room.id() - - var ownUserID: String { room.ownUserId() } - - let info: RoomInfoProxy - + lazy var id: String = info.id + init(roomListItem: RoomListItemProtocol, - room: RoomProtocol) async throws { + roomPreview: RoomPreviewProtocol, + ownUserID: String) async throws { self.roomListItem = roomListItem - self.room = room - info = try await RoomInfoProxy(roomInfo: room.roomInfo()) - } - - func acceptInvitation() async -> Result { - do { - try await room.join() - return .success(()) - } catch { - MXLog.error("Failed accepting invitation with error: \(error)") - return .failure(.sdkError(error)) - } + self.roomPreview = roomPreview + self.ownUserID = ownUserID + info = try RoomPreviewInfoProxy(roomPreviewInfo: roomPreview.info()) + inviter = await roomPreview.inviter().map(RoomMemberProxy.init) } func rejectInvitation() async -> Result { do { - return try await .success(room.leave()) + return try await .success(roomPreview.leave()) } catch { MXLog.error("Failed rejecting invitiation with error: \(error)") return .failure(.sdkError(error)) diff --git a/ElementX/Sources/Services/Room/KnockedRoomProxy.swift b/ElementX/Sources/Services/Room/KnockedRoomProxy.swift index c2c35de056..00321bf696 100644 --- a/ElementX/Sources/Services/Room/KnockedRoomProxy.swift +++ b/ElementX/Sources/Services/Room/KnockedRoomProxy.swift @@ -13,16 +13,15 @@ class KnockedRoomProxy: KnockedRoomProxyProtocol { private let roomListItem: RoomListItemProtocol private let roomPreview: RoomPreviewProtocol let info: BaseRoomInfoProxyProtocol + let ownUserID: String // A room identifier is constant and lazy stops it from being fetched // multiple times over FFI lazy var id = info.id - - let ownUserID: String - + init(roomListItem: RoomListItemProtocol, roomPreview: RoomPreviewProtocol, - ownUserID: String) async throws { + ownUserID: String) throws { self.roomListItem = roomListItem self.roomPreview = roomPreview self.ownUserID = ownUserID diff --git a/ElementX/Sources/Services/Room/RoomInfoProxy.swift b/ElementX/Sources/Services/Room/RoomInfoProxy.swift index 7fa274ff8d..9cd290228e 100644 --- a/ElementX/Sources/Services/Room/RoomInfoProxy.swift +++ b/ElementX/Sources/Services/Room/RoomInfoProxy.swift @@ -16,6 +16,8 @@ protocol BaseRoomInfoProxyProtocol { var canonicalAlias: String? { get } var avatarURL: URL? { get } var activeMembersCount: Int { get } + var isDirect: Bool { get } + var isSpace: Bool { get } } struct RoomInfoProxy: BaseRoomInfoProxyProtocol { @@ -70,12 +72,22 @@ struct RoomPreviewInfoProxy: BaseRoomInfoProxyProtocol { var id: String { roomPreviewInfo.roomId } var displayName: String? { roomPreviewInfo.name } - var avatar: RoomAvatar { - .room(id: id, name: displayName, avatarURL: avatarURL) - } - + var heroes: [RoomHero] { roomPreviewInfo.heroes ?? [] } var topic: String? { roomPreviewInfo.topic } var canonicalAlias: String? { roomPreviewInfo.canonicalAlias } var avatarURL: URL? { roomPreviewInfo.avatarUrl.flatMap(URL.init) } - var activeMembersCount: Int { Int(roomPreviewInfo.numJoinedMembers) } + var isDirect: Bool { roomPreviewInfo.isDirect ?? false } + var isSpace: Bool { roomPreviewInfo.roomType == .space } + var activeMembersCount: Int { Int(roomPreviewInfo.numActiveMembers ?? roomPreviewInfo.numJoinedMembers) } + + /// The room's avatar info for use in a ``RoomAvatarImage``. + var avatar: RoomAvatar { + if isDirect, avatarURL == nil { + if heroes.count == 1 { + return .heroes(heroes.map(UserProfileProxy.init)) + } + } + + return .room(id: id, name: displayName, avatarURL: avatarURL) + } } diff --git a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift index 550fcc0eaf..a19a735e79 100644 --- a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift @@ -33,9 +33,9 @@ protocol RoomProxyProtocol { // sourcery: AutoMockable protocol InvitedRoomProxyProtocol: RoomProxyProtocol { - var info: RoomInfoProxy { get } + var info: BaseRoomInfoProxyProtocol { get } + var inviter: RoomMemberProxyProtocol? { get } func rejectInvitation() async -> Result - func acceptInvitation() async -> Result } // sourcery: AutoMockable diff --git a/project.yml b/project.yml index d80b046579..1f07f11593 100644 --- a/project.yml +++ b/project.yml @@ -61,7 +61,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.69 + exactVersion: 1.0.70 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From 51227fffe31974dfa2f2b2079396cc3011e342c7 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Tue, 19 Nov 2024 21:53:57 +0200 Subject: [PATCH 38/74] Show both defaults and frequent emojis in the timeline item menu, make the list scrollable (#3534) --- .../Sources/Application/AppSettings.swift | 4 -- .../DeveloperOptionsScreenModels.swift | 1 - .../View/DeveloperOptionsScreen.swift | 4 -- .../View/ItemMenu/TimelineItemMenu.swift | 55 ++++++++++++------- .../ItemMenu/TimelineItemMenuAction.swift | 23 ++++---- .../Services/Emojis/EmojiProvider.swift | 4 +- ...melineItemMenu-iPad-en-GB.Authenticity.png | 4 +- ...elineItemMenu-iPad-en-GB.Button-shapes.png | 4 +- ...neItemMenu-iPad-en-GB.Identity-Changed.png | 4 +- ...est_timelineItemMenu-iPad-en-GB.Normal.png | 4 +- ...emMenu-iPad-en-GB.Own-Unsigned-Devices.png | 4 +- ...imelineItemMenu-iPad-en-GB.Unencrypted.png | 4 +- ...ineItemMenu-iPad-en-GB.Unknown-failure.png | 4 +- ...neItemMenu-iPad-en-GB.Unsigned-Devices.png | 4 +- ...t_timelineItemMenu-iPad-en-GB.Unsigned.png | 4 +- ...elineItemMenu-iPad-pseudo.Authenticity.png | 4 +- ...lineItemMenu-iPad-pseudo.Button-shapes.png | 4 +- ...eItemMenu-iPad-pseudo.Identity-Changed.png | 4 +- ...st_timelineItemMenu-iPad-pseudo.Normal.png | 4 +- ...mMenu-iPad-pseudo.Own-Unsigned-Devices.png | 4 +- ...melineItemMenu-iPad-pseudo.Unencrypted.png | 4 +- ...neItemMenu-iPad-pseudo.Unknown-failure.png | 4 +- ...eItemMenu-iPad-pseudo.Unsigned-Devices.png | 4 +- ..._timelineItemMenu-iPad-pseudo.Unsigned.png | 4 +- ...eItemMenu-iPhone-16-en-GB.Authenticity.png | 4 +- ...ItemMenu-iPhone-16-en-GB.Button-shapes.png | 4 +- ...mMenu-iPhone-16-en-GB.Identity-Changed.png | 4 +- ...imelineItemMenu-iPhone-16-en-GB.Normal.png | 4 +- ...u-iPhone-16-en-GB.Own-Unsigned-Devices.png | 4 +- ...neItemMenu-iPhone-16-en-GB.Unencrypted.png | 4 +- ...emMenu-iPhone-16-en-GB.Unknown-failure.png | 4 +- ...mMenu-iPhone-16-en-GB.Unsigned-Devices.png | 4 +- ...elineItemMenu-iPhone-16-en-GB.Unsigned.png | 4 +- ...ItemMenu-iPhone-16-pseudo.Authenticity.png | 4 +- ...temMenu-iPhone-16-pseudo.Button-shapes.png | 4 +- ...Menu-iPhone-16-pseudo.Identity-Changed.png | 4 +- ...melineItemMenu-iPhone-16-pseudo.Normal.png | 4 +- ...-iPhone-16-pseudo.Own-Unsigned-Devices.png | 4 +- ...eItemMenu-iPhone-16-pseudo.Unencrypted.png | 4 +- ...mMenu-iPhone-16-pseudo.Unknown-failure.png | 4 +- ...Menu-iPhone-16-pseudo.Unsigned-Devices.png | 4 +- ...lineItemMenu-iPhone-16-pseudo.Unsigned.png | 4 +- 42 files changed, 121 insertions(+), 114 deletions(-) diff --git a/ElementX/Sources/Application/AppSettings.swift b/ElementX/Sources/Application/AppSettings.swift index 5949761ec5..cb800e96a0 100644 --- a/ElementX/Sources/Application/AppSettings.swift +++ b/ElementX/Sources/Application/AppSettings.swift @@ -47,7 +47,6 @@ final class AppSettings { case fuzzyRoomListSearchEnabled case enableOnlySignedDeviceIsolationMode case knockingEnabled - case frequentEmojisEnabled } private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier @@ -281,9 +280,6 @@ final class AppSettings { @UserPreference(key: UserDefaultsKeys.knockingEnabled, defaultValue: false, storageType: .userDefaults(store)) var knockingEnabled - @UserPreference(key: UserDefaultsKeys.frequentEmojisEnabled, defaultValue: isDevelopmentBuild, storageType: .userDefaults(store)) - var frequentEmojisEnabled - #endif // MARK: - Shared diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift index 1024600448..2f1322eccd 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift @@ -50,7 +50,6 @@ protocol DeveloperOptionsProtocol: AnyObject { var enableOnlySignedDeviceIsolationMode: Bool { get set } var elementCallBaseURLOverride: URL? { get set } var knockingEnabled: Bool { get set } - var frequentEmojisEnabled: 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 08b06c6e82..bdeb01df78 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift @@ -53,10 +53,6 @@ struct DeveloperOptionsScreen: View { Toggle(isOn: $context.hideTimelineMedia) { Text("Hide image & video previews") } - - Toggle(isOn: $context.frequentEmojisEnabled) { - Text("Show frequently used emojis") - } } Section("Join rules") { diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift index 86a5ccead6..43e7144ac7 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift @@ -11,6 +11,7 @@ import SwiftUI struct TimelineItemMenu: View { @EnvironmentObject private var context: TimelineViewModel.Context @Environment(\.dismiss) private var dismiss + @Environment(\.horizontalSizeClass) private var horizontalSizeClass @State private var reactionsFrame = CGRect.zero @@ -109,31 +110,43 @@ struct TimelineItemMenu: View { } private var reactionsSection: some View { - ScrollView(.horizontal) { - HStack(alignment: .center, spacing: 8) { - ForEach(actions.reactions, id: \.key) { - reactionButton(for: $0.key) - } - - Button { - dismiss() - // Otherwise we get errors that a sheet is already presented - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { - context.send(viewAction: .displayEmojiPicker(itemID: item.id)) + HStack(spacing: 8) { + ScrollView(.horizontal) { + HStack(alignment: .center, spacing: 8) { + ForEach(actions.reactions, id: \.key) { + reactionButton(for: $0.key) } - } label: { - CompoundIcon(\.reactionAdd, size: .medium, relativeTo: .compound.headingLG) - .foregroundColor(.compound.iconSecondary) - .padding(10) } - .accessibilityLabel(L10n.actionReact) + .padding(.horizontal) + .frame(minWidth: reactionsFrame.width, maxWidth: .infinity, alignment: .center) + } + .scrollIndicators(.hidden) + .scrollBounceBehavior(.basedOnSize, axes: .horizontal) + .readFrame($reactionsFrame) + .overlay { + if horizontalSizeClass == .compact { + LinearGradient(stops: [.init(color: .clear, location: 0.0), + .init(color: .clear, location: 0.9), + .init(color: .compound.bgCanvasDefault, location: 1.0)], + startPoint: .leading, + endPoint: .trailing) + .allowsHitTesting(false) + } + } + + Button { + dismiss() + // Otherwise we get errors that a sheet is already presented + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + context.send(viewAction: .displayEmojiPicker(itemID: item.id)) + } + } label: { + CompoundIcon(\.reactionAdd, size: .medium, relativeTo: .compound.headingLG) + .foregroundColor(.compound.iconSecondary) + .padding(10) } - .padding(.horizontal) - .frame(minWidth: reactionsFrame.width, maxWidth: .infinity, alignment: .center) + .accessibilityLabel(L10n.actionReact) } - .scrollIndicators(.hidden) - .scrollBounceBehavior(.basedOnSize, axes: .horizontal) - .readFrame($reactionsFrame) } private func reactionButton(for emoji: String) -> some View { diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift index a2e7de4f20..b6ce6d036d 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift @@ -5,6 +5,7 @@ // Please see LICENSE in the repository root for full details. // +import OrderedCollections import SFSafeSymbols import SwiftUI @@ -25,30 +26,32 @@ struct TimelineItemMenuActions { self.actions = actions self.debugActions = debugActions - // Only process 5 of the most frequently used emojis instead of all of them - var frequentlyUsed = emojiProvider.frequentlyUsedSystemEmojis().prefix(5).map { TimelineItemMenuReaction(key: $0, symbol: .heart) } - - frequentlyUsed += [ + var frequentlyUsed: OrderedSet = [ .init(key: "👍️", symbol: .handThumbsup), .init(key: "👎️", symbol: .handThumbsdown), - .init(key: "🔥", symbol: .flame), - .init(key: "❤️", symbol: .heart), - .init(key: "👏", symbol: .handsClap) + .init(key: "🎉", symbol: .partyPopper), + .init(key: "❤️", symbol: .heart) ] - frequentlyUsed = Array(frequentlyUsed.prefix(5)) + frequentlyUsed.append(contentsOf: emojiProvider.frequentlyUsedSystemEmojis().map { TimelineItemMenuReaction(key: $0, symbol: .heart) }) reactions = if isReactable { - frequentlyUsed + Array(frequentlyUsed.elements.prefix(10)) } else { [] } } } -struct TimelineItemMenuReaction { +struct TimelineItemMenuReaction: Hashable { let key: String let symbol: SFSymbol + + // Frequently used emojis on the all use the same .heart SFSymbol. + // Override equatable so we can remove duplicates. + static func == (lhs: TimelineItemMenuReaction, rhs: TimelineItemMenuReaction) -> Bool { + lhs.key == rhs.key + } } enum TimelineItemMenuAction: Identifiable, Hashable { diff --git a/ElementX/Sources/Services/Emojis/EmojiProvider.swift b/ElementX/Sources/Services/Emojis/EmojiProvider.swift index 80c31ed0d5..104f65ce23 100644 --- a/ElementX/Sources/Services/Emojis/EmojiProvider.swift +++ b/ElementX/Sources/Services/Emojis/EmojiProvider.swift @@ -57,7 +57,7 @@ class EmojiProvider: EmojiProviderProtocol { } func frequentlyUsedSystemEmojis() -> [String] { - guard appSettings.frequentEmojisEnabled, !ProcessInfo.processInfo.isiOSAppOnMac else { + guard !ProcessInfo.processInfo.isiOSAppOnMac else { return [] } @@ -72,7 +72,7 @@ class EmojiProvider: EmojiProviderProtocol { } func markEmojiAsFrequentlyUsed(_ emoji: String) { - guard appSettings.frequentEmojisEnabled else { + guard !ProcessInfo.processInfo.isiOSAppOnMac else { return } 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 748dad4fa7..5614e91256 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:03139a4b36b40b979854ab2659f8bef19a4415a07a7922e13f22bfafbce96362 -size 139155 +oid sha256:bcc6fdf7c3f7e40f9beedb8f9779fa74b3c8d7020112398059783ff2820fa4ed +size 135575 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 d284619294..e6e1c3129a 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:d4bcf22687551f169a13c2b242ba0bc2fd20d93f1438a2a99263c4fde6677ff9 -size 146820 +oid sha256:3e337818f2c9ecd0e7abfe35868857394f3b1129e798354266035b65ed9fe9ee +size 142532 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 2e6a92bbe8..db49f13798 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:1e4244ced22d9ba2c2938a9939512fb8202d1e5f471fc0d00f58b58845abad2c -size 137736 +oid sha256:a7ba26595547bdab86bc57097fcccb0062b73c9afcccc5ee2d9481c24a5ee954 +size 134046 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 ee70aed177..6dc2b5e65b 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:26ea8ac5f8d377083815e42276831a7def7ec4d2c0ed5b118d431a362b4a123e -size 128100 +oid sha256:7f1d6997b3ca132dbf486145371ccc38418ee1ccfbb05ebd670f73f621008c48 +size 124084 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 c652521a45..e1bddfabb3 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:afa8b6189392fe1053312c29995783017ff9697b85f8960a75ecb76a83e05446 -size 138537 +oid sha256:fbf1b0ba7b26a5bf3040ceffbfcca15cf38445fe4db7a39b81b16826517c6762 +size 134605 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 7305c77aac..214c0a0e7d 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:36fa2f45e35a597c0c0dfe672616bc584f12e93c8d742c2fcdc0a40195dd7159 -size 132986 +oid sha256:bdcb99ed272db7ee82b09574da7e791ee371b35107ca8104a72acd71e99b1156 +size 129013 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 ee70aed177..6dc2b5e65b 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:26ea8ac5f8d377083815e42276831a7def7ec4d2c0ed5b118d431a362b4a123e -size 128100 +oid sha256:7f1d6997b3ca132dbf486145371ccc38418ee1ccfbb05ebd670f73f621008c48 +size 124084 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 59cc5be713..a8350dec89 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:1583ad4ade4b6eac9eface5466a742999213b9f4e2e80ac62d174338722d6799 -size 137445 +oid sha256:83ec69d4b69f3a33422b0a472665c65855a365b4f676888edb9eb054ebaf77d4 +size 133818 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 f3f4460871..af16a6b6e3 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:c80e3745e88d27713eebb5f28fe4ee1bcc65e8690e30cba71c83b6a240a818ac -size 136759 +oid sha256:e173a969f56bdfad935308070f5dc1958eaf7781fbcf18e01c81b95799ce3ae1 +size 132960 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 54692b74c7..73cb694b0b 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:faa541dc8e53791b4f0fbe78a3ef2f99afcff7b91fe9f6e6293ea831baf15b07 -size 146264 +oid sha256:c5a5a1d65cd3f0c569f2ca1fb80258e8179870acade4a1d68b3e9e67a52d8d29 +size 142541 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 eff2c1eda6..871bdb3e53 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:403ddbf0882f5ded4fbd1ac0e34d635909f260dd2f2988a979503ca29c59db5b -size 148734 +oid sha256:9fbc2bf481aeecb17f3be814b3bcf7147f2d8d757eb82a15b2a0db10a5ec8f40 +size 144452 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 9c0a9cd5f6..da7e6a2e88 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:4dd28156f64422ca6df2dc5178afdf6e3d840ab220e2e17bb55d55f3f306f359 -size 145601 +oid sha256:1eac1d2d29c71d9c332f26b311b50c7ef601896a6941a1f617d200e23bb88731 +size 141641 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 09237aa4aa..fbbe196d73 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:25d707eeb27e5fbb22a6ec3efe70142b8781a3ea5423d44d284deebd78bfda22 -size 129934 +oid sha256:39c0cc82049d6e4c12416c457a087d99b52169ab266da1beaa22888aa933bca5 +size 125934 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 bf4efa013a..01df243b16 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:4b3d27ebbcc1acf240e82893f4ea815bb117e8e7f033aa368983ef59e48e60bf -size 144624 +oid sha256:eac68c72456505eaafd6c94948857aaa2d54accc4990c3dd3cd1cb31023c89bf +size 140645 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 4e5a87fe62..65f5a2de07 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:ffbe89eadebb2a4590f2c8d5cfb2d053eafd190f7512c7b560d73fe057bc2419 -size 137105 +oid sha256:150daec2df86269a675887b754f64e067dcdb856dff9d1c8a36e746495745ab8 +size 133199 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 09237aa4aa..fbbe196d73 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:25d707eeb27e5fbb22a6ec3efe70142b8781a3ea5423d44d284deebd78bfda22 -size 129934 +oid sha256:39c0cc82049d6e4c12416c457a087d99b52169ab266da1beaa22888aa933bca5 +size 125934 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 a64e8653ce..ebe3d9742a 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:fd14d07d1258d5740e90cb017b42cb7715c61a7eb9ac0211ee1af57a0eac71fa -size 143967 +oid sha256:a1d61ad248aa93c90b680e51cdf4a30d8cfd9568a062b03b559d6f9d57fffddf +size 140013 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 ec0208b752..49a10d7bdf 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:039542c53b6877e128483381d0aa599d454401b60017eee2d73817d4475cfcfa -size 142473 +oid sha256:2c30cb638c2eecebb63ca66a5f0107bb85225aa786cbf32ecbca9974b42cd383 +size 139069 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 3d5951fd17..b3d2bd4605 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:fe429e48ab5e9733b17383b056d882cd73fec21dd79fd8fed6ef295a77c02b9c -size 91910 +oid sha256:dd17e2229ac0f1c09ef301589f24de7f879364dbc468460d6e387b2393d6b584 +size 88452 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 74bd759561..c5cf3ce854 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:f7d5688fb1e653dd4d7c025496bf21c4794566772028a4fcb164255be5829ef7 -size 91186 +oid sha256:2e9f207e4656524273989488b2e8f1d9ee2901d500a76b89dbbf01e831a146c7 +size 91341 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 793e5ea724..acee9f6830 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:09d0ef69aac97f605af70dee72274600e243d95b896e06ff4a5b88edfcbe492f -size 90909 +oid sha256:46f40c81c046bb1593d0ac0d1b396558e75ab4d9a85ce9f460610c623835711a +size 87463 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 7a688e37bd..afc3971093 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:ca46714baac623515ee64da0f80cb8588938dc322446e8100c2fa19c80c4103e -size 81690 +oid sha256:b1a6d6103056a883e4fa9344b65766867ef28355f359c428c6f8fc7b8a5b1dd4 +size 78383 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 173e3df801..3589187676 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:b668de157b45f5f1f75e9485d3c35e8a103428ac03563ff851b24111f3699553 -size 91806 +oid sha256:12b9450065c9aa924ac7b833d2c98a8ea011ea3ec470438869f08591590a5576 +size 88346 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 0982b3fddc..fa0bdd2c33 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:6533795aeb46d968aa65e814a8a6f16d8da8806ef367400d2ef7fddb19ffc0a6 -size 84498 +oid sha256:05ae1dfcf89ec7c5329c570e29b876935d261470a6fc074d961452f75e4ab4e3 +size 81155 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 7a688e37bd..afc3971093 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:ca46714baac623515ee64da0f80cb8588938dc322446e8100c2fa19c80c4103e -size 81690 +oid sha256:b1a6d6103056a883e4fa9344b65766867ef28355f359c428c6f8fc7b8a5b1dd4 +size 78383 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 79ea6f9974..b9a00d5ed0 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:1ebc67234b0185ddea83263dd44cd4f90dc578698d2cc40baa64167f87c28f88 -size 90370 +oid sha256:100ebc998da4d0625307771a9fda2dc78becccf2fe0e58cb514967cc26b77e46 +size 86917 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 16b2f95c14..eeb51c7cfa 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:ea7194599f6f232bcd6e2b4bf6a23095d8bdeba217ccfc5c1e53326e02118c5f -size 87424 +oid sha256:5d2451f6dfdb5d0342c13d9bba95f035610649f5e0c6c026b6b5c02a3f5ea792 +size 84457 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 4c71bda155..114f53c75e 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:14f96e9cc4c72a8be248885673df3b678d99b7a5227ea4751c37d027de86b543 -size 107635 +oid sha256:a7e0833f33a5372ac34cb1ffc904b3113c292ddfac1798f2ec49263f72487b8b +size 104147 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 9caa67cb73..7e06a52bec 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:917f4a8cdf90f2dec6ec9812bd19d6a87611376c007d5ab528aac8ca81fdafb0 -size 96764 +oid sha256:9dd681b7005cad7f3172e46704ce15f35348741ab4f61c25c7e25dbc976dd47f +size 96872 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 d64e40d969..1f8ad9ff39 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:439d46bc024a1c7a387e674f454f9b67fb78276d5761b88a86dc2b399daa3629 -size 105944 +oid sha256:66a515af35f86cc79842515e6f200a8ac9e66393bafa3d08dd73c94b55a0e273 +size 102463 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 439c073c12..cbf97d5941 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:8bf1639b2cf203490b7c0e0e801274fc7fd05b3942ebb9684e224192e1f1ca12 -size 87380 +oid sha256:f9f354421510618dc4c3ebdd4ed3f6aeb274236bd4d680948127a21737882a35 +size 83970 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 e37222e437..4d6d50c68f 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:a9283c5c852d4843ee9d58b2af0df2c4effc4693f47100b232bdb5cf7c7157c1 -size 108300 +oid sha256:20be265e58a5ce19848a1d9c9221587656efbeb1eefa982bf598021ed91b1976 +size 104759 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 c3e375e9a6..d2ca600aa9 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:55119111fd3419c9a280b49eaac288c4ff1da935280eb785815891e59dec6a4c -size 91962 +oid sha256:bbcb5ce6d51e66aa74d7ebb6cdaf574a80613cf5cbc2a52285f2db5758a260c8 +size 88609 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 439c073c12..cbf97d5941 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:8bf1639b2cf203490b7c0e0e801274fc7fd05b3942ebb9684e224192e1f1ca12 -size 87380 +oid sha256:f9f354421510618dc4c3ebdd4ed3f6aeb274236bd4d680948127a21737882a35 +size 83970 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 acb4756545..37099ec4fb 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:aa27e929fdcb97f2900eb540c9e0fdbce42dabacd99c1b8a84aa761406cb7e25 -size 104293 +oid sha256:cb4cba6c55ed6d5a399729817e3bbcf0109e940022009ec2b994d744a0e26b9e +size 100765 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 1065904980..5f247f2022 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:67a6b2f31d5cd87a54558c93ee7f56a6af75b9887f2cbad4b28aca781696b923 -size 99497 +oid sha256:e808c53766810d2cef79e239295f55b151a151cb42a7d7fd24f83ef889964ae1 +size 95987 From 5eb42eb8edc14c49ccd81a5cef19f11f24c05046 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 20 Nov 2024 11:49:26 +0200 Subject: [PATCH 39/74] Fix UI tests, update compound to roll back snapshot testing and avoid the requirement for Swift Testing. --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 10 +++++----- project.yml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 5403ca071d..a242e53b9f 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -8258,7 +8258,7 @@ repositoryURL = "https://github.com/element-hq/compound-ios"; requirement = { kind = revision; - revision = 80edb8829b4ca00c0a52a39b7d9024e3ebdc1acb; + revision = f0436aa767f614584bf119defa6372ddb3b60080; }; }; 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 af01bfc351..d911c6f347 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" : "d81c1aa03fed8662cf85702310542bdc9e5b3d93", - "version" : "2.0.2" + "revision" : "3adf924aec63f1addfe9124a95fa4c9e9b5bff7d", + "version" : "2.1.0" } }, { @@ -15,7 +15,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/compound-ios", "state" : { - "revision" : "80edb8829b4ca00c0a52a39b7d9024e3ebdc1acb" + "revision" : "f0436aa767f614584bf119defa6372ddb3b60080" } }, { @@ -248,8 +248,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-snapshot-testing", "state" : { - "revision" : "42a086182681cf661f5c47c9b7dc3931de18c6d7", - "version" : "1.17.6" + "revision" : "7b0bbbae90c41f848f90ac7b4df6c4f50068256d", + "version" : "1.17.5" } }, { diff --git a/project.yml b/project.yml index 1f07f11593..dda33c8cc2 100644 --- a/project.yml +++ b/project.yml @@ -65,7 +65,7 @@ packages: # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios - revision: 80edb8829b4ca00c0a52a39b7d9024e3ebdc1acb + revision: f0436aa767f614584bf119defa6372ddb3b60080 # path: ../compound-ios AnalyticsEvents: url: https://github.com/matrix-org/matrix-analytics-events From acd670ab5654e30a06b9efd14dec3af2b0e08290 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 20 Nov 2024 09:33:00 +0200 Subject: [PATCH 40/74] Link the MatrixRustSDK dynamically and only embed it in the main target --- ElementX.xcodeproj/project.pbxproj | 47 +++++++++++++++++-- .../xcshareddata/swiftpm/Package.resolved | 3 +- ElementX/SupportingFiles/target.yml | 1 + PreviewTests/SupportingFiles/target.yml | 1 + UnitTests/SupportingFiles/target.yml | 1 + project.yml | 3 +- 6 files changed, 49 insertions(+), 7 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index a242e53b9f..d9cf182e03 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -454,6 +454,7 @@ 61941DEE5F3834765770BE01 /* InviteUsersScreenSelectedItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10F32E0B4B83D2A11EE8D011 /* InviteUsersScreenSelectedItem.swift */; }; 61A36B9BB2ADE36CEFF5E98C /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E93A1BE7D8A2EBCAD51EEB4 /* Array.swift */; }; 62418EA4E3EB597AD184AEB6 /* PillConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB8D34E94AB07128DB73D6C7 /* PillConstants.swift */; }; + 62684AECDFC5C7DC989CBD9E /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 7B6BC3219ADD8AA0311D2B86 /* SnapshotTesting */; }; 627139A3D79F032BA81E3A53 /* UserSessionFlowCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FA29BAE9B0F2D90E57B261C /* UserSessionFlowCoordinatorTests.swift */; }; 62910B515BCB4B455E24D7C1 /* AdvancedSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D086854995173E897F993C26 /* AdvancedSettingsScreenViewModelProtocol.swift */; }; 6298AB0906DDD3525CD78C6B /* LoremSwiftum in Frameworks */ = {isa = PBXBuildFile; productRef = 1A6B622CCFDEFB92D9CF1CA5 /* LoremSwiftum */; }; @@ -595,7 +596,7 @@ 7D249465ED00988EEEC14E05 /* JoinedRoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 867DC9530C42F7B5176BE465 /* JoinedRoomProxyMock.swift */; }; 7D261B5119E78CC8E771CA15 /* GlobalSearchScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74653BE903970C0E36867D46 /* GlobalSearchScreenCoordinator.swift */; }; 7D58B4F46CAA9A7C3E4C6A30 /* UserDetailsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88410BD213FDF9B28E8B671F /* UserDetailsEditScreen.swift */; }; - 7D6DC832DE7A3DE874E2E9BC /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 7B6BC3219ADD8AA0311D2B86 /* SnapshotTesting */; }; + 7D6DC832DE7A3DE874E2E9BC /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = BB111AE9D390233CDD2C7FD5 /* MatrixRustSDK */; }; 7E2BB42805C59DB57E95610F /* PillView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7773CBFDBD458E0B7E270507 /* PillView.swift */; }; 7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */; }; 7ECF12D5DCD69F67BD3E3842 /* RoomTimelineControllerFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */; }; @@ -604,6 +605,7 @@ 7F825CBD857D65DC986087BA /* NoticeRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F54FA7C5CB7B342EF9B9B2F /* NoticeRoomTimelineView.swift */; }; 7F941B063C94E1718DFC2CF3 /* RoomChangeRolesScreenRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E6EB7960BC9D0F7396B3BD /* RoomChangeRolesScreenRow.swift */; }; 7FED77802940EA7DF4D0D3A2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */; }; + 7FF27DA70D833CFC5724EFC5 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = C07EA60CAB296D7726210F5B /* MatrixRustSDK */; }; 7FF6E1FBE6E9517FD29A1D8E /* RoomChangeRolesScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48A5C34C4E4268EF65D171EF /* RoomChangeRolesScreenModels.swift */; }; 8015842CB4DE1BE414D2CDED /* AppLockSetupBiometricsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C62E07C1164F5120727A2A8 /* AppLockSetupBiometricsScreenCoordinator.swift */; }; 804C15D8ADE0EA7A5268F58A /* OverridableAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */; }; @@ -943,6 +945,7 @@ C9A631FD968249B4BA0B7B3C /* ReactionsSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EE0FABA8ED6D6C1D6CE71D /* ReactionsSummaryView.swift */; }; C9ABF75A43F2D26F1D9A1F27 /* DeactivateAccountScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AC3FDB58F57386741A4FC7F /* DeactivateAccountScreenViewModel.swift */; }; C9BE065FA7D4E77E4C61CB69 /* MapLibreModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B81B6170DB690013CEB646F4 /* MapLibreModels.swift */; }; + C9C562D85999E436C7265AF1 /* MatrixRustSDK in Embed Frameworks */ = {isa = PBXBuildFile; productRef = A678E40E917620059695F067 /* MatrixRustSDK */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; C9F5B48D15B9BCAE1F8D564E /* RoomNotificationModeProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1511766C534367700C8DD75 /* RoomNotificationModeProxy.swift */; }; CA12AE0DCD57D49CD96C699A /* WaveformCursorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB9EABCA9348DFA27439A809 /* WaveformCursorView.swift */; }; CACD1352927336F01FC76612 /* EncryptionResetUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE4C76F31A382B8E4DD07583 /* EncryptionResetUITests.swift */; }; @@ -1245,6 +1248,17 @@ name = "Embed Foundation Extensions"; runOnlyForDeploymentPostprocessing = 0; }; + F5356A7EB31909A578B8B4FB /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + C9C562D85999E436C7265AF1 /* MatrixRustSDK in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -2418,6 +2432,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A7A4BAD642A61DCC41621311 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7FF27DA70D833CFC5724EFC5 /* MatrixRustSDK in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; BF59B36A7B2DB184B62826F6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -2438,7 +2460,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 7D6DC832DE7A3DE874E2E9BC /* SnapshotTesting in Frameworks */, + 7D6DC832DE7A3DE874E2E9BC /* MatrixRustSDK in Frameworks */, + 62684AECDFC5C7DC989CBD9E /* SnapshotTesting in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5791,6 +5814,7 @@ buildPhases = ( 11F93544B4FC60F78F47D89C /* Sources */, 9B3512762CF4A1D45A79C340 /* Resources */, + A7A4BAD642A61DCC41621311 /* Frameworks */, ); buildRules = ( ); @@ -5798,6 +5822,9 @@ 0EEC1557A40FBA6DF49D83A2 /* PBXTargetDependency */, ); name = UnitTests; + packageProductDependencies = ( + C07EA60CAB296D7726210F5B /* MatrixRustSDK */, + ); productName = UnitTests; productReference = AAC9344689121887B74877AF /* UnitTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; @@ -5817,6 +5844,7 @@ ); name = PreviewTests; packageProductDependencies = ( + BB111AE9D390233CDD2C7FD5 /* MatrixRustSDK */, 7B6BC3219ADD8AA0311D2B86 /* SnapshotTesting */, ); productName = PreviewTests; @@ -5834,6 +5862,7 @@ 215E1D91B98672C856F559D0 /* Resources */, EE878EAA342710DB973E0A87 /* Frameworks */, 8E3CD0D0BB6697512E867C1D /* Embed Foundation Extensions */, + F5356A7EB31909A578B8B4FB /* Embed Frameworks */, 98CA896D84BFD53B2554E891 /* ⚠️ SwiftLint */, B35AB66424BB30087EEE408C /* 🧹 SwiftFormat */, ); @@ -8137,8 +8166,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { - kind = exactVersion; - version = 1.0.70; + kind = revision; + revision = 50769941247cc87760c8d3c3a28f8753555c19fb; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { @@ -8512,6 +8541,11 @@ package = F76A08D0EA29A07A54F4EB4D /* XCRemoteSwiftPackageReference "swift-collections" */; productName = Collections; }; + BB111AE9D390233CDD2C7FD5 /* MatrixRustSDK */ = { + isa = XCSwiftPackageProductDependency; + package = 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */; + productName = MatrixRustSDK; + }; BC01130651CB23340B899032 /* DeviceKit */ = { isa = XCSwiftPackageProductDependency; package = D5F7D47BBAAE0CF1DDEB3034 /* XCRemoteSwiftPackageReference "DeviceKit" */; @@ -8522,6 +8556,11 @@ package = 821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */; productName = Emojibase; }; + C07EA60CAB296D7726210F5B /* MatrixRustSDK */ = { + isa = XCSwiftPackageProductDependency; + package = 6FC4820D8D4559CEECA064D7 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */; + productName = MatrixRustSDK; + }; C1BF15833233CD3BDB7E2B1D /* Mapbox */ = { isa = XCSwiftPackageProductDependency; package = 0CBF57301AA172C21F76CE86 /* XCRemoteSwiftPackageReference "maplibre-gl-native-distribution" */; diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d911c6f347..158a5b560d 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "e1651193fa976d2184526a0ca4699535e410d94d", - "version" : "1.0.70" + "revision" : "50769941247cc87760c8d3c3a28f8753555c19fb" } }, { diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml index e7b1587635..6d21c2ffd7 100644 --- a/ElementX/SupportingFiles/target.yml +++ b/ElementX/SupportingFiles/target.yml @@ -193,6 +193,7 @@ targets: # not used yet # - target: NCE - package: MatrixRustSDK + embed: true - package: Compound - package: Algorithms - package: AnalyticsEvents diff --git a/PreviewTests/SupportingFiles/target.yml b/PreviewTests/SupportingFiles/target.yml index d0620f3343..560bb0c262 100644 --- a/PreviewTests/SupportingFiles/target.yml +++ b/PreviewTests/SupportingFiles/target.yml @@ -31,6 +31,7 @@ targets: dependencies: - target: ElementX + - package: MatrixRustSDK - package: SnapshotTesting info: diff --git a/UnitTests/SupportingFiles/target.yml b/UnitTests/SupportingFiles/target.yml index f24d2827e5..957f321bf1 100644 --- a/UnitTests/SupportingFiles/target.yml +++ b/UnitTests/SupportingFiles/target.yml @@ -31,6 +31,7 @@ targets: dependencies: - target: ElementX + - package: MatrixRustSDK info: path: ../SupportingFiles/Info.plist diff --git a/project.yml b/project.yml index dda33c8cc2..296a4a5ecb 100644 --- a/project.yml +++ b/project.yml @@ -61,7 +61,8 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.70 + revision: 50769941247cc87760c8d3c3a28f8753555c19fb + # exactVersion: 1.0.70 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From b2137ad01d8024d2f0da8a7a9b062d57791c1e6a Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 20 Nov 2024 16:12:27 +0200 Subject: [PATCH 41/74] Handle NSItemProvider public.image data types. (#3541) --- .../Other/Extensions/NSItemProvider.swift | 121 +++++++++++++++++- .../PhotoLibraryPicker.swift | 2 +- .../Timeline/TimelineInteractionHandler.swift | 60 ++------- .../ShareExtensionViewController.swift | 46 +------ 4 files changed, 134 insertions(+), 95 deletions(-) diff --git a/ElementX/Sources/Other/Extensions/NSItemProvider.swift b/ElementX/Sources/Other/Extensions/NSItemProvider.swift index fef3478dbb..f567f7c280 100644 --- a/ElementX/Sources/Other/Extensions/NSItemProvider.swift +++ b/ElementX/Sources/Other/Extensions/NSItemProvider.swift @@ -6,23 +6,136 @@ // import Foundation +import UIKit import UniformTypeIdentifiers extension NSItemProvider { + struct PreferredContentType { + let type: UTType + let fileExtension: String + } + + func storeData() async -> URL? { + guard let contentType = preferredContentType else { + MXLog.error("Invalid NSItemProvider: \(self)") + return nil + } + + if contentType.type.identifier == UTType.image.identifier { + return await generateURLForUIImage(contentType) + } else { + return await generateURLForGenericData(contentType) + } + } + + private func generateURLForUIImage(_ contentType: PreferredContentType) async -> URL? { + guard let uiImage = try? await loadItem(forTypeIdentifier: contentType.type.identifier) as? UIImage else { + MXLog.error("Failed casting UIImage, invalid NSItemProvider: \(self)") + return nil + } + + guard let pngData = uiImage.pngData() else { + MXLog.error("Failed extracting PNG data out of the UIImage") + return nil + } + + do { + if let suggestedName = suggestedName as? NSString, + // Suggestions are nice but their extension is `jpeg` + let filename = (suggestedName.deletingPathExtension as NSString).appendingPathExtension(contentType.fileExtension) { + return try FileManager.default.writeDataToTemporaryDirectory(data: pngData, fileName: filename) + } else { + let filename = "\(UUID().uuidString).\(contentType.fileExtension)" + return try FileManager.default.writeDataToTemporaryDirectory(data: pngData, fileName: filename) + } + } catch { + MXLog.error("Failed storing NSItemProvider data \(self) with error: \(error)") + return nil + } + } + + private func generateURLForGenericData(_ contentType: PreferredContentType) async -> URL? { + let providerDescription = description + let shareData: Data? = await withCheckedContinuation { continuation in + _ = loadDataRepresentation(for: contentType.type) { data, error in + if let error { + MXLog.error("Failed processing NSItemProvider: \(providerDescription) with error: \(error)") + continuation.resume(returning: nil) + return + } + + guard let data else { + MXLog.error("Invalid NSItemProvider data: \(providerDescription)") + continuation.resume(returning: nil) + return + } + + continuation.resume(returning: data) + } + } + + guard let shareData else { + MXLog.error("Invalid share data") + return nil + } + + do { + if let filename = suggestedName { + let hasExtension = !(filename as NSString).pathExtension.isEmpty + let filename = hasExtension ? filename : "\(filename).\(contentType.fileExtension)" + return try FileManager.default.writeDataToTemporaryDirectory(data: shareData, fileName: filename) + } else { + let filename = "\(UUID().uuidString).\(contentType.fileExtension)" + return try FileManager.default.writeDataToTemporaryDirectory(data: shareData, fileName: filename) + } + } catch { + MXLog.error("Failed storing NSItemProvider data \(self) with error: \(error)") + return nil + } + } + var isSupportedForPasteOrDrop: Bool { preferredContentType != nil } - var preferredContentType: UTType? { + var preferredContentType: PreferredContentType? { let supportedContentTypes = registeredContentTypes - .filter { isMimeTypeSupported($0.preferredMIMEType) } + .filter { isMimeTypeSupported($0.preferredMIMEType) || isIdentifierSupported($0.identifier) } // Have .jpeg take priority over .heic if supportedContentTypes.contains(.jpeg) { - return .jpeg + guard let fileExtension = preferredFileExtension(for: .jpeg) else { + return nil + } + + return .init(type: .jpeg, fileExtension: fileExtension) + } + + guard let preferredContentType = supportedContentTypes.first, + let fileExtension = preferredFileExtension(for: preferredContentType) else { + return nil } - return supportedContentTypes.first + return .init(type: preferredContentType, fileExtension: fileExtension) + } + + private func preferredFileExtension(for contentType: UTType) -> String? { + if let fileExtension = contentType.preferredFilenameExtension { + return fileExtension + } + + switch contentType.identifier { + case UTType.image.identifier: + return "png" + default: + return nil + } + } + + private func isIdentifierSupported(_ identifier: String?) -> Bool { + // Don't filter out generic public.image content as screenshots are in this format + // and we can convert them to a PNG ourselves. + identifier == UTType.image.identifier } private func isMimeTypeSupported(_ mimeType: String?) -> Bool { diff --git a/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift b/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift index c1b1a4ad34..377d43a490 100644 --- a/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift +++ b/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift @@ -69,7 +69,7 @@ struct PhotoLibraryPicker: UIViewControllerRepresentable { photoLibraryPicker.userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier) } - provider.loadFileRepresentation(forTypeIdentifier: contentType.identifier) { [weak self] url, error in + provider.loadFileRepresentation(forTypeIdentifier: contentType.type.identifier) { [weak self] url, error in guard let url else { Task { @MainActor in self?.photoLibraryPicker.callback(.error(.failedLoadingFileRepresentation(error))) diff --git a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift index a70c982758..e21ee3b4a7 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift @@ -248,54 +248,20 @@ class TimelineInteractionHandler { // MARK: Pasting and dropping func handlePasteOrDrop(_ provider: NSItemProvider) { - guard let contentType = provider.preferredContentType, - let preferredExtension = contentType.preferredFilenameExtension else { - MXLog.error("Invalid NSItemProvider: \(provider)") - actionsSubject.send(.displayErrorToast(L10n.screenRoomErrorFailedProcessingMedia)) - return - } - - let providerSuggestedName = provider.suggestedName - let providerDescription = provider.description - - _ = provider.loadDataRepresentation(for: contentType) { data, error in - Task { @MainActor in - let loadingIndicatorIdentifier = UUID().uuidString - self.userIndicatorController.submitIndicator(UserIndicator(id: loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading, persistent: true)) - defer { - self.userIndicatorController.retractIndicatorWithId(loadingIndicatorIdentifier) - } - - if let error { - self.actionsSubject.send(.displayErrorToast(L10n.screenRoomErrorFailedProcessingMedia)) - MXLog.error("Failed processing NSItemProvider: \(providerDescription) with error: \(error)") - return - } - - guard let data else { - self.actionsSubject.send(.displayErrorToast(L10n.screenRoomErrorFailedProcessingMedia)) - MXLog.error("Invalid NSItemProvider data: \(providerDescription)") - return - } - - do { - let url = try await Task.detached { - if let filename = providerSuggestedName { - let hasExtension = !(filename as NSString).pathExtension.isEmpty - let filename = hasExtension ? filename : "\(filename).\(preferredExtension)" - return try FileManager.default.writeDataToTemporaryDirectory(data: data, fileName: filename) - } else { - let filename = "\(UUID().uuidString).\(preferredExtension)" - return try FileManager.default.writeDataToTemporaryDirectory(data: data, fileName: filename) - } - }.value - - self.actionsSubject.send(.displayMediaUploadPreviewScreen(url: url)) - } catch { - self.actionsSubject.send(.displayErrorToast(L10n.screenRoomErrorFailedProcessingMedia)) - MXLog.error("Failed storing NSItemProvider data \(providerDescription) with error: \(error)") - } + Task { + let loadingIndicatorIdentifier = UUID().uuidString + self.userIndicatorController.submitIndicator(UserIndicator(id: loadingIndicatorIdentifier, type: .modal, title: L10n.commonLoading, persistent: true)) + defer { + self.userIndicatorController.retractIndicatorWithId(loadingIndicatorIdentifier) } + + guard let fileURL = await provider.storeData() else { + MXLog.error("Failed storing NSItemProvider data \(provider)") + self.actionsSubject.send(.displayErrorToast(L10n.screenRoomErrorFailedProcessingMedia)) + return + } + + self.actionsSubject.send(.displayMediaUploadPreviewScreen(url: fileURL)) } } diff --git a/ShareExtension/Sources/ShareExtensionViewController.swift b/ShareExtension/Sources/ShareExtensionViewController.swift index e2060491cf..5ecafc5e3b 100644 --- a/ShareExtension/Sources/ShareExtensionViewController.swift +++ b/ShareExtension/Sources/ShareExtensionViewController.swift @@ -42,54 +42,14 @@ class ShareExtensionViewController: UIViewController { return nil } - guard let contentType = itemProvider.preferredContentType, - let preferredExtension = contentType.preferredFilenameExtension else { - MXLog.error("Invalid NSItemProvider: \(itemProvider)") + guard let fileURL = await itemProvider.storeData() else { + MXLog.error("Failed storing NSItemProvider data \(itemProvider)") return nil } let roomID = (extensionContext?.intent as? INSendMessageIntent)?.conversationIdentifier - let providerSuggestedName = itemProvider.suggestedName - let providerDescription = itemProvider.description - - let shareData: Data? = await withCheckedContinuation { continuation in - _ = itemProvider.loadDataRepresentation(for: contentType) { data, error in - if let error { - MXLog.error("Failed processing NSItemProvider: \(providerDescription) with error: \(error)") - continuation.resume(returning: nil) - return - } - - guard let data else { - MXLog.error("Invalid NSItemProvider data: \(providerDescription)") - continuation.resume(returning: nil) - return - } - continuation.resume(returning: data) - } - } - - guard let shareData else { - return nil - } - - do { - let url: URL - if let filename = providerSuggestedName { - let hasExtension = !(filename as NSString).pathExtension.isEmpty - let filename = hasExtension ? filename : "\(filename).\(preferredExtension)" - url = try FileManager.default.writeDataToTemporaryDirectory(data: shareData, fileName: filename) - } else { - let filename = "\(UUID().uuidString).\(preferredExtension)" - url = try FileManager.default.writeDataToTemporaryDirectory(data: shareData, fileName: filename) - } - - return .mediaFile(roomID: roomID, mediaFile: .init(url: url, suggestedName: providerSuggestedName)) - } catch { - MXLog.error("Failed storing NSItemProvider data \(providerDescription) with error: \(error)") - return nil - } + return .mediaFile(roomID: roomID, mediaFile: .init(url: fileURL, suggestedName: fileURL.lastPathComponent)) } private func openMainApp(payload: ShareExtensionPayload) async { From 1c6279281352fe46c56a13b7c9022ede795b6092 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 20 Nov 2024 16:58:39 +0200 Subject: [PATCH 42/74] Enable inline replies for push notifications. --- .../Notification/Manager/NotificationManager.swift | 12 ++++++------ .../NotificationManagerTests.swift | 11 ++++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/ElementX/Sources/Services/Notification/Manager/NotificationManager.swift b/ElementX/Sources/Services/Notification/Manager/NotificationManager.swift index d5fd7f7eb0..11fbda7147 100644 --- a/ElementX/Sources/Services/Notification/Manager/NotificationManager.swift +++ b/ElementX/Sources/Services/Notification/Manager/NotificationManager.swift @@ -29,16 +29,16 @@ final class NotificationManager: NSObject, NotificationManagerProtocol { // MARK: NotificationManagerProtocol weak var delegate: NotificationManagerDelegate? - + func start() { - // Not implemented yet - // let replyAction = UNTextInputNotificationAction(identifier: NotificationConstants.Action.inlineReply, - // title: L10n.actionQuickReply, - // options: []) + let replyAction = UNTextInputNotificationAction(identifier: NotificationConstants.Action.inlineReply, + title: L10n.actionQuickReply, + options: []) let messageCategory = UNNotificationCategory(identifier: NotificationConstants.Category.message, - actions: [], + actions: [replyAction], intentIdentifiers: [], options: []) + let inviteCategory = UNNotificationCategory(identifier: NotificationConstants.Category.invite, actions: [], intentIdentifiers: [], diff --git a/UnitTests/Sources/NotificationManager/NotificationManagerTests.swift b/UnitTests/Sources/NotificationManager/NotificationManagerTests.swift index 2755b65e41..a368e4e35a 100644 --- a/UnitTests/Sources/NotificationManager/NotificationManagerTests.swift +++ b/UnitTests/Sources/NotificationManager/NotificationManagerTests.swift @@ -108,15 +108,16 @@ final class NotificationManagerTests: XCTestCase { XCTAssertEqual(request.content.title, "Title") XCTAssertEqual(request.content.subtitle, "Subtitle") } - + func test_whenStart_notificationCategoriesAreSet() throws { - // let replyAction = UNTextInputNotificationAction(identifier: NotificationConstants.Action.inlineReply, - // title: L10n.actionQuickReply, - // options: []) + let replyAction = UNTextInputNotificationAction(identifier: NotificationConstants.Action.inlineReply, + title: L10n.actionQuickReply, + options: []) let messageCategory = UNNotificationCategory(identifier: NotificationConstants.Category.message, - actions: [], + actions: [replyAction], intentIdentifiers: [], options: []) + let inviteCategory = UNNotificationCategory(identifier: NotificationConstants.Category.invite, actions: [], intentIdentifiers: [], From 19ed65bbd5af20cadd4bcbb28c381e3e1929dc78 Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 20 Nov 2024 17:53:42 +0000 Subject: [PATCH 43/74] Fix the media upload preview screen on macOS. --- .../View/MediaUploadPreviewScreen.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift index 6da34ba5ed..bcd0309b65 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift @@ -10,11 +10,12 @@ import QuickLook import SwiftUI struct MediaUploadPreviewScreen: View { + @Environment(\.colorScheme) private var colorScheme + @ObservedObject var context: MediaUploadPreviewScreenViewModel.Context - var title: String { - ProcessInfo.processInfo.isiOSAppOnMac ? context.viewState.title ?? "" : "" - } + var title: String { ProcessInfo.processInfo.isiOSAppOnMac ? context.viewState.title ?? "" : "" } + var colorSchemeOverride: ColorScheme { ProcessInfo.processInfo.isiOSAppOnMac ? colorScheme : .dark } var body: some View { mainContent @@ -31,7 +32,7 @@ struct MediaUploadPreviewScreen: View { .toolbar { toolbar } .disabled(context.viewState.shouldDisableInteraction) .interactiveDismissDisabled() - .preferredColorScheme(.dark) + .preferredColorScheme(colorSchemeOverride) } @ViewBuilder @@ -40,6 +41,7 @@ struct MediaUploadPreviewScreen: View { Text(title) .font(.compound.headingMD) .foregroundColor(.compound.textSecondary) + .frame(maxWidth: .infinity, maxHeight: .infinity) } else { PreviewView(fileURL: context.viewState.url, title: context.viewState.title) From 3a9f54a9f6f3f6b08a8546f85d03cfc7cd31fa83 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Thu, 21 Nov 2024 13:28:04 +0000 Subject: [PATCH 44/74] Update the SDK. (#3545) --- ElementX.xcodeproj/project.pbxproj | 4 ++-- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 3 ++- project.yml | 3 +-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index d9cf182e03..679037fdd7 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -8166,8 +8166,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { - kind = revision; - revision = 50769941247cc87760c8d3c3a28f8753555c19fb; + kind = exactVersion; + version = 1.0.73; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 158a5b560d..a405104491 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,7 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "50769941247cc87760c8d3c3a28f8753555c19fb" + "revision" : "b3f97292695e8d63469c0d3ec608eb74423c6a2e", + "version" : "1.0.73" } }, { diff --git a/project.yml b/project.yml index 296a4a5ecb..16c5b4624e 100644 --- a/project.yml +++ b/project.yml @@ -61,8 +61,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - revision: 50769941247cc87760c8d3c3a28f8753555c19fb - # exactVersion: 1.0.70 + exactVersion: 1.0.73 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From c081e538b4b5dd14cb10a5c7f92ee53f78513e5d Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:48:38 +0000 Subject: [PATCH 45/74] Add support for sharing URLs and text. (#3546) * Add support for sharing URLs and text. * Fix a bug where a stored draft would overwrite the shared text. * Add tests. --- .../RoomFlowCoordinator.swift | 91 +++++++++++-------- .../UserSessionFlowCoordinator.swift | 19 ++-- .../Sources/Mocks/JoinedRoomProxyMock.swift | 1 + .../Other/Extensions/NSItemProvider.swift | 15 ++- .../ComposerToolbarViewModel.swift | 15 ++- .../ComposerToolbarViewModelProtocol.swift | 2 +- .../RoomScreen/RoomScreenCoordinator.swift | 12 ++- .../Screens/Timeline/TimelineModels.swift | 1 + .../ShareExtension/ShareExtensionModels.swift | 9 ++ .../ShareExtensionViewController.swift | 16 ++-- ShareExtension/SupportingFiles/Info.plist | 4 + .../ComposerToolbarViewModelTests.swift | 63 +++++++++---- .../Sources/RoomFlowCoordinatorTests.swift | 27 +++++- .../UserSessionFlowCoordinatorTests.swift | 27 +++++- 14 files changed, 219 insertions(+), 83 deletions(-) diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index 459aebc86e..8aaf6fc27f 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -62,9 +62,18 @@ private enum PresentationAction: Hashable { var focusedEvent: FocusEvent? { switch self { case .eventFocus(let focusEvent): - return focusEvent + focusEvent default: - return nil + nil + } + } + + var sharedText: String? { + switch self { + case .share(.text(_, let text)): + text + default: + nil } } } @@ -196,11 +205,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { roomScreenCoordinator?.focusOnEvent(.init(eventID: eventID, shouldSetPin: false)) } case .share(let payload): - guard case let .mediaFile(roomID, _) = payload else { - return - } - - guard let roomID, roomID == self.roomID else { + guard let roomID = payload.roomID, roomID == self.roomID else { fatalError("Navigation route doesn't belong to this room flow.") } @@ -615,8 +620,10 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { case .eventFocus(let focusedEvent): roomScreenCoordinator?.focusOnEvent(focusedEvent) case .share(.mediaFile(_, let mediaFile)): - stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: mediaFile.url)) - default: + stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: mediaFile.url), userInfo: EventUserInfo(animated: animated)) + case .share(.text(_, let text)): + roomScreenCoordinator?.shareText(text) + case .none: break } @@ -624,32 +631,57 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } } - Task { - // Flag the room as read on entering, the timeline will take care of the read receipts - await roomProxy.flagAsUnread(false) - } + // Flag the room as read on entering, the timeline will take care of the read receipts + Task { await roomProxy.flagAsUnread(false) } - let userID = userSession.clientProxy.userID + analytics.trackViewRoom(isDM: roomProxy.infoPublisher.value.isDirect, isSpace: roomProxy.infoPublisher.value.isSpace) + let coordinator = makeRoomScreenCoordinator(presentationAction: presentationAction) + roomScreenCoordinator = coordinator + + if !isChildFlow { + let animated = UIDevice.current.userInterfaceIdiom == .phone ? animated : false + navigationStackCoordinator.setRootCoordinator(coordinator, animated: animated) { [weak self] in + self?.stateMachine.tryEvent(.dismissFlow) + } + } else { + if joinRoomScreenCoordinator != nil { + navigationStackCoordinator.pop() + } + + navigationStackCoordinator.push(coordinator, animated: animated) { [weak self] in + self?.stateMachine.tryEvent(.dismissFlow) + } + } + + switch presentationAction { + case .share(.mediaFile(_, let mediaFile)): + stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: mediaFile.url), userInfo: EventUserInfo(animated: animated)) + case .share(.text), .eventFocus: + break // These are both handled in the coordinator's init. + case .none: + break + } + } + + private func makeRoomScreenCoordinator(presentationAction: PresentationAction?) -> RoomScreenCoordinator { + let userID = userSession.clientProxy.userID let timelineItemFactory = RoomTimelineItemFactory(userID: userID, attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)) - let timelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy, initialFocussedEventID: presentationAction?.focusedEvent?.eventID, timelineItemFactory: timelineItemFactory, mediaProvider: userSession.mediaProvider) self.timelineController = timelineController - analytics.trackViewRoom(isDM: roomProxy.infoPublisher.value.isDirect, isSpace: roomProxy.infoPublisher.value.isSpace) - let completionSuggestionService = CompletionSuggestionService(roomProxy: roomProxy) - let composerDraftService = ComposerDraftService(roomProxy: roomProxy, timelineItemfactory: timelineItemFactory) let parameters = RoomScreenCoordinatorParameters(clientProxy: userSession.clientProxy, roomProxy: roomProxy, focussedEvent: presentationAction?.focusedEvent, + sharedText: presentationAction?.sharedText, timelineController: timelineController, mediaProvider: userSession.mediaProvider, mediaPlayerProvider: MediaPlayerProvider(), @@ -697,28 +729,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } .store(in: &cancellables) - roomScreenCoordinator = coordinator - if !isChildFlow { - let animated = UIDevice.current.userInterfaceIdiom == .phone ? animated : false - navigationStackCoordinator.setRootCoordinator(coordinator, animated: animated) { [weak self] in - self?.stateMachine.tryEvent(.dismissFlow) - } - } else { - if joinRoomScreenCoordinator != nil { - navigationStackCoordinator.pop() - } - - navigationStackCoordinator.push(coordinator, animated: animated) { [weak self] in - self?.stateMachine.tryEvent(.dismissFlow) - } - } - - switch presentationAction { - case .share(.mediaFile(_, let mediaFile)): - stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: mediaFile.url), userInfo: EventUserInfo(animated: animated)) - default: - break - } + return coordinator } private func presentJoinRoomScreen(via: [String], animated: Bool) { diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index d6ff185383..0c7af9484a 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -207,16 +207,13 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { case .settings, .chatBackupSettings: settingsFlowCoordinator.handleAppRoute(appRoute, animated: animated) case .share(let payload): - switch payload { - case .mediaFile(let roomID, _): - if let roomID { - stateMachine.processEvent(.selectRoom(roomID: roomID, - via: [], - entryPoint: .share(payload)), - userInfo: .init(animated: animated)) - } else { - stateMachine.processEvent(.showShareExtensionRoomList(sharePayload: payload), userInfo: .init(animated: animated)) - } + if let roomID = payload.roomID { + stateMachine.processEvent(.selectRoom(roomID: roomID, + via: [], + entryPoint: .share(payload)), + userInfo: .init(animated: animated)) + } else { + stateMachine.processEvent(.showShareExtensionRoomList(sharePayload: payload), userInfo: .init(animated: animated)) } } } @@ -938,6 +935,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { let sharePayload = switch sharePayload { case .mediaFile(_, let mediaFile): ShareExtensionPayload.mediaFile(roomID: roomID, mediaFile: mediaFile) + case .text(_, let text): + ShareExtensionPayload.text(roomID: roomID, text: text) } navigationSplitCoordinator.setSheetCoordinator(nil) diff --git a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift index ff385d9121..0cd26ef425 100644 --- a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift @@ -123,6 +123,7 @@ extension JoinedRoomProxyMock { matrixToEventPermalinkReturnValue = .success(.homeDirectory) loadDraftReturnValue = .success(nil) clearDraftReturnValue = .success(()) + sendTypingNotificationIsTypingReturnValue = .success(()) } } diff --git a/ElementX/Sources/Other/Extensions/NSItemProvider.swift b/ElementX/Sources/Other/Extensions/NSItemProvider.swift index f567f7c280..67aedca111 100644 --- a/ElementX/Sources/Other/Extensions/NSItemProvider.swift +++ b/ElementX/Sources/Other/Extensions/NSItemProvider.swift @@ -6,7 +6,7 @@ // import Foundation -import UIKit +import SwiftUI import UniformTypeIdentifiers extension NSItemProvider { @@ -15,6 +15,19 @@ extension NSItemProvider { let fileExtension: String } + func loadTransferable(type transferableType: T.Type) async -> T? { + try? await withCheckedContinuation { continuation in + _ = loadTransferable(type: T.self) { result in + continuation.resume(returning: result) + } + } + .get() + } + + func loadString() async -> String? { + try? await loadItem(forTypeIdentifier: UTType.text.identifier) as? String + } + func storeData() async -> URL? { guard let contentType = preferredContentType else { MXLog.error("Invalid NSItemProvider: \(self)") diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift index 36471da729..06623b8c7a 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift @@ -15,6 +15,7 @@ import WysiwygComposer typealias ComposerToolbarViewModelType = StateStoreViewModel final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerToolbarViewModelProtocol { + private var initialText: String? private let wysiwygViewModel: WysiwygComposerViewModel private let completionSuggestionService: CompletionSuggestionServiceProtocol private let analyticsService: AnalyticsService @@ -41,12 +42,14 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool private var replyLoadingTask: Task? - init(wysiwygViewModel: WysiwygComposerViewModel, + init(initialText: String? = nil, + wysiwygViewModel: WysiwygComposerViewModel, completionSuggestionService: CompletionSuggestionServiceProtocol, mediaProvider: MediaProviderProtocol, mentionDisplayHelper: MentionDisplayHelper, analyticsService: AnalyticsService, composerDraftService: ComposerDraftServiceProtocol) { + self.initialText = initialText self.wysiwygViewModel = wysiwygViewModel self.completionSuggestionService = completionSuggestionService self.analyticsService = analyticsService @@ -206,6 +209,8 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool } else { set(text: plainText) } + case .setFocus: + state.bindings.composerFocused = true case .removeFocus: state.bindings.composerFocused = false case .clear: @@ -219,8 +224,12 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool } } - func loadDraft() { - Task { + func loadDraft() async { + if let initialText { + set(text: initialText) + set(mode: .default) + state.bindings.composerFocused = true + } else { guard case let .success(draft) = await draftService.loadDraft(), let draft else { return diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModelProtocol.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModelProtocol.swift index 88db5d5cba..f7d19700bd 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModelProtocol.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModelProtocol.swift @@ -15,6 +15,6 @@ protocol ComposerToolbarViewModelProtocol { var keyCommands: [WysiwygKeyCommand] { get } func process(timelineAction: TimelineComposerAction) - func loadDraft() + func loadDraft() async func saveDraft() } diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift index 500461ea0e..b920ef687b 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift @@ -15,6 +15,7 @@ struct RoomScreenCoordinatorParameters { let clientProxy: ClientProxyProtocol let roomProxy: JoinedRoomProxyProtocol var focussedEvent: FocusEvent? + var sharedText: String? let timelineController: RoomTimelineControllerProtocol let mediaProvider: MediaProviderProtocol let mediaPlayerProvider: MediaPlayerProviderProtocol @@ -88,7 +89,8 @@ final class RoomScreenCoordinator: CoordinatorProtocol { maxCompressedHeight: ComposerConstant.maxHeight, maxExpandedHeight: ComposerConstant.maxHeight, parserStyle: .elementX) - let composerViewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel, + let composerViewModel = ComposerToolbarViewModel(initialText: parameters.sharedText, + wysiwygViewModel: wysiwygViewModel, completionSuggestionService: parameters.completionSuggestionService, mediaProvider: parameters.mediaProvider, mentionDisplayHelper: ComposerMentionDisplayHelper(timelineContext: timelineViewModel.context), @@ -172,7 +174,7 @@ final class RoomScreenCoordinator: CoordinatorProtocol { .store(in: &cancellables) // Loading the draft requires the subscriptions to be set up first otherwise the room won't be be able to propagate the information to the composer. - composerViewModel.loadDraft() + Task { await composerViewModel.loadDraft() } } func focusOnEvent(_ focussedEvent: FocusEvent) { @@ -183,6 +185,12 @@ final class RoomScreenCoordinator: CoordinatorProtocol { Task { await timelineViewModel.focusOnEvent(eventID: eventID) } } + func shareText(_ string: String) { + composerViewModel.process(timelineAction: .setMode(mode: .default)) // Make sure we're not e.g. replying. + composerViewModel.process(timelineAction: .setText(plainText: string, htmlText: nil)) + composerViewModel.process(timelineAction: .setFocus) + } + func stop() { composerViewModel.saveDraft() timelineViewModel.stop() diff --git a/ElementX/Sources/Screens/Timeline/TimelineModels.swift b/ElementX/Sources/Screens/Timeline/TimelineModels.swift index 0d407cf939..0f0d65d10d 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineModels.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineModels.swift @@ -79,6 +79,7 @@ enum TimelineViewAction { enum TimelineComposerAction { case setMode(mode: ComposerMode) case setText(plainText: String, htmlText: String?) + case setFocus case removeFocus case clear } diff --git a/ElementX/Sources/ShareExtension/ShareExtensionModels.swift b/ElementX/Sources/ShareExtension/ShareExtensionModels.swift index 3324554c65..a5147b2c93 100644 --- a/ElementX/Sources/ShareExtension/ShareExtensionModels.swift +++ b/ElementX/Sources/ShareExtension/ShareExtensionModels.swift @@ -13,6 +13,15 @@ enum ShareExtensionConstants { enum ShareExtensionPayload: Hashable, Codable { case mediaFile(roomID: String?, mediaFile: ShareExtensionMediaFile) + case text(roomID: String?, text: String) + + var roomID: String? { + switch self { + case .mediaFile(let roomID, _), + .text(let roomID, _): + roomID + } + } } struct ShareExtensionMediaFile: Hashable, Codable { diff --git a/ShareExtension/Sources/ShareExtensionViewController.swift b/ShareExtension/Sources/ShareExtensionViewController.swift index 5ecafc5e3b..96bfe173ac 100644 --- a/ShareExtension/Sources/ShareExtensionViewController.swift +++ b/ShareExtension/Sources/ShareExtensionViewController.swift @@ -42,14 +42,18 @@ class ShareExtensionViewController: UIViewController { return nil } - guard let fileURL = await itemProvider.storeData() else { - MXLog.error("Failed storing NSItemProvider data \(itemProvider)") + let roomID = (extensionContext?.intent as? INSendMessageIntent)?.conversationIdentifier + + if let fileURL = await itemProvider.storeData() { + return .mediaFile(roomID: roomID, mediaFile: .init(url: fileURL, suggestedName: fileURL.lastPathComponent)) + } else if let url = await itemProvider.loadTransferable(type: URL.self) { + return .text(roomID: roomID, text: url.absoluteString) + } else if let string = await itemProvider.loadString() { + return .text(roomID: roomID, text: string) + } else { + MXLog.error("Failed loading NSItemProvider data: \(itemProvider)") return nil } - - let roomID = (extensionContext?.intent as? INSendMessageIntent)?.conversationIdentifier - - return .mediaFile(roomID: roomID, mediaFile: .init(url: fileURL, suggestedName: fileURL.lastPathComponent)) } private func openMainApp(payload: ShareExtensionPayload) async { diff --git a/ShareExtension/SupportingFiles/Info.plist b/ShareExtension/SupportingFiles/Info.plist index 863d9f93c3..d8ad392ed8 100644 --- a/ShareExtension/SupportingFiles/Info.plist +++ b/ShareExtension/SupportingFiles/Info.plist @@ -36,6 +36,10 @@ 1 NSExtensionActivationSupportsMovieWithMaxCount 1 + NSExtensionActivationSupportsText + + NSExtensionActivationSupportsWebURLWithMaxCount + 1 NSExtensionPointIdentifier diff --git a/UnitTests/Sources/ComposerToolbarViewModelTests.swift b/UnitTests/Sources/ComposerToolbarViewModelTests.swift index 9779ae8bf0..1c9327fd98 100644 --- a/UnitTests/Sources/ComposerToolbarViewModelTests.swift +++ b/UnitTests/Sources/ComposerToolbarViewModelTests.swift @@ -23,17 +23,7 @@ class ComposerToolbarViewModelTests: XCTestCase { AppSettings.resetAllSettings() appSettings = AppSettings() ServiceLocator.shared.register(appSettings: appSettings) - wysiwygViewModel = WysiwygComposerViewModel() - completionSuggestionServiceMock = CompletionSuggestionServiceMock(configuration: .init()) - draftServiceMock = ComposerDraftServiceMock() - viewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel, - completionSuggestionService: completionSuggestionServiceMock, - mediaProvider: MediaProviderMock(configuration: .init()), - mentionDisplayHelper: ComposerMentionDisplayHelper.mock, - analyticsService: ServiceLocator.shared.analytics, - composerDraftService: draftServiceMock) - - viewModel.context.composerFormattingEnabled = true + setUpViewModel() } override func tearDown() { @@ -340,7 +330,7 @@ class ComposerToolbarViewModelTests: XCTestCase { return .success(nil) } - viewModel.loadDraft() + await viewModel.loadDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertFalse(viewModel.context.composerFormattingEnabled) XCTAssertTrue(viewModel.state.composerEmpty) @@ -356,7 +346,7 @@ class ComposerToolbarViewModelTests: XCTestCase { htmlText: nil, draftType: .newMessage)) } - viewModel.loadDraft() + await viewModel.loadDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertFalse(viewModel.context.composerFormattingEnabled) @@ -373,7 +363,7 @@ class ComposerToolbarViewModelTests: XCTestCase { htmlText: "Hello world!", draftType: .newMessage)) } - viewModel.loadDraft() + await viewModel.loadDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertTrue(viewModel.context.composerFormattingEnabled) @@ -391,7 +381,7 @@ class ComposerToolbarViewModelTests: XCTestCase { htmlText: nil, draftType: .edit(eventID: "testID"))) } - viewModel.loadDraft() + await viewModel.loadDraft() await fulfillment(of: [expectation], timeout: 10) XCTAssertFalse(viewModel.context.composerFormattingEnabled) @@ -424,7 +414,7 @@ class ComposerToolbarViewModelTests: XCTestCase { return .success(.init(details: loadedReply, isThreaded: true)) } - viewModel.loadDraft() + await viewModel.loadDraft() await fulfillment(of: [draftExpectation], timeout: 10) XCTAssertFalse(viewModel.context.composerFormattingEnabled) @@ -464,7 +454,7 @@ class ComposerToolbarViewModelTests: XCTestCase { return .success(.init(details: loadedReply, isThreaded: true)) } - viewModel.loadDraft() + await viewModel.loadDraft() await fulfillment(of: [draftExpectation], timeout: 10) XCTAssertFalse(viewModel.context.composerFormattingEnabled) @@ -622,6 +612,45 @@ class ComposerToolbarViewModelTests: XCTestCase { viewModel.process(viewAction: .sendMessage) try await deferred.fulfill() } + + func testRestoreDoesntOverwriteInitialText() async { + let sharedText = "Some shared text" + let expectation = expectation(description: "Wait for draft to be restored") + expectation.isInverted = true + setUpViewModel(initialText: sharedText) { + defer { expectation.fulfill() } + return .success(.init(plainText: "Hello world!", + htmlText: nil, + draftType: .newMessage)) + } + viewModel.context.composerFormattingEnabled = false + await viewModel.loadDraft() + + await fulfillment(of: [expectation], timeout: 1) + XCTAssertFalse(viewModel.context.composerFormattingEnabled) + XCTAssertEqual(viewModel.state.composerMode, .default) + XCTAssertEqual(viewModel.context.plainComposerText, NSAttributedString(string: sharedText)) + } + + // MARK: - Helpers + + private func setUpViewModel(initialText: String? = nil, loadDraftClosure: (() async -> Result)? = nil) { + wysiwygViewModel = WysiwygComposerViewModel() + completionSuggestionServiceMock = CompletionSuggestionServiceMock(configuration: .init()) + draftServiceMock = ComposerDraftServiceMock() + if let loadDraftClosure { + draftServiceMock.loadDraftClosure = loadDraftClosure + } + + viewModel = ComposerToolbarViewModel(initialText: initialText, + wysiwygViewModel: wysiwygViewModel, + completionSuggestionService: completionSuggestionServiceMock, + mediaProvider: MediaProviderMock(configuration: .init()), + mentionDisplayHelper: ComposerMentionDisplayHelper.mock, + analyticsService: ServiceLocator.shared.analytics, + composerDraftService: draftServiceMock) + viewModel.context.composerFormattingEnabled = true + } } private extension MentionSuggestionItem { diff --git a/UnitTests/Sources/RoomFlowCoordinatorTests.swift b/UnitTests/Sources/RoomFlowCoordinatorTests.swift index 6e2534b889..4ec720826e 100644 --- a/UnitTests/Sources/RoomFlowCoordinatorTests.swift +++ b/UnitTests/Sources/RoomFlowCoordinatorTests.swift @@ -218,7 +218,7 @@ class RoomFlowCoordinatorTests: XCTestCase { XCTAssert(navigationStackCoordinator.stackCoordinators.first is RoomScreenCoordinator) } - func testShareRoute() async throws { + func testShareMediaRoute() async throws { await setupRoomFlowCoordinator() try await process(route: .room(roomID: "1", via: [])) @@ -243,6 +243,31 @@ class RoomFlowCoordinatorTests: XCTestCase { XCTAssertTrue((navigationStackCoordinator.sheetCoordinator as? NavigationStackCoordinator)?.rootCoordinator is MediaUploadPreviewScreenCoordinator) } + func testShareTextRoute() async throws { + await setupRoomFlowCoordinator() + + try await process(route: .room(roomID: "1", via: [])) + XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) + XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) + + let sharePayload: ShareExtensionPayload = .text(roomID: "1", text: "Important text") + try await process(route: .share(sharePayload)) + + XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator) + XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) + + XCTAssertNil(navigationStackCoordinator.sheetCoordinator, "The media upload sheet shouldn't be shown when sharing text.") + + try await process(route: .childRoom(roomID: "2", via: [])) + XCTAssertNil(navigationStackCoordinator.sheetCoordinator) + XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 1) + + try await process(route: .share(sharePayload)) + + XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0) + XCTAssertNil(navigationStackCoordinator.sheetCoordinator, "The media upload sheet shouldn't be shown when sharing text.") + } + // MARK: - Private private func process(route: AppRoute) async throws { diff --git a/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift b/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift index 30ed610786..be295696a1 100644 --- a/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift +++ b/UnitTests/Sources/UserSessionFlowCoordinatorTests.swift @@ -242,7 +242,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase { "A new timeline should be created for the same room ID, so that the screen isn't stale while loading.") } - func testShareRouteWithoutRoom() async throws { + func testShareMediaRouteWithoutRoom() async throws { try await process(route: .settings, expectedState: .settingsScreen(selectedRoomID: nil)) XCTAssertTrue((splitCoordinator?.sheetCoordinator as? NavigationStackCoordinator)?.rootCoordinator is SettingsScreenCoordinator) @@ -253,7 +253,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase { XCTAssertTrue((splitCoordinator?.sheetCoordinator as? NavigationStackCoordinator)?.rootCoordinator is RoomSelectionScreenCoordinator) } - func testShareRouteWithRoom() async throws { + func testShareMediaRouteWithRoom() async throws { try await process(route: .event(eventID: "1", roomID: "1", via: []), expectedState: .roomList(selectedRoomID: "1")) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) @@ -265,6 +265,29 @@ class UserSessionFlowCoordinatorTests: XCTestCase { XCTAssertTrue((splitCoordinator?.sheetCoordinator as? NavigationStackCoordinator)?.rootCoordinator is MediaUploadPreviewScreenCoordinator) } + func testShareTextRouteWithoutRoom() async throws { + try await process(route: .settings, expectedState: .settingsScreen(selectedRoomID: nil)) + XCTAssertTrue((splitCoordinator?.sheetCoordinator as? NavigationStackCoordinator)?.rootCoordinator is SettingsScreenCoordinator) + + let sharePayload: ShareExtensionPayload = .text(roomID: nil, text: "Important Text") + try await process(route: .share(sharePayload), + expectedState: .shareExtensionRoomList(sharePayload: sharePayload)) + + XCTAssertTrue((splitCoordinator?.sheetCoordinator as? NavigationStackCoordinator)?.rootCoordinator is RoomSelectionScreenCoordinator) + } + + func testShareTextRouteWithRoom() async throws { + try await process(route: .event(eventID: "1", roomID: "1", via: []), expectedState: .roomList(selectedRoomID: "1")) + XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) + + let sharePayload: ShareExtensionPayload = .text(roomID: "2", text: "Important text") + try await process(route: .share(sharePayload), + expectedState: .roomList(selectedRoomID: "2")) + + XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) + XCTAssertNil(splitCoordinator?.sheetCoordinator, "The media upload sheet shouldn't be shown when sharing text.") + } + // MARK: - Private private func process(route: AppRoute, expectedState: UserSessionFlowCoordinatorStateMachine.State) async throws { From 7e1476d973039a4259117729da0f4feb53521ff8 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Thu, 21 Nov 2024 18:18:27 +0000 Subject: [PATCH 46/74] Add support for adding/editing/removing media captions. (#3547) * Add support for editing media captions. * Add composer snapshots. * PR comment. --- .../en.lproj/Localizable.strings | 5 ++ ElementX/Sources/Generated/Strings.swift | 10 +++ .../Mocks/Generated/GeneratedMocks.swift | 8 +-- .../ComposerToolbarModels.swift | 4 +- .../ComposerToolbarViewModel.swift | 4 +- .../View/MessageComposer.swift | 27 +++++--- .../Timeline/TimelineInteractionHandler.swift | 63 +++++++++++-------- .../Screens/Timeline/TimelineViewModel.swift | 8 ++- .../ItemMenu/TimelineItemMenuAction.swift | 13 +++- .../TimelineItemMenuActionProvider.swift | 10 ++- .../MockRoomTimelineController.swift | 7 +++ .../RoomTimelineController.swift | 30 ++++++++- .../RoomTimelineControllerProtocol.swift | 7 +++ ...ventBasedMessageTimelineItemProtocol.swift | 9 +++ .../Services/Timeline/TimelineProxy.swift | 4 +- .../Timeline/TimelineProxyProtocol.swift | 2 +- .../test_messageComposer-iPad-en-GB.1.png | 4 +- .../test_messageComposer-iPad-pseudo.1.png | 4 +- ...test_messageComposer-iPhone-16-en-GB.1.png | 4 +- ...est_messageComposer-iPhone-16-pseudo.1.png | 4 +- .../ComposerToolbarViewModelTests.swift | 12 ++-- 21 files changed, 178 insertions(+), 61 deletions(-) diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 1058c72968..a9efc2209c 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Record voice message."; "a11y_voice_message_stop_recording" = "Stop recording"; "action_accept" = "Accept"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Add to timeline"; "action_back" = "Back"; "action_call" = "Call"; @@ -47,6 +48,7 @@ "action_discard" = "Discard"; "action_done" = "Done"; "action_edit" = "Edit"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Edit poll"; "action_enable" = "Enable"; "action_end_poll" = "End poll"; @@ -81,6 +83,7 @@ "action_react" = "React"; "action_reject" = "Reject"; "action_remove" = "Remove"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Reply"; "action_reply_in_thread" = "Reply in thread"; "action_report_bug" = "Report bug"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Set up recovery to protect your account"; "common_about" = "About"; "common_acceptable_use_policy" = "Acceptable use policy"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Advanced settings"; "common_analytics" = "Analytics"; "common_appearance" = "Appearance"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Direct chat"; "common_edited_suffix" = "(edited)"; "common_editing" = "Editing"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "Encryption enabled"; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 5eab6c3017..1d45cfdbb8 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -76,6 +76,8 @@ internal enum L10n { internal static var a11yVoiceMessageStopRecording: String { return L10n.tr("Localizable", "a11y_voice_message_stop_recording") } /// Accept internal static var actionAccept: String { return L10n.tr("Localizable", "action_accept") } + /// Add caption + internal static var actionAddCaption: String { return L10n.tr("Localizable", "action_add_caption") } /// Add to timeline internal static var actionAddToTimeline: String { return L10n.tr("Localizable", "action_add_to_timeline") } /// Back @@ -126,6 +128,8 @@ internal enum L10n { internal static var actionDone: String { return L10n.tr("Localizable", "action_done") } /// Edit internal static var actionEdit: String { return L10n.tr("Localizable", "action_edit") } + /// Edit caption + internal static var actionEditCaption: String { return L10n.tr("Localizable", "action_edit_caption") } /// Edit poll internal static var actionEditPoll: String { return L10n.tr("Localizable", "action_edit_poll") } /// Enable @@ -198,6 +202,8 @@ internal enum L10n { internal static var actionReject: String { return L10n.tr("Localizable", "action_reject") } /// Remove internal static var actionRemove: String { return L10n.tr("Localizable", "action_remove") } + /// Remove caption + internal static var actionRemoveCaption: String { return L10n.tr("Localizable", "action_remove_caption") } /// Reply internal static var actionReply: String { return L10n.tr("Localizable", "action_reply") } /// Reply in thread @@ -276,6 +282,8 @@ internal enum L10n { internal static var commonAbout: String { return L10n.tr("Localizable", "common_about") } /// Acceptable use policy internal static var commonAcceptableUsePolicy: String { return L10n.tr("Localizable", "common_acceptable_use_policy") } + /// Adding caption + internal static var commonAddingCaption: String { return L10n.tr("Localizable", "common_adding_caption") } /// Advanced settings internal static var commonAdvancedSettings: String { return L10n.tr("Localizable", "common_advanced_settings") } /// Analytics @@ -312,6 +320,8 @@ internal enum L10n { internal static var commonEditedSuffix: String { return L10n.tr("Localizable", "common_edited_suffix") } /// Editing internal static var commonEditing: String { return L10n.tr("Localizable", "common_editing") } + /// Editing caption + internal static var commonEditingCaption: String { return L10n.tr("Localizable", "common_editing_caption") } /// * %1$@ %2$@ internal static func commonEmote(_ p1: Any, _ p2: Any) -> String { return L10n.tr("Localizable", "common_emote", String(describing: p1), String(describing: p2)) diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index a8def51e01..45e2fd5d50 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -14133,8 +14133,8 @@ class TimelineProxyMock: TimelineProxyProtocol { var editNewContentCalled: Bool { return editNewContentCallsCount > 0 } - var editNewContentReceivedArguments: (eventOrTransactionID: EventOrTransactionId, newContent: RoomMessageEventContentWithoutRelation)? - var editNewContentReceivedInvocations: [(eventOrTransactionID: EventOrTransactionId, newContent: RoomMessageEventContentWithoutRelation)] = [] + var editNewContentReceivedArguments: (eventOrTransactionID: EventOrTransactionId, newContent: EditedContent)? + var editNewContentReceivedInvocations: [(eventOrTransactionID: EventOrTransactionId, newContent: EditedContent)] = [] var editNewContentUnderlyingReturnValue: Result! var editNewContentReturnValue: Result! { @@ -14160,9 +14160,9 @@ class TimelineProxyMock: TimelineProxyProtocol { } } } - var editNewContentClosure: ((EventOrTransactionId, RoomMessageEventContentWithoutRelation) async -> Result)? + var editNewContentClosure: ((EventOrTransactionId, EditedContent) async -> Result)? - func edit(_ eventOrTransactionID: EventOrTransactionId, newContent: RoomMessageEventContentWithoutRelation) async -> Result { + func edit(_ eventOrTransactionID: EventOrTransactionId, newContent: EditedContent) async -> Result { editNewContentCallsCount += 1 editNewContentReceivedArguments = (eventOrTransactionID: eventOrTransactionID, newContent: newContent) DispatchQueue.main.async { diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarModels.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarModels.swift index 3459fb1c81..bfc6767a2b 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarModels.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarModels.swift @@ -284,9 +284,11 @@ extension FormatType { } enum ComposerMode: Equatable { + enum EditType { case `default`, addCaption, editCaption } + case `default` case reply(eventID: String, replyDetails: TimelineItemReplyDetails, isThread: Bool) - case edit(originalEventOrTransactionID: EventOrTransactionId) + case edit(originalEventOrTransactionID: EventOrTransactionId, type: EditType) case recordVoiceMessage(state: AudioRecorderState) case previewVoiceMessage(state: AudioPlayerState, waveform: WaveformSource, isUploading: Bool) diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift index 06623b8c7a..c8e77830c2 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/ComposerToolbarViewModel.swift @@ -267,7 +267,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool case .newMessage: set(mode: .default) case .edit(let eventID): - set(mode: .edit(originalEventOrTransactionID: .eventId(eventId: eventID))) + set(mode: .edit(originalEventOrTransactionID: .eventId(eventId: eventID), type: .default)) case .reply(let eventID): set(mode: .reply(eventID: eventID, replyDetails: .loading(eventID: eventID), isThread: false)) replyLoadingTask = Task { @@ -323,7 +323,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool switch state.composerMode { case .default: type = .newMessage - case .edit(.eventId(let originalEventID)): + case .edit(.eventId(let originalEventID), .default): type = .edit(eventID: originalEventID) case .reply(let eventID, _, _): type = .reply(eventID: eventID) diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift index 89f8903d07..0662cc0076 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift @@ -82,8 +82,8 @@ struct MessageComposer: View { switch mode { case .reply(_, let replyDetails, _): MessageComposerReplyHeader(replyDetails: replyDetails, action: cancellationAction) - case .edit: - MessageComposerEditHeader(action: cancellationAction) + case .edit(_, let editType): + MessageComposerEditHeader(editType: editType, action: cancellationAction) case .recordVoiceMessage, .previewVoiceMessage, .default: EmptyView() } @@ -152,14 +152,20 @@ private struct MessageComposerReplyHeader: View { } private struct MessageComposerEditHeader: View { + let editType: ComposerMode.EditType let action: () -> Void + private var title: String { + switch editType { + case .default: L10n.commonEditing + case .addCaption: L10n.commonAddingCaption + case .editCaption: L10n.commonEditingCaption + } + } + var body: some View { HStack(alignment: .center, spacing: 8) { - Label(L10n.commonEditing, - icon: \.editSolid, - iconSize: .xSmall, - relativeTo: .compound.bodySMSemibold) + Label(title, icon: \.editSolid, iconSize: .xSmall, relativeTo: .compound.bodySMSemibold) .labelStyle(MessageComposerHeaderLabelStyle()) Spacer() Button(action: action) { @@ -294,13 +300,20 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview { messageComposer() messageComposer(.init(string: "Some message"), - mode: .edit(originalEventOrTransactionID: .eventId(eventId: UUID().uuidString))) + mode: .edit(originalEventOrTransactionID: .eventId(eventId: UUID().uuidString), type: .default)) messageComposer(mode: .reply(eventID: UUID().uuidString, replyDetails: .loaded(sender: .init(id: "Kirk"), eventID: "123", eventContent: .message(.text(.init(body: "Text: Where the wild things are")))), isThread: false)) + + Color.clear.frame(height: 20) + + messageComposer(.init(string: "Some new caption"), + mode: .edit(originalEventOrTransactionID: .eventId(eventId: UUID().uuidString), type: .addCaption)) + messageComposer(.init(string: "Some updated caption"), + mode: .edit(originalEventOrTransactionID: .eventId(eventId: UUID().uuidString), type: .editCaption)) } .padding(.horizontal) diff --git a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift index e21ee3b4a7..18e6ef0ee8 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift @@ -100,10 +100,7 @@ class TimelineInteractionHandler { switch action { case .copy: - guard let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol else { - return - } - + guard let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol else { return } UIPasteboard.general.string = messageTimelineItem.body case .edit: switch timelineItem { @@ -118,6 +115,19 @@ class TimelineInteractionHandler { default: MXLog.error("Cannot edit item with id: \(timelineItem.id)") } + case .addCaption, .editCaption: + switch timelineItem { + case let messageTimelineItem as EventBasedMessageTimelineItemProtocol: + processEditMessageEvent(messageTimelineItem) + default: + MXLog.error("Cannot add/edit caption on item with id: \(timelineItem.id)") + } + case .removeCaption: + guard case let .event(_, eventOrTransactionID) = timelineItem.id else { + MXLog.error("Failed removing caption, missing event ID") + return + } + Task { await timelineController.removeCaption(eventOrTransactionID) } case .copyPermalink: guard let eventID = eventTimelineItem.id.eventID else { actionsSubject.send(.displayErrorToast(L10n.errorFailedCreatingThePermalink)) @@ -133,17 +143,10 @@ class TimelineInteractionHandler { UIPasteboard.general.url = permalinkURL } case .redact: - guard case let .event(_, eventOrTransactionID) = itemID else { - fatalError() - } - - Task { - await timelineController.redact(eventOrTransactionID) - } + guard case let .event(_, eventOrTransactionID) = itemID else { fatalError() } + Task { await timelineController.redact(eventOrTransactionID) } case .reply: - guard let eventID = eventTimelineItem.id.eventID else { - return - } + guard let eventID = eventTimelineItem.id.eventID else { return } let replyInfo = buildReplyInfo(for: eventTimelineItem) let replyDetails = TimelineItemReplyDetails.loaded(sender: eventTimelineItem.sender, eventID: eventID, eventContent: replyInfo.type) @@ -156,21 +159,14 @@ class TimelineInteractionHandler { MXLog.info("Showing debug info for \(eventTimelineItem.id)") actionsSubject.send(.showDebugInfo(debugInfo)) case .retryDecryption(let sessionID): - Task { - await timelineController.retryDecryption(for: sessionID) - } + Task { await timelineController.retryDecryption(for: sessionID) } case .report: actionsSubject.send(.displayReportContent(itemID: itemID, senderID: eventTimelineItem.sender.id)) case .react: displayEmojiPicker(for: itemID) case .toggleReaction(let key): - Task { - guard case let .event(_, eventOrTransactionID) = itemID else { - fatalError() - } - - await timelineController.toggleReaction(key, to: eventOrTransactionID) - } + guard case let .event(_, eventOrTransactionID) = itemID else { fatalError() } + Task { await timelineController.toggleReaction(key, to: eventOrTransactionID) } case .endPoll(let pollStartID): endPoll(pollStartID: pollStartID) case .pin: @@ -202,18 +198,35 @@ class TimelineInteractionHandler { let text: String var htmlText: String? + var editType = ComposerMode.EditType.default switch messageTimelineItem.contentType { case .text(let content): text = content.body htmlText = content.formattedBodyHTMLString case .emote(let content): text = "/me " + content.body + case .audio(let content): + text = content.caption ?? "" + htmlText = content.formattedCaptionHTMLString + editType = text.isEmpty ? .addCaption : .editCaption + case .file(let content): + text = content.caption ?? "" + htmlText = content.formattedCaptionHTMLString + editType = text.isEmpty ? .addCaption : .editCaption + case .image(let content): + text = content.caption ?? "" + htmlText = content.formattedCaptionHTMLString + editType = text.isEmpty ? .addCaption : .editCaption + case .video(let content): + text = content.caption ?? "" + htmlText = content.formattedCaptionHTMLString + editType = text.isEmpty ? .addCaption : .editCaption default: text = messageTimelineItem.body } // Always update the mode first and then the text so that the composer has time to save the text draft - actionsSubject.send(.composer(action: .setMode(mode: .edit(originalEventOrTransactionID: eventOrTransactionID)))) + actionsSubject.send(.composer(action: .setMode(mode: .edit(originalEventOrTransactionID: eventOrTransactionID, type: editType)))) actionsSubject.send(.composer(action: .setText(plainText: text, htmlText: htmlText))) } diff --git a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift index 94db414a07..76fb206eb9 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift @@ -606,11 +606,17 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { html: html, inReplyToEventID: eventID, intentionalMentions: intentionalMentions) - case .edit(let originalEventOrTransactionID): + case .edit(let originalEventOrTransactionID, .default): await timelineController.edit(originalEventOrTransactionID, message: message, html: html, intentionalMentions: intentionalMentions) + case .edit(let originalEventOrTransactionID, .addCaption), + .edit(let originalEventOrTransactionID, .editCaption): + await timelineController.editCaption(originalEventOrTransactionID, + message: message, + html: html, + intentionalMentions: intentionalMentions) case .default: switch slashCommand(message: message) { case .join: diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift index b6ce6d036d..38f8246225 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift @@ -57,6 +57,9 @@ struct TimelineItemMenuReaction: Hashable { enum TimelineItemMenuAction: Identifiable, Hashable { case copy case edit + case addCaption + case editCaption + case removeCaption case copyPermalink case redact case reply(isThread: Bool) @@ -76,7 +79,7 @@ enum TimelineItemMenuAction: Identifiable, Hashable { /// Whether the item should cancel a reply/edit occurring in the composer. var switchToDefaultComposer: Bool { switch self { - case .reply, .edit: + case .reply, .edit, .addCaption, .editCaption: return false default: return true @@ -106,7 +109,7 @@ enum TimelineItemMenuAction: Identifiable, Hashable { /// Whether or not the action is destructive. var isDestructive: Bool { switch self { - case .redact, .report: + case .redact, .report, .removeCaption: return true default: return false @@ -130,6 +133,12 @@ enum TimelineItemMenuAction: Identifiable, Hashable { Label(L10n.actionCopy, icon: \.copy) case .edit: Label(L10n.actionEdit, icon: \.edit) + case .addCaption: + Label(L10n.actionAddCaption, icon: \.edit) + case .editCaption: + Label(L10n.actionEditCaption, icon: \.edit) + case .removeCaption: + Label(L10n.actionRemoveCaption, icon: \.delete) case .copyPermalink: Label(L10n.actionCopyLinkToMessage, icon: \.link) case .reply(let isThread): diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift index 9fcc47575a..df74221431 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift @@ -65,7 +65,15 @@ struct TimelineItemMenuActionProvider { } if item.isEditable { - actions.append(.edit) + if let messageItem = item as? EventBasedMessageTimelineItemProtocol, messageItem.supportsMediaCaption { + if messageItem.hasMediaCaption { + actions.append(contentsOf: [.editCaption, .removeCaption]) + } else { + actions.append(.addCaption) + } + } else if !(item is VoiceMessageRoomTimelineItem) { + actions.append(.edit) + } } if canCurrentUserPin, let eventID = item.id.eventID { diff --git a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift index 0ec25915e7..b8cf4387e2 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/MockRoomTimelineController.swift @@ -91,6 +91,13 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol { html: String?, intentionalMentions: IntentionalMentions) async { } + func editCaption(_ eventOrTransactionID: EventOrTransactionId, + message: String, + html: String?, + intentionalMentions: IntentionalMentions) async { } + + func removeCaption(_ eventOrTransactionID: EventOrTransactionId) async { } + func redact(_ eventOrTransactionID: EventOrTransactionId) async { } func pin(eventID: String) async { } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift index edcf2ef221..a9abcd63ff 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift @@ -238,7 +238,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol { html: html, intentionalMentions: intentionalMentions.toRustMentions()) - switch await activeTimeline.edit(eventOrTransactionID, newContent: messageContent) { + switch await activeTimeline.edit(eventOrTransactionID, newContent: .roomMessage(content: messageContent)) { case .success: MXLog.info("Finished editing message by event") case let .failure(error): @@ -246,6 +246,34 @@ class RoomTimelineController: RoomTimelineControllerProtocol { } } + func editCaption(_ eventOrTransactionID: EventOrTransactionId, + message: String, + html: String?, + intentionalMentions: IntentionalMentions) async { + // We're waiting on an API for including mentions: https://github.com/matrix-org/matrix-rust-sdk/issues/4302 + MXLog.info("Editing timeline item caption: \(eventOrTransactionID) in \(roomID)") + + // When formattedCaption is nil, caption will be parsed as markdown and generate the HTML for us. + let newContent = createCaptionEdit(caption: message, formattedCaption: html.map { .init(format: .html, body: $0) }) + switch await activeTimeline.edit(eventOrTransactionID, newContent: newContent) { + case .success: + MXLog.info("Finished editing caption") + case let .failure(error): + MXLog.error("Failed editing caption with error: \(error)") + } + } + + func removeCaption(_ eventOrTransactionID: EventOrTransactionId) async { + // Set a `nil` caption to remove it from the event. + let newContent = createCaptionEdit(caption: nil, formattedCaption: nil) + switch await activeTimeline.edit(eventOrTransactionID, newContent: newContent) { + case .success: + MXLog.info("Finished removing caption.") + case let .failure(error): + MXLog.error("Failed removing caption with error: \(error)") + } + } + func redact(_ eventOrTransactionID: EventOrTransactionId) async { MXLog.info("Send redaction in \(roomID)") diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift index 0d13a2994a..e32356e25a 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineControllerProtocol.swift @@ -56,6 +56,13 @@ protocol RoomTimelineControllerProtocol { html: String?, intentionalMentions: IntentionalMentions) async + func editCaption(_ eventOrTransactionID: EventOrTransactionId, + message: String, + html: String?, + intentionalMentions: IntentionalMentions) async + + func removeCaption(_ eventOrTransactionID: EventOrTransactionId) async + func toggleReaction(_ reaction: String, to eventOrTransactionID: EventOrTransactionId) async func redact(_ eventOrTransactionID: EventOrTransactionId) async diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift index 6b4ae9f5ea..a0832abf5c 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift @@ -26,6 +26,15 @@ protocol EventBasedMessageTimelineItemProtocol: EventBasedTimelineItemProtocol { } extension EventBasedMessageTimelineItemProtocol { + var supportsMediaCaption: Bool { + switch contentType { + case .audio, .file, .image, .video: + true + case .emote, .notice, .text, .location, .voice: + false + } + } + var hasMediaCaption: Bool { switch contentType { case .audio(let content): diff --git a/ElementX/Sources/Services/Timeline/TimelineProxy.swift b/ElementX/Sources/Services/Timeline/TimelineProxy.swift index 0a7a1b1dca..0c2422de17 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxy.swift @@ -164,9 +164,9 @@ final class TimelineProxy: TimelineProxyProtocol { } } - func edit(_ eventOrTransactionID: EventOrTransactionId, newContent: RoomMessageEventContentWithoutRelation) async -> Result { + func edit(_ eventOrTransactionID: EventOrTransactionId, newContent: EditedContent) async -> Result { do { - try await timeline.edit(eventOrTransactionId: eventOrTransactionID, newContent: .roomMessage(content: newContent)) + try await timeline.edit(eventOrTransactionId: eventOrTransactionID, newContent: newContent) MXLog.info("Finished editing timeline item: \(eventOrTransactionID)") diff --git a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift index d0d5285fb2..3bff76ecba 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift @@ -38,7 +38,7 @@ protocol TimelineProxyProtocol { func paginateForwards(requestSize: UInt16) async -> Result func edit(_ eventOrTransactionID: EventOrTransactionId, - newContent: RoomMessageEventContentWithoutRelation) async -> Result + newContent: EditedContent) async -> Result func redact(_ eventOrTransactionID: EventOrTransactionId, reason: String?) async -> Result diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png index aee9e9b7d3..20eb21a0c4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a5e7e651f73e10b1b7c5fad0a3eb631d9f50f5f42286f1faaed852316dd287d -size 98836 +oid sha256:389426d51309b08493728679fe367ca3469d0f7962423c10ea3b2b599685599c +size 125743 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png index 61a955e37b..3f2e93a144 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4914f7dc335cc0333584c2ad34034ce5a28e6fb3bb52d05f27734ed2dae5e7a6 -size 99876 +oid sha256:037ea34c80269e1a2761710c061aad688fbdf32d41b667c01b83ef027f9ea319 +size 129460 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png index a28707e06c..f33e3e05a1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9951096cb1ddc3050415353192108a4489908d8355b30189845a7da5fa2b5d83 -size 55103 +oid sha256:a55833e52c9f9bee6ba1b5162f69f3f650ae7a1965ff89f03533e7b8b40cabd4 +size 76082 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png index bda11829e5..4619c54083 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:745116e5588711197b37e391b2f2ca6359c9a4cb8b3dd718ec55dd29c33d72a1 -size 57224 +oid sha256:a934bf0353d41916807d166a1b49b8cb9732a2fd791605a0c3ffdbac387fab8a +size 80923 diff --git a/UnitTests/Sources/ComposerToolbarViewModelTests.swift b/UnitTests/Sources/ComposerToolbarViewModelTests.swift index 1c9327fd98..f1a1123282 100644 --- a/UnitTests/Sources/ComposerToolbarViewModelTests.swift +++ b/UnitTests/Sources/ComposerToolbarViewModelTests.swift @@ -31,14 +31,14 @@ class ComposerToolbarViewModelTests: XCTestCase { } func testComposerFocus() { - viewModel.process(timelineAction: .setMode(mode: .edit(originalEventOrTransactionID: .eventId(eventId: "mock")))) + viewModel.process(timelineAction: .setMode(mode: .edit(originalEventOrTransactionID: .eventId(eventId: "mock"), type: .default))) XCTAssertTrue(viewModel.state.bindings.composerFocused) viewModel.process(timelineAction: .removeFocus) XCTAssertFalse(viewModel.state.bindings.composerFocused) } func testComposerMode() { - let mode: ComposerMode = .edit(originalEventOrTransactionID: .eventId(eventId: "mock")) + let mode: ComposerMode = .edit(originalEventOrTransactionID: .eventId(eventId: "mock"), type: .default) viewModel.process(timelineAction: .setMode(mode: mode)) XCTAssertEqual(viewModel.state.composerMode, mode) viewModel.process(timelineAction: .clear) @@ -46,7 +46,7 @@ class ComposerToolbarViewModelTests: XCTestCase { } func testComposerModeIsPublished() { - let mode: ComposerMode = .edit(originalEventOrTransactionID: .eventId(eventId: "mock")) + let mode: ComposerMode = .edit(originalEventOrTransactionID: .eventId(eventId: "mock"), type: .default) let expectation = expectation(description: "Composer mode is published") let cancellable = viewModel .context @@ -226,7 +226,7 @@ class ComposerToolbarViewModelTests: XCTestCase { } viewModel.context.composerFormattingEnabled = false - viewModel.process(timelineAction: .setMode(mode: .edit(originalEventOrTransactionID: .eventId(eventId: "testID")))) + viewModel.process(timelineAction: .setMode(mode: .edit(originalEventOrTransactionID: .eventId(eventId: "testID"), type: .default))) viewModel.context.plainComposerText = .init(string: "Hello world!") viewModel.saveDraft() @@ -385,7 +385,7 @@ class ComposerToolbarViewModelTests: XCTestCase { await fulfillment(of: [expectation], timeout: 10) XCTAssertFalse(viewModel.context.composerFormattingEnabled) - XCTAssertEqual(viewModel.state.composerMode, .edit(originalEventOrTransactionID: .eventId(eventId: "testID"))) + XCTAssertEqual(viewModel.state.composerMode, .edit(originalEventOrTransactionID: .eventId(eventId: "testID"), type: .default)) XCTAssertEqual(viewModel.context.plainComposerText, NSAttributedString(string: "Hello world!")) } @@ -473,7 +473,7 @@ class ComposerToolbarViewModelTests: XCTestCase { func testSaveVolatileDraftWhenEditing() { viewModel.context.composerFormattingEnabled = false viewModel.context.plainComposerText = .init(string: "Hello world!") - viewModel.process(timelineAction: .setMode(mode: .edit(originalEventOrTransactionID: .eventId(eventId: UUID().uuidString)))) + viewModel.process(timelineAction: .setMode(mode: .edit(originalEventOrTransactionID: .eventId(eventId: UUID().uuidString), type: .default))) let draft = draftServiceMock.saveVolatileDraftReceivedDraft XCTAssertNotNil(draft) From e315451448a209027e02527d54e87c763a373e2d Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Thu, 21 Nov 2024 20:14:05 +0100 Subject: [PATCH 47/74] Knock Requests List Screen (#3533) * created the basic navigation and files * updated the logic so that the buttons that do not have permissions won't show * added the empty state * progress in making the list UI * update tests * UI improvements * fixed an issue with media provider * update button style * fixed a navigation bug * pr suggestions * pr suggestions --- ElementX.xcodeproj/project.pbxproj | 28 ++++ .../en.lproj/Localizable.strings | 4 + .../RoomFlowCoordinator.swift | 30 ++++ ElementX/Sources/Generated/Strings.swift | 8 + .../KnockRequestsListScreenCoordinator.swift | 45 ++++++ .../KnockRequestsListScreenModels.swift | 24 +++ .../KnockRequestsListScreenViewModel.swift | 75 +++++++++ ...kRequestsListScreenViewModelProtocol.swift | 14 ++ .../View/KnockRequestCell.swift | 147 +++++++++++------- .../KnockRequestsListEmptyStateView.swift | 38 +++++ .../View/KnockRequestsListScreen.swift | 96 ++++++++++++ .../RoomDetailsScreenCoordinator.swift | 3 + .../RoomDetailsScreenModels.swift | 9 ++ .../RoomDetailsScreenViewModel.swift | 8 + .../View/RoomDetailsScreen.swift | 11 ++ .../View/KnockRequestsBannerView.swift | 31 ++-- .../Sources/GeneratedPreviewTests.swift | 12 ++ ...nockRequestCell-iPad-en-GB.Long-reason.png | 4 +- ...tCell-iPad-en-GB.No-Accept-and-Decline.png | 3 + ..._knockRequestCell-iPad-en-GB.No-Accept.png | 3 + ...est_knockRequestCell-iPad-en-GB.No-Ban.png | 3 + ...st_knockRequestCell-iPad-en-GB.No-name.png | 4 +- ..._knockRequestCell-iPad-en-GB.No-reason.png | 4 +- ...ockRequestCell-iPad-en-GB.Short-reason.png | 4 +- ...ockRequestCell-iPad-pseudo.Long-reason.png | 4 +- ...Cell-iPad-pseudo.No-Accept-and-Decline.png | 3 + ...knockRequestCell-iPad-pseudo.No-Accept.png | 3 + ...st_knockRequestCell-iPad-pseudo.No-Ban.png | 3 + ...t_knockRequestCell-iPad-pseudo.No-name.png | 4 +- ...knockRequestCell-iPad-pseudo.No-reason.png | 4 +- ...ckRequestCell-iPad-pseudo.Short-reason.png | 4 +- ...equestCell-iPhone-16-en-GB.Long-reason.png | 4 +- ...-iPhone-16-en-GB.No-Accept-and-Decline.png | 3 + ...kRequestCell-iPhone-16-en-GB.No-Accept.png | 3 + ...nockRequestCell-iPhone-16-en-GB.No-Ban.png | 3 + ...ockRequestCell-iPhone-16-en-GB.No-name.png | 4 +- ...kRequestCell-iPhone-16-en-GB.No-reason.png | 4 +- ...questCell-iPhone-16-en-GB.Short-reason.png | 4 +- ...questCell-iPhone-16-pseudo.Long-reason.png | 4 +- ...iPhone-16-pseudo.No-Accept-and-Decline.png | 3 + ...RequestCell-iPhone-16-pseudo.No-Accept.png | 3 + ...ockRequestCell-iPhone-16-pseudo.No-Ban.png | 3 + ...ckRequestCell-iPhone-16-pseudo.No-name.png | 4 +- ...RequestCell-iPhone-16-pseudo.No-reason.png | 4 +- ...uestCell-iPhone-16-pseudo.Short-reason.png | 4 +- ...annerView-iPad-en-GB.Multiple-Requests.png | 4 +- ...d-en-GB.Single-Request-No-Display-Name.png | 4 +- ...-en-GB.Single-Request-no-accept-action.png | 3 + ...-iPad-en-GB.Single-Request-with-reason.png | 4 +- ...tsBannerView-iPad-en-GB.Single-Request.png | 4 +- ...nnerView-iPad-pseudo.Multiple-Requests.png | 4 +- ...-pseudo.Single-Request-No-Display-Name.png | 4 +- ...pseudo.Single-Request-no-accept-action.png | 3 + ...iPad-pseudo.Single-Request-with-reason.png | 4 +- ...sBannerView-iPad-pseudo.Single-Request.png | 4 +- ...View-iPhone-16-en-GB.Multiple-Requests.png | 4 +- ...6-en-GB.Single-Request-No-Display-Name.png | 4 +- ...-en-GB.Single-Request-no-accept-action.png | 3 + ...ne-16-en-GB.Single-Request-with-reason.png | 4 +- ...nerView-iPhone-16-en-GB.Single-Request.png | 4 +- ...iew-iPhone-16-pseudo.Multiple-Requests.png | 4 +- ...-pseudo.Single-Request-No-Display-Name.png | 4 +- ...pseudo.Single-Request-no-accept-action.png | 3 + ...e-16-pseudo.Single-Request-with-reason.png | 4 +- ...erView-iPhone-16-pseudo.Single-Request.png | 4 +- ...equestsListEmptyStateView-iPad-en-GB.1.png | 3 + ...questsListEmptyStateView-iPad-pseudo.1.png | 3 + ...tsListEmptyStateView-iPhone-16-en-GB.1.png | 3 + ...sListEmptyStateView-iPhone-16-pseudo.1.png | 3 + ...t_knockRequestsListScreen-iPad-en-GB.1.png | 3 + ...uestsListScreen-iPad-en-GB.Empty-state.png | 3 + ..._knockRequestsListScreen-iPad-pseudo.1.png | 3 + ...estsListScreen-iPad-pseudo.Empty-state.png | 3 + ...ckRequestsListScreen-iPhone-16-en-GB.1.png | 3 + ...ListScreen-iPhone-16-en-GB.Empty-state.png | 3 + ...kRequestsListScreen-iPhone-16-pseudo.1.png | 3 + ...istScreen-iPhone-16-pseudo.Empty-state.png | 3 + ...mDetailsScreen-iPad-en-GB.Generic-Room.png | 4 +- ...omDetailsScreen-iPad-en-GB.Simple-Room.png | 4 +- ...DetailsScreen-iPad-pseudo.Generic-Room.png | 4 +- ...mDetailsScreen-iPad-pseudo.Simple-Room.png | 4 +- ...ilsScreen-iPhone-16-en-GB.Generic-Room.png | 4 +- ...ailsScreen-iPhone-16-en-GB.Simple-Room.png | 4 +- ...lsScreen-iPhone-16-pseudo.Generic-Room.png | 4 +- ...nockRequestsListScreenViewModelTests.swift | 23 +++ 85 files changed, 701 insertions(+), 145 deletions(-) create mode 100644 ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift create mode 100644 ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift create mode 100644 ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift create mode 100644 ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModelProtocol.swift create mode 100644 ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListEmptyStateView.swift create mode 100644 ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Accept-and-Decline.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Accept.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Ban.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Accept-and-Decline.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Accept.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Ban.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Accept-and-Decline.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Accept.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Ban.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Accept-and-Decline.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Accept.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Ban.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-no-accept-action.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-no-accept-action.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-no-accept-action.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-no-accept-action.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPad-en-GB.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPad-pseudo.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPhone-16-en-GB.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPhone-16-pseudo.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.Empty-state.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.Empty-state.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.Empty-state.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.1.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.Empty-state.png create mode 100644 UnitTests/Sources/KnockRequestsListScreenViewModelTests.swift diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 679037fdd7..ec24800e13 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -30,6 +30,7 @@ 024E70451A7CD9E4E034D8A9 /* VoiceMessageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D529B976F8B2AA654D923422 /* VoiceMessageRoomTimelineItem.swift */; }; 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 */; }; 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 */; }; @@ -548,6 +549,7 @@ 755727E0B756430DFFEC4732 /* SessionVerificationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF05DA24F71B455E8EFEBC3B /* SessionVerificationViewModelTests.swift */; }; 756EA0D663261889EF64E6D4 /* VoiceMessageRecordingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9CBF577B9711CFBB4FA40D /* VoiceMessageRecordingView.swift */; }; 7573D682F089205F7F1D96CF /* SessionDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C2067FF58B4996323EB40C /* SessionDirectories.swift */; }; + 75ED4B73983228BB6922CE3C /* KnockRequestsListScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A5C217DD0749EC709EED028 /* KnockRequestsListScreenViewModelProtocol.swift */; }; 762DAF94846C7AC8550F1CC1 /* MediaPlayerProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5E23D8EE6CBACF32F1EC874 /* MediaPlayerProviderProtocol.swift */; }; 762DB0973865293F0C3D3D7B /* SessionVerificationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */; }; 763D69741D58D2B650BC1FC9 /* CallScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F37FA1A5D55633E1942B153B /* CallScreenCoordinator.swift */; }; @@ -755,6 +757,7 @@ 9DE801D278AC34737467F937 /* VoiceMessageMediaManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 889DEDD63C68ABDA8AD29812 /* VoiceMessageMediaManagerProtocol.swift */; }; 9E838A62918E47BC72D6640D /* UserIndicatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AB54B4F94686CCF0289B72F /* UserIndicatorPresenter.swift */; }; 9EBDC79CAC9B63A0D626E333 /* LegalInformationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EB2CAA266B921D128C35710 /* LegalInformationScreenCoordinator.swift */; }; + 9EE71509E6E7519A2B2388B3 /* KnockRequestsListScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD9C9A31D9AB3B6D8128E69 /* KnockRequestsListScreenModels.swift */; }; 9EF9773DBE3F6497A25CE236 /* test_apple_image.heic in Resources */ = {isa = PBXBuildFile; fileRef = F6B676B4866F5B383DE819B2 /* test_apple_image.heic */; }; 9F11B9F347F9E2D236799FB3 /* ElementCallServiceConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 406C90AF8C3E98DF5D4E5430 /* ElementCallServiceConstants.swift */; }; 9F11E743EA01482E78A438B0 /* GlobalSearchScreenCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DB19219E6CC4D002E15D48 /* GlobalSearchScreenCell.swift */; }; @@ -765,6 +768,7 @@ A009BDFB0A6816D4C392ADCB /* SettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */; }; A021827B528F1EDC9101CA58 /* AppCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBC776F301D374A3298C69DA /* AppCoordinatorProtocol.swift */; }; A0601810597769B81C2358AF /* EncryptionResetPasswordScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A2B5274C1D3D2999D643786 /* EncryptionResetPasswordScreenViewModelProtocol.swift */; }; + A0861B727B273B5B3DD7FBF6 /* KnockRequestsListScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09227E671DB30795C43FFFD /* KnockRequestsListScreenViewModel.swift */; }; A0868BDE84D2140A885BE3C9 /* EncryptionResetScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E8562F4D7DE073BC32902AB /* EncryptionResetScreenViewModelProtocol.swift */; }; A0D7E5BD0298A97DCBDCE40B /* Emojibase in Frameworks */ = {isa = PBXBuildFile; productRef = C05729B1684C331F5FFE9232 /* Emojibase */; }; A10D6CCDE2010C09EEA1A593 /* HomeScreenRoomList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7661EFFCAA307A97D71132A /* HomeScreenRoomList.swift */; }; @@ -802,6 +806,7 @@ A6F345328CCC5C9B0DAE2257 /* LogViewerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB05221D7D941CC82DC8480 /* LogViewerScreenViewModel.swift */; }; A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; }; A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; }; + A756F17A2CEDFF9700128047 /* KnockRequestsListEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A756F1792CEDFF7300128047 /* KnockRequestsListEmptyStateView.swift */; }; A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; A808DC3F72D15C6C5A52317E /* TimelineItemDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCDA016D05107DED3B9495CB /* TimelineItemDebugView.swift */; }; A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; }; @@ -816,6 +821,7 @@ AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10CC626F97AD70FF0420C115 /* RoomSummaryProviderProtocol.swift */; }; AA5924D3B67F7ACD98BBEFDC /* OrientationManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4756240773D26AB74C22668 /* OrientationManagerProtocol.swift */; }; AA93B3F9B5DD097DEF79F981 /* NotificationSettingsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBB0328F2887BF0A65BC5D49 /* NotificationSettingsEditScreen.swift */; }; + AAA551AD8768309024D4907B /* KnockRequestsListScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1511B1DCECC0DC75EB267328 /* KnockRequestsListScreen.swift */; }; AADE7C2497A7B55D8BED7BD6 /* IdentityConfirmedScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8319173DD66C07F45DC48848 /* IdentityConfirmedScreenViewModelProtocol.swift */; }; AAF0BBED840DF4A53EE85E77 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = C2C69B8BA5A9702E7A8BC08F /* MatrixRustSDK */; }; ABD29E06DD1224812E750AF8 /* ReadReceiptCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D75941CBD7D336F831924EC /* ReadReceiptCell.swift */; }; @@ -880,6 +886,7 @@ B9CB30FED3E29D2036EA3FCC /* DeveloperOptionsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54C4E7B46099462F12000C91 /* DeveloperOptionsScreenViewModelProtocol.swift */; }; BA31448FBD9697F8CB9A83CD /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E2245243369B99216C7D84E /* ImageCache.swift */; }; BA43D782BE85C7F5F20C624A /* AttributedStringBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */; }; + BA48D6AFF6421D199148C0A1 /* KnockRequestsListScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9AC2CC94FA06F728883B694 /* KnockRequestsListScreenViewModelTests.swift */; }; BA4C9049BC96DED3A2F3B82E /* RoomNotificationSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */; }; BAC845780F17CCFBC5A9CA37 /* AppLockUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */; }; BB04B1D8E7401C90506D401E /* QRCodeLoginServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536C0E2178949B290776EA4E /* QRCodeLoginServiceProtocol.swift */; }; @@ -1358,6 +1365,7 @@ 13BE9781699FB510E9263192 /* AppSettingsHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettingsHook.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 = ""; }; 1562EAF6231151A675BED7A9 /* RoomDirectorySearchScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreenCoordinator.swift; sourceTree = ""; }; 15748C254911E3654C93B0ED /* MentionBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionBuilder.swift; sourceTree = ""; }; 1575947B7A6FE08C57FE5EE4 /* NetworkMonitorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitorProtocol.swift; sourceTree = ""; }; @@ -1747,6 +1755,7 @@ 69CB8242D69B7E4D0B32E18D /* AggregatedReactionMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AggregatedReactionMock.swift; sourceTree = ""; }; 69D42EE0102D2857933625DD /* CreateRoomViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomViewModelTests.swift; sourceTree = ""; }; 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoPlistReader.swift; sourceTree = ""; }; + 6A5C217DD0749EC709EED028 /* KnockRequestsListScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListScreenViewModelProtocol.swift; sourceTree = ""; }; 6A8E19C4645D3F5F9FB02355 /* UnitTestsAppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitTestsAppCoordinator.swift; sourceTree = ""; }; 6AB54B4F94686CCF0289B72F /* UserIndicatorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorPresenter.swift; sourceTree = ""; }; 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegex.swift; sourceTree = ""; }; @@ -1893,6 +1902,7 @@ 8AE78FA0011E07920AE83135 /* PlainMentionBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlainMentionBuilder.swift; sourceTree = ""; }; 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaLoader.swift; sourceTree = ""; }; 8BCCE3D12B0A9C6E559B5B5A /* EmojiProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderProtocol.swift; sourceTree = ""; }; + 8BD9C9A31D9AB3B6D8128E69 /* KnockRequestsListScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListScreenModels.swift; sourceTree = ""; }; 8BEBF0E59F25E842EDB6FD11 /* LocationSharingScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSharingScreenModels.swift; sourceTree = ""; }; 8C44BBC892499BE45B074F89 /* AppLockScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenCoordinator.swift; sourceTree = ""; }; 8C8616254EE40CA8BA5E9BC2 /* VideoRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItemContent.swift; sourceTree = ""; }; @@ -2007,6 +2017,7 @@ A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriverProtocol.swift; sourceTree = ""; }; A6EA0D8B0BBD8805F7D5A133 /* TextBasedRoomTimelineViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineViewProtocol.swift; sourceTree = ""; }; A73A07BAEDD74C48795A996A /* AsyncSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncSequence.swift; sourceTree = ""; }; + A756F1792CEDFF7300128047 /* KnockRequestsListEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListEmptyStateView.swift; sourceTree = ""; }; A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationTokenTests.swift; sourceTree = ""; }; A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = ""; }; A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -2177,7 +2188,9 @@ C95ADE8D9527523572532219 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = hu; path = hu.lproj/Localizable.stringsdict; sourceTree = ""; }; C97F8963B14EB0AF3940DDBF /* NotificationSettingsEditScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenRoomCell.swift; sourceTree = ""; }; C99FDEEB71173C4C6FA2734C /* UserSessionFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionFlowCoordinator.swift; sourceTree = ""; }; + C9AC2CC94FA06F728883B694 /* KnockRequestsListScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListScreenViewModelTests.swift; sourceTree = ""; }; C9E535B3388755B65C34CD10 /* UnsupportedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineView.swift; sourceTree = ""; }; + C9E8A8EC299E12490588B07C /* KnockRequestsListScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListScreenCoordinator.swift; sourceTree = ""; }; C9F893F4A111CB7BA5C96949 /* AppLockSetupBiometricsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenViewModel.swift; sourceTree = ""; }; CA28F29C9F93E93CC3C2C715 /* NavigationRootCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinator.swift; sourceTree = ""; }; CA29952595B804DA221A0C1D /* ComposerToolbarViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarViewModelTests.swift; sourceTree = ""; }; @@ -2205,6 +2218,7 @@ D01FD1171FF40E34D707FD00 /* BigIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigIcon.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 = ""; }; D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = ""; }; D0C2D52E36AD614B3C003EF6 /* RoomTimelineItemViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemViewState.swift; sourceTree = ""; }; D1896F6288D80E1F3EFB3DF8 /* ka */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ka; path = ka.lproj/Localizable.stringsdict; sourceTree = ""; }; @@ -3990,6 +4004,7 @@ 845DDBDE5A0887E73D38B826 /* InviteUsersViewModelTests.swift */, DE5127D6EA05B2E45D0A7D59 /* JoinRoomScreenViewModelTests.swift */, FDB9C37196A4C79F24CE80C6 /* KeychainControllerTests.swift */, + C9AC2CC94FA06F728883B694 /* KnockRequestsListScreenViewModelTests.swift */, 6E5725BC6C63604CB769145B /* LegalInformationScreenViewModelTests.swift */, C070FD43DC6BF4E50217965A /* LocalizationTests.swift */, 3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */, @@ -5034,6 +5049,10 @@ BF0415BE807CA2BCFC210008 /* KnockRequestsListScreen */ = { isa = PBXGroup; children = ( + C9E8A8EC299E12490588B07C /* KnockRequestsListScreenCoordinator.swift */, + 8BD9C9A31D9AB3B6D8128E69 /* KnockRequestsListScreenModels.swift */, + D09227E671DB30795C43FFFD /* KnockRequestsListScreenViewModel.swift */, + 6A5C217DD0749EC709EED028 /* KnockRequestsListScreenViewModelProtocol.swift */, F2BBD71E8BF13D2DD2A19064 /* View */, ); path = KnockRequestsListScreen; @@ -5595,7 +5614,9 @@ F2BBD71E8BF13D2DD2A19064 /* View */ = { isa = PBXGroup; children = ( + A756F1792CEDFF7300128047 /* KnockRequestsListEmptyStateView.swift */, 44B71F6D9062E8EB8929BB97 /* KnockRequestCell.swift */, + 1511B1DCECC0DC75EB267328 /* KnockRequestsListScreen.swift */, ); path = View; sourceTree = ""; @@ -6386,6 +6407,7 @@ A216C83ADCF32BA5EF8A6FBC /* InviteUsersViewModelTests.swift in Sources */, 7C0E29E0279866C62EC67A28 /* JoinRoomScreenViewModelTests.swift in Sources */, EEC40663922856C65D1E0DF5 /* KeychainControllerTests.swift in Sources */, + BA48D6AFF6421D199148C0A1 /* KnockRequestsListScreenViewModelTests.swift in Sources */, CC961529F9F1854BEC3272C9 /* LayoutMocks.swift in Sources */, 8AC256AF0EC54658321C9241 /* LegalInformationScreenViewModelTests.swift in Sources */, 0033481EE363E4914295F188 /* LocalizationTests.swift in Sources */, @@ -6733,6 +6755,7 @@ 36926D795D6D19177C7812F8 /* EncryptionResetPasswordScreenCoordinator.swift in Sources */, B1B255CE0E4306DD6E09D936 /* EncryptionResetPasswordScreenModels.swift in Sources */, D6152E21036B88C44ECB22E7 /* EncryptionResetPasswordScreenViewModel.swift in Sources */, + A756F17A2CEDFF9700128047 /* KnockRequestsListEmptyStateView.swift in Sources */, A0601810597769B81C2358AF /* EncryptionResetPasswordScreenViewModelProtocol.swift in Sources */, F3F9D61C53C348043D3D6F51 /* EncryptionResetScreen.swift in Sources */, 3041EBA2660F28FFB7BDA339 /* EncryptionResetScreenCoordinator.swift in Sources */, @@ -6817,6 +6840,11 @@ CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */, 2748E5574A1031DD05E54FDA /* KnockRequestCell.swift in Sources */, D5E8EE8A288EFCCF646860EA /* KnockRequestsBannerView.swift in Sources */, + AAA551AD8768309024D4907B /* KnockRequestsListScreen.swift in Sources */, + 0307469D99B5FE6C7043AE39 /* KnockRequestsListScreenCoordinator.swift in Sources */, + 9EE71509E6E7519A2B2388B3 /* KnockRequestsListScreenModels.swift in Sources */, + A0861B727B273B5B3DD7FBF6 /* KnockRequestsListScreenViewModel.swift in Sources */, + 75ED4B73983228BB6922CE3C /* KnockRequestsListScreenViewModelProtocol.swift in Sources */, C969A62F3D9F14318481A33B /* KnockedRoomProxy.swift in Sources */, 6681D6D3ADF69EBD2625F29A /* KnockedRoomProxyMock.swift in Sources */, 454F8DDC4442C0DE54094902 /* LABiometryType.swift in Sources */, diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index a9efc2209c..24b113fce0 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -370,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index 8aaf6fc27f..6c7f78e79e 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -413,6 +413,11 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { return .presentingChild(childRoomID: roomID, previousState: fromState) case (.presentingChild(_, let previousState), .dismissChildFlow): return previousState + + case (.roomDetails, .presentKnockRequestsListScreen): + return .knockRequestsList + case (.knockRequestsList, .dismissKnockRequestsListScreen): + return .roomDetails(isRoot: false) default: return nil @@ -565,6 +570,11 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { presentResolveSendFailure(failure: failure, sendHandle: sendHandle) case (.resolveSendFailure, .dismissResolveSendFailure, .room): break + + case (.roomDetails, .presentKnockRequestsListScreen, .knockRequestsList): + presentKnockRequestsList() + case (.knockRequestsList, .dismissKnockRequestsListScreen, .roomDetails): + break // Child flow case (_, .startChildFlow(let roomID, let via, let entryPoint), .presentingChild): @@ -837,6 +847,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { actionsSubject.send(.presentCallScreen(roomProxy: roomProxy)) case .presentPinnedEventsTimeline: stateMachine.tryEvent(.presentPinnedEventsTimeline) + case .presentKnockingRequestsListScreen: + stateMachine.tryEvent(.presentKnockRequestsListScreen) } } .store(in: &cancellables) @@ -883,6 +895,20 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { } } + private func presentKnockRequestsList() { + let parameters = KnockRequestsListScreenCoordinatorParameters(roomProxy: roomProxy, mediaProvider: userSession.mediaProvider) + let coordinator = KnockRequestsListScreenCoordinator(parameters: parameters) + + coordinator.actionsPublisher + .sink { [weak self] _ in + } + .store(in: &cancellables) + + navigationStackCoordinator.push(coordinator) { [weak self] in + self?.stateMachine.tryEvent(.dismissKnockRequestsListScreen) + } + } + private func presentRoomDetailsEditScreen() { let stackCoordinator = NavigationStackCoordinator() @@ -1546,6 +1572,7 @@ private extension RoomFlowCoordinator { case rolesAndPermissions case pinnedEventsTimeline(previousState: PinnedEventsTimelineSource) case resolveSendFailure + case knockRequestsList /// A child flow is in progress. case presentingChild(childRoomID: String, previousState: State) @@ -1624,6 +1651,9 @@ private extension RoomFlowCoordinator { // Child room flow events case startChildFlow(roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint) case dismissChildFlow + + case presentKnockRequestsListScreen + case dismissKnockRequestsListScreen } } diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 1d45cfdbb8..82f7d0a327 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -1298,8 +1298,16 @@ internal enum L10n { } /// Are you sure you want to turn off key storage and delete it? internal static var screenKeyBackupDisableTitle: String { return L10n.tr("Localizable", "screen_key_backup_disable_title") } + /// Accept all + internal static var screenKnockRequestsListAcceptAllButtonTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_button_title") } /// Decline and ban internal static var screenKnockRequestsListDeclineAndBanActionTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_and_ban_action_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") } + /// Requests to join + internal static var screenKnockRequestsListTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_title") } /// This account has been deactivated. internal static var screenLoginErrorDeactivatedAccount: String { return L10n.tr("Localizable", "screen_login_error_deactivated_account") } /// Incorrect username and/or password diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift new file mode 100644 index 0000000000..00a0c32245 --- /dev/null +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift @@ -0,0 +1,45 @@ +// +// Copyright 2022-2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +// periphery:ignore:all - this is just a knockRequestsList remove this comment once generating the final file + +import Combine +import SwiftUI + +struct KnockRequestsListScreenCoordinatorParameters { + let roomProxy: JoinedRoomProxyProtocol + let mediaProvider: MediaProviderProtocol +} + +enum KnockRequestsListScreenCoordinatorAction { } + +final class KnockRequestsListScreenCoordinator: CoordinatorProtocol { + private let viewModel: KnockRequestsListScreenViewModelProtocol + + private var cancellables = Set() + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(parameters: KnockRequestsListScreenCoordinatorParameters) { + viewModel = KnockRequestsListScreenViewModel(roomProxy: parameters.roomProxy, + mediaProvider: parameters.mediaProvider) + } + + func start() { + viewModel.actionsPublisher.sink { [weak self] action in + MXLog.info("Coordinator: received view model action: \(action)") + } + .store(in: &cancellables) + } + + func toPresentable() -> AnyView { + AnyView(KnockRequestsListScreen(context: viewModel.context)) + } +} diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift new file mode 100644 index 0000000000..6459148289 --- /dev/null +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift @@ -0,0 +1,24 @@ +// +// 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 KnockRequestsListScreenViewModelAction { } + +struct KnockRequestsListScreenViewState: BindableState { + var requests: [KnockRequestCellInfo] = [] + var canAccept = false + var canDecline = false + var canBan = false +} + +enum KnockRequestsListScreenViewAction { + case acceptAllRequests + case acceptRequest(userID: String) + case declineRequest(userID: String) + case ban(userID: String) +} diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift new file mode 100644 index 0000000000..3593196948 --- /dev/null +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift @@ -0,0 +1,75 @@ +// +// 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 KnockRequestsListScreenViewModelType = StateStoreViewModel + +class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, KnockRequestsListScreenViewModelProtocol { + private let roomProxy: JoinedRoomProxyProtocol + + private let actionsSubject: PassthroughSubject = .init() + var actionsPublisher: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(roomProxy: JoinedRoomProxyProtocol, mediaProvider: MediaProviderProtocol) { + self.roomProxy = roomProxy + super.init(initialViewState: KnockRequestsListScreenViewState(), mediaProvider: mediaProvider) + + Task { + await updatePermissions() + } + + setupSubscriptions() + } + + // MARK: - Public + + override func process(viewAction: KnockRequestsListScreenViewAction) { + switch viewAction { + case .acceptAllRequests: + break + case .acceptRequest(let userID): + break + case .declineRequest(let userID): + break + case .ban(let userID): + break + } + } + + // MARK: - Private + + private func setupSubscriptions() { + roomProxy.infoPublisher + .throttle(for: .milliseconds(200), scheduler: DispatchQueue.main, latest: true) + .sink { [weak self] _ in + Task { await self?.updatePermissions() } + } + .store(in: &cancellables) + } + + private func updatePermissions() async { + state.canAccept = await (try? roomProxy.canUserInvite(userID: roomProxy.ownUserID).get()) == true + state.canDecline = await (try? roomProxy.canUserKick(userID: roomProxy.ownUserID).get()) == true + 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) + } +} + +extension KnockRequestsListScreenViewModel { + static func mockWithInitialState(_ initialViewState: KnockRequestsListScreenViewState) -> KnockRequestsListScreenViewModel { + .init(initialViewState: initialViewState) + } +} diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModelProtocol.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModelProtocol.swift new file mode 100644 index 0000000000..c6ca4a7119 --- /dev/null +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModelProtocol.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 KnockRequestsListScreenViewModelProtocol { + var actionsPublisher: AnyPublisher { get } + var context: KnockRequestsListScreenViewModelType.Context { get } +} diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift index 837f6d33d4..41d7da1927 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift @@ -15,8 +15,9 @@ import Compound import SwiftUI -struct KnockRequestCellInfo { - let userID: String +struct KnockRequestCellInfo: Identifiable { + /// user identifier of the usee that sent the request + let id: String let displayName: String? let avatarUrl: URL? let timestamp: String? @@ -26,67 +27,92 @@ struct KnockRequestCellInfo { struct KnockRequestCell: View { let cellInfo: KnockRequestCellInfo var mediaProvider: MediaProviderProtocol? - let onAccept: (String) -> Void - let onDecline: (String) -> Void - let onDeclineAndBan: (String) -> Void + let onAccept: ((String) -> Void)? + let onDecline: ((String) -> Void)? + let onDeclineAndBan: ((String) -> Void)? var body: some View { - VStack(spacing: 0) { - HStack(alignment: .top, spacing: 16) { - LoadableAvatarImage(url: cellInfo.avatarUrl, - name: cellInfo.displayName, - contentID: cellInfo.userID, - avatarSize: .user(on: .knockingUserList), - mediaProvider: mediaProvider) - VStack(alignment: .leading, spacing: 12) { - VStack(alignment: .leading, spacing: 0) { - HStack(alignment: .top, spacing: 0) { - Text(cellInfo.displayName ?? cellInfo.userID) - .font(.compound.bodyLGSemibold) - .foregroundStyle(.compound.textPrimary) - .frame(maxWidth: .infinity, alignment: .leading) - if let timestamp = cellInfo.timestamp { - Text(timestamp) - .font(.compound.bodySM) - .foregroundStyle(.compound.textSecondary) - } - } - if cellInfo.displayName != nil { - Text(cellInfo.userID) - .font(.compound.bodyMD) - .foregroundStyle(.compound.textSecondary) - } - } - if let reason = cellInfo.reason { - DisclosableText(text: reason) - } - actions + HStack(alignment: .top, spacing: 16) { + LoadableAvatarImage(url: cellInfo.avatarUrl, + name: cellInfo.displayName, + contentID: cellInfo.id, + avatarSize: .user(on: .knockingUserList), + mediaProvider: mediaProvider) + VStack(alignment: .leading, spacing: 12) { + header + if let reason = cellInfo.reason { + DisclosableText(text: reason) + } + actions + } + .padding(.trailing, 16) + .overlay(alignment: .bottom) { + // Custom separator that uses the same color from the compound one + Color.compound._borderInteractiveSecondaryAlpha + .frame(height: 0.5) + } + } + .padding(.top, 16) + .padding(.leading, 16) + .background(.compound.bgCanvasDefault) + } + + private var header: some View { + VStack(alignment: .leading, spacing: 0) { + HStack(alignment: .top, spacing: 0) { + Text(cellInfo.displayName ?? cellInfo.id) + .font(.compound.bodyLGSemibold) + .foregroundStyle(.compound.textPrimary) + .frame(maxWidth: .infinity, alignment: .leading) + if let timestamp = cellInfo.timestamp { + Text(timestamp) + .font(.compound.bodySM) + .foregroundStyle(.compound.textSecondary) } } - .padding(16) - Divider() + if cellInfo.displayName != nil { + Text(cellInfo.id) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textSecondary) + } } } @ViewBuilder private var actions: some View { - HStack(spacing: 16) { - Button(L10n.actionDecline) { - onDecline(cellInfo.userID) + VStack(spacing: 0) { + if onDecline != nil || onAccept != nil { + HStack(spacing: 16) { + if let onDecline { + Button(L10n.actionDecline) { + onDecline(cellInfo.id) + } + .buttonStyle(.compound(.secondary, size: .medium)) + } + + if let onAccept { + Button(L10n.actionAccept) { + onAccept(cellInfo.id) + } + .buttonStyle(.compound(.primary, size: .medium)) + } + } } - .buttonStyle(.compound(.secondary)) - Button(L10n.actionAccept) { - onAccept(cellInfo.userID) + + if let onDeclineAndBan { + Button(role: .destructive) { + onDeclineAndBan(cellInfo.id) + } label: { + Text(L10n.screenKnockRequestsListDeclineAndBanActionTitle) + .padding(.top, 8) + .padding(.bottom, 4) + } + .frame(maxWidth: .infinity) + .buttonStyle(.compound(.plain)) + .padding(.top, 16) } - .buttonStyle(.compound(.primary)) - } - Button(L10n.screenKnockRequestsListDeclineAndBanActionTitle, role: .destructive) { - onDeclineAndBan(cellInfo.userID) } - .buttonStyle(.compound(.plain)) - .frame(maxWidth: .infinity) - .padding(.top, 12) - .padding(.bottom, 4) + .padding(.bottom, 16) } } @@ -130,9 +156,10 @@ private struct DisclosableText: View { } } label: { CompoundIcon(\.chevronDown, size: .medium, relativeTo: .compound.bodyMD) + .foregroundStyle(.compound.iconTertiary) + .rotationEffect(.degrees(isExpanded ? 180 : 0)) } - .rotationEffect(.degrees(isExpanded ? 180 : 0)) - .foregroundStyle(.compound.iconTertiary) + .buttonStyle(.plain) .opacity(collapsedHeight < expandedHeight ? 1 : 0) .disabled(collapsedHeight >= expandedHeight) } @@ -141,13 +168,13 @@ private struct DisclosableText: View { struct KnockRequestCell_Previews: PreviewProvider, TestablePreview { // swiftlint:disable:next line_length - static let aliceWithLongReason = KnockRequestCellInfo(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 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 aliceWithShortReason = KnockRequestCellInfo(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 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 aliceWithNoReason = KnockRequestCellInfo(userID: "@alice:matrix.org", displayName: "Alice", avatarUrl: nil, timestamp: "20 Nov 2024", reason: nil) + static let aliceWithNoReason = KnockRequestCellInfo(id: "@alice:matrix.org", displayName: "Alice", avatarUrl: nil, timestamp: "20 Nov 2024", reason: nil) - static let aliceWithNoName = KnockRequestCellInfo(userID: "@alice:matrix.org", displayName: nil, 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 var previews: some View { KnockRequestCell(cellInfo: aliceWithLongReason, onAccept: { _ in }, onDecline: { _ in }, onDeclineAndBan: { _ in }) @@ -158,5 +185,11 @@ struct KnockRequestCell_Previews: PreviewProvider, TestablePreview { .previewDisplayName("No reason") KnockRequestCell(cellInfo: aliceWithNoName, onAccept: { _ 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") } } diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListEmptyStateView.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListEmptyStateView.swift new file mode 100644 index 0000000000..6f168e67c0 --- /dev/null +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListEmptyStateView.swift @@ -0,0 +1,38 @@ +// +// 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 KnockRequestsListEmptyStateView: View { + var body: some View { + VStack(spacing: 16) { + BigIcon(icon: \.askToJoin) + VStack(spacing: 8) { + Text(L10n.screenKnockRequestsListEmptyStateTitle) + .multilineTextAlignment(.center) + .font(.compound.headingMDBold) + .foregroundStyle(.compound.textPrimary) + Text(L10n.screenKnockRequestsListEmptyStateDescription) + .multilineTextAlignment(.center) + .foregroundStyle(.compound.textSecondary) + .font(.compound.bodyMD) + } + Spacer() + } + .padding(.top, 53) + .padding(.horizontal, 40) + } +} + +// MARK: - Previews + +struct KnockRequestsListEmptyStateView_Previews: PreviewProvider, TestablePreview { + static var previews: some View { + KnockRequestsListEmptyStateView() + } +} diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift new file mode 100644 index 0000000000..792dba762e --- /dev/null +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift @@ -0,0 +1,96 @@ +// +// 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 KnockRequestsListScreen: View { + @ObservedObject var context: KnockRequestsListScreenViewModel.Context + + var body: some View { + mainContent + .navigationBarTitleDisplayMode(.inline) + .navigationTitle(L10n.screenKnockRequestsListTitle) + .background(.compound.bgCanvasDefault) + .overlay { + if context.viewState.requests.isEmpty { + KnockRequestsListEmptyStateView() + } + } + .safeAreaInset(edge: .bottom) { + if !context.viewState.requests.isEmpty { + acceptAllButton + } + } + } + + @ViewBuilder + private var mainContent: some View { + ScrollView { + LazyVStack(spacing: 0) { + ForEach(context.viewState.requests) { requestInfo in + ListRow(kind: .custom { + KnockRequestCell(cellInfo: requestInfo, + mediaProvider: context.mediaProvider, + onAccept: context.viewState.canAccept ? onAccept : nil, + onDecline: context.viewState.canDecline ? onDecline : nil, + onDeclineAndBan: context.viewState.canBan ? onDeclineAndBan : nil) + }) + } + } + .padding(.top, 40) + } + } + + private var acceptAllButton: some View { + Button(L10n.screenKnockRequestsListAcceptAllButtonTitle) { + context.send(viewAction: .acceptAllRequests) + } + .buttonStyle(.compound(.secondary)) + .padding(.horizontal, 16) + .padding(.top, 16) + .padding(.bottom, 4) + .background(.compound.bgCanvasDefault) + } + + private func onAccept(userID: String) { + context.send(viewAction: .acceptRequest(userID: userID)) + } + + private func onDecline(userID: String) { + context.send(viewAction: .declineRequest(userID: userID)) + } + + private func onDeclineAndBan(userID: String) { + context.send(viewAction: .ban(userID: userID)) + } +} + +// MARK: - Previews + +struct KnockRequestsListScreen_Previews: PreviewProvider, TestablePreview { + static let emptyViewModel = KnockRequestsListScreenViewModel.mockWithInitialState(.init()) + + 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!")], + canAccept: true, + canDecline: true, + canBan: true)) + + static var previews: some View { + NavigationStack { + KnockRequestsListScreen(context: viewModel.context) + } + NavigationStack { + KnockRequestsListScreen(context: emptyViewModel.context) + } + .previewDisplayName("Empty state") + } +} diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift index 92dbcc3b42..43e2f1b2aa 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift @@ -29,6 +29,7 @@ enum RoomDetailsScreenCoordinatorAction { case presentRolesAndPermissionsScreen case presentCall case presentPinnedEventsTimeline + case presentKnockingRequestsListScreen } final class RoomDetailsScreenCoordinator: CoordinatorProtocol { @@ -79,6 +80,8 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol { actionsSubject.send(.presentCall) case .displayPinnedEventsTimeline: actionsSubject.send(.presentPinnedEventsTimeline) + case .displayKnockingRequests: + actionsSubject.send(.presentKnockingRequestsListScreen) } } .store(in: &cancellables) diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift index e1854f8a41..b918884175 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift @@ -22,6 +22,7 @@ enum RoomDetailsScreenViewModelAction { case requestRolesAndPermissionsPresentation case startCall case displayPinnedEventsTimeline + case displayKnockingRequests } // MARK: View @@ -42,9 +43,16 @@ struct RoomDetailsScreenViewState: BindableState { var canEditRoomTopic = false var canEditRoomAvatar = false var canEditRolesOrPermissions = false + var canKickUsers = false + var canBanUsers = false var notificationSettingsState: RoomDetailsNotificationSettingsState = .loading var canJoinCall = false var pinnedEventsActionState = RoomDetailsScreenPinnedEventsActionState.loading + var knockingEnabled = false + + var canSeeKnockingRequests: Bool { + knockingEnabled && dmRecipient == nil && (canInviteUsers || canKickUsers || canBanUsers) + } var canEdit: Bool { !isDirect && (canEditRoomName || canEditRoomTopic || canEditRoomAvatar) @@ -188,6 +196,7 @@ enum RoomDetailsScreenViewAction { case processTapRolesAndPermissions case processTapCall case processTapPinnedEvents + case processTapRequestsToJoin } enum RoomDetailsScreenViewShortcut { diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift index d56498ef80..ed7b4cf446 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift @@ -75,6 +75,10 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr bindings: .init()), mediaProvider: mediaProvider) + appSettings.$knockingEnabled + .weakAssign(to: \.state.knockingEnabled, on: self) + .store(in: &cancellables) + appMediator.networkMonitor.reachabilityPublisher .filter { $0 == .reachable } .receive(on: DispatchQueue.main) @@ -160,6 +164,8 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr case .processTapPinnedEvents: analyticsService.trackInteraction(name: .PinnedMessageRoomInfoButton) actionsSubject.send(.displayPinnedEventsTimeline) + case .processTapRequestsToJoin: + actionsSubject.send(.displayKnockingRequests) } } @@ -212,6 +218,8 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr state.canEditRoomAvatar = await (try? roomProxy.canUser(userID: roomProxy.ownUserID, sendStateEvent: .roomAvatar).get()) == true state.canEditRolesOrPermissions = await (try? roomProxy.suggestedRole(for: roomProxy.ownUserID).get()) == .administrator state.canInviteUsers = await (try? roomProxy.canUserInvite(userID: roomProxy.ownUserID).get()) == true + state.canKickUsers = await (try? roomProxy.canUserKick(userID: roomProxy.ownUserID).get()) == true + state.canBanUsers = await (try? roomProxy.canUserBan(userID: roomProxy.ownUserID).get()) == true } private func setupNotificationSettingsSubscription() { diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift index 207f10796c..1873fbf15b 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -160,6 +160,15 @@ struct RoomDetailsScreen: View { }) .accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.people) } + 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 { @@ -294,6 +303,7 @@ struct RoomDetailsScreen: View { struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { static let genericRoomViewModel = { + ServiceLocator.shared.settings.knockingEnabled = true let members: [RoomMemberProxyMock] = [ .mockMeAdmin, .mockAlice, @@ -357,6 +367,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { }() static let simpleRoomViewModel = { + ServiceLocator.shared.settings.knockingEnabled = true let members: [RoomMemberProxyMock] = [ .mockMeAdmin, .mockAlice, diff --git a/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift b/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift index dab249999c..ae33410794 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/KnockRequestsBannerView.swift @@ -18,7 +18,7 @@ struct KnockRequestInfo { struct KnockRequestsBannerView: View { let requests: [KnockRequestInfo] let onDismiss: () -> Void - let onAccept: (String) -> Void + let onAccept: ((String) -> Void)? let onViewAll: () -> Void var mediaProvider: MediaProviderProtocol? @@ -34,9 +34,16 @@ struct KnockRequestsBannerView: View { @ViewBuilder private var mainContent: some View { if requests.count == 1 { - SingleKnockRequestBannerContent(request: requests[0], onDismiss: onDismiss, onAccept: onAccept, onViewAll: onViewAll) + SingleKnockRequestBannerContent(request: requests[0], + onDismiss: onDismiss, + onAccept: onAccept, + onViewAll: onViewAll, + mediaProvider: mediaProvider) } else if requests.count > 1 { - MultipleKnockRequestsBannerContent(requests: requests, onDismiss: onDismiss, onViewAll: onViewAll) + MultipleKnockRequestsBannerContent(requests: requests, + onDismiss: onDismiss, + onViewAll: onViewAll, + mediaProvider: mediaProvider) } else { EmptyView() } @@ -46,7 +53,7 @@ struct KnockRequestsBannerView: View { private struct SingleKnockRequestBannerContent: View { let request: KnockRequestInfo let onDismiss: () -> Void - let onAccept: (String) -> Void + let onAccept: ((String) -> Void)? let onViewAll: () -> Void var mediaProvider: MediaProviderProtocol? @@ -93,11 +100,13 @@ private struct SingleKnockRequestBannerContent: View { private var actions: some View { HStack(spacing: 12) { Button(L10n.screenRoomSingleKnockRequestViewButtonTitle, action: onViewAll) - .buttonStyle(.compound(.secondary)) - Button(L10n.screenRoomSingleKnockRequestAcceptButtonTitle, action: { - onAccept(request.userID) - }) - .buttonStyle(.compound(.primary)) + .buttonStyle(.compound(.secondary, size: .medium)) + if let onAccept { + Button(L10n.screenRoomSingleKnockRequestAcceptButtonTitle, action: { + onAccept(request.userID) + }) + .buttonStyle(.compound(.primary, size: .medium)) + } } .padding(.top, request.reason == nil ? 0 : 2) .frame(maxWidth: .infinity) @@ -142,7 +151,7 @@ private struct MultipleKnockRequestsBannerContent: View { Button(L10n.screenRoomMultipleKnockRequestsViewAllButtonTitle) { onViewAll() } - .buttonStyle(.compound(.primary)) + .buttonStyle(.compound(.primary, size: .medium)) } } } @@ -181,6 +190,8 @@ struct KnockRequestsBannerView_Previews: PreviewProvider, TestablePreview { static var previews: some View { KnockRequestsBannerView(requests: singleRequest, onDismiss: { }, onAccept: { _ in }, onViewAll: { }) .previewDisplayName("Single Request") + KnockRequestsBannerView(requests: singleRequest, onDismiss: { }, onAccept: nil, onViewAll: { }) + .previewDisplayName("Single Request, no accept action") KnockRequestsBannerView(requests: singleRequestWithReason, onDismiss: { }, onAccept: { _ in }, onViewAll: { }) .previewDisplayName("Single Request with reason") KnockRequestsBannerView(requests: singleRequestNoDisplayName, onDismiss: { }, onAccept: { _ in }, onViewAll: { }) diff --git a/PreviewTests/Sources/GeneratedPreviewTests.swift b/PreviewTests/Sources/GeneratedPreviewTests.swift index f18c1d9278..33d08949e3 100644 --- a/PreviewTests/Sources/GeneratedPreviewTests.swift +++ b/PreviewTests/Sources/GeneratedPreviewTests.swift @@ -317,6 +317,18 @@ extension PreviewTests { } } + func test_knockRequestsListEmptyStateView() { + for preview in KnockRequestsListEmptyStateView_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + + func test_knockRequestsListScreen() { + for preview in KnockRequestsListScreen_Previews._allPreviews { + assertSnapshots(matching: preview) + } + } + func test_legalInformationScreen() { for preview in LegalInformationScreen_Previews._allPreviews { assertSnapshots(matching: preview) diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Long-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Long-reason.png index e3ea93d796..bae5a70112 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Long-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Long-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5466569f96a2d74dc598b7d870ae76d237c0e7dbf181f3e0adf497b0956e2649 -size 119491 +oid sha256:48b0893d0ea480cd8ed616725e802c369974107b7cc9ecf2776a638d3262fea3 +size 117222 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Accept-and-Decline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Accept-and-Decline.png new file mode 100644 index 0000000000..680c126c0e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Accept-and-Decline.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea688a6d22a077644d73dfda17acd4bc7e05ed333492c8344082fa4de452e8c9 +size 93005 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Accept.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Accept.png new file mode 100644 index 0000000000..d2a737d597 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Accept.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a4f99e888211cbce93dc2337149c7ea3d3021c5fb7d5fe825e270b8d3ef0a0e +size 97309 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Ban.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Ban.png new file mode 100644 index 0000000000..291b6899ed --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-Ban.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35c6e2fcf10e9276b2d9db775959a82c7fc6a7a45414cc2a5bf1ab849eafc3bb +size 98028 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-name.png index c7c77c488c..d16cda6de8 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-name.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-name.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b61e8c99338ff1316736d3f8945cbc32c407a276493a63de0ffe9f1325479cc3 -size 93546 +oid sha256:7c7f218094ea94484039eb30960094fe69658867b2f6793ee5308ca1d5fc4e63 +size 91440 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-reason.png index cbd704292e..ec38fb8108 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.No-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79a32205860de5d076cbf226156962519586058e50a89ea7c29cf15b2d66fb75 -size 94500 +oid sha256:00f5defb9806f8957dd2f08e011b26017335b1d34c621a31148d053bd495737b +size 92432 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Short-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Short-reason.png index afb85ca2e7..16e9d93dde 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Short-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-en-GB.Short-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc9ebf6bcd889f2d0a0a855404b6be2ae140d40a69a21767dc9ecc3958539a79 -size 103862 +oid sha256:84b3af435f25e50fe78803eaae8b6a38847cf40cbe56606c7e3cb0142cb5bd00 +size 101763 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Long-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Long-reason.png index 049a445c87..95643e388b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Long-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Long-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:af31b5df7d0f0d97a8c306ece8cbaa611bfbc3a98e78a189ed5349f16faa5cc5 -size 121175 +oid sha256:afa4b8b10c68b1074955312dfd8fd58f9e4b6866cef1e1f41eac82f5d38c2366 +size 118761 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Accept-and-Decline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Accept-and-Decline.png new file mode 100644 index 0000000000..be47daaf8a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Accept-and-Decline.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64fbca409e089763527195e78ff4f5ce9b71ada7249ce177a35251a2b62e28b6 +size 93548 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Accept.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Accept.png new file mode 100644 index 0000000000..02301db424 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Accept.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0fa0e01f526285a00ed6ce491e6b0837c90244059d9cbc7eb0bc71e9b588e84e +size 98413 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Ban.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Ban.png new file mode 100644 index 0000000000..e023a5a25a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-Ban.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:50e377ed4ad1eb150222e178caea25b2f1965688879722051b99fc4a3e9a0513 +size 98936 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-name.png index ef4aebf232..163145d418 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-name.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-name.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98eec884b96bcaa6eec3510a8c362762d2a0d3238eecd287782e2d41a778af83 -size 95103 +oid sha256:28abf5766be915dd6723e7bdee24725ac3cb702665dc105a96823ad8ba95bd92 +size 92951 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-reason.png index 9f63dd5294..42b1135067 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.No-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b974d372c92c5fb724778d384fc3072d95cc2bea1c9662d123fc24fbfba6890a -size 96049 +oid sha256:41011733a39814817ffb7c537d5e74761b4c2cec6848c20a27724f86592e0d53 +size 93942 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Short-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Short-reason.png index bb5e34c8ab..68dab7cc3a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Short-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPad-pseudo.Short-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97c9af346e966100a44f1db6814e516455ba90c3a4154de9a5f657f955dfefa3 -size 105493 +oid sha256:2cd6faa13983c923bf7b7979a935ecf36607f6272577e53b66cc3f661ae820c8 +size 103297 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Long-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Long-reason.png index 403ce85c6d..13f661740c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Long-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Long-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce6497c50fbf9e9b0f6bb6713cacb55bb389a31232785faa1368b341d300b563 -size 62895 +oid sha256:e504a0e147399d856bbdd8b0b61bce6f5c79dd88221261f1a632ad77c8d3f472 +size 60864 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Accept-and-Decline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Accept-and-Decline.png new file mode 100644 index 0000000000..ca0d2bec49 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Accept-and-Decline.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b41449a70b60e61b9437ca5c8f886f733d9ad67b672da9c43e643a2ece2daa7 +size 50526 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Accept.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Accept.png new file mode 100644 index 0000000000..183f17d33d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Accept.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:689ddaeb4c545fba7ae22a27c71eef58636193bfc2c552a892e895d08fd616f4 +size 55394 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Ban.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Ban.png new file mode 100644 index 0000000000..3e80d5eead --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-Ban.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2b2d39bfeb9c5eeb3bd0fbe081f1b30c310ca12fe9cedb972cafe38b3550797f +size 55280 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-name.png index 0e554bf98f..12c4417d3c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-name.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-name.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6360a04a6d30220c3b8d9aed2de8309aa54b4234824fa73cc44ac40c0c89ed2 -size 50804 +oid sha256:dd4a4b2f42ff295cebc742c561f5eb45f7aac1b38fc32e3f6e05536e6f7fa5a6 +size 48788 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-reason.png index 19c432cb94..2e57093cbb 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.No-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ca01bbaee8ec50a79370b222b15fcb9d028db3b3782d5ab0757cce738497821 -size 51417 +oid sha256:4a313f92f2f98e591988a9feebbd70101a2979cb3ec3e20b54a7a38118d15fd1 +size 49405 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Short-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Short-reason.png index fc89ccaedd..bc9ea0ebdd 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Short-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-en-GB.Short-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb2cfa269efe2a538abd7c93d577878366b84f4e44701f8a4314a2f4eb53a3d8 -size 60576 +oid sha256:6c9ba64a469cf367399029c12fb37c61f0f5f2f1963d65cf45594259482a50d3 +size 58910 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Long-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Long-reason.png index 9f39dd4ad3..5bf5771f06 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Long-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Long-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14478f6bac6fb2a792c369f8568e4cf51a89029dd4b9434262db4eb0e76e7328 -size 70929 +oid sha256:40e1f746d1ba51e90b8e0e76baa3aa81368c724686865818d5c24fe871eaed42 +size 67968 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Accept-and-Decline.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Accept-and-Decline.png new file mode 100644 index 0000000000..e77a9d50fb --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Accept-and-Decline.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7fab6e0aec518e2ae448fb4934ffd5f7ce01eb2640b63199a1509f1e8b254dc +size 52786 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Accept.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Accept.png new file mode 100644 index 0000000000..811ee96ae7 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Accept.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a51f19aa29edfadb1d2eb825b395b19aafe1330675a3fa540816d1a2d3430c2 +size 58846 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Ban.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Ban.png new file mode 100644 index 0000000000..7ca7bdd7a9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-Ban.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4704df4d40737803ba1cbde55a06db24e9e931240b5cde7432436e576972b9d7 +size 59940 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-name.png index 41e77b4ff1..667809db65 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-name.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-name.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:388b944b239c1dd130e6c1463e777c9aa85186e3bf70402d8853e88b7c19be22 -size 59396 +oid sha256:9fd2286d9c82ad62a4204129d57f2ed20befa6cf4c72de6fc8f074fb0438d357 +size 56148 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-reason.png index 101c51af89..96e9e03fdc 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.No-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1257061c8bef2b9fd9173e696ffecbfbd017b0f06eabe1228e80d3873007e271 -size 60458 +oid sha256:74f835f0d5895d2afbd05222a9e99d3e0192c3fa3d2178a8618cf9be6c52e771 +size 56928 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Short-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Short-reason.png index c0c7df2611..b71c8c6398 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Short-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestCell-iPhone-16-pseudo.Short-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4e982a79556a5fdef82435ec63dca8a24970e8c80248c751fb89f06b09fa6061 -size 68971 +oid sha256:273e1de0f9ca8e78fab88213cc4170e13bdf76d4a1e769d698e410b070b595db +size 65761 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 64654e9a21..a8d96c2b2a 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:a00d27886b5820fc2f46d201f9e40460010470702c4de0c1889173e0e9b7a3bf -size 93142 +oid sha256:3879eccedadd6ef4dd6ae91070a0271b0fa064c025614933d0ac364ded809340 +size 91991 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-No-Display-Name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-No-Display-Name.png index 85c1395791..1058de5eb7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-No-Display-Name.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-No-Display-Name.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bece9623232e1204708162f137c93120d8da2a75b88787b233aa2cb09b54f630 -size 97166 +oid sha256:b6eda3b084f228d4aa583bdb8b7903d81f78738d01972be40854a9fa0e65a327 +size 95267 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-no-accept-action.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-no-accept-action.png new file mode 100644 index 0000000000..a1fdd87e38 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-no-accept-action.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c70474ce9b6a549f77ab2a2253ef565a5d1d887f486f77a4ee20dc59f9a952eb +size 93164 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-with-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-with-reason.png index 7f7b2389a9..134bd24e6e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-with-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request-with-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00dbd02aed2799c2bd9d87ae1c551e0327fae075d4fc772f526572ed8771791d -size 111929 +oid sha256:5abf4bc3d8d591e6ecf7b47a7bb368fab3734184e78c353e3de0dc6ab9ff0767 +size 109665 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request.png index bc47f76b82..4676c105bd 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-en-GB.Single-Request.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0526b9fca57c50bf32249b9b3557916eae97c430b430a19cedaa06d4dfaa0ce3 -size 99219 +oid sha256:a740945882890eceb0c971bd87f4384f8a051db9640624ce5dd9cde1ffd09c69 +size 97409 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 7b7b1c6189..cf3f2802c9 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:04db101605f075891d02b3d46dff7cd12577e93808de4b58297147f81f9c4d00 -size 94022 +oid sha256:494a4003821e6bdad2cafeaf1d3403de5801450a268b1a444fa227b3f04ecff9 +size 92830 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-No-Display-Name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-No-Display-Name.png index ff83bdd77d..b01bf11dd9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-No-Display-Name.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-No-Display-Name.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ac5e83a0da72ff4f45cfa53ea53e97b45ace007d44ba6278f476f15b72e711e2 -size 100502 +oid sha256:e1376bad4b66e258b3ab72baca9d9baa67344c7860ae3aa1de094ea791503c97 +size 98556 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-no-accept-action.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-no-accept-action.png new file mode 100644 index 0000000000..70a7e13cae --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-no-accept-action.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83bd0c9f15a4119624157a5e109b6de045f3deeceb9d38a8a91ba4d5aad4e5f0 +size 97656 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-with-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-with-reason.png index aa7ff64ae0..2a54a6a6d0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-with-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request-with-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:401ba2ecfaea3b01487163af4b49c23b2ec0677356f240fec177da2e839cc188 -size 116728 +oid sha256:3977847df019b9ba0997e97f26fd26d2f82087af4685df8f36330d995a58ff27 +size 114432 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request.png index 8d47a0657f..06c53593db 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPad-pseudo.Single-Request.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b75c803de335663b3447151060475fdcd9f1e488da36f96da250ecd1bea01bd -size 104073 +oid sha256:6deb588da8f5614bc82f6c4ff40171cebb6788e303cec6b2dcf24eb164c258d0 +size 102325 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 ee92977682..7327e9bc9e 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:4b4b78c20f278e17836ebf1685bd2c7a55c6f22f54f7cbadd430f606f369272d -size 50876 +oid sha256:415af5d4976c78a0ea3d69441cf77498d3c2412592c8c4c920105bc1f5e0805d +size 50054 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-No-Display-Name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-No-Display-Name.png index 12c868d368..c26d074677 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-No-Display-Name.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-No-Display-Name.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8c1312811b4df9e02203b4f6a1e72546311b1b6c5a476088e66b21712b15005 -size 54839 +oid sha256:866773bffcc2adbc48607fce04578e874f96e4165b9c7d59ff032e5aa4b1c2a6 +size 53082 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-no-accept-action.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-no-accept-action.png new file mode 100644 index 0000000000..fee8d1c535 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-no-accept-action.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7121b64c323fe2aafd3b8339cd7568655633ffdba21a5fb1fcd63b3da8c8ac1b +size 49578 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-with-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-with-reason.png index 32cfbe4834..7dffb218ac 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-with-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request-with-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:248c6ebf2601a23aa6c58642f4001e62d299e36c426e8948e3dac744a32ee801 -size 67213 +oid sha256:a5c4174827ce2e8a6523e2583886ebc84deebb193ed3e31314ebb2fa00ed26aa +size 65732 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request.png index adefebe187..8f62fccfce 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-en-GB.Single-Request.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc821155dedf651cb75fd830fe8436be1d5c2e1131a6c491934f8eb357f08024 -size 54814 +oid sha256:1b2cb2a46e0aebed7ecf5524e535d26486d6f8257207990c3b4e6270c513a938 +size 53199 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 a0bde28117..71e1663a3d 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:8c3e3e0747511cf80b1d0e546a0e16e9eac85dbd4bcfdda0585d21a6fc525d07 -size 50476 +oid sha256:69c9eb6ef65eb92d7270002ceaa4a4e3d2326980c8656b6a5ea34f3c3cc62e98 +size 49455 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-No-Display-Name.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-No-Display-Name.png index 2001e846ed..bac658835a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-No-Display-Name.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-No-Display-Name.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6b08d7f64d1719c39a1d9ce22725e1615f47843eb5b1918d926a4f30b13552d -size 61108 +oid sha256:6ee70dfee6160813a77e9454e9f7ce9e15e07fbda752798c1e53919c5588646f +size 59781 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-no-accept-action.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-no-accept-action.png new file mode 100644 index 0000000000..fc3db44927 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-no-accept-action.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e04373d07a3db38bda0b1d148a6292feddbc644fe02dfe86950a25045d5a4ac +size 56618 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-with-reason.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-with-reason.png index 8e472ff40f..db592eecaa 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-with-reason.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request-with-reason.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f13de390d5293d48e7a360ce61c5bd0a363726a451a61b29a05444d00428bde -size 74128 +oid sha256:4691136d112bd2fc4111a4098091702bd630e6bed8fc7b6846da7806bdd7d5cc +size 72243 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request.png index d1672d5ec8..05dea83c9f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsBannerView-iPhone-16-pseudo.Single-Request.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1291268bc8c285e9908505c371b3419c943bf694c267a959ab99c65779cdf6ff -size 63143 +oid sha256:42ff41e8edc658a8566ebb9d14913d5f53fec54d2a8c338bbd0437e37f55ec28 +size 61177 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPad-en-GB.1.png new file mode 100644 index 0000000000..695465a97d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f33183a07c36917bec2694c171c89ad4e5ec0adaa4af6c8104435a84af52879 +size 89328 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPad-pseudo.1.png new file mode 100644 index 0000000000..4aebb0f188 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18800fd1da9c4dd0df37b61398fe8149813794f37577bfc0064fb2236f002e0c +size 100061 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..9ad818958b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b6d8164231a4a6080e4d072708d3b1acc007369e00a5a6f201a48cdf864727c +size 47150 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..6cc2a47623 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListEmptyStateView-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7edd4be41770ed698f301c0e309250f9b30e0b6c6a8ff07653a07cb5d270bc3c +size 65967 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.1.png new file mode 100644 index 0000000000..937ff09571 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b80ef8df0aba9769a0043bc0c0566d02a2cd1fc7b5f6de759160de11f99151f6 +size 179185 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.Empty-state.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.Empty-state.png new file mode 100644 index 0000000000..62e8d4a88e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-en-GB.Empty-state.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f16763c4a89f74509642f65014a50f342901a591fb6aabd1e208c30d0f94044 +size 93575 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.1.png new file mode 100644 index 0000000000..29ae9097ee --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4fdd7f67cc4189b862040ccc77e40a2f53570049d00b97f87576fd0f9e6983a0 +size 185315 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.Empty-state.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.Empty-state.png new file mode 100644 index 0000000000..2c2338c76f --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPad-pseudo.Empty-state.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8311f3d620bbdea7ab23b388ee2d75b3fc48c7ac91d6f7f4087665827839139 +size 104827 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.1.png new file mode 100644 index 0000000000..bebb0c26d9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c1ac9798ba13c0bb5b02e30e33496ad901793db6dde53214bc3b9378c87080e +size 116495 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.Empty-state.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.Empty-state.png new file mode 100644 index 0000000000..54f5787916 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-en-GB.Empty-state.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b37ef180f2c17dfa72f50ca93be65b23f060af632cd745686e4b39e83a38fdb2 +size 51302 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.1.png new file mode 100644 index 0000000000..1150f7a583 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d645007cbf2bbdc7153408a0709b99db9bb9c38c6ba196141927840baedad99 +size 127708 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.Empty-state.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.Empty-state.png new file mode 100644 index 0000000000..c6bc9552e0 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_knockRequestsListScreen-iPhone-16-pseudo.Empty-state.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a8b0ca34a899b5500d4538f029630dc80859493d36d1010fed3bfe82102528f +size 70245 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 be6ff1bc32..24ee96c2ae 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:162f3f7d89b385d26a3dd7e83c560e148001271b94458f1c97ab3bc5ba04735e -size 173481 +oid sha256:12f8dddc315ccc8ea2d4158254be65769f9d5bcc58bdd7613e4223ae22a36f70 +size 174040 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 10945db8be..d298dc2299 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:299de08d08e1a8e31555b2cff1f2f74c3724a4f396ac8edff3004ba3500aa78b -size 146568 +oid sha256:d7198ec0f5b671f2909415c3d87a499584d4afd6268507b37a7176bb261169fa +size 149752 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 259cd0e917..b5fc7cce45 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:d3e4a05c141803ba5c7bdb7fee4c4059d1b28d88614e32c842cd6a5c8b711feb -size 179948 +oid sha256:b9130f74c15d8f53f70ab3c6389ee97496f05996f4529864dd84a0854fb99371 +size 179894 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 0c6c80750a..73465f586e 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:a58443a60e339c3041d3c154f056559f558aeabefff42375cd11a1c8aa602c8b -size 155595 +oid sha256:bca314935dec069cbc120122a131b512655f861cf8c9e5daa2ae5f1a8766d30f +size 160283 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 72e8f6ef6e..c15e2c0b92 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:2b181035e41897519ea7edd67feabdd46727000b7028bf3e2d35fa54b5d90a23 -size 111799 +oid sha256:cda8e8481480985513bbba1a25a8621aafef7699d2f1f9297769ea20dc571e32 +size 111920 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 abff795aad..cd3b1ba072 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:1ff2b602ea177f6324527e5531720e718c36e922b7606c0bc67f8c5f8b6a9d23 -size 93986 +oid sha256:e8d59ded6b52bbdc156eaf01a8a26ed960e64c7d87f2d05c4b7923c4d8cf651d +size 96987 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 17669ea564..88c796aecc 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:f94ecc74654a4a51b6cc927d7fabf70f6465a433811447ce1e1bb0a80ab87cba -size 127605 +oid sha256:0bf2e3e38fee10e28c1fa5415e7b97bd07a1c1cddc52d3cfd446fa9fdabb20bf +size 128305 diff --git a/UnitTests/Sources/KnockRequestsListScreenViewModelTests.swift b/UnitTests/Sources/KnockRequestsListScreenViewModelTests.swift new file mode 100644 index 0000000000..fba35e93f7 --- /dev/null +++ b/UnitTests/Sources/KnockRequestsListScreenViewModelTests.swift @@ -0,0 +1,23 @@ +// +// 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 KnockRequestsListScreenViewModelTests: XCTestCase { + var viewModel: KnockRequestsListScreenViewModelProtocol! + + var context: KnockRequestsListScreenViewModelType.Context { + viewModel.context + } + + override func setUpWithError() throws { + viewModel = KnockRequestsListScreenViewModel(roomProxy: JoinedRoomProxyMock(.init()), mediaProvider: MediaProviderMock()) + } +} From 3f4bca48b19c676eb0e634bdd2a1dfd22ef63631 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 21 Nov 2024 10:18:14 +0200 Subject: [PATCH 48/74] Delay handling inline notification replies until the user session is established --- .../Sources/Application/AppCoordinator.swift | 78 +++++++++++++------ 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 5d4ad70d7e..111a913405 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -30,8 +30,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg private var userSession: UserSessionProtocol? { didSet { userSessionObserver?.cancel() - if let userSession { - userSession.clientProxy.roomsToAwait = storedRoomsToAwait + if userSession != nil { configureElementCallService() configureNotificationManager() observeUserSessionChanges() @@ -55,8 +54,10 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg let notificationManager: NotificationManagerProtocol private let appRouteURLParser: AppRouteURLParser + @Consumable private var storedAppRoute: AppRoute? - private var storedRoomsToAwait: Set = [] + @Consumable private var storedInlineReply: (roomID: String, message: String)? + @Consumable private var storedRoomsToAwait: Set? init(appDelegate: AppDelegate) { let appHooks = AppHooks() @@ -313,7 +314,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg if let userSession { userSession.clientProxy.roomsToAwait.insert(roomID) } else { - storedRoomsToAwait.insert(roomID) + storedRoomsToAwait = [roomID] } } @@ -321,32 +322,19 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg } func handleInlineReply(_ service: NotificationManagerProtocol, content: UNNotificationContent, replyText: String) async { - guard let userSession else { - fatalError("User session not setup") - } - MXLog.info("[AppCoordinator] handle notification reply") guard let roomID = content.userInfo[NotificationConstants.UserInfoKey.roomIdentifier] as? String else { return } - guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else { - MXLog.error("Tried to reply in an unjoined room: \(roomID)") + if userSession == nil { + // Store the data so it can be used after the session is established + storedInlineReply = (roomID, replyText) return } - switch await roomProxy.timeline.sendMessage(replyText, - html: nil, - inReplyToEventID: nil, - intentionalMentions: .empty) { - case .success: - break - default: - // error or no room proxy - await service.showLocalNotification(with: "⚠️ " + L10n.commonError, - subtitle: L10n.errorSomeMessagesHaveNotBeenSent) - } + await processInlineReply(roomID: roomID, replyText: replyText) } // MARK: - Private @@ -474,6 +462,24 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg authenticationFlowCoordinator?.start() } + + private func runPostSessionSetupTasks() async { + guard let userSession, let userSessionFlowCoordinator else { + fatalError("User session not setup") + } + + if let storedRoomsToAwait { + userSession.clientProxy.roomsToAwait = storedRoomsToAwait + } + + if let storedAppRoute { + userSessionFlowCoordinator.handleAppRoute(storedAppRoute, animated: false) + } + + if let storedInlineReply { + await processInlineReply(roomID: storedInlineReply.roomID, replyText: storedInlineReply.message) + } + } private func startAuthenticationSoftLogout() { guard let userSession else { @@ -554,9 +560,9 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg userSessionFlowCoordinator.start() self.userSessionFlowCoordinator = userSessionFlowCoordinator - - if let storedAppRoute { - userSessionFlowCoordinator.handleAppRoute(storedAppRoute, animated: false) + + Task { + await runPostSessionSetupTasks() } } @@ -832,7 +838,29 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg SentrySDK.close() MXLog.info("SentrySDK stopped") } - + + private func processInlineReply(roomID: String, replyText: String) async { + guard let userSession else { + fatalError("User session not setup") + } + + guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else { + MXLog.error("Tried to reply in an unjoined room: \(roomID)") + return + } + + switch await roomProxy.timeline.sendMessage(replyText, + html: nil, + inReplyToEventID: nil, + intentionalMentions: .empty) { + case .success: + break + default: + await notificationManager.showLocalNotification(with: "⚠️ " + L10n.commonError, + subtitle: L10n.errorSomeMessagesHaveNotBeenSent) + } + } + // MARK: Toasts and loading indicators private static let loadingIndicatorIdentifier = "\(AppCoordinator.self)-Loading" From 9180bac13cd3ebf00d823e878156e0d84fd446be Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Fri, 22 Nov 2024 10:37:18 +0000 Subject: [PATCH 49/74] =?UTF-8?q?Also=20put=20the=20share=20extension=20In?= =?UTF-8?q?fo.plist=20updates=20in=20the=20xcodegen=20yaml=20=F0=9F=A4=A6?= =?UTF-8?q?=E2=80=8D=E2=99=82=EF=B8=8F=20(#3549)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ElementX.xcodeproj/project.pbxproj | 8 ++++---- ShareExtension/SupportingFiles/target.yml | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index ec24800e13..4d4c5add3b 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -806,7 +806,6 @@ A6F345328CCC5C9B0DAE2257 /* LogViewerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB05221D7D941CC82DC8480 /* LogViewerScreenViewModel.swift */; }; A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; }; A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; }; - A756F17A2CEDFF9700128047 /* KnockRequestsListEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A756F1792CEDFF7300128047 /* KnockRequestsListEmptyStateView.swift */; }; A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; A808DC3F72D15C6C5A52317E /* TimelineItemDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCDA016D05107DED3B9495CB /* TimelineItemDebugView.swift */; }; A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; }; @@ -1085,6 +1084,7 @@ E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9E543072DE58E751F028998 /* TimelineProxy.swift */; }; E84ADFE9696936C18C2424B5 /* SecureBackupScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A00BB9CD12CF6AC98D5485 /* SecureBackupScreen.swift */; }; E89536FC8C0E4B79E9842A78 /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */; }; + E8B290CBB7E5FF5E3C1B6124 /* KnockRequestsListEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 627A8B5E798CC778C363655E /* KnockRequestsListEmptyStateView.swift */; }; E8C65C19F7C40EE545172DD6 /* RoomScreenFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4137900E28201C314C835C11 /* RoomScreenFooterView.swift */; }; E9347F56CF0683208F4D9249 /* RoomNotificationSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A9B5225D0881CEFA2CF7C9 /* RoomNotificationSettingsScreenViewModel.swift */; }; E9560744F7B0292E20ECE5F2 /* RoomDetailsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */; }; @@ -1726,6 +1726,7 @@ 61B33F23681660E940BA57F4 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/SAS.strings; sourceTree = ""; }; 622D09D4ECE759189009AEAF /* MapLibreMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLibreMapView.swift; sourceTree = ""; }; 624244C398804ADC885239AA /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = ""; }; + 627A8B5E798CC778C363655E /* KnockRequestsListEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListEmptyStateView.swift; sourceTree = ""; }; 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderTests.swift; sourceTree = ""; }; 62B07B296D7A9D2F09120853 /* OrderedSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderedSet.swift; sourceTree = ""; }; 638790D3F915F0909315C47A /* PollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollView.swift; sourceTree = ""; }; @@ -2017,7 +2018,6 @@ A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriverProtocol.swift; sourceTree = ""; }; A6EA0D8B0BBD8805F7D5A133 /* TextBasedRoomTimelineViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineViewProtocol.swift; sourceTree = ""; }; A73A07BAEDD74C48795A996A /* AsyncSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncSequence.swift; sourceTree = ""; }; - A756F1792CEDFF7300128047 /* KnockRequestsListEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListEmptyStateView.swift; sourceTree = ""; }; A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationTokenTests.swift; sourceTree = ""; }; A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = ""; }; A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -5614,8 +5614,8 @@ F2BBD71E8BF13D2DD2A19064 /* View */ = { isa = PBXGroup; children = ( - A756F1792CEDFF7300128047 /* KnockRequestsListEmptyStateView.swift */, 44B71F6D9062E8EB8929BB97 /* KnockRequestCell.swift */, + 627A8B5E798CC778C363655E /* KnockRequestsListEmptyStateView.swift */, 1511B1DCECC0DC75EB267328 /* KnockRequestsListScreen.swift */, ); path = View; @@ -6755,7 +6755,6 @@ 36926D795D6D19177C7812F8 /* EncryptionResetPasswordScreenCoordinator.swift in Sources */, B1B255CE0E4306DD6E09D936 /* EncryptionResetPasswordScreenModels.swift in Sources */, D6152E21036B88C44ECB22E7 /* EncryptionResetPasswordScreenViewModel.swift in Sources */, - A756F17A2CEDFF9700128047 /* KnockRequestsListEmptyStateView.swift in Sources */, A0601810597769B81C2358AF /* EncryptionResetPasswordScreenViewModelProtocol.swift in Sources */, F3F9D61C53C348043D3D6F51 /* EncryptionResetScreen.swift in Sources */, 3041EBA2660F28FFB7BDA339 /* EncryptionResetScreenCoordinator.swift in Sources */, @@ -6840,6 +6839,7 @@ CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */, 2748E5574A1031DD05E54FDA /* KnockRequestCell.swift in Sources */, D5E8EE8A288EFCCF646860EA /* KnockRequestsBannerView.swift in Sources */, + E8B290CBB7E5FF5E3C1B6124 /* KnockRequestsListEmptyStateView.swift in Sources */, AAA551AD8768309024D4907B /* KnockRequestsListScreen.swift in Sources */, 0307469D99B5FE6C7043AE39 /* KnockRequestsListScreenCoordinator.swift in Sources */, 9EE71509E6E7519A2B2388B3 /* KnockRequestsListScreenModels.swift in Sources */, diff --git a/ShareExtension/SupportingFiles/target.yml b/ShareExtension/SupportingFiles/target.yml index 469de107a8..cca24f0522 100644 --- a/ShareExtension/SupportingFiles/target.yml +++ b/ShareExtension/SupportingFiles/target.yml @@ -57,6 +57,8 @@ targets: NSExtensionActivationSupportsFileWithMaxCount: 1 NSExtensionActivationSupportsImageWithMaxCount: 1 NSExtensionActivationSupportsMovieWithMaxCount: 1 + NSExtensionActivationSupportsText: true + NSExtensionActivationSupportsWebURLWithMaxCount: 1 settings: base: From 26e07f24573b9aa9a49d1b361d8f276a957b039c Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Mon, 25 Nov 2024 13:14:02 +0100 Subject: [PATCH 50/74] Knock Requests banner display logic (#3550) * added the join rule to the info * update SDK and added logic to display the banner in the room screen * added the logic to display the banner --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../Sources/Mocks/InvitedRoomProxyMock.swift | 3 +- .../Sources/Mocks/JoinedRoomProxyMock.swift | 4 +- .../Sources/Mocks/KnockedRoomProxyMock.swift | 3 +- .../KnockRequestsListScreenModels.swift | 14 +++-- .../KnockRequestsListScreenViewModel.swift | 15 +++++- .../View/KnockRequestsListScreen.swift | 27 +++++----- .../RoomDetailsScreenModels.swift | 3 +- .../RoomDetailsScreenViewModel.swift | 6 +++ .../View/RoomDetailsScreen.swift | 6 ++- .../Screens/RoomScreen/RoomScreenModels.swift | 12 +++++ .../RoomScreen/RoomScreenViewModel.swift | 18 +++++-- .../Screens/RoomScreen/View/RoomScreen.swift | 53 +++++++++++++++---- .../Sources/Services/Room/RoomInfoProxy.swift | 1 + project.yml | 2 +- 16 files changed, 131 insertions(+), 42 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 4d4c5add3b..271b341de5 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -8195,7 +8195,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.73; + version = 1.0.74; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index a405104491..0290c04dfa 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "b3f97292695e8d63469c0d3ec608eb74423c6a2e", - "version" : "1.0.73" + "revision" : "66d32e79ae20dd31201cd16eced53cfcc0c3239d", + "version" : "1.0.74" } }, { diff --git a/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift b/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift index 65c71d8ea1..79b48100c8 100644 --- a/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift @@ -59,7 +59,8 @@ extension RoomInfo { numUnreadMessages: 0, numUnreadNotifications: 0, numUnreadMentions: 0, - pinnedEventIds: []) + pinnedEventIds: [], + joinRule: .invite) } } diff --git a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift index 0cd26ef425..d8acfaf791 100644 --- a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift @@ -39,6 +39,7 @@ struct JoinedRoomProxyMockConfiguration { var canUserPin = true var shouldUseAutoUpdatingTimeline = false + var joinRule: JoinRule? } extension JoinedRoomProxyMock { @@ -166,6 +167,7 @@ extension RoomInfo { numUnreadMessages: 0, numUnreadNotifications: 0, numUnreadMentions: 0, - pinnedEventIds: Array(configuration.pinnedEventIDs)) + pinnedEventIds: Array(configuration.pinnedEventIDs), + joinRule: configuration.joinRule) } } diff --git a/ElementX/Sources/Mocks/KnockedRoomProxyMock.swift b/ElementX/Sources/Mocks/KnockedRoomProxyMock.swift index 76559bae13..82d84d31ab 100644 --- a/ElementX/Sources/Mocks/KnockedRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/KnockedRoomProxyMock.swift @@ -57,6 +57,7 @@ extension RoomInfo { numUnreadMessages: 0, numUnreadNotifications: 0, numUnreadMentions: 0, - pinnedEventIds: []) + pinnedEventIds: [], + joinRule: .knock) } } diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift index 6459148289..f45b0e6ec0 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift @@ -11,9 +11,17 @@ enum KnockRequestsListScreenViewModelAction { } struct KnockRequestsListScreenViewState: BindableState { var requests: [KnockRequestCellInfo] = [] - var canAccept = false - var canDecline = false - var canBan = 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 + + // 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) + } } enum KnockRequestsListScreenViewAction { diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift index 3593196948..2c8327e22a 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift @@ -22,6 +22,7 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn self.roomProxy = roomProxy super.init(initialViewState: KnockRequestsListScreenViewState(), mediaProvider: mediaProvider) + updateRoomInfo(roomInfo: roomProxy.infoPublisher.value) Task { await updatePermissions() } @@ -48,13 +49,23 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn private func setupSubscriptions() { roomProxy.infoPublisher - .throttle(for: .milliseconds(200), scheduler: DispatchQueue.main, latest: true) - .sink { [weak self] _ in + .receive(on: DispatchQueue.main) + .sink { [weak self] roomInfo in + self?.updateRoomInfo(roomInfo: roomInfo) Task { await self?.updatePermissions() } } .store(in: &cancellables) } + private func updateRoomInfo(roomInfo: RoomInfoProxy) { + switch roomInfo.joinRule { + case .knock, .knockRestricted: + state.isKnockableRoom = true + default: + state.isKnockableRoom = false + } + } + private func updatePermissions() async { state.canAccept = await (try? roomProxy.canUserInvite(userID: roomProxy.ownUserID).get()) == true state.canDecline = await (try? roomProxy.canUserKick(userID: roomProxy.ownUserID).get()) == true diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift index 792dba762e..da85216743 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.requests.isEmpty { + if !context.viewState.shouldDisplayRequests { KnockRequestsListEmptyStateView() } } .safeAreaInset(edge: .bottom) { - if !context.viewState.requests.isEmpty { + if context.viewState.shouldDisplayRequests { acceptAllButton } } @@ -32,14 +32,16 @@ struct KnockRequestsListScreen: View { private var mainContent: some View { ScrollView { LazyVStack(spacing: 0) { - ForEach(context.viewState.requests) { requestInfo in - ListRow(kind: .custom { - KnockRequestCell(cellInfo: requestInfo, - mediaProvider: context.mediaProvider, - onAccept: context.viewState.canAccept ? onAccept : nil, - onDecline: context.viewState.canDecline ? onDecline : nil, - onDeclineAndBan: context.viewState.canBan ? onDeclineAndBan : nil) - }) + if context.viewState.shouldDisplayRequests { + ForEach(context.viewState.requests) { requestInfo in + ListRow(kind: .custom { + KnockRequestCell(cellInfo: requestInfo, + mediaProvider: context.mediaProvider, + onAccept: context.viewState.canAccept ? onAccept : nil, + onDecline: context.viewState.canDecline ? onDecline : nil, + onDeclineAndBan: context.viewState.canBan ? onDeclineAndBan : nil) + }) + } } } .padding(.top, 40) @@ -79,10 +81,7 @@ struct KnockRequestsListScreen_Previews: PreviewProvider, TestablePreview { // 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!")], - canAccept: true, - canDecline: true, - canBan: true)) + .init(id: "@dan:matrix.org", displayName: "Dan", avatarUrl: nil, timestamp: "Now", reason: "Hello! It's a me! Dan!")])) static var previews: some View { NavigationStack { diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift index b918884175..cfd247cdc3 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift @@ -49,9 +49,10 @@ struct RoomDetailsScreenViewState: BindableState { var canJoinCall = false var pinnedEventsActionState = RoomDetailsScreenPinnedEventsActionState.loading var knockingEnabled = false + var isKnockableRoom = false var canSeeKnockingRequests: Bool { - knockingEnabled && dmRecipient == nil && (canInviteUsers || canKickUsers || canBanUsers) + knockingEnabled && dmRecipient == nil && isKnockableRoom && (canInviteUsers || canKickUsers || canBanUsers) } var canEdit: Bool { diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift index ed7b4cf446..34a8d8a271 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift @@ -189,6 +189,12 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr state.topicSummary = topic?.unattributedStringByReplacingNewlinesWithSpaces() state.joinedMembersCount = roomInfo.joinedMembersCount state.bindings.isFavourite = roomInfo.isFavourite + switch roomInfo.joinRule { + case .knock, .knockRestricted: + state.isKnockableRoom = true + default: + state.isKnockableRoom = false + } } private func fetchMembersIfNeeded() async { diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift index 1873fbf15b..042ba4e614 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -323,7 +323,8 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { isDirect: false, isEncrypted: true, canonicalAlias: "#alias:domain.com", - members: members)) + members: members, + joinRule: .knock)) var notificationSettingsProxyMockConfiguration = NotificationSettingsProxyMockConfiguration() notificationSettingsProxyMockConfiguration.roomMode.isDefault = false @@ -378,7 +379,8 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { name: "Room A", isDirect: false, isEncrypted: false, - members: members)) + members: members, + joinRule: .knock)) let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init()) return RoomDetailsScreenViewModel(roomProxy: roomProxy, diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift index 92c9bfdbe2..4c8ff2009f 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift @@ -39,6 +39,18 @@ struct RoomScreenViewState: BindableState { var hasOngoingCall: Bool var shouldShowCallButton = true + var isKnockingEnabled = false + var isKnockableRoom = false + 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 shouldSeeKnockRequests: Bool { + isKnockingEnabled && isKnockableRoom && !unseenKnockRequests.isEmpty && (canAcceptKnocks || canDeclineKnocks || canBan) + } + var footerDetails: RoomScreenFooterViewDetails? var bindings: RoomScreenViewStateBindings diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift index 93c95e1a3f..3e43a48370 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift @@ -117,6 +117,10 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol // MARK: - Private private func setupSubscriptions(ongoingCallRoomIDPublisher: CurrentValuePublisher) { + appSettings.$knockingEnabled + .weakAssign(to: \.state.isKnockingEnabled, on: self) + .store(in: &cancellables) + let roomInfoSubscription = roomProxy .infoPublisher @@ -236,10 +240,18 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol state.pinnedEventsBannerState = .loading(numbersOfEvents: pinnedEventIDs.count) } - let userID = roomProxy.ownUserID - if case let .success(permission) = await roomProxy.canUserJoinCall(userID: userID) { - state.canJoinCall = permission + switch (roomProxy.isEncryptedOneToOneRoom, roomInfo.joinRule) { + case (false, .knock), (false, .knockRestricted): + state.isKnockableRoom = true + default: + state.isKnockableRoom = false } + + let ownUserID = roomProxy.ownUserID + state.canJoinCall = await (try? roomProxy.canUserJoinCall(userID: ownUserID).get()) == true + state.canAcceptKnocks = await (try? roomProxy.canUserInvite(userID: ownUserID).get()) == true + state.canDeclineKnocks = await (try? roomProxy.canUserKick(userID: ownUserID).get()) == true + state.canBan = await (try? roomProxy.canUserBan(userID: ownUserID).get()) == true } private func setupPinnedEventsTimelineProviderIfNeeded() { diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift index 9e187d8ab3..3df34b6439 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift @@ -29,12 +29,11 @@ struct RoomScreen: View { timeline .background(Color.compound.bgCanvasDefault.ignoresSafeArea()) .overlay(alignment: .top) { - Group { - if roomContext.viewState.shouldShowPinnedEventsBanner { - pinnedItemsBanner - } - } - .animation(.elementDefault, value: roomContext.viewState.shouldShowPinnedEventsBanner) + pinnedItemsBanner + } + // This can overlay on top of the pinnedItemsBanner + .overlay(alignment: .top) { + knockRequestsBanner } .safeAreaInset(edge: .bottom, spacing: 0) { VStack(spacing: 0) { @@ -119,11 +118,45 @@ struct RoomScreen: View { } } + @ViewBuilder private var pinnedItemsBanner: some View { - PinnedItemsBannerView(state: roomContext.viewState.pinnedEventsBannerState, - onMainButtonTap: { roomContext.send(viewAction: .tappedPinnedEventsBanner) }, - onViewAllButtonTap: { roomContext.send(viewAction: .viewAllPins) }) - .transition(.move(edge: .top)) + Group { + if roomContext.viewState.shouldShowPinnedEventsBanner { + PinnedItemsBannerView(state: roomContext.viewState.pinnedEventsBannerState, + onMainButtonTap: { roomContext.send(viewAction: .tappedPinnedEventsBanner) }, + onViewAllButtonTap: { roomContext.send(viewAction: .viewAllPins) }) + .transition(.move(edge: .top)) + } + } + .animation(.elementDefault, value: roomContext.viewState.shouldShowPinnedEventsBanner) + } + + @ViewBuilder + private var knockRequestsBanner: some View { + Group { + if roomContext.viewState.shouldSeeKnockRequests { + KnockRequestsBannerView(requests: roomContext.viewState.unseenKnockRequests, + onDismiss: dismissKnockRequestsBanner, + onAccept: roomContext.viewState.canAcceptKnocks ? acceptKnockRequest : nil, + onViewAll: onViewAllKnockRequests, + mediaProvider: roomContext.mediaProvider) + .padding(.top, 16) + .transition(.move(edge: .top)) + } + } + .animation(.elementDefault, value: roomContext.viewState.shouldSeeKnockRequests) + } + + private func dismissKnockRequestsBanner() { + // TODO: Implement + } + + private func acceptKnockRequest(userID: String) { + // TODO: Implement + } + + private func onViewAllKnockRequests() { + // TODO: Implement } private var scrollToBottomButton: some View { diff --git a/ElementX/Sources/Services/Room/RoomInfoProxy.swift b/ElementX/Sources/Services/Room/RoomInfoProxy.swift index 9cd290228e..5e9da29e3a 100644 --- a/ElementX/Sources/Services/Room/RoomInfoProxy.swift +++ b/ElementX/Sources/Services/Room/RoomInfoProxy.swift @@ -65,6 +65,7 @@ struct RoomInfoProxy: BaseRoomInfoProxyProtocol { var unreadNotificationsCount: UInt { UInt(roomInfo.numUnreadNotifications) } var unreadMentionsCount: UInt { UInt(roomInfo.numUnreadMentions) } var pinnedEventIDs: Set { Set(roomInfo.pinnedEventIds) } + var joinRule: JoinRule? { roomInfo.joinRule } } struct RoomPreviewInfoProxy: BaseRoomInfoProxyProtocol { diff --git a/project.yml b/project.yml index 16c5b4624e..9739ec753b 100644 --- a/project.yml +++ b/project.yml @@ -61,7 +61,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.73 + exactVersion: 1.0.74 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From ba8edc31c78095c7c22f200d400dbe9d91b83495 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Mon, 25 Nov 2024 12:20:34 +0000 Subject: [PATCH 51/74] Translations update (#3552) * Translations update * Run the workflow at 3am instead. --------- Co-authored-by: Velin92 <34335419+Velin92@users.noreply.github.com> Co-authored-by: Doug --- .github/workflows/translations-pr.yml | 4 +- .../be.lproj/Localizable.strings | 9 +++ .../bg.lproj/Localizable.strings | 9 +++ .../cs.lproj/Localizable.strings | 9 +++ .../de.lproj/Localizable.strings | 9 +++ .../el.lproj/Localizable.strings | 77 +++++++++++-------- .../el.lproj/Localizable.stringsdict | 4 +- .../es.lproj/Localizable.strings | 9 +++ .../et.lproj/Localizable.strings | 9 +++ .../fa.lproj/Localizable.strings | 9 +++ .../fi.lproj/Localizable.strings | 13 +++- .../fr.lproj/Localizable.strings | 9 +++ .../hu.lproj/Localizable.strings | 9 +++ .../id.lproj/Localizable.strings | 9 +++ .../it.lproj/Localizable.strings | 9 +++ .../ka.lproj/Localizable.strings | 9 +++ .../nl.lproj/Localizable.strings | 11 ++- .../pl.lproj/Localizable.strings | 9 +++ .../pt-BR.lproj/Localizable.strings | 15 +++- .../pt.lproj/Localizable.strings | 9 +++ .../ro.lproj/Localizable.strings | 9 +++ .../ru.lproj/Localizable.strings | 11 ++- .../sk.lproj/Localizable.strings | 9 +++ .../sv.lproj/Localizable.strings | 19 +++-- .../uk.lproj/Localizable.strings | 9 +++ .../uz.lproj/Localizable.strings | 11 ++- .../zh-Hans.lproj/Localizable.strings | 9 +++ .../zh-Hant-TW.lproj/Localizable.strings | 9 +++ 28 files changed, 285 insertions(+), 51 deletions(-) diff --git a/.github/workflows/translations-pr.yml b/.github/workflows/translations-pr.yml index 5a5003fdf7..695344cebc 100644 --- a/.github/workflows/translations-pr.yml +++ b/.github/workflows/translations-pr.yml @@ -1,8 +1,8 @@ name: Open Translations PR on: schedule: - # At 00:00 on every Monday UTC - - cron: '0 0 * * 1' + # At 03:00 on every Monday UTC + - cron: '0 3 * * 1' workflow_dispatch: jobs: diff --git a/ElementX/Resources/Localizations/be.lproj/Localizable.strings b/ElementX/Resources/Localizations/be.lproj/Localizable.strings index 952ffd4c66..c554a8ba59 100644 --- a/ElementX/Resources/Localizations/be.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/be.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Запісаць галасавое паведамленне."; "a11y_voice_message_stop_recording" = "Спыніць запіс"; "action_accept" = "Прыняць"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Дадаць у хроніку"; "action_back" = "Назад"; "action_call" = "Званок"; @@ -47,6 +48,7 @@ "action_discard" = "Адмяніць"; "action_done" = "Гатова"; "action_edit" = "Рэдагаваць"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Рэдагаваць апытанне"; "action_enable" = "Уключыць"; "action_end_poll" = "Скончыць апытанне"; @@ -81,6 +83,7 @@ "action_react" = "Рэакцыя"; "action_reject" = "Адхіліць"; "action_remove" = "Выдаліць"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Адказаць"; "action_reply_in_thread" = "Адказаць у гутаркі"; "action_report_bug" = "Паведаміць пра памылку"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Наладзіць аднаўленне"; "common_about" = "Аб праграме"; "common_acceptable_use_policy" = "Палітыка дапушчальнага выкарыстання"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Пашыраныя налады"; "common_analytics" = "Аналітыка"; "common_appearance" = "Знешні выгляд"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Прамы чат"; "common_edited_suffix" = "(Адрэдагавана)"; "common_editing" = "Рэдагаванне"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "Шыфраванне ўключана"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Націсніце на паведамленне і абярыце «%1$@ », каб уключыць сюды."; "screen_pinned_timeline_empty_state_headline" = "Замацуеце важныя паведамленні, каб іх можна было лёгка знайсці"; "screen_reset_encryption_password_error" = "Адбылася невядомая памылка. Калі ласка, праверце правільнасць пароля вашага ўліковага запісу і паўтарыце спробу."; diff --git a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings index ebe91601ed..de474f50d2 100644 --- a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Record voice message."; "a11y_voice_message_stop_recording" = "Stop recording"; "action_accept" = "Приемане"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Add to timeline"; "action_back" = "Назад"; "action_call" = "Call"; @@ -47,6 +48,7 @@ "action_discard" = "Discard"; "action_done" = "Готово"; "action_edit" = "Редактиране"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Редактиране на анкетата"; "action_enable" = "Активиране"; "action_end_poll" = "Приключване на анкетата"; @@ -81,6 +83,7 @@ "action_react" = "Реакция"; "action_reject" = "Reject"; "action_remove" = "Премахване"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Отговор"; "action_reply_in_thread" = "Отговор в нишка"; "action_report_bug" = "Report bug"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Set up recovery to protect your account"; "common_about" = "Относно"; "common_acceptable_use_policy" = "Acceptable use policy"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Разширени настройки"; "common_analytics" = "Статистика"; "common_appearance" = "Облик"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Директен чат"; "common_edited_suffix" = "(редактирано)"; "common_editing" = "Редактиране"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "Шифроването е включено"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; diff --git a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings index 44aa4500b5..df250261a6 100644 --- a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Nahrajte hlasovou zprávu."; "a11y_voice_message_stop_recording" = "Zastavit nahrávání"; "action_accept" = "Přijmout"; +"action_add_caption" = "Přidat titulek"; "action_add_to_timeline" = "Přidat na časovou osu"; "action_back" = "Zpět"; "action_call" = "Hovor"; @@ -47,6 +48,7 @@ "action_discard" = "Vyřadit"; "action_done" = "Hotovo"; "action_edit" = "Upravit"; +"action_edit_caption" = "Upravit titulek"; "action_edit_poll" = "Upravit hlasování"; "action_enable" = "Povolit"; "action_end_poll" = "Ukončit hlasování"; @@ -81,6 +83,7 @@ "action_react" = "Reagovat"; "action_reject" = "Odmítnout"; "action_remove" = "Odstranit"; +"action_remove_caption" = "Odstranit titulek"; "action_reply" = "Odpovědět"; "action_reply_in_thread" = "Odpovědět ve vlákně"; "action_report_bug" = "Nahlásit chybu"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Nastavení obnovy"; "common_about" = "O aplikaci"; "common_acceptable_use_policy" = "Zásady používání"; +"common_adding_caption" = "Přidání titulku"; "common_advanced_settings" = "Pokročilá nastavení"; "common_analytics" = "Analytika"; "common_appearance" = "Vzhled"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Přímý chat"; "common_edited_suffix" = "(upraveno)"; "common_editing" = "Úpravy"; +"common_editing_caption" = "Úprava titulku"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Šifrování"; "common_encryption_enabled" = "Šifrování povoleno"; @@ -365,7 +370,11 @@ "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_button_title" = "Přijmout vše"; "screen_knock_requests_list_decline_and_ban_action_title" = "Odmítnout a vykázat"; +"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_title" = "Žádosti o vstup"; "screen_pinned_timeline_empty_state_description" = "Přidržte zprávu a vyberte „%1$@“, kterou chcete zahrnout sem."; "screen_pinned_timeline_empty_state_headline" = "Připněte důležité zprávy, aby je bylo možné snadno najít"; "screen_reset_encryption_password_error" = "Došlo k neznámé chybě. Zkontrolujte, zda je heslo k účtu správné a zkuste to znovu."; diff --git a/ElementX/Resources/Localizations/de.lproj/Localizable.strings b/ElementX/Resources/Localizations/de.lproj/Localizable.strings index 64480a742c..96f128ed64 100644 --- a/ElementX/Resources/Localizations/de.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/de.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Sprachnachricht aufnehmen."; "a11y_voice_message_stop_recording" = "Aufnahme beenden"; "action_accept" = "Akzeptieren"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Zum Nachrichtenverlauf hinzufügen"; "action_back" = "Zurück"; "action_call" = "Anruf"; @@ -47,6 +48,7 @@ "action_discard" = "Verwerfen"; "action_done" = "Erledigt"; "action_edit" = "Bearbeiten"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Umfrage bearbeiten"; "action_enable" = "Aktivieren"; "action_end_poll" = "Umfrage beenden"; @@ -81,6 +83,7 @@ "action_react" = "Reagieren"; "action_reject" = "Ablehnen"; "action_remove" = "Entfernen"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Antworten"; "action_reply_in_thread" = "Im Thread antworten"; "action_report_bug" = "Fehler melden"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Wiederherstellung einrichten"; "common_about" = "Über"; "common_acceptable_use_policy" = "Nutzungsrichtlinie"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Erweiterte Einstellungen"; "common_analytics" = "Analysedaten"; "common_appearance" = "Erscheinungsbild"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Direktnachricht"; "common_edited_suffix" = "(bearbeitet)"; "common_editing" = "Bearbeitung"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "Verschlüsselung aktiviert"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Drücke auf eine Nachricht und wähle “%1$@”, um sie hier einzufügen."; "screen_pinned_timeline_empty_state_headline" = "Fixiere wichtige Nachrichten, so dass sie leicht gefunden werden können"; "screen_reset_encryption_password_error" = "Es ist ein unbekannter Fehler aufgetreten. Bitte überprüfe das Passwort deines Kontos und versuche es erneut."; diff --git a/ElementX/Resources/Localizations/el.lproj/Localizable.strings b/ElementX/Resources/Localizations/el.lproj/Localizable.strings index 4d1647d964..9d2a10296c 100644 --- a/ElementX/Resources/Localizations/el.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/el.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Εγγραφή φωνητικού μηνύματος."; "a11y_voice_message_stop_recording" = "Διακοπή καταγραφής"; "action_accept" = "Αποδοχή"; +"action_add_caption" = "Προσθήκη λεζάντας"; "action_add_to_timeline" = "Προσθήκη στο χρονοδιάγραμμα"; "action_back" = "Πίσω"; "action_call" = "Κάλεσε"; @@ -47,6 +48,7 @@ "action_discard" = "Απόρριψη"; "action_done" = "Έγινε"; "action_edit" = "Επεξεργασία"; +"action_edit_caption" = "Επεξεργασία λεζάντας"; "action_edit_poll" = "Επεξεργασία δημοσκόπησης"; "action_enable" = "Ενεργοποίηση"; "action_end_poll" = "Λήξη δημοσκόπησης"; @@ -81,6 +83,7 @@ "action_react" = "Αντέδρασε"; "action_reject" = "Απόρριψη"; "action_remove" = "Αφαίρεση"; +"action_remove_caption" = "Αφαίρεση λεζάντας"; "action_reply" = "Απάντηση"; "action_reply_in_thread" = "Απάντηση στο θέμα"; "action_report_bug" = "Αναφορά σφάλματος"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Ρύθμιση ανάκτησης"; "common_about" = "Σχετικά"; "common_acceptable_use_policy" = "Πολιτική αποδεκτής χρήσης"; +"common_adding_caption" = "Η λεζάντα προστίθεται"; "common_advanced_settings" = "Ρυθμίσεις για προχωρημένους"; "common_analytics" = "Στατιστικά στοιχεία"; "common_appearance" = "Εμφάνιση"; @@ -137,8 +141,9 @@ "common_direct_chat" = "Άμεση συνομιλία"; "common_edited_suffix" = "(επεξεργάστηκε)"; "common_editing" = "Επεξεργάζεται"; +"common_editing_caption" = "Η λεζάντα επεξεργάζεται"; "common_emote" = "* %1$@ %2$@"; -"common_encryption" = "Encryption"; +"common_encryption" = "Κρυπτογράφηση"; "common_encryption_enabled" = "Η κρυπτογράφηση ενεργοποιήθηκε"; "common_enter_your_pin" = "Εισήγαγε το PIN σου"; "common_error" = "Σφάλμα"; @@ -149,7 +154,7 @@ "common_favourited" = "Είναι αγαπημένο"; "common_file" = "Αρχείο"; "common_forward_message" = "Προώθηση μηνύματος"; -"common_frequently_used" = "Frequently used"; +"common_frequently_used" = "Χρησιμοποιείται συχνά"; "common_gif" = "GIF"; "common_image" = "Εικόνα"; "common_in_reply_to" = "Σε απάντηση στον χρήστη %1$@"; @@ -225,7 +230,7 @@ "common_unable_to_invite_title" = "Δεν είναι δυνατή η αποστολή προσκλήσεων"; "common_unlock" = "Ξεκλείδωμα"; "common_unmute" = "Άρση σίγασης"; -"common_unsupported_call" = "Unsupported call"; +"common_unsupported_call" = "Μη υποστηριζόμενη κλήση"; "common_unsupported_event" = "Μη υποστηριζόμενο συμβάν"; "common_username" = "Όνομα χρήστη"; "common_verification_cancelled" = "Η επαλήθευση ακυρώθηκε"; @@ -233,7 +238,7 @@ "common_verification_failed" = "Αποτυχία επαλήθευσης"; "common_verified" = "Επαληθεύτηκε"; "common_verify_device" = "Επαλήθευση συσκευής"; -"common_verify_identity" = "Verify identity"; +"common_verify_identity" = "Επαλήθευση ταυτότητας"; "common_video" = "Βίντεο"; "common_voice_message" = "Φωνητικό μήνυμα"; "common_waiting" = "Αναμονή…"; @@ -245,10 +250,10 @@ "common.send_to" = "Αποστολή σε"; "common.you" = "Εσύ"; "common_unable_to_decrypt_insecure_device" = "Στάλθηκε από μια μη ασφαλής συσκευή"; -"common_unable_to_decrypt_verification_violation" = "Sender's verified identity has changed"; +"common_unable_to_decrypt_verification_violation" = "Η επαληθευμένη ταυτότητα του αποστολέα έχει αλλάξει"; "confirm_recovery_key_banner_message" = "Επιβεβαίωσε το κλειδί ανάκτησης για να διατηρήσεις την πρόσβαση στο χώρο αποθήκευσης κλειδιών και στο ιστορικό μηνυμάτων."; -"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_primary_button_title" = "Εισήγαγε το κλειδί ανάκτησης"; +"confirm_recovery_key_banner_secondary_button_title" = "Ξέχασες το κλειδί ανάκτησης;"; "confirm_recovery_key_banner_title" = "Ο χώρος αποθήκευσης κλειδιών σου δεν είναι συγχρονισμένος"; "crash_detection_dialog_content" = "Το %1$@ διακόπηκε την τελευταία φορά που χρησιμοποιήθηκε. Θα 'θελες να μοιραστείς μια αναφορά σφάλματος μαζί μας;"; "crypto_identity_change_pin_violation" = "Η ταυτότητα του χρήστη %1$@ φαίνεται να έχει αλλάξει. %2$@"; @@ -344,7 +349,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" = "Προαιρετική λεζάντα..."; "screen_advanced_settings_element_call_base_url" = "Προσαρμοσμένο URL βάσης κλήσεων Element"; "screen_advanced_settings_element_call_base_url_description" = "Όρισε μια προσαρμοσμένη διεύθυνση βάσης URL για κλήση Element."; "screen_advanced_settings_element_call_base_url_validation_error" = "Μη έγκυρη διεύθυνση URL, βεβαιώσου ότι έχεις συμπεριλάβει το πρωτόκολλο (http/https) και τη σωστή διεύθυνση."; @@ -353,11 +358,11 @@ "screen_create_room_room_access_section_header" = "Πρόσβαση Δωματίου"; "screen_create_room_room_access_section_knocking_option_description" = "Οποιοσδήποτε μπορεί να ζητήσει να συμμετάσχει στο δωμάτιο, αλλά ένας διαχειριστής ή συντονιστής θα πρέπει να αποδεχθεί το αίτημα"; "screen_create_room_room_access_section_knocking_option_title" = "Αίτημα συμμετοχής"; -"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_create_room_room_address_invalid_symbols_error_description" = "Ορισμένοι χαρακτήρες δεν επιτρέπονται. Υποστηρίζονται μόνο γράμματα, ψηφία και τα ακόλουθα σύμβολα ! $ & '() * +/; = ? @ [] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Αυτή η διεύθυνση δωματίου υπάρχει ήδη, δοκίμασε να επεξεργαστείς το πεδίο διεύθυνσης δωματίου ή να αλλάξεις το όνομα δωματίου"; +"screen_create_room_room_address_section_footer" = "Για να είναι ορατό αυτό το δωμάτιο στον κατάλογο των δημόσιων δωματίων, θα χρειαστείς μια διεύθυνση δωματίου."; +"screen_create_room_room_address_section_title" = "Διεύθυνση δωματίου"; +"screen_create_room_room_visibility_section_title" = "Ορατότητα δωματίου"; "screen_join_room_cancel_knock_action" = "Ακύρωση αιτήματος"; "screen_join_room_cancel_knock_alert_confirmation" = "Ναι, ακύρωση"; "screen_join_room_cancel_knock_alert_description" = "Σίγουρα θες να ακυρώσεις το αίτημά σου για συμμετοχή σε αυτό το δωμάτιο;"; @@ -365,7 +370,11 @@ "screen_join_room_knock_message_description" = "Μήνυμα (προαιρετικό)"; "screen_join_room_knock_sent_description" = "Θα λάβεις πρόσκληση για συμμετοχή στο δωμάτιο εάν το αίτημά σου γίνει αποδεκτό."; "screen_join_room_knock_sent_title" = "Το αίτημα συμμετοχής στάλθηκε"; -"screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_accept_all_button_title" = "Αποδοχή όλων"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Απόρριψη και αποκλεισμός"; +"screen_knock_requests_list_empty_state_description" = "Όταν κάποιος θα ζητήσει να συμμετάσχει στο δωμάτιο, θα μπορείς να δεις το αίτημά του εδώ."; +"screen_knock_requests_list_empty_state_title" = "Δεν υπάρχει εκκρεμές αίτημα συμμετοχής"; +"screen_knock_requests_list_title" = "Αιτήματα συμμετοχής"; "screen_pinned_timeline_empty_state_description" = "Πάτα σε ένα μήνυμα και επέλεξε «%1$@» για να συμπεριληφθεί εδώ."; "screen_pinned_timeline_empty_state_headline" = "Καρφίτσωσε σημαντικά μηνύματα, ώστε να μπορούν να εντοπιστούν εύκολα"; "screen_reset_encryption_password_error" = "Συνέβη ένα άγνωστο σφάλμα. Έλεγξε ότι ο κωδικός πρόσβασης του λογαριασμού σου είναι σωστός και δοκίμασε ξανά."; @@ -378,16 +387,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Μία ή περισσότερες από τις συσκευές σου δεν έχουν επαληθευτεί. Μπορείς να στείλεις το μήνυμα ούτως ή άλλως, ή μπορείς να το ακυρώσεις προς το παρόν και να προσπαθήσεις ξανά αργότερα αφού επαληθεύσεις όλες τις συσκευές σου."; "screen_resolve_send_failure_you_unsigned_device_title" = "Το μήνυμά σου δεν στάλθηκε επειδή δεν έχεις επαληθεύσει τουλάχιστον μία από τις συσκευές σου"; "screen_room_mentions_at_room_subtitle" = "Ειδοποίησε όλο το δωμάτιο"; -"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; +"screen_room_multiple_knock_requests_view_all_button_title" = "Προβολή όλων"; "screen_room_pinned_banner_indicator" = "%1$@ από %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Καρφιτσωμένα μηνύματα"; "screen_room_pinned_banner_loading_description" = "Φόρτωση μηνύματος..."; "screen_room_pinned_banner_view_all_button_title" = "Προβολή Όλων"; -"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" = "Αποδοχή"; +"screen_room_single_knock_request_title" = "Ο χρήστης %1$@ θέλει να μπει σε αυτό το δωμάτιο"; +"screen_room_single_knock_request_view_button_title" = "Προβολή"; "screen_room_details_pinned_events_row_title" = "Καρφιτσωμένα μηνύματα"; -"screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_requests_to_join_title" = "Αιτήματα συμμετοχής"; "screen_roomlist_knock_event_sent_description" = "Το αίτημα συμμετοχής στάλθηκε"; "screen_timeline_item_menu_send_failure_changed_identity" = "Το μήνυμα δεν στάλθηκε επειδή η επαληθευμένη ταυτότητα του χρήστη %1$@ έχει αλλάξει."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Το μήνυμα δεν στάλθηκε επειδή ο χρήστης %1$@ δεν έχει επαληθεύσει όλες τις συσκευές."; @@ -400,8 +409,8 @@ "screen_account_provider_signup_title" = "Πρόκειται να δημιουργήσεις έναν λογαριασμό στο %@"; "screen_advanced_settings_developer_mode" = "Λειτουργία προγραμματιστή"; "screen_advanced_settings_developer_mode_description" = "Ενεργοποίησε την πρόσβαση σε δυνατότητες και λειτουργικότητα για προγραμματιστές."; -"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" = "Ανέβασε φωτογραφίες και βίντεο γρηγορότερα και μείωσε τη χρήση δεδομένων"; +"screen_advanced_settings_media_compression_title" = "Βελτιστοποίηση ποιότητας των μέσων"; "screen_advanced_settings_rich_text_editor_description" = "Απενεργοποίησε τον επεξεργαστή εμπλουτισμένου κειμένου για να πληκτρολογήσεις Markdown χειροκίνητα."; "screen_advanced_settings_send_read_receipts" = "Αποδεικτικά ανάγνωσης"; "screen_advanced_settings_send_read_receipts_description" = "Εάν απενεργοποιηθεί, τα αποδεικτικά ανάγνωσης δεν θα στέλνονται σε κανέναν. Θα εξακολουθείς να λαμβάνεις αποδεικτικά ανάγνωσης από άλλους χρήστες."; @@ -470,11 +479,11 @@ "screen_chat_backup_key_backup_action_enable" = "Ενεργοποίηση αντιγράφων ασφαλείας"; "screen_chat_backup_key_backup_description" = "Αποθήκευσε την κρυπτογραφική σου ταυτότητα και τα κλειδιά μηνυμάτων με ασφάλεια στον διακομιστή. Αυτό θα σου επιτρέψει να δεις το ιστορικό μηνυμάτων σου σε οποιεσδήποτε νέες συσκευές. %1$@."; "screen_chat_backup_key_backup_title" = "Χώρος αποθήκευσης κλειδιού"; -"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_storage_disabled_error" = "Η αποθήκευση κλειδιών πρέπει να είναι ενεργοποιημένη για να ρυθμίσεις την ανάκτηση."; +"screen_chat_backup_key_storage_toggle_description" = "Μεταφόρτωση κλειδιών από αυτήν τη συσκευή"; +"screen_chat_backup_key_storage_toggle_title" = "Να επιτρέπεται η αποθήκευση κλειδιών"; "screen_chat_backup_recovery_action_change" = "Αλλαγή κλειδιού ανάκτησης"; -"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_change_description" = "Ανάκτησε την κρυπτογραφική σου ταυτότητα και το ιστορικό μηνυμάτων με ένα κλειδί ανάκτησης εάν έχεις χάσει όλες τις υπάρχουσες συσκευές σου."; "screen_chat_backup_recovery_action_confirm_description" = "Ο αποθηκευτικός χώρος κλειδιών σου δεν είναι συγχρονισμένος αυτήν τη στιγμή."; "screen_chat_backup_recovery_action_setup_description" = "Απόκτησε πρόσβαση στα κρυπτογραφημένα σου μηνύματα εάν χάσεις όλες τις συσκευές σου ή έχεις αποσυνδεθεί από το %1$@ παντού."; "screen_create_account_title" = "Δημιουργία λογαριασμού"; @@ -795,7 +804,7 @@ "screen_room_timeline_add_reaction" = "Προσθήκη emoji"; "screen_room_timeline_beginning_of_room" = "Αυτή είναι η αρχή του %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Αυτή είναι η αρχή τούτης της συνομιλίας."; -"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; +"screen_room_timeline_legacy_call" = "Μη υποστηριζόμενη κλήση. Ρώτα εάν ο καλών μπορεί να χρησιμοποιήσει τη νέα εφαρμογή Element X."; "screen_room_timeline_less_reactions" = "Εμφάνιση λιγότερων"; "screen_room_timeline_message_copied" = "Το μήνυμα αντιγράφηκε"; "screen_room_timeline_no_permission_to_post" = "Δεν έχεις άδεια να δημοσιεύσεις σε αυτό το δωμάτιο"; @@ -848,18 +857,18 @@ "screen_session_verification_ready_subtitle" = "Σύγκρινε ένα μοναδικό σύνολο emojis."; "screen_session_verification_request_accepted_subtitle" = "Σύγκρινε τα μοναδικά emoji και σιγουρέψου ότι εμφανίζονται με την ίδια σειρά."; "screen_session_verification_request_details_timestamp" = "Έχεις συνδεθεί"; -"screen_session_verification_request_failure_title" = "Verification failed"; +"screen_session_verification_request_failure_title" = "Αποτυχία επαλήθευσης"; "screen_session_verification_request_footer" = "Συνέχισε μόνο εάν ξεκίνησες εσύ αυτήν την επαλήθευση."; "screen_session_verification_request_subtitle" = "Επαλήθευσε την άλλη συσκευή για να διατηρήσεις το ιστορικό μηνυμάτων σου ασφαλές."; -"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_success_subtitle" = "Τώρα μπορείς να διαβάσεις ή να στείλεις μηνύματα με ασφάλεια στην άλλη συσκευή σου."; +"screen_session_verification_request_success_title" = "Η συσκευή επαληθεύτηκε"; "screen_session_verification_request_title" = "Ζητήθηκε επαλήθευση"; "screen_session_verification_they_dont_match" = "Δεν ταιριάζουν"; "screen_session_verification_they_match" = "Ταιριάζουν"; -"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" = "Βεβαιώσου ότι έχεις ανοιχτή την εφαρμογή στην άλλη συσκευή πριν ξεκινήσεις την επαλήθευση από εδώ."; +"screen_session_verification_use_another_device_title" = "Άνοιξε την εφαρμογή σε άλλη επαληθευμένη συσκευή"; +"screen_session_verification_waiting_another_device_subtitle" = "Πρόκειται να δεις ένα αναδυόμενο παράθυρο στην άλλη συσκευή. Ξεκίνα την επαλήθευση από εκεί τώρα."; +"screen_session_verification_waiting_another_device_title" = "Έναρξη επαλήθευσης στην άλλη συσκευή"; "screen_session_verification_waiting_to_accept_subtitle" = "Αποδέξου το αίτημα για να ξεκινήσεις τη διαδικασία επαλήθευσης στην άλλη συνεδρία σου για να συνεχίσεις."; "screen_session_verification_waiting_to_accept_title" = "Αναμονή για αποδοχή αιτήματος"; "screen_share_location_title" = "Κοινή χρήση τοποθεσίας"; @@ -1046,7 +1055,7 @@ "screen_notification_settings_mentions_section_title" = "Αναφορές"; "screen_qr_code_login_invalid_scan_state_retry_button" = "Προσπάθησε ξανά"; "screen_recovery_key_change_generate_key_description" = "Μην το μοιραστείς με κανέναν!"; -"screen_recovery_key_confirm_title" = "Enter your recovery key"; +"screen_recovery_key_confirm_title" = "Εισήγαγε το κλειδί ανάκτησης"; "screen_report_content_block_user" = "Αποκλεισμός χρήστη"; "screen_reset_encryption_password_placeholder" = "Εισαγωγή..."; "screen_room_attachment_source_camera_photo" = "Τράβηξε φωτογραφία"; diff --git a/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict index bb2306250e..de66f82709 100644 --- a/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/el.lproj/Localizable.stringsdict @@ -237,9 +237,9 @@ NSStringFormatValueTypeKey d one - %1$@ +%2$d other want to join this room + Οι χρήστες %1$@ +%2$d ακόμη θέλουν να συμμετάσχουν σε αυτό το δωμάτιο other - %1$@ +%2$d others want to join this room + Οι χρήστες %1$@ +%2$d ακόμη θέλουν να συμμετάσχουν σε αυτό το δωμάτιο screen_room_timeline_state_changes diff --git a/ElementX/Resources/Localizations/es.lproj/Localizable.strings b/ElementX/Resources/Localizations/es.lproj/Localizable.strings index 98f3626bef..71aa00537b 100644 --- a/ElementX/Resources/Localizations/es.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/es.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Grabar mensaje de voz"; "a11y_voice_message_stop_recording" = "Detener grabación"; "action_accept" = "Aceptar"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Añadir a la cronología"; "action_back" = "Atrás"; "action_call" = "Call"; @@ -47,6 +48,7 @@ "action_discard" = "Descartar"; "action_done" = "Hecho"; "action_edit" = "Editar"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Editar encuesta"; "action_enable" = "Activar"; "action_end_poll" = "Finalizar encuesta"; @@ -81,6 +83,7 @@ "action_react" = "Reaccionar"; "action_reject" = "Reject"; "action_remove" = "Eliminar"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Responder"; "action_reply_in_thread" = "Responder en el hilo"; "action_report_bug" = "Informar de un error"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Set up recovery to protect your account"; "common_about" = "Acerca de"; "common_acceptable_use_policy" = "Política de uso aceptable"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Ajustes avanzados"; "common_analytics" = "Estadísticas"; "common_appearance" = "Apariencia"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Chat directo"; "common_edited_suffix" = "(editado)"; "common_editing" = "Edición"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "Cifrado activado"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; diff --git a/ElementX/Resources/Localizations/et.lproj/Localizable.strings b/ElementX/Resources/Localizations/et.lproj/Localizable.strings index 3351125538..3b206cc39e 100644 --- a/ElementX/Resources/Localizations/et.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/et.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Salvesta häälsõnum"; "a11y_voice_message_stop_recording" = "Lõpeta salvestamine"; "action_accept" = "Nõustu"; +"action_add_caption" = "Lisa selgitus"; "action_add_to_timeline" = "Lisa ajajoonele"; "action_back" = "Tagasi"; "action_call" = "Helista"; @@ -47,6 +48,7 @@ "action_discard" = "Loobu"; "action_done" = "Valmis"; "action_edit" = "Muuda"; +"action_edit_caption" = "Muuda selgitust"; "action_edit_poll" = "Muuda küsitlust"; "action_enable" = "Võta kasutusele"; "action_end_poll" = "Lõpeta küsitlus"; @@ -81,6 +83,7 @@ "action_react" = "Reageeri"; "action_reject" = "Keeldu"; "action_remove" = "Eemalda"; +"action_remove_caption" = "Eemalda selgitus"; "action_reply" = "Vasta"; "action_reply_in_thread" = "Vasta jutulõngas"; "action_report_bug" = "Teata veast"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Seadista taastamine"; "common_about" = "Rakenduse teave"; "common_acceptable_use_policy" = "Vastuvõetava kasutamise põhimõtted"; +"common_adding_caption" = "Lisame selgitust"; "common_advanced_settings" = "Täiendavad seadistused"; "common_analytics" = "Analüütika"; "common_appearance" = "Välimus"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Otsevestlus"; "common_edited_suffix" = "(muudetud)"; "common_editing" = "Muutmine"; +"common_editing_caption" = "Muudame selgitust"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Krüptimine"; "common_encryption_enabled" = "Krüptimine on kasutusel"; @@ -365,7 +370,11 @@ "screen_join_room_knock_message_description" = "Selgitus (kui soovid lisada)"; "screen_join_room_knock_sent_description" = "Kui sinu liitumispalvega ollakse nõus, siis saad kutse jututoaga liitumiseks."; "screen_join_room_knock_sent_title" = "Liitumispalve on saadetud"; +"screen_knock_requests_list_accept_all_button_title" = "Nõustu kõigiga"; "screen_knock_requests_list_decline_and_ban_action_title" = "Keeldu ja määra suhtluskeeld"; +"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_title" = "Liitumispalved"; "screen_pinned_timeline_empty_state_description" = "Siia lisamiseks vajuta sõnumil ja vali „%1$@“."; "screen_pinned_timeline_empty_state_headline" = "Et olulisi sõnumeid oleks lihtsam leida, tõsta nad esile"; "screen_reset_encryption_password_error" = "Tekkis teadmata viga. Palun kontrolli, kas sinu kasutajakonto salasõna on õige ja proovi uuesti."; diff --git a/ElementX/Resources/Localizations/fa.lproj/Localizable.strings b/ElementX/Resources/Localizations/fa.lproj/Localizable.strings index a6d5a0b676..9b81467001 100644 --- a/ElementX/Resources/Localizations/fa.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fa.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "ضبط پیام صوتی."; "a11y_voice_message_stop_recording" = "توقّف ضبط"; "action_accept" = "پذیرش"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "افزودن به خط زمانی"; "action_back" = "بازگشت"; "action_call" = "تماس"; @@ -47,6 +48,7 @@ "action_discard" = "دور ریختن"; "action_done" = "انجام شد"; "action_edit" = "ویرایش"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "ویرایش نظرسنجی"; "action_enable" = "به کار انداختن"; "action_end_poll" = "پایان نظرسنجی"; @@ -81,6 +83,7 @@ "action_react" = "واکنش"; "action_reject" = "رد کردن"; "action_remove" = "برداشتن"; +"action_remove_caption" = "Remove caption"; "action_reply" = "پاسخ"; "action_reply_in_thread" = "پاسخ در رشته"; "action_report_bug" = "گزارش اشکال"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "برپایی بازیابی"; "common_about" = "درباره"; "common_acceptable_use_policy" = "سیاست استفادهٔ پذیرفتنی"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "تنظیمات پیش‌رفته"; "common_analytics" = "تجزیه و تحلیل"; "common_appearance" = "ظاهر"; @@ -137,6 +141,7 @@ "common_direct_chat" = "گپ مستقیم"; "common_edited_suffix" = "(ویراسته)"; "common_editing" = "ویرایش"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "رمزنگاری به کار افتاده"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; diff --git a/ElementX/Resources/Localizations/fi.lproj/Localizable.strings b/ElementX/Resources/Localizations/fi.lproj/Localizable.strings index a53e3d8290..8ec1f1dbe8 100644 --- a/ElementX/Resources/Localizations/fi.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fi.lproj/Localizable.strings @@ -22,6 +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_to_timeline" = "Lisää aikajanalle"; "action_back" = "Takaisin"; "action_call" = "Soita"; @@ -47,6 +48,7 @@ "action_discard" = "Hylkää"; "action_done" = "Valmis"; "action_edit" = "Muokkaa"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Muokkaa kyselyä"; "action_enable" = "Ota käyttöön"; "action_end_poll" = "Lopeta kysely"; @@ -81,6 +83,7 @@ "action_react" = "Reagoi"; "action_reject" = "Hylkää"; "action_remove" = "Poista"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Vastaa"; "action_reply_in_thread" = "Vastaa ketjuun"; "action_report_bug" = "Ilmoita virheestä"; @@ -119,6 +122,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_advanced_settings" = "Edistyneet asetukset"; "common_analytics" = "Analytiikka"; "common_appearance" = "Ulkoasu"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Yksityinen keskustelu"; "common_edited_suffix" = "(muokattu)"; "common_editing" = "Muokataan viestiä"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Salaus"; "common_encryption_enabled" = "Salaus käytössä"; @@ -225,7 +230,7 @@ "common_unable_to_invite_title" = "Kutsujen lähettäminen ei onnistunut"; "common_unlock" = "Avaa"; "common_unmute" = "Poista mykistys"; -"common_unsupported_call" = "Unsupported call"; +"common_unsupported_call" = "Puhelu, jota ei tueta"; "common_unsupported_event" = "Tapahtumaa ei tueta"; "common_username" = "Käyttäjänimi"; "common_verification_cancelled" = "Vahvistus peruttu"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Paina viestiä ja valitse “%1$@” lisätäksesi sen tänne."; "screen_pinned_timeline_empty_state_headline" = "Kiinnitä tärkeät viestit, jotta ne löytyvät helposti."; "screen_reset_encryption_password_error" = "Tapahtui tuntematon virhe. Tarkista, että tilisi salasana on oikein ja yritä uudelleen."; @@ -795,7 +804,7 @@ "screen_room_timeline_add_reaction" = "Lisää emoji"; "screen_room_timeline_beginning_of_room" = "Tämä on huoneen %1$@ alku."; "screen_room_timeline_beginning_of_room_no_name" = "Tämä on tämän keskustelun alku."; -"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; +"screen_room_timeline_legacy_call" = "Puhelu, jota ei tueta. Kysy, voiko soittaja käyttää uutta Element X -sovellusta."; "screen_room_timeline_less_reactions" = "Näytä vähemmän"; "screen_room_timeline_message_copied" = "Viesti kopioitu"; "screen_room_timeline_no_permission_to_post" = "Sinulla ei ole oikeutta kirjoittaa tässä huoneessa"; diff --git a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings index 73f4c756eb..fa725fba8d 100644 --- a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Enregistrer un message vocal."; "a11y_voice_message_stop_recording" = "Arrêter l'enregistrement"; "action_accept" = "Accepter"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Ajouter à la discussion"; "action_back" = "Retour"; "action_call" = "Appel"; @@ -47,6 +48,7 @@ "action_discard" = "Annuler"; "action_done" = "Terminé"; "action_edit" = "Modifier"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Modifier le sondage"; "action_enable" = "Activer"; "action_end_poll" = "Terminer le sondage"; @@ -81,6 +83,7 @@ "action_react" = "Réagissez"; "action_reject" = "Rejeter"; "action_remove" = "Supprimer"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Répondre"; "action_reply_in_thread" = "Répondre dans le fil de discussion"; "action_report_bug" = "Signaler un problème"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Configurer la récupération"; "common_about" = "À propos"; "common_acceptable_use_policy" = "Politique d’utilisation acceptable"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Paramètres avancés"; "common_analytics" = "Statistiques d’utilisation"; "common_appearance" = "Apparence"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Discussion à deux"; "common_edited_suffix" = "(modifié)"; "common_editing" = "Édition"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Chiffrement"; "common_encryption_enabled" = "Chiffrement activé"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Cliquez (clic long) sur un message et choisissez « %1$@ » pour qu‘il apparaisse ici."; "screen_pinned_timeline_empty_state_headline" = "Épinglez les messages importants pour leur donner plus de visibilité"; "screen_reset_encryption_password_error" = "Une erreur s'est produite. Vérifiez que le mot de passe de votre compte est correct et réessayez."; diff --git a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings index 8a4a10e10a..870977da2d 100644 --- a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings @@ -22,6 +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_to_timeline" = "Hozzáadás az idővonalhoz"; "action_back" = "Vissza"; "action_call" = "Hívás"; @@ -47,6 +48,7 @@ "action_discard" = "Elvetés"; "action_done" = "Kész"; "action_edit" = "Szerkesztés"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Szavazás szerkesztése"; "action_enable" = "Engedélyezés"; "action_end_poll" = "Szavazás lezárása"; @@ -81,6 +83,7 @@ "action_react" = "Reakció"; "action_reject" = "Elutasítás"; "action_remove" = "Eltávolítás"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Válasz"; "action_reply_in_thread" = "Válasz az üzenetszálban"; "action_report_bug" = "Hiba jelentése"; @@ -119,6 +122,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_advanced_settings" = "Speciális beállítások"; "common_analytics" = "Elemzések"; "common_appearance" = "Megjelenítés"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Közvetlen csevegés"; "common_edited_suffix" = "(szerkesztve)"; "common_editing" = "Szerkesztés"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Titkosítás"; "common_encryption_enabled" = "Titkosítás engedélyezve"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Nyomjon hosszan az üzenetre, és válassza a „%1$@” lehetőséget, hogy itt szerepeljen."; "screen_pinned_timeline_empty_state_headline" = "Tűzze ki a fontos üzeneteket, hogy könnyen felfedezhetők legyenek"; "screen_reset_encryption_password_error" = "Ismeretlen hiba történt. Ellenőrizze, hogy a fiókja jelszava helyes-e, és próbálja meg újra."; diff --git a/ElementX/Resources/Localizations/id.lproj/Localizable.strings b/ElementX/Resources/Localizations/id.lproj/Localizable.strings index 8625bc47b0..1128e3f4a6 100644 --- a/ElementX/Resources/Localizations/id.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/id.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Rekam pesan suara."; "a11y_voice_message_stop_recording" = "Berhenti merekam"; "action_accept" = "Terima"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Tambahkan ke lini masa"; "action_back" = "Kembali"; "action_call" = "Panggil"; @@ -47,6 +48,7 @@ "action_discard" = "Abaikan"; "action_done" = "Selesai"; "action_edit" = "Sunting"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Sunting pemungutan suara"; "action_enable" = "Aktifkan"; "action_end_poll" = "Akhiri pemungutan suara"; @@ -81,6 +83,7 @@ "action_react" = "Bereaksi"; "action_reject" = "Tolak"; "action_remove" = "Hapus"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Balas"; "action_reply_in_thread" = "Balas dalam utas"; "action_report_bug" = "Laporkan kutu"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Siapkan pemulihan"; "common_about" = "Tentang"; "common_acceptable_use_policy" = "Kebijakan penggunaan wajar"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Pengaturan tingkat lanjut"; "common_analytics" = "Analitik"; "common_appearance" = "Penampilan"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Obrolan langsung"; "common_edited_suffix" = "(disunting)"; "common_editing" = "Penyuntingan"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Enkripsi"; "common_encryption_enabled" = "Enkripsi diaktifkan"; @@ -365,7 +370,11 @@ "screen_join_room_knock_message_description" = "Pesan (opsional)"; "screen_join_room_knock_sent_description" = "Anda akan menerima undangan untuk bergabung dengan ruangan jika permintaan Anda diterima."; "screen_join_room_knock_sent_title" = "Permintaan untuk bergabung dikirim"; +"screen_knock_requests_list_accept_all_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Tekan pesan dan pilih “%1$@” untuk disertakan di sini."; "screen_pinned_timeline_empty_state_headline" = "Sematkan pesan penting agar mudah ditemukan"; "screen_reset_encryption_password_error" = "Terjadi kesalahan yang tidak diketahui. Harap periksa apakah kata sandi akun Anda sudah benar dan coba lagi."; diff --git a/ElementX/Resources/Localizations/it.lproj/Localizable.strings b/ElementX/Resources/Localizations/it.lproj/Localizable.strings index 29b162b895..6cf966b9da 100644 --- a/ElementX/Resources/Localizations/it.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/it.lproj/Localizable.strings @@ -22,6 +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_to_timeline" = "Aggiungi alla conversazione"; "action_back" = "Indietro"; "action_call" = "Chiama"; @@ -47,6 +48,7 @@ "action_discard" = "Annulla"; "action_done" = "Fine"; "action_edit" = "Modifica"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Modifica sondaggio"; "action_enable" = "Attiva"; "action_end_poll" = "Termina sondaggio"; @@ -81,6 +83,7 @@ "action_react" = "Reagisci"; "action_reject" = "Rifiuta"; "action_remove" = "Rimuovi"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Rispondi"; "action_reply_in_thread" = "Rispondi nella discussione"; "action_report_bug" = "Segnala un problema"; @@ -119,6 +122,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_advanced_settings" = "Impostazioni avanzate"; "common_analytics" = "Statistiche di utilizzo"; "common_appearance" = "Aspetto"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Conversazione diretta"; "common_edited_suffix" = "(modificato)"; "common_editing" = "Modifica in corso"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "Crittografia abilitata"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Premi su un messaggio e scegli “%1$@” per includerlo qui."; "screen_pinned_timeline_empty_state_headline" = "Fissa i messaggi importanti così che possano essere trovati facilmente"; "screen_reset_encryption_password_error" = "Si è verificato un errore sconosciuto. Controlla che la password del tuo account sia corretta e riprova."; diff --git a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings index ac0243f611..76743f9003 100644 --- a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "ხმოვანი შეტყობინების ჩაწერა."; "a11y_voice_message_stop_recording" = "ჩაწერის შეწყვეტა"; "action_accept" = "მიღება"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "დამატება ქრონოლოგიაში"; "action_back" = "უკან"; "action_call" = "Call"; @@ -47,6 +48,7 @@ "action_discard" = "Discard"; "action_done" = "მზადაა"; "action_edit" = "რედაქტირება"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "გამოკითხვის რედაქტირება"; "action_enable" = "ჩართვა"; "action_end_poll" = "გამოკითხვის დასრულება"; @@ -81,6 +83,7 @@ "action_react" = "რეაგირება"; "action_reject" = "Reject"; "action_remove" = "წაშლა"; +"action_remove_caption" = "Remove caption"; "action_reply" = "პასუხი"; "action_reply_in_thread" = "პასუხი თემაში"; "action_report_bug" = "ხარვეზის შეტყობინება"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Set up recovery to protect your account"; "common_about" = "შესახებ"; "common_acceptable_use_policy" = "მისაღები გამოყენების პოლიტიკა"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "გაფართოებული პარამეტრები"; "common_analytics" = "ანალიტიკა"; "common_appearance" = "გარეგნობა"; @@ -137,6 +141,7 @@ "common_direct_chat" = "პირდაპირი ჩატი"; "common_edited_suffix" = "(რედაქტირებულია)"; "common_editing" = "რედაქტირება"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "დაშიფვრა ჩართულია"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; diff --git a/ElementX/Resources/Localizations/nl.lproj/Localizable.strings b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings index 017f166710..db6deefbd5 100644 --- a/ElementX/Resources/Localizations/nl.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Spraakbericht opnemen."; "a11y_voice_message_stop_recording" = "Opnemen stoppen"; "action_accept" = "Accepteren"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Toevoegen aan tijdlijn"; "action_back" = "Terug"; "action_call" = "Bellen"; @@ -47,6 +48,7 @@ "action_discard" = "Verwerpen"; "action_done" = "Gereed"; "action_edit" = "Bewerken"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Peiling wijzigen"; "action_enable" = "Activeren"; "action_end_poll" = "Peiling beëindigen"; @@ -81,6 +83,7 @@ "action_react" = "Reageren"; "action_reject" = "Weiger"; "action_remove" = "Verwijderen"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Antwoorden"; "action_reply_in_thread" = "Antwoord in subchat"; "action_report_bug" = "Probleem melden"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Set up recovery to protect your account"; "common_about" = "Over"; "common_acceptable_use_policy" = "Beleid inzake redelijk gebruik"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Geavanceerde instellingen"; "common_analytics" = "Gebruiksgegevens"; "common_appearance" = "Weergave"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Directe chat"; "common_edited_suffix" = "(bewerkt)"; "common_editing" = "Bewerken"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "Encryptie ingeschakeld"; @@ -290,7 +295,7 @@ "event_shield_reason_unknown_device" = "Versleuteld door een onbekend of verwijderd apparaat."; "event_shield_reason_unsigned_device" = "Versleuteld door een apparaat dat niet is geverifieerd door de eigenaar."; "event_shield_reason_unverified_identity" = "Versleuteld door een niet-geverifieerde gebruiker."; -"full_screen_intent_banner_message" = "To ensure you never miss an important call, please change your settings to allow full-screen notifications when your phone is locked."; +"full_screen_intent_banner_message" = "Pas je instellingen aan om meldingen op het volledige scherm toe te staan wanneer de telefoon is vergrendeld. Zo mis je nooit een belangrijk gesprek."; "full_screen_intent_banner_title" = "Verbeter je gesprekservaring"; "invite_friends_rich_title" = "🔐️ Sluit je bij mij aan op %1$@"; "invite_friends_text" = "Hé, praat met me op %1$@: %2$@"; @@ -365,7 +370,11 @@ "screen_join_room_knock_message_description" = "Bericht (optioneel)"; "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" = "Verzoek om toe te treden verzonden"; +"screen_knock_requests_list_accept_all_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Druk op een bericht en kies „%1$@” om het hier toe te voegen."; "screen_pinned_timeline_empty_state_headline" = "Zet belangrijke berichten vast zodat ze gemakkelijk te vinden zijn"; "screen_reset_encryption_password_error" = "Er is een onbekende fout opgetreden. Controleer of het wachtwoord van je account juist is en probeer het opnieuw."; diff --git a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings index 97fdc287a0..b6a0b10941 100644 --- a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Nagraj wiadomość głosową."; "a11y_voice_message_stop_recording" = "Zatrzymaj nagrywanie"; "action_accept" = "Akceptuj"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Dodaj do osi czasu"; "action_back" = "Wróć"; "action_call" = "Zadzwoń"; @@ -47,6 +48,7 @@ "action_discard" = "Odrzuć"; "action_done" = "Gotowe"; "action_edit" = "Edytuj"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Edytuj ankietę"; "action_enable" = "Włącz"; "action_end_poll" = "Zakończ ankietę"; @@ -81,6 +83,7 @@ "action_react" = "Dodaj reakcję"; "action_reject" = "Odrzuć"; "action_remove" = "Usuń"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Odpowiedz"; "action_reply_in_thread" = "Odpowiedz w wątku"; "action_report_bug" = "Zgłoś błąd"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Skonfiguruj przywracanie"; "common_about" = "O programie"; "common_acceptable_use_policy" = "Polityka użytkowania"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Ustawienia zaawansowane"; "common_analytics" = "Analityka"; "common_appearance" = "Wygląd"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Czat prywatny"; "common_edited_suffix" = "(edytowane)"; "common_editing" = "Edytowanie"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Szyfrowanie"; "common_encryption_enabled" = "Szyfrowanie włączone"; @@ -365,7 +370,11 @@ "screen_join_room_knock_message_description" = "Wiadomość (opcjonalne)"; "screen_join_room_knock_sent_description" = "Otrzymasz zaproszenie dołączenia do pokoju, jeśli prośba zostanie zaakceptowana."; "screen_join_room_knock_sent_title" = "Wysłano prośbę o dołączenie"; +"screen_knock_requests_list_accept_all_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Naciśnij wiadomość i wybierz “%1$@”, aby dołączyć tutaj."; "screen_pinned_timeline_empty_state_headline" = "Przypinaj ważne wiadomości, aby można było je łatwo znaleźć"; "screen_reset_encryption_password_error" = "Wystąpił nieznany błąd. Sprawdź, czy hasło jest poprawne i spróbuj ponownie."; diff --git a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings index cf0fdb3188..508dabe58e 100644 --- a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Gravar mensagem de voz."; "a11y_voice_message_stop_recording" = "Parar gravação"; "action_accept" = "Aceitar"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Adicionar à linha do tempo"; "action_back" = "Voltar"; "action_call" = "Chamar"; @@ -47,6 +48,7 @@ "action_discard" = "Descartar"; "action_done" = "Concluído"; "action_edit" = "Editar"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Editar enquete"; "action_enable" = "Habilitar"; "action_end_poll" = "Encerrar enquete"; @@ -81,6 +83,7 @@ "action_react" = "Reagir"; "action_reject" = "Recusar"; "action_remove" = "Remover"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Responder"; "action_reply_in_thread" = "Responder no tópico"; "action_report_bug" = "Reportar erro"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Set up recovery to protect your account"; "common_about" = "Sobre"; "common_acceptable_use_policy" = "Política de uso aceitável"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Configurações avançadas"; "common_analytics" = "Telemetria"; "common_appearance" = "Aparência"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Conversa privada"; "common_edited_suffix" = "(editado)"; "common_editing" = "Editando"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "Criptografia ativada"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -469,7 +478,7 @@ "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_title" = "Backup"; +"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"; @@ -495,9 +504,9 @@ "screen_create_poll_title" = "Criar enquete"; "screen_create_room_action_create_room" = "Nova sala"; "screen_create_room_error_creating_room" = "Ocorreu um erro ao criar a sala"; -"screen_create_room_private_option_description" = "As mensagens nesta sala serão criptografadas. A criptografia não pode ser desativada posteriormente."; +"screen_create_room_private_option_description" = "Apenas as pessoas convidadas podem aceder a esta sala. Todas as mensagens são criptografadas de ponta a ponta."; "screen_create_room_private_option_title" = "Sala privativa (somente por convite)"; -"screen_create_room_public_option_description" = "As mensagens não serão criptografadas e qualquer pessoa pode lê-las. Você pode ativar a criptografia posteriormente."; +"screen_create_room_public_option_description" = "Qualquer um pode encontrar esta sala.\nVocê pode mudar isso a qualquer momento nas configurações da sala."; "screen_create_room_public_option_title" = "Sala pública (qualquer pessoa)"; "screen_create_room_topic_label" = "Tópico (opcional)"; "screen_deactivate_account_confirmation_dialog_content" = "Please confirm that you want to deactivate your account. This action cannot be undone."; diff --git a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings index 58087838d3..b6c1abf085 100644 --- a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Gravar mensagem de voz."; "a11y_voice_message_stop_recording" = "Parar gravação"; "action_accept" = "Aceitar"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Adicionar à cronologia"; "action_back" = "Voltar"; "action_call" = "Chamar"; @@ -47,6 +48,7 @@ "action_discard" = "Descartar"; "action_done" = "Feito"; "action_edit" = "Editar"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Editar sondagem"; "action_enable" = "Ativar"; "action_end_poll" = "Fim da sondagem"; @@ -81,6 +83,7 @@ "action_react" = "Reagir"; "action_reject" = "Rejeitar"; "action_remove" = "Remover"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Responder"; "action_reply_in_thread" = "Responder ao tópico"; "action_report_bug" = "Comunicar problema"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Configurar a recuperação"; "common_about" = "Sobre"; "common_acceptable_use_policy" = "Política de utilização aceitável"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Configurações avançadas"; "common_analytics" = "Recolha e análise de dados"; "common_appearance" = "Aparência"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Conversa direta"; "common_edited_suffix" = "(editada)"; "common_editing" = "A editar"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encriptação"; "common_encryption_enabled" = "Cifragem ativada"; @@ -365,7 +370,11 @@ "screen_join_room_knock_message_description" = "Mensagem (opcional)"; "screen_join_room_knock_sent_description" = "Irá receber um convite para participar na sala se seu pedido for aceite."; "screen_join_room_knock_sent_title" = "Pedido de adesão enviado"; +"screen_knock_requests_list_accept_all_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Pressione uma mensagem e escolha \"%1$@\" para incluir aqui."; "screen_pinned_timeline_empty_state_headline" = "Fixa mensagens importantes para que possam ser facilmente descobertas"; "screen_reset_encryption_password_error" = "Um erro desconhecido aconteceu. Verifique se a senha da sua conta está correta e tente novamente."; diff --git a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings index 727293079f..7aef2d3cc6 100644 --- a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Înregistrați un mesaj vocal"; "a11y_voice_message_stop_recording" = "Opriți înregistrarea"; "action_accept" = "Acceptați"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Adăugați conversației"; "action_back" = "Înapoi"; "action_call" = "Apel"; @@ -47,6 +48,7 @@ "action_discard" = "Renunţare"; "action_done" = "Efectuat"; "action_edit" = "Editați"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Editați sondajul"; "action_enable" = "Activați"; "action_end_poll" = "Închideți sondajul"; @@ -81,6 +83,7 @@ "action_react" = "Reacționați"; "action_reject" = "Respinge"; "action_remove" = "Ștergeți"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Răspundeți"; "action_reply_in_thread" = "Răspundeți în fir"; "action_report_bug" = "Raportați o eroare"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Set up recovery to protect your account"; "common_about" = "Despre"; "common_acceptable_use_policy" = "Politică de utilizare rezonabilă"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Setări avansate"; "common_analytics" = "Analitice"; "common_appearance" = "Aspect"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Chat direct"; "common_edited_suffix" = "(editat)"; "common_editing" = "Editare"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "Criptare activată"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; diff --git a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings index 19a7d3735e..55c700e373 100644 --- a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Записать голосовое сообщение."; "a11y_voice_message_stop_recording" = "Остановить запись"; "action_accept" = "Разрешить"; +"action_add_caption" = "Добавить подпись"; "action_add_to_timeline" = "Добавить в хронологию"; "action_back" = "Назад"; "action_call" = "Позвонить"; @@ -47,6 +48,7 @@ "action_discard" = "Отменить"; "action_done" = "Готово"; "action_edit" = "Редактировать"; +"action_edit_caption" = "Изменить подпись"; "action_edit_poll" = "Редактировать опрос"; "action_enable" = "Включить"; "action_end_poll" = "Завершить опрос"; @@ -81,6 +83,7 @@ "action_react" = "Реакция"; "action_reject" = "Отклонить"; "action_remove" = "Удалить"; +"action_remove_caption" = "Удалить подпись"; "action_reply" = "Ответить"; "action_reply_in_thread" = "Ответить в теме"; "action_report_bug" = "Сообщить об ошибке"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Для защиты вашего аккаунта рекомендуется настроить восстановление"; "common_about" = "О приложении"; "common_acceptable_use_policy" = "Политика допустимого использования"; +"common_adding_caption" = "Добавление подписи"; "common_advanced_settings" = "Дополнительные настройки"; "common_analytics" = "Аналитика"; "common_appearance" = "Внешний вид"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Личный чат"; "common_edited_suffix" = "(изменено)"; "common_editing" = "Редактирование"; +"common_editing_caption" = "Редактирование подписи"; "common_emote" = "%1$@%2$@"; "common_encryption" = "Шифрование"; "common_encryption_enabled" = "Шифрование включено"; @@ -365,7 +370,11 @@ "screen_join_room_knock_message_description" = "Сообщение (опционально)"; "screen_join_room_knock_sent_description" = "Вы получите приглашение присоединиться к комнате, как только ваш запрос будет принят."; "screen_join_room_knock_sent_title" = "Запрос на присоединение отправлен"; +"screen_knock_requests_list_accept_all_button_title" = "Принять всё"; "screen_knock_requests_list_decline_and_ban_action_title" = "Отклонить и запретить"; +"screen_knock_requests_list_empty_state_description" = "Вы сможете увидеть запрос, когда кто-то попросит присоединиться к комнате."; +"screen_knock_requests_list_empty_state_title" = "Нет ожидающих запросов на присоединение"; +"screen_knock_requests_list_title" = "Запросы на присоединение"; "screen_pinned_timeline_empty_state_description" = "Нажмите на сообщение и выберите “%1$@”, чтобы добавить его сюда."; "screen_pinned_timeline_empty_state_headline" = "Закрепите важные сообщения, чтобы их можно было легко найти"; "screen_reset_encryption_password_error" = "Произошла неизвестная ошибка. Проверьте правильность пароля учетной записи и повторите попытку."; @@ -387,7 +396,7 @@ "screen_room_single_knock_request_title" = "%1$@ хочет присоединиться к этой комнате"; "screen_room_single_knock_request_view_button_title" = "Просмотр"; "screen_room_details_pinned_events_row_title" = "Закрепленные сообщения"; -"screen_room_details_requests_to_join_title" = "Requests to join"; +"screen_room_details_requests_to_join_title" = "Запросы на вступление"; "screen_roomlist_knock_event_sent_description" = "Запрос на присоединение отправлен"; "screen_timeline_item_menu_send_failure_changed_identity" = "Сообщение не отправлено, потому что верифицированная личность %1$@ изменилась."; "screen_timeline_item_menu_send_failure_unsigned_device" = "Сообщение не отправлено, потому что %1$@ не проверил одно или несколько устройств."; diff --git a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings index 45597d7dce..5157db2c85 100644 --- a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Nahrať hlasovú správu."; "a11y_voice_message_stop_recording" = "Zastaviť nahrávanie"; "action_accept" = "Prijať"; +"action_add_caption" = "Pridať titulok"; "action_add_to_timeline" = "Pridať na časovú os"; "action_back" = "Späť"; "action_call" = "Zavolať"; @@ -47,6 +48,7 @@ "action_discard" = "Zahodiť"; "action_done" = "Hotovo"; "action_edit" = "Upraviť"; +"action_edit_caption" = "Upraviť titulok"; "action_edit_poll" = "Upraviť anketu"; "action_enable" = "Povoliť"; "action_end_poll" = "Ukončiť anketu"; @@ -81,6 +83,7 @@ "action_react" = "Reagovať"; "action_reject" = "Odmietnuť"; "action_remove" = "Odstrániť"; +"action_remove_caption" = "Odstrániť titulok"; "action_reply" = "Odpovedať"; "action_reply_in_thread" = "Odpovedať vo vlákne"; "action_report_bug" = "Nahlásiť chybu"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Nastaviť obnovenie"; "common_about" = "O aplikácii"; "common_acceptable_use_policy" = "Zásady prijateľného používania"; +"common_adding_caption" = "Pridáva sa titulok"; "common_advanced_settings" = "Pokročilé nastavenia"; "common_analytics" = "Analytika"; "common_appearance" = "Vzhľad"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Priama konverzácia"; "common_edited_suffix" = "(upravené)"; "common_editing" = "Upravuje sa"; +"common_editing_caption" = "Úprava titulku"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Šifrovanie"; "common_encryption_enabled" = "Šifrovanie zapnuté"; @@ -365,7 +370,11 @@ "screen_join_room_knock_message_description" = "Správa (voliteľné)"; "screen_join_room_knock_sent_description" = "Ak bude vaša žiadosť prijatá, dostanete pozvánku na vstup do miestnosti."; "screen_join_room_knock_sent_title" = "Žiadosť o pripojenie bola odoslaná"; +"screen_knock_requests_list_accept_all_button_title" = "Prijať všetky"; "screen_knock_requests_list_decline_and_ban_action_title" = "Odmietnuť a zakázať"; +"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_title" = "Žiadosti o pripojenie"; "screen_pinned_timeline_empty_state_description" = "Stlačte správu a vyberte možnosť „%1$@“, ktorú chcete zahrnúť sem."; "screen_pinned_timeline_empty_state_headline" = "Pripnite dôležité správy, aby sa dali ľahko nájsť"; "screen_reset_encryption_password_error" = "Nastala neznáma chyba. Skontrolujte, či je heslo vášho účtu správne a skúste to znova."; diff --git a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings index b7a28d19f1..befb12583a 100644 --- a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Spela in röstmeddelande."; "a11y_voice_message_stop_recording" = "Stoppa inspelning"; "action_accept" = "Godkänn"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Lägg till i tidslinjen"; "action_back" = "Tillbaka"; "action_call" = "Ring"; @@ -47,6 +48,7 @@ "action_discard" = "Kassera"; "action_done" = "Klar"; "action_edit" = "Redigera"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Redigera omröstning"; "action_enable" = "Aktivera"; "action_end_poll" = "Avsluta omröstning"; @@ -81,6 +83,7 @@ "action_react" = "Reagera"; "action_reject" = "Avvisa"; "action_remove" = "Ta bort"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Svara"; "action_reply_in_thread" = "Svara i tråd"; "action_report_bug" = "Rapportera bugg"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Ställ in återställning"; "common_about" = "Om"; "common_acceptable_use_policy" = "Policy för godtagbar användning"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Avancerade inställningar"; "common_analytics" = "Analysdata"; "common_appearance" = "Utseende"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Direktchatt"; "common_edited_suffix" = "(redigerad)"; "common_editing" = "Redigerar"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "Kryptering aktiverad"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Tryck på ett meddelande och välj ”%1$@” för att inkludera det här."; "screen_pinned_timeline_empty_state_headline" = "Fäst viktiga meddelanden så att de lätt kan upptäckas"; "screen_reset_encryption_password_error" = "Ett okänt fel inträffade. Kontrollera att ditt kontolösenord är korrekt och försök igen."; @@ -468,14 +477,14 @@ "screen_change_server_title" = "Välj din server"; "screen_chat_backup_key_backup_action_disable" = "Stäng av säkerhetskopiering"; "screen_chat_backup_key_backup_action_enable" = "Slå på säkerhetskopiering"; -"screen_chat_backup_key_backup_description" = "Säkerhetskopior ser till att du inte blir av med din meddelandehistorik. %1$@."; +"screen_chat_backup_key_backup_description" = "Lagra din kryptografiska identitet och dina meddelandenycklar säkert på servern. Detta gör att du kan se din meddelandehistorik på alla nya enheter. %1$@."; "screen_chat_backup_key_backup_title" = "Nyckellagring"; "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" = "Byt återställningsnyckel"; "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" = "Din chattsäkerhetskopia är för närvarande osynkroniserad."; +"screen_chat_backup_recovery_action_confirm_description" = "Din nyckellagring är för närvarande osynkroniserad."; "screen_chat_backup_recovery_action_setup_description" = "Få tillgång till dina krypterade meddelanden om du tappar bort alla dina enheter eller blir utloggad ur %1$@ överallt."; "screen_create_account_title" = "Create account"; "screen_create_new_recovery_key_list_item_1" = "Öppna %1$@ på en skrivbordsenhet"; @@ -666,7 +675,7 @@ "screen_recovery_key_setup_confirmation_title" = "Har du sparat din återställningsnyckel?"; "screen_recovery_key_setup_description" = "Din chattsäkerhetskopia skyddas av en återställningsnyckel. Om du behöver en ny återställningsnyckel efter installationen kan du återskapa genom att välja ”Byt återställningsnyckel”."; "screen_recovery_key_setup_generate_key" = "Generera din återställningsnyckel"; -"screen_recovery_key_setup_generate_key_description" = "Se till att du kan lagra din återställningsnyckel någonstans säkert"; +"screen_recovery_key_setup_generate_key_description" = "Dela inte detta med någon!"; "screen_recovery_key_setup_success" = "Konfiguration av återställning lyckades"; "screen_recovery_key_setup_title" = "Ställ in återställning"; "screen_report_content_block_user_hint" = "Markera om du vill dölja alla nuvarande och framtida meddelanden från denna användare"; @@ -924,7 +933,7 @@ "state_event_room_invite_you" = "%1$@ bjöd in dig"; "state_event_room_join" = "%1$@ gick med i rummet"; "state_event_room_join_by_you" = "Du gick med i rummet"; -"state_event_room_knock" = "%1$@ begärde att gå med"; +"state_event_room_knock" = "%1$@ begär att gå med"; "state_event_room_knock_accepted" = "%1$@ tillät %2$@ att gå med"; "state_event_room_knock_accepted_by_you" = "Du lät %1$@ att gå med"; "state_event_room_knock_by_you" = "Du begärde att gå med"; @@ -1045,7 +1054,7 @@ "screen_login_subtitle" = "Matrix är ett öppet nätverk för säker, decentraliserad kommunikation."; "screen_notification_settings_mentions_section_title" = "Omnämnanden"; "screen_qr_code_login_invalid_scan_state_retry_button" = "Försök igen"; -"screen_recovery_key_change_generate_key_description" = "Se till att du kan lagra din återställningsnyckel någonstans säkert"; +"screen_recovery_key_change_generate_key_description" = "Dela inte detta med någon!"; "screen_recovery_key_confirm_title" = "Enter your recovery key"; "screen_report_content_block_user" = "Blockera användare"; "screen_reset_encryption_password_placeholder" = "Ange …"; diff --git a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings index d4ddc00a79..4b49907eed 100644 --- a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Записати голосове повідомлення."; "a11y_voice_message_stop_recording" = "Припинити запис"; "action_accept" = "Прийняти"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Додати до стрічки"; "action_back" = "Назад"; "action_call" = "Зателефонувати"; @@ -47,6 +48,7 @@ "action_discard" = "Відкинути"; "action_done" = "Готово"; "action_edit" = "Редагувати"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "Редагувати опитування"; "action_enable" = "Увімкнути"; "action_end_poll" = "Завершити опитування"; @@ -81,6 +83,7 @@ "action_react" = "Реакція"; "action_reject" = "Відхилити"; "action_remove" = "Вилучити"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Відповісти"; "action_reply_in_thread" = "Відповісти в гілці"; "action_report_bug" = "Повідомити про помилку"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Налаштуйте відновлення для захисту свого облікового запису"; "common_about" = "Відомості"; "common_acceptable_use_policy" = "Політика прийнятного використання"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Додаткові налаштування"; "common_analytics" = "Аналітика"; "common_appearance" = "Тема"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Особиста бесіда"; "common_edited_suffix" = "(відредаговано)"; "common_editing" = "Редагування"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Шифрування"; "common_encryption_enabled" = "Шифрування ввімкнено"; @@ -365,7 +370,11 @@ "screen_join_room_knock_message_description" = "Повідомлення (необов'язково)"; "screen_join_room_knock_sent_description" = "Ви отримаєте запрошення приєднатися до кімнати, якщо ваш запит буде прийнятий."; "screen_join_room_knock_sent_title" = "Запит на приєднання надіслано"; +"screen_knock_requests_list_accept_all_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Натисніть на повідомлення і виберіть \"%1$@\", щоб додати його сюди."; "screen_pinned_timeline_empty_state_headline" = "Закріпіть важливі повідомлення, щоб їх можна було легко знайти"; "screen_reset_encryption_password_error" = "Сталася невідома помилка. Будь ласка, перевірте правильність пароля свого облікового запису та повторіть спробу."; diff --git a/ElementX/Resources/Localizations/uz.lproj/Localizable.strings b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings index 48db2eb1e1..98edd1ed8d 100644 --- a/ElementX/Resources/Localizations/uz.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "Ovoz yozishni amalga oshiring"; "a11y_voice_message_stop_recording" = "Stop recording"; "action_accept" = "Qabul qiling"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "Vaqt jadvaliga qo'shing"; "action_back" = "Orqaga"; "action_call" = "Call"; @@ -47,6 +48,7 @@ "action_discard" = "Discard"; "action_done" = "Bajarildi"; "action_edit" = "Tahrirlash"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "So‘rovnomani tahrirlash"; "action_enable" = "Yoqish"; "action_end_poll" = "So‘rovnomani tugatish"; @@ -81,6 +83,7 @@ "action_react" = "Reaksiya qilish"; "action_reject" = "Reject"; "action_remove" = "Ochirish"; +"action_remove_caption" = "Remove caption"; "action_reply" = "Javob bering"; "action_reply_in_thread" = "Mavzuda javob bering"; "action_report_bug" = "Xato haqida xabar berish"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Set up recovery to protect your account"; "common_about" = "Haqida"; "common_acceptable_use_policy" = "Qabul qilinadigan foydalanish siyosati"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "Kengaytirilgan sozlamalar"; "common_analytics" = "Analitika"; "common_appearance" = "Appearance"; @@ -137,6 +141,7 @@ "common_direct_chat" = "Direct chat"; "common_edited_suffix" = "(tahrirlangan)"; "common_editing" = "Tahrirlash"; +"common_editing_caption" = "Editing caption"; "common_emote" = "*%1$@%2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "Shifrlash yoqilgan"; @@ -346,7 +351,7 @@ "rich_text_editor_a11y_add_attachment" = "Biriktirma qo'shing"; "rich_text_editor_composer_caption_placeholder" = "Optional caption…"; "screen_advanced_settings_element_call_base_url" = "Maxsus element qo‘ng‘iroqlar bazasi URL manzili"; -"screen_advanced_settings_element_call_base_url_description" = "Set a custom base URL for Element Call."; +"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."; "screen_create_room_room_access_section_anyone_option_description" = "Anyone can join this room"; "screen_create_room_room_access_section_anyone_option_title" = "Anyone"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; diff --git a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings index 202cafb0cb..738a895efa 100644 --- a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "录制语音消息。"; "a11y_voice_message_stop_recording" = "停止录制"; "action_accept" = "接受"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "添加到时间线"; "action_back" = "返回"; "action_call" = "呼叫"; @@ -47,6 +48,7 @@ "action_discard" = "丢弃"; "action_done" = "完成"; "action_edit" = "编辑"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "编辑投票"; "action_enable" = "启用"; "action_end_poll" = "结束投票"; @@ -81,6 +83,7 @@ "action_react" = "回应"; "action_reject" = "拒绝"; "action_remove" = "移除"; +"action_remove_caption" = "Remove caption"; "action_reply" = "回复"; "action_reply_in_thread" = "在消息列中回复"; "action_report_bug" = "报告错误"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "设置恢复"; "common_about" = "关于"; "common_acceptable_use_policy" = "可接受的使用政策"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "高级设置"; "common_analytics" = "分析"; "common_appearance" = "外观"; @@ -137,6 +141,7 @@ "common_direct_chat" = "私聊"; "common_edited_suffix" = "(已编辑)"; "common_editing" = "编辑中"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "加密"; "common_encryption_enabled" = "已启用加密"; @@ -365,7 +370,11 @@ "screen_join_room_knock_message_description" = "消息(可选)"; "screen_join_room_knock_sent_description" = "如果您的请求被接受,您将收到加入房间的邀请。"; "screen_join_room_knock_sent_title" = "加入请求已发送"; +"screen_knock_requests_list_accept_all_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "按下消息并选择 “%1$@” 将其包含在此处。"; "screen_pinned_timeline_empty_state_headline" = "固定重要消息,以便轻松发现它们"; "screen_reset_encryption_password_error" = "发生未知错误。请检查您的帐户密码是否正确,然后重试。"; diff --git a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings index cd3b91b6b8..a191abfb3b 100644 --- a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings @@ -22,6 +22,7 @@ "a11y_voice_message_record" = "錄製語音訊息。"; "a11y_voice_message_stop_recording" = "停止錄音"; "action_accept" = "接受"; +"action_add_caption" = "Add caption"; "action_add_to_timeline" = "新增至時間軸"; "action_back" = "返回"; "action_call" = "通話"; @@ -47,6 +48,7 @@ "action_discard" = "捨棄"; "action_done" = "完成"; "action_edit" = "編輯"; +"action_edit_caption" = "Edit caption"; "action_edit_poll" = "編輯投票"; "action_enable" = "啟用"; "action_end_poll" = "結束投票"; @@ -81,6 +83,7 @@ "action_react" = "回應"; "action_reject" = "拒絕"; "action_remove" = "移除"; +"action_remove_caption" = "Remove caption"; "action_reply" = "回覆"; "action_reply_in_thread" = "在討論串中回覆"; "action_report_bug" = "回報程式錯誤"; @@ -119,6 +122,7 @@ "banner_set_up_recovery_title" = "Set up recovery to protect your account"; "common_about" = "關於"; "common_acceptable_use_policy" = "可接受使用政策"; +"common_adding_caption" = "Adding caption"; "common_advanced_settings" = "進階設定"; "common_analytics" = "分析"; "common_appearance" = "外觀"; @@ -137,6 +141,7 @@ "common_direct_chat" = "私訊"; "common_edited_suffix" = "(已編輯)"; "common_editing" = "編輯中"; +"common_editing_caption" = "Editing caption"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Encryption"; "common_encryption_enabled" = "已啟用加密"; @@ -365,7 +370,11 @@ "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_button_title" = "Accept all"; "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_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; From 03aaf849eef8f41d818c59f4e47999ba0b7329c3 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Tue, 26 Nov 2024 10:36:46 +0000 Subject: [PATCH 52/74] Update how file captions are rendered (#3554) * Update the File/Audio captions layout to match Figma. * Fix caption sizing issues. The send info label was being added incorrectly. * Update icon size and regenerate snapshots. * Fix a regression in the location timeline item layout. --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 6 +- .../View/MessageComposer.swift | 2 + .../View/Replies/TimelineReplyView.swift | 3 + .../Style/TimelineItemBubbledStylerView.swift | 4 + .../Style/TimelineItemSendInfoLabel.swift | 16 +- .../AudioRoomTimelineView.swift | 56 ++++--- .../FileRoomTimelineView.swift | 137 ++++++++++++------ .../AudioRoomTimelineItemContent.swift | 1 + .../FileRoomTimelineItemContent.swift | 1 + .../VoiceMessageRoomTimelineView.swift | 1 + .../RoomTimelineItemFactory.swift | 2 + ...est_audioRoomTimelineView-iPad-en-GB.1.png | 4 +- ...st_audioRoomTimelineView-iPad-pseudo.1.png | 4 +- ...udioRoomTimelineView-iPhone-16-en-GB.1.png | 4 +- ...dioRoomTimelineView-iPhone-16-pseudo.1.png | 4 +- ...test_fileRoomTimelineView-iPad-en-GB.1.png | 4 +- ...est_fileRoomTimelineView-iPad-pseudo.1.png | 4 +- ...fileRoomTimelineView-iPhone-16-en-GB.1.png | 4 +- ...ileRoomTimelineView-iPhone-16-pseudo.1.png | 4 +- ...dStylerView-iPad-en-GB.Pinned-messages.png | 4 +- ...StylerView-iPad-en-GB.Thread-decorator.png | 4 +- ...StylerView-iPad-pseudo.Pinned-messages.png | 4 +- ...tylerView-iPad-pseudo.Thread-decorator.png | 4 +- ...erView-iPhone-16-en-GB.Pinned-messages.png | 4 +- ...rView-iPhone-16-en-GB.Thread-decorator.png | 4 +- ...rView-iPhone-16-pseudo.Pinned-messages.png | 4 +- ...View-iPhone-16-pseudo.Thread-decorator.png | 4 +- UnitTests/Sources/LoggingTests.swift | 1 + project.yml | 2 +- 30 files changed, 188 insertions(+), 110 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 271b341de5..29ef45876c 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -8315,7 +8315,7 @@ repositoryURL = "https://github.com/element-hq/compound-ios"; requirement = { kind = revision; - revision = f0436aa767f614584bf119defa6372ddb3b60080; + revision = 901f3f2fc150db82cf8a2c4da53914b31f681b56; }; }; 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 0290c04dfa..ce20e47b9f 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" : "3adf924aec63f1addfe9124a95fa4c9e9b5bff7d", - "version" : "2.1.0" + "revision" : "31b236f02c811704b68e8aae429865fe8eb8d8ba", + "version" : "2.1.1" } }, { @@ -15,7 +15,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/compound-ios", "state" : { - "revision" : "f0436aa767f614584bf119defa6372ddb3b60080" + "revision" : "901f3f2fc150db82cf8a2c4da53914b31f681b56" } }, { diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift index 0662cc0076..649321db83 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift @@ -237,6 +237,7 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview { duration: 100, waveform: nil, source: nil, + fileSize: nil, contentType: nil)))), .loaded(sender: .init(id: "James"), eventID: "123", @@ -246,6 +247,7 @@ struct MessageComposer_Previews: PreviewProvider, TestablePreview { eventContent: .message(.file(.init(filename: "brain-surgery.pdf", caption: "File: Crash course in brain surgery", source: nil, + fileSize: nil, thumbnailSource: nil, contentType: nil)))), .loaded(sender: .init(id: "Cliff"), diff --git a/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift b/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift index bd82866912..48810a9023 100644 --- a/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Replies/TimelineReplyView.swift @@ -250,6 +250,7 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview { duration: 0, waveform: nil, source: nil, + fileSize: nil, contentType: nil))))), TimelineReplyView(placement: .timeline, @@ -258,6 +259,7 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview { eventContent: .message(.file(.init(filename: "file.txt", caption: "Some file", source: nil, + fileSize: nil, thumbnailSource: nil, contentType: nil))))), @@ -289,6 +291,7 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview { duration: 0, waveform: nil, source: nil, + fileSize: nil, contentType: nil))))), TimelineReplyView(placement: .timeline, timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Bob"), diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift index e1b025cec9..e91db5d2ef 100644 --- a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift @@ -514,6 +514,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview duration: 100, waveform: EstimatedWaveform.mockWaveform, source: nil, + fileSize: nil, contentType: nil), properties: RoomTimelineItemProperties(encryptionAuthenticity: .notGuaranteed(color: .gray))), playerState: AudioPlayerState(id: .timelineItemIdentifier(.randomEvent), @@ -552,6 +553,7 @@ private struct MockTimelineContent: View { duration: 100, waveform: EstimatedWaveform.mockWaveform, source: nil, + fileSize: nil, contentType: nil), replyDetails: replyDetails)) @@ -565,6 +567,7 @@ private struct MockTimelineContent: View { content: .init(filename: "file.txt", caption: "File", source: nil, + fileSize: nil, thumbnailSource: nil, contentType: nil), replyDetails: replyDetails)) @@ -616,6 +619,7 @@ private struct MockTimelineContent: View { duration: 100, waveform: EstimatedWaveform.mockWaveform, source: nil, + fileSize: nil, contentType: nil), replyDetails: replyDetails), playerState: AudioPlayerState(id: .timelineItemIdentifier(.randomEvent), diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemSendInfoLabel.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemSendInfoLabel.swift index b350a9b2e7..aef73a383f 100644 --- a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemSendInfoLabel.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemSendInfoLabel.swift @@ -152,12 +152,20 @@ private extension TimelineItemSendInfo { layoutType = switch timelineItem { case is TextBasedRoomTimelineItem: .overlay(capsuleStyle: false) - case let message as EventBasedMessageTimelineItemProtocol where message is ImageRoomTimelineItem || message is VideoRoomTimelineItem: - .overlay(capsuleStyle: !message.hasMediaCaption) + case let message as EventBasedMessageTimelineItemProtocol: + switch message { + case is ImageRoomTimelineItem, is VideoRoomTimelineItem: + .overlay(capsuleStyle: !message.hasMediaCaption) + case is AudioRoomTimelineItem, is FileRoomTimelineItem: + // swiftlint:disable:next void_function_in_ternary + message.hasMediaCaption ? .overlay(capsuleStyle: false) : .horizontal(spacing: 0) // No spacing as the content already contains it. + case let locationTimelineItem as LocationRoomTimelineItem: + .overlay(capsuleStyle: locationTimelineItem.content.geoURI != nil) + default: + .horizontal() + } case is StickerRoomTimelineItem: .overlay(capsuleStyle: true) - case let locationTimelineItem as LocationRoomTimelineItem: - .overlay(capsuleStyle: locationTimelineItem.content.geoURI != nil) case is PollRoomTimelineItem: .vertical(spacing: 16) default: diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift index b89ec72f76..7c9fb5c8b1 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift @@ -10,18 +10,16 @@ import SwiftUI struct AudioRoomTimelineView: View { let timelineItem: AudioRoomTimelineItem - + var body: some View { TimelineStyler(timelineItem: timelineItem) { - Label(title: { Text(timelineItem.body) }, - icon: { Image(systemName: "waveform") - .foregroundColor(.compound.iconPrimary) - }) - .labelStyle(RoomTimelineViewLabelStyle()) - .font(.compound.bodyLG) - .padding(.vertical, 12) - .padding(.horizontal, 6) - .accessibilityLabel(L10n.commonAudio) + 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) } } } @@ -30,21 +28,31 @@ struct AudioRoomTimelineView_Previews: PreviewProvider, TestablePreview { static let viewModel = TimelineViewModel.mock static var previews: some View { - body.environmentObject(viewModel.context) + VStack(spacing: 20) { + AudioRoomTimelineView(timelineItem: makeItem(filename: "audio.ogg", + fileSize: 2 * 1024 * 1024)) + + AudioRoomTimelineView(timelineItem: makeItem(filename: "Best Song Ever.mp3", + fileSize: 7 * 1024 * 1024, + caption: "This song rocks!")) + } + .environmentObject(viewModel.context) } - static var body: some View { - AudioRoomTimelineView(timelineItem: AudioRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "audio.ogg", - duration: 300, - waveform: nil, - source: nil, - contentType: nil))) + static func makeItem(filename: String, fileSize: UInt, caption: String? = nil) -> AudioRoomTimelineItem { + .init(id: .randomEvent, + timestamp: "Now", + 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/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift index d9b3ccd4d5..b2f2e5d8df 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift @@ -13,63 +13,110 @@ struct FileRoomTimelineView: View { var body: some View { TimelineStyler(timelineItem: timelineItem) { - Label { Text(timelineItem.body) } icon: { - CompoundIcon(\.document) - .foregroundColor(.compound.iconPrimary) + MediaFileRoomTimelineContent(filename: timelineItem.content.filename, + fileSize: timelineItem.content.fileSize, + caption: timelineItem.content.caption, + formattedCaption: timelineItem.content.formattedCaption, + additionalWhitespaces: timelineItem.additionalWhitespaces()) + .accessibilityLabel(L10n.commonFile) + } + } +} + +// MARK: Content + +struct MediaFileRoomTimelineContent: View { + let filename: String + let fileSize: UInt? + let caption: String? + let formattedCaption: AttributedString? + let additionalWhitespaces: Int + var isAudioFile = false + + var icon: KeyPath { + isAudioFile ? \.audio : \.attachment + } + + var body: some View { + VStack(alignment: .leading, spacing: 8) { + filePreview + + if let formattedCaption { + FormattedBodyText(attributedString: formattedCaption, + additionalWhitespacesCount: additionalWhitespaces) + } else if let caption { + FormattedBodyText(text: caption, + additionalWhitespacesCount: additionalWhitespaces) + } + } + } + + var filePreview: some View { + Label { + HStack(spacing: 4) { + Text(filename) + .truncationMode(.middle) + + if let fileSize { + Text("(\(fileSize.formatted(.byteCount(style: .file))))") + .layoutPriority(1) // We want the filename to truncate rather than the size. + } } - .labelStyle(RoomTimelineViewLabelStyle()) .font(.compound.bodyLG) - .padding(.vertical, 8) - .padding(.horizontal, 6) - .accessibilityLabel(L10n.commonFile) + .foregroundStyle(.compound.textPrimary) + .lineLimit(1) + } icon: { + CompoundIcon(icon, size: .xSmall, relativeTo: .body) + .foregroundColor(.compound.iconPrimary) + .scaledPadding(8) + .background(.compound.iconOnSolidPrimary, in: Circle()) } + .labelStyle(.custom(spacing: 8, alignment: .center)) + .padding(.horizontal, 4) // Add to the styler's padding of 8, as we use the default insets for the caption. } } +// MARK: - Previews + struct FileRoomTimelineView_Previews: PreviewProvider, TestablePreview { static let viewModel = TimelineViewModel.mock static var previews: some View { - body.environmentObject(viewModel.context) - } - - static var body: some View { VStack(spacing: 20.0) { - FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "document.pdf", - source: nil, - thumbnailSource: nil, - contentType: nil))) - - FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "document.docx", - source: nil, - thumbnailSource: nil, - contentType: nil))) + FileRoomTimelineView(timelineItem: makeItem(filename: "document.pdf")) + + FileRoomTimelineView(timelineItem: makeItem(filename: "document.pdf", + fileSize: 3 * 1024 * 1024)) + + FileRoomTimelineView(timelineItem: makeItem(filename: "spreadsheet.xlsx", + fileSize: 17 * 1024, + caption: "The important figures you asked me to send over.")) - FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: .randomEvent, - timestamp: "Now", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: "Bob"), - content: .init(filename: "document.txt", - source: nil, - thumbnailSource: nil, - contentType: nil))) + FileRoomTimelineView(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: "Now", + 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/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItemContent.swift index 4ca8d5c1f1..0691ed5dec 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/AudioRoomTimelineItemContent.swift @@ -17,5 +17,6 @@ struct AudioRoomTimelineItemContent: Hashable { let duration: TimeInterval let waveform: EstimatedWaveform? let source: MediaSourceProxy? + let fileSize: UInt? let contentType: UTType? } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItemContent.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItemContent.swift index 67f00ee1ba..3a2f52cf56 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItemContent.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/FileRoomTimelineItemContent.swift @@ -15,6 +15,7 @@ struct FileRoomTimelineItemContent: Hashable { /// The original textual representation of the formatted caption directly from the event (usually HTML code) var formattedCaptionHTMLString: String? let source: MediaSourceProxy? + let fileSize: UInt? let thumbnailSource: MediaSourceProxy? let contentType: UTType? } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift index 0e70287ac5..27e1699e68 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift @@ -67,6 +67,7 @@ struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview { duration: 300, waveform: EstimatedWaveform.mockWaveform, source: nil, + fileSize: nil, contentType: nil)) static let playerState = AudioPlayerState(id: .timelineItemIdentifier(timelineItemIdentifier), diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index 4f0401a4b6..0843b042f2 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -503,6 +503,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { duration: messageContent.audio?.duration ?? 0, waveform: waveform, source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype), + fileSize: messageContent.info?.size.map(UInt.init), contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename)) } @@ -572,6 +573,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { formattedCaption: formattedCaption, formattedCaptionHTMLString: htmlCaption, source: MediaSourceProxy(source: messageContent.source, mimeType: messageContent.info?.mimetype), + fileSize: messageContent.info?.size.map(UInt.init), thumbnailSource: thumbnailSource, contentType: UTType(mimeType: messageContent.info?.mimetype, fallbackFilename: messageContent.filename)) } 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 b9681ce33c..77d646e93d 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:fa607ea20134baf6191f63c8779cf36e992c040f5819b798c9be56fd22098593 -size 76297 +oid sha256:11690714e9762d729ca2b9777494f4ffe479ca03b95e282c6dafcbcd0c6e47d1 +size 99579 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 b9681ce33c..738fbac9c3 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:fa607ea20134baf6191f63c8779cf36e992c040f5819b798c9be56fd22098593 -size 76297 +oid sha256:d029be2d41fb70268aafe9e252edea552014545591c9f06ddb5abbb7b872ad88 +size 102503 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 42dccb4a75..3d6a58edaf 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:470baef15b29e19a7ae58a12682d590baa1f7759b0915f2e96f5594cc0eed1c2 -size 35522 +oid sha256:6d06795ef84b2f9eef65341825a0dcef00f5c0e646a0a441824b9a656eb57ef7 +size 55300 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 42dccb4a75..0d6d54cc85 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:470baef15b29e19a7ae58a12682d590baa1f7759b0915f2e96f5594cc0eed1c2 -size 35522 +oid sha256:796fe32ebed61725457773d6bc27768f2a38fd5af2c0492fcd488125f8126fd0 +size 57907 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 2bcba76ae0..a6a5188237 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:4f624a30e09d9565a05f87d05ccf04078398f143b7932dac46667be81cb3e62b -size 97559 +oid sha256:90f04fdb63831afb462488dc0afbcf78e9a2c1f8ccfae3855432d6b23f23f0d4 +size 137263 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 2bcba76ae0..b981dcc80e 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:4f624a30e09d9565a05f87d05ccf04078398f143b7932dac46667be81cb3e62b -size 97559 +oid sha256:daf4fbf2db6fb4412d80e949cb4374a5aa456bd1458919ee1d90f36fead48d07 +size 141084 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 83d78ac8e7..0386112477 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:1aa13a458240d535e549c8807310618cefa9d668e77fb0e7e961c247f1f16cd3 -size 55007 +oid sha256:a938ef5e6940b0f3c65a345db8c34b648873a7f2037f154569f22fa35e71aaa6 +size 89747 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 83d78ac8e7..4188d70a77 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:1aa13a458240d535e549c8807310618cefa9d668e77fb0e7e961c247f1f16cd3 -size 55007 +oid sha256:3615b93b61f8eb6baa432734763d405fe3f6b679d67e11a25277e760188f8189 +size 93512 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 a66bfd00bb..305ad5bb7b 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:b45a09f5c5f8ef2b33a9df690d89593a033bd059b54c5c2ab8c0f93f0276d849 -size 792454 +oid sha256:31312441ddb1fe7fa2676ec39ae63baded5f37dfb15885a4b1ba60c57bd2aa6f +size 779529 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 22147dedb9..20743368bd 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:94dfce790f72ce05f4dc60fb3c1d496c75ff9cd4cf0d399642c04a3cd55939c4 -size 182264 +oid sha256:dcfa8241cb8d5e245905a542a42ab355468dbfad3c98d2470ddcc777de7cd877 +size 186237 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 a66bfd00bb..305ad5bb7b 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:b45a09f5c5f8ef2b33a9df690d89593a033bd059b54c5c2ab8c0f93f0276d849 -size 792454 +oid sha256:31312441ddb1fe7fa2676ec39ae63baded5f37dfb15885a4b1ba60c57bd2aa6f +size 779529 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 4c574799a8..6af4c09f5b 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:bd08759268776f28320c82083904dbdfce23f28dbc5d5d33ee421f0a749f06b6 -size 189871 +oid sha256:53bfc5618c802866c2c1d611940c608cc444cd4f190043d2419ef639b134025c +size 193601 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 3ccfc81eac..bbb97786f6 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:03de5c32a0b0e47ea2b2d54214048fa1f9dadd7a7bed970af935d1c1ca0cf7ce -size 445294 +oid sha256:8cf67596ee0f149f600c1d5f4a61916683e56fbe303db96259f3b8d610d9afd0 +size 437588 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 2b5ea119ef..6f7eec15b4 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:ee12fa3438d396b0e7ef5abe50ca4c3fdfd906578e36e1b94b19fdbdeba50775 -size 135556 +oid sha256:04e188585bab8bcd1865df322954ca66db33162a534d9fa4e8066639fb509789 +size 135546 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 3ccfc81eac..bbb97786f6 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:03de5c32a0b0e47ea2b2d54214048fa1f9dadd7a7bed970af935d1c1ca0cf7ce -size 445294 +oid sha256:8cf67596ee0f149f600c1d5f4a61916683e56fbe303db96259f3b8d610d9afd0 +size 437588 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 9a55ba4585..7f3c6b2b55 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:de203ede489e3b3a48dc5cf171a0faa86f56b7993e4372c124b48d34632c9389 -size 138215 +oid sha256:4cdcf82c941481d377b72600aa68130fe1bdd81f459a6d60f10cf61366a6e862 +size 138005 diff --git a/UnitTests/Sources/LoggingTests.swift b/UnitTests/Sources/LoggingTests.swift index 26595f3613..dc7389e969 100644 --- a/UnitTests/Sources/LoggingTests.swift +++ b/UnitTests/Sources/LoggingTests.swift @@ -173,6 +173,7 @@ class LoggingTests: XCTestCase { content: .init(filename: "FileString", caption: "FileString", source: nil, + fileSize: nil, thumbnailSource: nil, contentType: nil)) diff --git a/project.yml b/project.yml index 9739ec753b..ab59e70c1b 100644 --- a/project.yml +++ b/project.yml @@ -65,7 +65,7 @@ packages: # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios - revision: f0436aa767f614584bf119defa6372ddb3b60080 + revision: 901f3f2fc150db82cf8a2c4da53914b31f681b56 # path: ../compound-ios AnalyticsEvents: url: https://github.com/matrix-org/matrix-analytics-events From fe984a1301ea892a636ae675bbacaeeeb0284704 Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:47:34 +0100 Subject: [PATCH 53/74] Knock Requests navigation flows (#3555) * implemented navigations * better naming for the enum * removed list to banned users navigation * polished the code * avatarURL --- .../en.lproj/Localizable.strings | 9 ++++ .../RoomFlowCoordinator.swift | 42 ++++++++----------- ElementX/Sources/Generated/Strings.swift | 22 ++++++++++ .../KnockRequestsListScreenCoordinator.swift | 7 +--- .../KnockRequestsListScreenModels.swift | 15 ++++++- .../KnockRequestsListScreenViewModel.swift | 27 ++++++++++-- .../View/KnockRequestCell.swift | 12 +++--- .../View/KnockRequestsListScreen.swift | 11 ++--- .../RoomScreen/RoomScreenCoordinator.swift | 3 ++ .../Screens/RoomScreen/RoomScreenModels.swift | 4 ++ .../RoomScreen/RoomScreenViewModel.swift | 8 ++++ .../Screens/RoomScreen/View/RoomScreen.swift | 6 +-- 12 files changed, 118 insertions(+), 48 deletions(-) diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 24b113fce0..85fac299a8 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -370,7 +370,16 @@ "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"; diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index 6c7f78e79e..b25c076bf7 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -316,10 +316,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { case (.roomMembersList, .dismissRoomMembersList): return .roomDetails(isRoot: false) - case (.room, .presentRoomMemberDetails(userID: let userID)): - return .roomMemberDetails(userID: userID, previousState: .room) - case (.roomMembersList, .presentRoomMemberDetails(userID: let userID)): - return .roomMemberDetails(userID: userID, previousState: .roomMembersList) + case (_, .presentRoomMemberDetails(userID: let userID)): + return .roomMemberDetails(userID: userID, previousState: fromState) case (.roomMemberDetails(_, let previousState), .dismissRoomMemberDetails): return previousState @@ -328,12 +326,10 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { case (.userProfile(_, let previousState), .dismissUserProfile): return previousState - case (.roomDetails, .presentInviteUsersScreen): - return .inviteUsersScreen(fromRoomMembersList: false) - case (.roomMembersList, .presentInviteUsersScreen): - return .inviteUsersScreen(fromRoomMembersList: true) - case (.inviteUsersScreen(let fromRoomMembersList), .dismissInviteUsersScreen): - return fromRoomMembersList ? .roomMembersList : .roomDetails(isRoot: false) + case (_, .presentInviteUsersScreen): + return .inviteUsersScreen(previousState: fromState) + case (.inviteUsersScreen(let previousState), .dismissInviteUsersScreen): + return previousState case (.room, .presentReportContent(let itemID, let senderID)): return .reportContent(itemID: itemID, senderID: senderID) @@ -398,9 +394,6 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { return .rolesAndPermissions case (.rolesAndPermissions, .dismissRolesAndPermissionsScreen): return .roomDetails(isRoot: false) - - case (.roomDetails, .presentRoomMemberDetails(let userID)): - return .roomMemberDetails(userID: userID, previousState: fromState) case (.room, .presentResolveSendFailure): return .resolveSendFailure @@ -414,10 +407,10 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { case (.presentingChild(_, let previousState), .dismissChildFlow): return previousState - case (.roomDetails, .presentKnockRequestsListScreen): - return .knockRequestsList - case (.knockRequestsList, .dismissKnockRequestsListScreen): - return .roomDetails(isRoot: false) + case (_, .presentKnockRequestsListScreen): + return .knockRequestsList(previousState: fromState) + case (.knockRequestsList(let previousState), .dismissKnockRequestsListScreen): + return previousState default: return nil @@ -575,6 +568,10 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { presentKnockRequestsList() case (.knockRequestsList, .dismissKnockRequestsListScreen, .roomDetails): break + case (.room, .presentKnockRequestsListScreen, .knockRequestsList): + presentKnockRequestsList() + case (.knockRequestsList, .dismissKnockRequestsListScreen, .room): + break // Child flow case (_, .startChildFlow(let roomID, let via, let entryPoint), .presentingChild): @@ -735,6 +732,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { stateMachine.tryEvent(.presentPinnedEventsTimeline) case .presentResolveSendFailure(failure: let failure, sendHandle: let sendHandle): stateMachine.tryEvent(.presentResolveSendFailure(failure: failure, sendHandle: sendHandle)) + case .presentKnockRequestsList: + stateMachine.tryEvent(.presentKnockRequestsListScreen) } } .store(in: &cancellables) @@ -899,11 +898,6 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { let parameters = KnockRequestsListScreenCoordinatorParameters(roomProxy: roomProxy, mediaProvider: userSession.mediaProvider) let coordinator = KnockRequestsListScreenCoordinator(parameters: parameters) - coordinator.actionsPublisher - .sink { [weak self] _ in - } - .store(in: &cancellables) - navigationStackCoordinator.push(coordinator) { [weak self] in self?.stateMachine.tryEvent(.dismissKnockRequestsListScreen) } @@ -1559,7 +1553,7 @@ private extension RoomFlowCoordinator { case roomMembersList case roomMemberDetails(userID: String, previousState: State) case userProfile(userID: String, previousState: State) - case inviteUsersScreen(fromRoomMembersList: Bool) + case inviteUsersScreen(previousState: State) case mediaUploadPicker(source: MediaPickerScreenSource) case mediaUploadPreview(fileURL: URL) case emojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set) @@ -1572,7 +1566,7 @@ private extension RoomFlowCoordinator { case rolesAndPermissions case pinnedEventsTimeline(previousState: PinnedEventsTimelineSource) case resolveSendFailure - case knockRequestsList + case knockRequestsList(previousState: State) /// A child flow is in progress. case presentingChild(childRoomID: String, previousState: State) diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 82f7d0a327..db23287898 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -1298,8 +1298,30 @@ internal enum L10n { } /// Are you sure you want to turn off key storage and delete it? internal static var screenKeyBackupDisableTitle: String { return L10n.tr("Localizable", "screen_key_backup_disable_title") } + /// Yes, accept all + internal static var screenKnockRequestsListAcceptAllAlertConfirmButtonTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_alert_confirm_button_title") } + /// Are you sure you want to accept all requests to join? + internal static var screenKnockRequestsListAcceptAllAlertDescription: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_alert_description") } + /// Accept all requests + 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") } + /// 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. + internal static func screenKnockRequestsListBanAlertDescription(_ p1: Any) -> String { + return L10n.tr("Localizable", "screen_knock_requests_list_ban_alert_description", String(describing: p1)) + } + /// Decline and ban from accessing + internal static var screenKnockRequestsListBanAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_ban_alert_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? + internal static func screenKnockRequestsListDeclineAlertDescription(_ p1: Any) -> String { + return L10n.tr("Localizable", "screen_knock_requests_list_decline_alert_description", String(describing: p1)) + } + /// Decline access + 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") } /// When somebody will ask to join the room, you’ll be able to see their request here. diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift index 00a0c32245..5d14686abb 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenCoordinator.swift @@ -32,12 +32,7 @@ final class KnockRequestsListScreenCoordinator: CoordinatorProtocol { mediaProvider: parameters.mediaProvider) } - func start() { - viewModel.actionsPublisher.sink { [weak self] action in - MXLog.info("Coordinator: received view model action: \(action)") - } - .store(in: &cancellables) - } + func start() { } func toPresentable() -> AnyView { AnyView(KnockRequestsListScreen(context: viewModel.context)) diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift index f45b0e6ec0..5747aff5f9 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift @@ -10,7 +10,8 @@ import Foundation enum KnockRequestsListScreenViewModelAction { } struct KnockRequestsListScreenViewState: BindableState { - var requests: [KnockRequestCellInfo] = [] + // 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")] // 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 @@ -22,6 +23,18 @@ struct KnockRequestsListScreenViewState: BindableState { var shouldDisplayRequests: Bool { !requests.isEmpty && isKnockableRoom && (canAccept || canDecline || canBan) } + + var bindings = KnockRequestsListStateBindings() +} + +struct KnockRequestsListStateBindings { + var alertInfo: AlertInfo? +} + +enum KnockRequestsListAlertType { + case acceptAllRequests + case declineRequest + case declineAndBan } enum KnockRequestsListScreenViewAction { diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift index 2c8327e22a..391cc60a95 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift @@ -35,13 +35,34 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn override func process(viewAction: KnockRequestsListScreenViewAction) { switch viewAction { case .acceptAllRequests: - break + state.bindings.alertInfo = .init(id: .acceptAllRequests, + title: L10n.screenKnockRequestsListAcceptAllAlertTitle, + message: L10n.screenKnockRequestsListAcceptAllAlertDescription, + primaryButton: .init(title: L10n.screenKnockRequestsListAcceptAllAlertConfirmButtonTitle, + // TODO: Implement action + action: nil), + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) case .acceptRequest(let userID): + // TODO: Implement break case .declineRequest(let userID): - break + state.bindings.alertInfo = .init(id: .declineRequest, + title: L10n.screenKnockRequestsListDeclineAlertTitle, + message: L10n.screenKnockRequestsListDeclineAlertDescription(userID), + primaryButton: .init(title: L10n.screenKnockRequestsListDeclineAlertConfirmButtonTitle, + role: .destructive, + // TODO: Implement action + action: nil), + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) case .ban(let userID): - break + 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), + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) } } diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift index 41d7da1927..db6962d1f1 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestCell.swift @@ -19,7 +19,7 @@ struct KnockRequestCellInfo: Identifiable { /// user identifier of the usee that sent the request let id: String let displayName: String? - let avatarUrl: URL? + let avatarURL: URL? let timestamp: String? let reason: String? } @@ -33,7 +33,7 @@ struct KnockRequestCell: View { var body: some View { HStack(alignment: .top, spacing: 16) { - LoadableAvatarImage(url: cellInfo.avatarUrl, + LoadableAvatarImage(url: cellInfo.avatarURL, name: cellInfo.displayName, contentID: cellInfo.id, avatarSize: .user(on: .knockingUserList), @@ -168,13 +168,13 @@ private struct DisclosableText: View { 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(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 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(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 aliceWithNoReason = KnockRequestCellInfo(id: "@alice:matrix.org", displayName: "Alice", avatarUrl: nil, timestamp: "20 Nov 2024", reason: nil) + static let aliceWithNoReason = KnockRequestCellInfo(id: "@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(id: "@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 }) diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift index da85216743..d3bc5915a4 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/View/KnockRequestsListScreen.swift @@ -26,6 +26,7 @@ struct KnockRequestsListScreen: View { acceptAllButton } } + .alert(item: $context.alertInfo) } @ViewBuilder @@ -75,13 +76,13 @@ struct KnockRequestsListScreen: View { // MARK: - Previews struct KnockRequestsListScreen_Previews: PreviewProvider, TestablePreview { - static let emptyViewModel = KnockRequestsListScreenViewModel.mockWithInitialState(.init()) + static let emptyViewModel = KnockRequestsListScreenViewModel.mockWithInitialState(.init(requests: [])) - static let viewModel = KnockRequestsListScreenViewModel.mockWithInitialState(.init(requests: [.init(id: "@alice:matrix.org", displayName: "Alice", avatarUrl: nil, timestamp: "Now", reason: "Hello"), + 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!")])) + .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 { diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift index b920ef687b..94b94d51a6 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift @@ -42,6 +42,7 @@ enum RoomScreenCoordinatorAction { case presentCallScreen case presentPinnedEventsTimeline case presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, sendHandle: SendHandleProxy) + case presentKnockRequestsList } final class RoomScreenCoordinator: CoordinatorProtocol { @@ -169,6 +170,8 @@ final class RoomScreenCoordinator: CoordinatorProtocol { actionsSubject.send(.presentCallScreen) case .removeComposerFocus: composerViewModel.process(timelineAction: .removeFocus) + case .displayKnockRequests: + actionsSubject.send(.presentKnockRequestsList) } } .store(in: &cancellables) diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift index 4c8ff2009f..e9b16fa378 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift @@ -14,6 +14,7 @@ enum RoomScreenViewModelAction { case displayRoomDetails case displayCall case removeComposerFocus + case displayKnockRequests } enum RoomScreenViewAction { @@ -22,6 +23,9 @@ enum RoomScreenViewAction { case displayRoomDetails case displayCall case footerViewAction(RoomScreenFooterViewAction) + case acceptKnock(userID: String) + case dismissKnockRequests + case viewKnockRequests } struct RoomScreenViewState: BindableState { diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift index 3e43a48370..c518a39e4a 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift @@ -103,6 +103,14 @@ 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 .dismissKnockRequests: + // TODO: API to mark knocks as seen required + break + case .viewKnockRequests: + actionsSubject.send(.displayKnockRequests) } } diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift index 3df34b6439..aad279595b 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift @@ -148,15 +148,15 @@ struct RoomScreen: View { } private func dismissKnockRequestsBanner() { - // TODO: Implement + roomContext.send(viewAction: .dismissKnockRequests) } private func acceptKnockRequest(userID: String) { - // TODO: Implement + roomContext.send(viewAction: .acceptKnock(userID: userID)) } private func onViewAllKnockRequests() { - // TODO: Implement + roomContext.send(viewAction: .viewKnockRequests) } private var scrollToBottomButton: some View { From 3f0f4429373a4a45d099180f892aa49d5964afad Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:23:20 +0000 Subject: [PATCH 54/74] Fix the presentation of QuickLook when viewing logs on macOS. (#3556) --- .../BugReportFlowCoordinator.swift | 15 +++++++++++++-- .../LogViewerScreen/View/LogViewerScreen.swift | 6 +----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift index 04a37713d5..efc6b0b33e 100644 --- a/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift @@ -6,6 +6,7 @@ // import Combine +import Foundation struct BugReportFlowCoordinatorParameters { enum PresentationMode { @@ -93,12 +94,22 @@ class BugReportFlowCoordinator: FlowCoordinatorProtocol { switch action { case .done: - internalNavigationStackCoordinator?.pop() + if ProcessInfo.processInfo.isiOSAppOnMac { + internalNavigationStackCoordinator?.setSheetCoordinator(nil) + } else { + internalNavigationStackCoordinator?.pop() + } } } .store(in: &cancellables) - internalNavigationStackCoordinator?.push(coordinator) + if ProcessInfo.processInfo.isiOSAppOnMac { + // On macOS the QuickLook is a separate window, closing a pushed QuickLook + // controller closes the whole Settings sheet so lets add another one. + internalNavigationStackCoordinator?.setSheetCoordinator(coordinator) + } else { + internalNavigationStackCoordinator?.push(coordinator) + } } private func dismiss() { diff --git a/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift b/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift index cdb9cace9f..c401dc2e4f 100644 --- a/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift +++ b/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift @@ -25,11 +25,7 @@ private struct PreviewView: UIViewControllerRepresentable { previewController.dataSource = context.coordinator previewController.delegate = context.coordinator - if ProcessInfo.processInfo.isiOSAppOnMac { - return previewController - } else { - return UINavigationController(rootViewController: previewController) - } + return UINavigationController(rootViewController: previewController) } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { } From 36980840ed2f23bb3da273472a310c235b9491cf Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Tue, 26 Nov 2024 16:25:46 +0200 Subject: [PATCH 55/74] Move timeline item tap gestures to the items themselves instead of the bubbled styler (#3553) * Stop observing the timeline context where not necessary. * Rename the timeline `itemTapped` action to `mediaTapped` --- .../Sources/Other/SwiftUI/Views/LoadableImage.swift | 2 +- .../Sources/Screens/Timeline/TimelineModels.swift | 2 +- .../Sources/Screens/Timeline/TimelineViewModel.swift | 6 +++--- .../View/Style/TimelineItemBubbledStylerView.swift | 10 +++++----- .../TimelineItemViews/AudioRoomTimelineView.swift | 3 ++- .../CallNotificationRoomTimelineView.swift | 4 ++-- .../View/TimelineItemViews/FileRoomTimelineView.swift | 9 ++++++++- .../TimelineItemViews/ImageRoomTimelineView.swift | 10 +++++++--- .../TimelineItemViews/LocationRoomTimelineView.swift | 4 ++++ .../TimelineItemViews/StickerRoomTimelineView.swift | 11 ++++++++--- .../TimelineItemViews/VideoRoomTimelineView.swift | 7 +++++-- .../Timeline/View/TimelineSenderAvatarView.swift | 4 ++-- .../VoiceMessages/VoiceMessageRoomTimelineView.swift | 10 +++++----- 13 files changed, 53 insertions(+), 29 deletions(-) diff --git a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift index ad3a4fb75c..c8702156d3 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift @@ -204,7 +204,7 @@ private struct LoadableImageContent: View { var messageBubbleWithActions: some View { messageBubble - .onTapGesture { - context.send(viewAction: .itemTapped(itemID: timelineItem.id)) - } - // We need a tap gesture before this long one so that it doesn't - // steal away the gestures from the scroll view .longPressWithFeedback { context.send(viewAction: .displayTimelineItemMenu(itemID: timelineItem.id)) } @@ -396,6 +391,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview } } .environmentObject(viewModel.context) + .environment(\.timelineContext, viewModel.context) } static var replies: some View { @@ -427,6 +423,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview groupStyle: .single)) } .environmentObject(viewModel.context) + .environment(\.timelineContext, viewModel.context) } static var threads: some View { @@ -434,6 +431,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview MockTimelineContent(isThreaded: true) } .environmentObject(viewModel.context) + .environment(\.timelineContext, viewModel.context) } static var pinned: some View { @@ -441,6 +439,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview MockTimelineContent(isPinned: true) } .environmentObject(viewModelWithPins.context) + .environment(\.timelineContext, viewModel.context) } static var encryptionAuthenticity: some View { @@ -523,6 +522,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview waveform: EstimatedWaveform.mockWaveform)) } .environmentObject(viewModel.context) + .environment(\.timelineContext, viewModel.context) } } diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift index 7c9fb5c8b1..dd0ef08829 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/AudioRoomTimelineView.swift @@ -13,7 +13,8 @@ struct AudioRoomTimelineView: View { var body: some View { TimelineStyler(timelineItem: timelineItem) { - MediaFileRoomTimelineContent(filename: timelineItem.content.filename, + MediaFileRoomTimelineContent(timelineItemID: timelineItem.id, + filename: timelineItem.content.filename, fileSize: timelineItem.content.fileSize, caption: timelineItem.content.caption, formattedCaption: timelineItem.content.formattedCaption, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallNotificationRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallNotificationRoomTimelineView.swift index c584b8a34f..e4a8c93b0a 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallNotificationRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/CallNotificationRoomTimelineView.swift @@ -10,7 +10,7 @@ import Foundation import SwiftUI struct CallNotificationRoomTimelineView: View { - @EnvironmentObject private var context: TimelineViewModel.Context + @Environment(\.timelineContext) private var context let timelineItem: CallNotificationRoomTimelineItem @@ -20,7 +20,7 @@ struct CallNotificationRoomTimelineView: View { name: timelineItem.sender.displayName ?? timelineItem.sender.id, contentID: timelineItem.sender.id, avatarSize: .user(on: .timeline), - mediaProvider: context.mediaProvider) + mediaProvider: context?.mediaProvider) .accessibilityHidden(true) VStack(alignment: .leading, spacing: 0) { diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift index b2f2e5d8df..3bb13c6585 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/FileRoomTimelineView.swift @@ -13,7 +13,8 @@ struct FileRoomTimelineView: View { var body: some View { TimelineStyler(timelineItem: timelineItem) { - MediaFileRoomTimelineContent(filename: timelineItem.content.filename, + MediaFileRoomTimelineContent(timelineItemID: timelineItem.id, + filename: timelineItem.content.filename, fileSize: timelineItem.content.fileSize, caption: timelineItem.content.caption, formattedCaption: timelineItem.content.formattedCaption, @@ -26,6 +27,9 @@ 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? @@ -40,6 +44,9 @@ struct MediaFileRoomTimelineContent: View { var body: some View { VStack(alignment: .leading, spacing: 8) { filePreview + .onTapGesture { + context?.send(viewAction: .mediaTapped(itemID: timelineItemID)) + } if let formattedCaption { FormattedBodyText(attributedString: formattedCaption, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift index 53bd61704b..86ad073d08 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift @@ -9,7 +9,7 @@ import Foundation import SwiftUI struct ImageRoomTimelineView: View { - @EnvironmentObject private var context: TimelineViewModel.Context + @Environment(\.timelineContext) private var context let timelineItem: ImageRoomTimelineItem var hasMediaCaption: Bool { timelineItem.content.caption != nil } @@ -23,6 +23,9 @@ struct ImageRoomTimelineView: View { // This clip shape is distinct from the one in the styler as that one // operates on the entire message so wouldn't round the bottom corners. .clipShape(RoundedRectangle(cornerRadius: hasMediaCaption ? 6 : 0)) + .onTapGesture { + context?.send(viewAction: .mediaTapped(itemID: timelineItem.id)) + } if let attributedCaption = timelineItem.content.formattedCaption { FormattedBodyText(attributedString: attributedCaption, @@ -44,7 +47,7 @@ struct ImageRoomTimelineView: View { mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.content.blurhash, size: timelineItem.content.imageInfo.size, - mediaProvider: context.mediaProvider) { + mediaProvider: context?.mediaProvider) { placeholder } .timelineMediaFrame(imageInfo: timelineItem.content.imageInfo) @@ -53,7 +56,7 @@ struct ImageRoomTimelineView: View { mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.content.blurhash, size: timelineItem.content.thumbnailInfo?.size ?? timelineItem.content.imageInfo.size, - mediaProvider: context.mediaProvider) { + mediaProvider: context?.mediaProvider) { placeholder } .timelineMediaFrame(imageInfo: timelineItem.content.thumbnailInfo ?? timelineItem.content.imageInfo) @@ -73,6 +76,7 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview { static var previews: some View { body .environmentObject(viewModel.context) + .environment(\.timelineContext, viewModel.context) } static var body: some View { diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift index 6d3752dbd2..6c6b70189f 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/LocationRoomTimelineView.swift @@ -8,6 +8,7 @@ import SwiftUI struct LocationRoomTimelineView: View { + @Environment(\.timelineContext) private var context let timelineItem: LocationRoomTimelineItem var body: some View { @@ -15,6 +16,9 @@ struct LocationRoomTimelineView: View { mainContent .accessibilityElement(children: .ignore) .accessibilityLabel(accessibilityLabel) + .onTapGesture { + context?.send(viewAction: .mediaTapped(itemID: timelineItem.id)) + } } } diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift index b411148670..043d68834b 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift @@ -9,7 +9,7 @@ import Foundation import SwiftUI struct StickerRoomTimelineView: View { - @EnvironmentObject private var context: TimelineViewModel.Context + @Environment(\.timelineContext) private var context let timelineItem: StickerRoomTimelineItem var body: some View { @@ -18,12 +18,15 @@ struct StickerRoomTimelineView: View { mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.blurhash, size: timelineItem.imageInfo.size, - mediaProvider: context.mediaProvider) { + mediaProvider: context?.mediaProvider) { placeholder } .timelineMediaFrame(imageInfo: timelineItem.imageInfo) .accessibilityElement(children: .ignore) .accessibilityLabel("\(L10n.commonSticker), \(timelineItem.body)") + .onTapGesture { + context?.send(viewAction: .mediaTapped(itemID: timelineItem.id)) + } } } @@ -38,7 +41,9 @@ struct StickerRoomTimelineView_Previews: PreviewProvider, TestablePreview { static let viewModel = TimelineViewModel.mock static var previews: some View { - body.environmentObject(viewModel.context) + body + .environmentObject(viewModel.context) + .environment(\.timelineContext, viewModel.context) } static var body: some View { diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift index 030b584998..88337eb78f 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift @@ -9,7 +9,7 @@ import Foundation import SwiftUI struct VideoRoomTimelineView: View { - @EnvironmentObject private var context: TimelineViewModel.Context + @Environment(\.timelineContext) private var context let timelineItem: VideoRoomTimelineItem private var hasMediaCaption: Bool { timelineItem.content.caption != nil } @@ -24,6 +24,9 @@ struct VideoRoomTimelineView: View { // This clip shape is distinct from the one in the styler as that one // operates on the entire message so wouldn't round the bottom corners. .clipShape(RoundedRectangle(cornerRadius: hasMediaCaption ? 6 : 0)) + .onTapGesture { + context?.send(viewAction: .mediaTapped(itemID: timelineItem.id)) + } if let attributedCaption = timelineItem.content.formattedCaption { FormattedBodyText(attributedString: attributedCaption, @@ -45,7 +48,7 @@ struct VideoRoomTimelineView: View { mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.content.blurhash, size: timelineItem.content.thumbnailInfo?.size, - mediaProvider: context.mediaProvider) { imageView in + mediaProvider: context?.mediaProvider) { imageView in imageView .overlay { playIcon } } placeholder: { diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineSenderAvatarView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineSenderAvatarView.swift index 4dd222bcec..72fb09764b 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineSenderAvatarView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineSenderAvatarView.swift @@ -9,7 +9,7 @@ import Foundation import SwiftUI struct TimelineSenderAvatarView: View { - @EnvironmentObject private var context: TimelineViewModel.Context + @Environment(\.timelineContext) private var context let timelineItem: EventBasedTimelineItemProtocol @@ -18,7 +18,7 @@ struct TimelineSenderAvatarView: View { name: timelineItem.sender.displayName, contentID: timelineItem.sender.id, avatarSize: .user(on: .timeline), - mediaProvider: context.mediaProvider) + mediaProvider: context?.mediaProvider) .overlay { Circle().stroke(Color.compound.bgCanvasDefault, lineWidth: 3) } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift index 27e1699e68..df55cf05df 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Messages/VoiceMessages/VoiceMessageRoomTimelineView.swift @@ -9,7 +9,7 @@ import Foundation import SwiftUI struct VoiceMessageRoomTimelineView: View { - @EnvironmentObject private var context: TimelineViewModel.Context + @Environment(\.timelineContext) private var context private let timelineItem: VoiceMessageRoomTimelineItem private let playerState: AudioPlayerState @State private var resumePlaybackAfterScrubbing = false @@ -31,22 +31,22 @@ struct VoiceMessageRoomTimelineView: View { } private func onPlaybackPlayPause() { - context.send(viewAction: .handleAudioPlayerAction(.playPause(itemID: timelineItem.id))) + context?.send(viewAction: .handleAudioPlayerAction(.playPause(itemID: timelineItem.id))) } private func onPlaybackSeek(_ progress: Double) { - context.send(viewAction: .handleAudioPlayerAction(.seek(itemID: timelineItem.id, progress: progress))) + context?.send(viewAction: .handleAudioPlayerAction(.seek(itemID: timelineItem.id, progress: progress))) } private func onPlaybackScrubbing(_ dragging: Bool) { if dragging { if playerState.playbackState == .playing { resumePlaybackAfterScrubbing = true - context.send(viewAction: .handleAudioPlayerAction(.playPause(itemID: timelineItem.id))) + context?.send(viewAction: .handleAudioPlayerAction(.playPause(itemID: timelineItem.id))) } } else { if resumePlaybackAfterScrubbing { - context.send(viewAction: .handleAudioPlayerAction(.playPause(itemID: timelineItem.id))) + context?.send(viewAction: .handleAudioPlayerAction(.playPause(itemID: timelineItem.id))) resumePlaybackAfterScrubbing = false } } From ed4063a2229d7fb645195a1b4cbecd6362b302d0 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Tue, 26 Nov 2024 17:16:32 +0200 Subject: [PATCH 56/74] Bump the RustSDK to v1.0.75 --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../Mocks/Generated/SDKGeneratedMocks.swift | 65 ------------------- project.yml | 2 +- 4 files changed, 4 insertions(+), 69 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 29ef45876c..eddd1befb0 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -8195,7 +8195,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.74; + version = 1.0.75; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index ce20e47b9f..dca464ac2e 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "66d32e79ae20dd31201cd16eced53cfcc0c3239d", - "version" : "1.0.74" + "revision" : "6b14c048543bac9effe5e44fa90333bfa7dd9435", + "version" : "1.0.75" } }, { diff --git a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift index eb7722fe12..9c76fc5c50 100644 --- a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift @@ -8248,71 +8248,6 @@ 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 diff --git a/project.yml b/project.yml index ab59e70c1b..ea2d55d7c3 100644 --- a/project.yml +++ b/project.yml @@ -61,7 +61,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.74 + exactVersion: 1.0.75 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From a292c41ca5ef6aec602bd2fd15da45dbd6aaca79 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Wed, 27 Nov 2024 06:30:10 +0000 Subject: [PATCH 57/74] Move the media caption composer (and Add Caption action) behind a feature flag for now. (#3560) --- ElementX/Sources/Application/AppSettings.swift | 4 ++++ .../FlowCoordinators/RoomFlowCoordinator.swift | 3 ++- .../MediaUploadPreviewScreenCoordinator.swift | 4 +++- .../MediaUploadPreviewScreenModels.swift | 1 + .../MediaUploadPreviewScreenViewModel.swift | 5 +++-- .../View/MediaUploadPreviewScreen.swift | 13 ++++++++----- .../View/PinnedEventsTimelineScreen.swift | 1 + .../Screens/RoomScreen/View/RoomScreen.swift | 1 + .../DeveloperOptionsScreenModels.swift | 1 + .../View/DeveloperOptionsScreen.swift | 4 ++++ .../Sources/Screens/Timeline/TimelineModels.swift | 1 + .../Screens/Timeline/TimelineViewModel.swift | 5 +++++ .../ItemMenu/TimelineItemMenuActionProvider.swift | 3 ++- .../View/Style/TimelineItemBubbledStylerView.swift | 1 + .../MediaUploadPreviewScreenViewModelTests.swift | 3 ++- 15 files changed, 39 insertions(+), 11 deletions(-) diff --git a/ElementX/Sources/Application/AppSettings.swift b/ElementX/Sources/Application/AppSettings.swift index cb800e96a0..eff6e295a1 100644 --- a/ElementX/Sources/Application/AppSettings.swift +++ b/ElementX/Sources/Application/AppSettings.swift @@ -47,6 +47,7 @@ final class AppSettings { case fuzzyRoomListSearchEnabled case enableOnlySignedDeviceIsolationMode case knockingEnabled + case createMediaCaptionsEnabled } private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier @@ -280,6 +281,9 @@ 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 diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index b25c076bf7..3a58bdfac1 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -996,7 +996,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { roomProxy: roomProxy, mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: appSettings), title: url.lastPathComponent, - url: url) + url: url, + createMediaCaptionsEnabled: appSettings.createMediaCaptionsEnabled) let mediaUploadPreviewScreenCoordinator = MediaUploadPreviewScreenCoordinator(parameters: parameters) diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift index 42633e9b54..78bf651045 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift @@ -14,6 +14,7 @@ struct MediaUploadPreviewScreenCoordinatorParameters { let mediaUploadingPreprocessor: MediaUploadingPreprocessor let title: String? let url: URL + let createMediaCaptionsEnabled: Bool } enum MediaUploadPreviewScreenCoordinatorAction { @@ -34,7 +35,8 @@ final class MediaUploadPreviewScreenCoordinator: CoordinatorProtocol { roomProxy: parameters.roomProxy, mediaUploadingPreprocessor: parameters.mediaUploadingPreprocessor, title: parameters.title, - url: parameters.url) + url: parameters.url, + createMediaCaptionsEnabled: parameters.createMediaCaptionsEnabled) } func start() { diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift index f9c1eb178e..ecd05d345b 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift @@ -14,6 +14,7 @@ enum MediaUploadPreviewScreenViewModelAction { struct MediaUploadPreviewScreenViewState: BindableState { let url: URL let title: String? + let showMediaCaptionComposer: Bool var shouldDisableInteraction = false var bindings = MediaUploadPreviewScreenBindings() diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift index c7f2164db3..e4d8decd4f 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift @@ -32,13 +32,14 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, roomProxy: JoinedRoomProxyProtocol, mediaUploadingPreprocessor: MediaUploadingPreprocessor, title: String?, - url: URL) { + url: URL, + createMediaCaptionsEnabled: Bool) { self.userIndicatorController = userIndicatorController self.roomProxy = roomProxy self.mediaUploadingPreprocessor = mediaUploadingPreprocessor self.url = url - super.init(initialViewState: MediaUploadPreviewScreenViewState(url: url, title: title)) + super.init(initialViewState: MediaUploadPreviewScreenViewState(url: url, title: title, showMediaCaptionComposer: createMediaCaptionsEnabled)) } override func process(viewAction: MediaUploadPreviewScreenViewAction) { diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift index bcd0309b65..807df69935 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift @@ -22,10 +22,12 @@ struct MediaUploadPreviewScreen: View { .id(context.viewState.url) .ignoresSafeArea(edges: [.horizontal]) .safeAreaInset(edge: .bottom, spacing: 0) { - composer - .padding(.horizontal, 12) - .padding(.vertical, 16) - .background() // Don't use compound so we match the QLPreviewController. + if context.viewState.showMediaCaptionComposer { + composer + .padding(.horizontal, 12) + .padding(.vertical, 16) + .background() // Don't use compound so we match the QLPreviewController. + } } .navigationTitle(title) .navigationBarTitleDisplayMode(.inline) @@ -156,7 +158,8 @@ struct MediaUploadPreviewScreen_Previews: PreviewProvider, TestablePreview { roomProxy: JoinedRoomProxyMock(), mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings), title: "App Icon.png", - url: snapshotURL) + url: snapshotURL, + createMediaCaptionsEnabled: true) static var previews: some View { NavigationStack { MediaUploadPreviewScreen(context: viewModel.context) diff --git a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift index 8a18ec2744..80dcd267cd 100644 --- a/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift +++ b/ElementX/Sources/Screens/PinnedEventsTimelineScreen/View/PinnedEventsTimelineScreen.swift @@ -37,6 +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, emojiProvider: timelineContext.viewState.emojiProvider) .makeActions() diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift index aad279595b..c6f1792259 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift @@ -75,6 +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, emojiProvider: timelineContext.viewState.emojiProvider) .makeActions() diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift index 2f1322eccd..d8a496c8f0 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/DeveloperOptionsScreenModels.swift @@ -50,6 +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 } } extension AppSettings: DeveloperOptionsProtocol { } diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift index bdeb01df78..de6909cc5f 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift @@ -53,6 +53,10 @@ struct DeveloperOptionsScreen: View { 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/Timeline/TimelineModels.swift b/ElementX/Sources/Screens/Timeline/TimelineModels.swift index 8e8bc71fcf..2108e635a0 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineModels.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineModels.swift @@ -99,6 +99,7 @@ struct TimelineViewState: BindableState { 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/TimelineViewModel.swift b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift index 66ce90d751..3777feed1d 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift @@ -81,6 +81,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { timelineViewState: 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: [:]), @@ -447,6 +448,10 @@ 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) diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift index df74221431..cad18009e4 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift @@ -16,6 +16,7 @@ struct TimelineItemMenuActionProvider { let pinnedEventIDs: Set let isDM: Bool let isViewSourceEnabled: Bool + let isCreateMediaCaptionsEnabled: Bool let isPinnedEventsTimeline: Bool let emojiProvider: EmojiProviderProtocol @@ -68,7 +69,7 @@ struct TimelineItemMenuActionProvider { if let messageItem = item as? EventBasedMessageTimelineItemProtocol, messageItem.supportsMediaCaption { if messageItem.hasMediaCaption { actions.append(contentsOf: [.editCaption, .removeCaption]) - } else { + } else if isCreateMediaCaptionsEnabled { actions.append(.addCaption) } } else if !(item is VoiceMessageRoomTimelineItem) { diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift index a99fdf1fa0..037f7f1829 100644 --- a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift @@ -143,6 +143,7 @@ struct TimelineItemBubbledStylerView: View { pinnedEventIDs: context.viewState.pinnedEventIDs, isDM: context.viewState.isEncryptedOneToOneRoom, isViewSourceEnabled: context.viewState.isViewSourceEnabled, + isCreateMediaCaptionsEnabled: context.viewState.isCreateMediaCaptionsEnabled, isPinnedEventsTimeline: context.viewState.isPinnedEventsTimeline, emojiProvider: context.viewState.emojiProvider) TimelineItemMacContextMenu(item: timelineItem, actionProvider: provider) { action in diff --git a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift index c74ec03185..9a47185aea 100644 --- a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift +++ b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift @@ -125,7 +125,8 @@ class MediaUploadPreviewScreenViewModelTests: XCTestCase { roomProxy: roomProxy, mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings), title: "Some File", - url: url) + url: url, + createMediaCaptionsEnabled: true) } private func verifyCaption(_ caption: String?, expectedCaption: String?) -> Result { From be8c1477c025d9141f5938f9f3b673f0e105011c Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 27 Nov 2024 09:57:18 +0200 Subject: [PATCH 58/74] Stop delaying ElementCall until the next sync loop and only notify other participants when presumed to already be up to date. (#3559) --- .../UserSessionFlowCoordinator.swift | 16 ++-- .../CallScreen/CallScreenViewModel.swift | 78 ++++++++----------- .../Screens/CallScreen/View/CallScreen.swift | 3 +- .../ElementCallConfiguration.swift | 11 ++- 4 files changed, 52 insertions(+), 56 deletions(-) diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index 0c7af9484a..a057d2a741 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -201,7 +201,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { case .userProfile(let userID): stateMachine.processEvent(.showUserProfileScreen(userID: userID), userInfo: .init(animated: animated)) case .call(let roomID): - Task { await presentCallScreen(roomID: roomID) } + Task { await presentCallScreen(roomID: roomID, notifyOtherParticipants: false) } case .genericCallLink(let url): presentCallScreen(genericCallLink: url) case .settings, .chatBackupSettings: @@ -579,7 +579,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { switch action { case .presentCallScreen(let roomProxy): - presentCallScreen(roomProxy: roomProxy) + // Here we assume that the app is running and the call state is already up to date + presentCallScreen(roomProxy: roomProxy, notifyOtherParticipants: !roomProxy.infoPublisher.value.hasRoomCall) case .finished: stateMachine.processEvent(.deselectRoom) } @@ -657,22 +658,23 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { presentCallScreen(configuration: .init(genericCallLink: url)) } - private func presentCallScreen(roomID: String) async { + private func presentCallScreen(roomID: String, notifyOtherParticipants: Bool) async { guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else { return } - presentCallScreen(roomProxy: roomProxy) + presentCallScreen(roomProxy: roomProxy, notifyOtherParticipants: notifyOtherParticipants) } - private func presentCallScreen(roomProxy: JoinedRoomProxyProtocol) { + private func presentCallScreen(roomProxy: JoinedRoomProxyProtocol, notifyOtherParticipants: Bool) { let colorScheme: ColorScheme = appMediator.windowManager.mainWindow.traitCollection.userInterfaceStyle == .light ? .light : .dark presentCallScreen(configuration: .init(roomProxy: roomProxy, clientProxy: userSession.clientProxy, clientID: InfoPlistReader.main.bundleIdentifier, elementCallBaseURL: appSettings.elementCallBaseURL, elementCallBaseURLOverride: appSettings.elementCallBaseURLOverride, - colorScheme: colorScheme)) + colorScheme: colorScheme, + notifyOtherParticipants: notifyOtherParticipants)) } private var callScreenPictureInPictureController: AVPictureInPictureController? @@ -899,7 +901,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { navigationSplitCoordinator.setSheetCoordinator(nil) stateMachine.processEvent(.selectRoom(roomID: roomID, via: [], entryPoint: .room)) case .startCall(let roomID): - Task { await self.presentCallScreen(roomID: roomID) } + Task { await self.presentCallScreen(roomID: roomID, notifyOtherParticipants: false) } case .dismiss: navigationSplitCoordinator.setSheetCoordinator(nil) } diff --git a/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift b/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift index 4c41b43586..c00623c447 100644 --- a/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift +++ b/ElementX/Sources/Screens/CallScreen/CallScreenViewModel.swift @@ -24,8 +24,6 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol actionsSubject.eraseToAnyPublisher() } - private var syncUpdateCancellable: AnyCancellable? - /// Designated initialiser /// - Parameters: /// - elementCallService: service responsible for setting up CallKit @@ -43,7 +41,7 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol switch configuration.kind { case .genericCallLink(let url): widgetDriver = GenericCallLinkWidgetDriver(url: url) - case .roomCall(let roomProxy, let clientProxy, _, _, _, _): + case .roomCall(let roomProxy, let clientProxy, _, _, _, _, _): guard let deviceID = clientProxy.deviceID else { fatalError("Missing device ID for the call.") } widgetDriver = roomProxy.elementCallWidgetDriver(deviceID: deviceID) } @@ -137,47 +135,39 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol case .genericCallLink(let url): state.url = url // We need widget messaging to work before enabling CallKit, otherwise mute, hangup etc do nothing. - - case .roomCall(let roomProxy, let clientProxy, let clientID, let elementCallBaseURL, let elementCallBaseURLOverride, let colorScheme): - // Wait for room states to be up to date before starting the call and notifying others - syncUpdateCancellable = clientProxy.actionsPublisher - .filter(\.isSyncUpdate) - .timeout(.seconds(5), scheduler: DispatchQueue.main) - .first() // Timeout will make the publisher complete, use first to handle both branches in the same place - .sink(receiveCompletion: { [weak self] _ in - Task { [weak self] in - guard let self else { return } - - let baseURL = if let elementCallBaseURLOverride { - elementCallBaseURLOverride - } else if case .success(let wellKnown) = await clientProxy.getElementWellKnown(), let wellKnownCall = wellKnown?.call { - wellKnownCall.widgetURL - } else { - elementCallBaseURL - } - - switch await widgetDriver.start(baseURL: baseURL, clientID: clientID, colorScheme: colorScheme) { - case .success(let url): - state.url = url - case .failure(let error): - MXLog.error("Failed starting ElementCall Widget Driver with error: \(error)") - state.bindings.alertInfo = .init(id: UUID(), - title: L10n.errorUnknown, - primaryButton: .init(title: L10n.actionOk) { - self.actionsSubject.send(.dismiss) - }) - - return - } - - await elementCallService.setupCallSession(roomID: roomProxy.id, - roomDisplayName: roomProxy.infoPublisher.value.displayName ?? roomProxy.id) - - _ = await roomProxy.sendCallNotificationIfNeeded() - - syncUpdateCancellable = nil - } - }, receiveValue: { _ in }) + + case .roomCall(let roomProxy, let clientProxy, let clientID, let elementCallBaseURL, let elementCallBaseURLOverride, let colorScheme, let notifyOtherParticipants): + Task { [weak self] in + guard let self else { return } + + let baseURL = if let elementCallBaseURLOverride { + elementCallBaseURLOverride + } else if case .success(let wellKnown) = await clientProxy.getElementWellKnown(), let wellKnownCall = wellKnown?.call { + wellKnownCall.widgetURL + } else { + elementCallBaseURL + } + + switch await widgetDriver.start(baseURL: baseURL, clientID: clientID, colorScheme: colorScheme) { + case .success(let url): + state.url = url + case .failure(let error): + MXLog.error("Failed starting ElementCall Widget Driver with error: \(error)") + state.bindings.alertInfo = .init(id: UUID(), + title: L10n.errorUnknown, + primaryButton: .init(title: L10n.actionOk) { + self.actionsSubject.send(.dismiss) + }) + return + } + + await elementCallService.setupCallSession(roomID: roomProxy.id, + roomDisplayName: roomProxy.infoPublisher.value.displayName ?? roomProxy.id) + + if notifyOtherParticipants { + _ = await roomProxy.sendCallNotificationIfNeeded() + } + } } } diff --git a/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift b/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift index 97e224ed93..2cd0d5559a 100644 --- a/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift +++ b/ElementX/Sources/Screens/CallScreen/View/CallScreen.swift @@ -303,7 +303,8 @@ struct CallScreen_Previews: PreviewProvider { clientID: "io.element.elementx", elementCallBaseURL: "https://call.element.io", elementCallBaseURLOverride: nil, - colorScheme: .light), + colorScheme: .light, + notifyOtherParticipants: false), allowPictureInPicture: false, appHooks: AppHooks()) }() diff --git a/ElementX/Sources/Services/ElementCall/ElementCallConfiguration.swift b/ElementX/Sources/Services/ElementCall/ElementCallConfiguration.swift index 31da3bb16f..29bbdf3cd3 100644 --- a/ElementX/Sources/Services/ElementCall/ElementCallConfiguration.swift +++ b/ElementX/Sources/Services/ElementCall/ElementCallConfiguration.swift @@ -21,7 +21,8 @@ struct ElementCallConfiguration { clientID: String, elementCallBaseURL: URL, elementCallBaseURLOverride: URL?, - colorScheme: ColorScheme) + colorScheme: ColorScheme, + notifyOtherParticipants: Bool) } /// The type of call being configured i.e. whether it's an external URL or an internal room call. @@ -58,13 +59,15 @@ struct ElementCallConfiguration { clientID: String, elementCallBaseURL: URL, elementCallBaseURLOverride: URL?, - colorScheme: ColorScheme) { + colorScheme: ColorScheme, + notifyOtherParticipants: Bool) { kind = .roomCall(roomProxy: roomProxy, clientProxy: clientProxy, clientID: clientID, elementCallBaseURL: elementCallBaseURL, elementCallBaseURLOverride: elementCallBaseURLOverride, - colorScheme: colorScheme) + colorScheme: colorScheme, + notifyOtherParticipants: notifyOtherParticipants) } /// A string representing the call being configured. @@ -72,7 +75,7 @@ struct ElementCallConfiguration { switch kind { case .genericCallLink(let url): url.absoluteString - case .roomCall(let roomProxy, _, _, _, _, _): + case .roomCall(let roomProxy, _, _, _, _, _, _): roomProxy.id } } From e70a95cfa29ecba2760f0d3a2f738e9e27f0d39a Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:35:53 +0000 Subject: [PATCH 59/74] Add back missing send button when media captions are disabled. (#3561) --- .../View/MediaUploadPreviewScreen.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift index 807df69935..2b4e722abd 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift @@ -76,6 +76,16 @@ struct MediaUploadPreviewScreen: View { // follow the dark colour scheme on devices running with dark mode disabled. .tint(.compound.textActionPrimary) } + + if !context.viewState.showMediaCaptionComposer { + ToolbarItem(placement: .confirmationAction) { + Button { context.send(viewAction: .send) } label: { + Text(L10n.actionSend) + } + // Same fix as above (this button is temporary anyway). + .tint(.compound.textActionPrimary) + } + } } } From 751be7b3a77d841b7723522f976d7c82dd2dc9a5 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Thu, 28 Nov 2024 08:34:38 +0000 Subject: [PATCH 60/74] Update the SDK. (#3565) * Update the SDK. * Add mockMXC URLs to fix all the crashes during tests. * Refactor Voice Messages to not use a MediaSource for local files. --- ElementX.xcodeproj/project.pbxproj | 6 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../Mocks/Generated/GeneratedMocks.swift | 361 ++---------------- .../Sources/Mocks/MediaProviderMock.swift | 3 +- .../Sources/Mocks/RoomMemberProxyMock.swift | 6 +- .../Mocks/RoomSummaryProviderMock.swift | 4 +- ElementX/Sources/Other/Extensions/URL.swift | 8 + .../SwiftUI/Views/AvatarHeaderView.swift | 2 +- .../Other/SwiftUI/Views/RoomAvatarImage.swift | 4 +- .../Other/SwiftUI/Views/RoomHeaderView.swift | 2 +- .../View/GlobalSearchScreenCell.swift | 2 +- .../View/HomeScreenInviteCell.swift | 2 +- .../View/HomeScreenKnockedCell.swift | 2 +- .../JoinRoomScreen/View/JoinRoomScreen.swift | 6 +- .../View/RoomDirectorySearchScreen.swift | 2 +- .../RoomMembersListScreenMemberCell.swift | 4 +- .../View/CompletionSuggestionView.swift | 2 +- .../View/ComposerToolbar.swift | 2 +- .../View/MentionSuggestionItemView.swift | 2 +- .../Timeline/TimelineInteractionHandler.swift | 9 +- .../View/ReadReceipts/ReadReceiptCell.swift | 2 +- .../Services/Audio/Player/AudioPlayer.swift | 16 +- .../Audio/Player/AudioPlayerProtocol.swift | 26 +- .../Audio/Player/AudioPlayerState.swift | 2 +- .../Services/Client/ClientProxyProtocol.swift | 2 +- .../Media/Provider/MediaSourceProxy.swift | 5 +- .../MediaPlayer/MediaPlayerProtocol.swift | 34 -- .../MediaPlayer/MediaPlayerProvider.swift | 16 +- .../MediaPlayerProviderProtocol.swift | 2 +- .../Services/Timeline/TimelineItemProxy.swift | 6 +- .../VoiceMessage/VoiceMessageRecorder.swift | 10 +- .../UITests/UITestsAppCoordinator.swift | 24 +- ...test_completionSuggestion-iPad-en-GB.1.png | 4 +- ...est_completionSuggestion-iPad-pseudo.1.png | 4 +- ...completionSuggestion-iPhone-16-en-GB.1.png | 4 +- ...ompletionSuggestion-iPhone-16-pseudo.1.png | 4 +- ...serToolbar-iPad-en-GB.With-Suggestions.png | 4 +- ...erToolbar-iPad-pseudo.With-Suggestions.png | 4 +- ...olbar-iPhone-16-en-GB.With-Suggestions.png | 4 +- ...lbar-iPhone-16-pseudo.With-Suggestions.png | 4 +- .../test_joinRoomScreen-iPad-en-GB.Invite.png | 4 +- .../test_joinRoomScreen-iPad-en-GB.Join.png | 4 +- .../test_joinRoomScreen-iPad-en-GB.Knock.png | 4 +- ...test_joinRoomScreen-iPad-en-GB.Knocked.png | 4 +- ...test_joinRoomScreen-iPad-pseudo.Invite.png | 4 +- .../test_joinRoomScreen-iPad-pseudo.Join.png | 4 +- .../test_joinRoomScreen-iPad-pseudo.Knock.png | 4 +- ...est_joinRoomScreen-iPad-pseudo.Knocked.png | 4 +- ..._joinRoomScreen-iPhone-16-en-GB.Invite.png | 4 +- ...st_joinRoomScreen-iPhone-16-en-GB.Join.png | 4 +- ...t_joinRoomScreen-iPhone-16-en-GB.Knock.png | 4 +- ...joinRoomScreen-iPhone-16-en-GB.Knocked.png | 4 +- ...joinRoomScreen-iPhone-16-pseudo.Invite.png | 4 +- ...t_joinRoomScreen-iPhone-16-pseudo.Join.png | 4 +- ..._joinRoomScreen-iPhone-16-pseudo.Knock.png | 4 +- ...oinRoomScreen-iPhone-16-pseudo.Knocked.png | 4 +- ...mentionSuggestionItemView-iPad-en-GB.1.png | 4 +- ...entionSuggestionItemView-iPad-pseudo.1.png | 4 +- ...onSuggestionItemView-iPhone-16-en-GB.1.png | 4 +- ...nSuggestionItemView-iPhone-16-pseudo.1.png | 4 +- ..._readReceiptCell-iPad-en-GB.With-Image.png | 4 +- ...readReceiptCell-iPad-pseudo.With-Image.png | 4 +- ...ReceiptCell-iPhone-16-en-GB.With-Image.png | 4 +- ...eceiptCell-iPhone-16-pseudo.With-Image.png | 4 +- .../ComposerToolbarViewModelTests.swift | 2 +- .../Sources/MediaPlayerProviderTests.swift | 41 +- .../MediaProvider/MediaLoaderTests.swift | 4 +- .../MediaProvider/MediaProviderTests.swift | 24 +- .../RoomDetailsEditScreenViewModelTests.swift | 4 +- .../Sources/RoomScreenViewModelTests.swift | 4 +- .../UserProfileScreenViewModelTests.swift | 4 +- .../Sources/VoiceMessageCacheTests.swift | 2 +- .../VoiceMessageMediaManagerTests.swift | 2 +- .../Sources/VoiceMessageRecorderTests.swift | 17 +- project.yml | 2 +- 75 files changed, 222 insertions(+), 590 deletions(-) delete mode 100644 ElementX/Sources/Services/MediaPlayer/MediaPlayerProtocol.swift diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index eddd1befb0..555db7e68a 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -983,7 +983,6 @@ D02AA6208C7ACB9BE6332394 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; }; D02DEB36D32A72A1B365E452 /* SessionVerificationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 796CBD0C56FA0D3AEDAB255B /* SessionVerificationScreenCoordinator.swift */; }; D050D7756E92CA061ED0ABF0 /* SecureBackupLogoutConfirmationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74E08B8A66948E9690F38B94 /* SecureBackupLogoutConfirmationScreenViewModelProtocol.swift */; }; - D0550B8E0AE2C0CDBE52C88F /* MediaPlayerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE87C931165F5E201CACBB87 /* MediaPlayerProtocol.swift */; }; D0A965852D6C04138FA55181 /* SecureBackupLogoutConfirmationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF239C619971FDE48132550 /* SecureBackupLogoutConfirmationScreenModels.swift */; }; D10BA4F041DC58580A440A32 /* RoomRolesAndPermissionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B1DC3B3FB40A7F4AE9B7BF /* RoomRolesAndPermissionsScreen.swift */; }; D12F440F7973F1489F61389D /* NotificationSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */; }; @@ -2414,7 +2413,6 @@ FDEDD4D2DE0646DA724985D5 /* QRCodeLoginScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginScreenModels.swift; sourceTree = ""; }; FDF73F49E6B6683F7E2D26F0 /* SecureBackupScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenCoordinator.swift; sourceTree = ""; }; FE1E6FAA3719E9B7A2D5510B /* FormattingToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattingToolbar.swift; sourceTree = ""; }; - FE87C931165F5E201CACBB87 /* MediaPlayerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProtocol.swift; sourceTree = ""; }; FF720BA68256297680980481 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; }; FFECCE59967018204876D0A5 /* LocationMarkerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationMarkerView.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -3785,7 +3783,6 @@ 6709362D60732DED2069AE0F /* MediaPlayer */ = { isa = PBXGroup; children = ( - FE87C931165F5E201CACBB87 /* MediaPlayerProtocol.swift */, E8A1F98AE670377B20679FF5 /* MediaPlayerProvider.swift */, F5E23D8EE6CBACF32F1EC874 /* MediaPlayerProviderProtocol.swift */, ); @@ -6894,7 +6891,6 @@ 208C19811613F9A10F8A7B75 /* MediaLoader.swift in Sources */, A2434D4DFB49A68E5CD0F53C /* MediaLoaderProtocol.swift in Sources */, 4E0D9E09B52CEC4C0E6211A8 /* MediaPickerScreenCoordinator.swift in Sources */, - D0550B8E0AE2C0CDBE52C88F /* MediaPlayerProtocol.swift in Sources */, F66BCCC825D6CA51724A94D0 /* MediaPlayerProvider.swift in Sources */, 762DAF94846C7AC8550F1CC1 /* MediaPlayerProviderProtocol.swift in Sources */, B6EC2148FA5443C9289BEEBA /* MediaProvider.swift in Sources */, @@ -8195,7 +8191,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.75; + version = 1.0.76; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index dca464ac2e..00f2e1f4d9 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "6b14c048543bac9effe5e44fa90333bfa7dd9435", - "version" : "1.0.75" + "revision" : "dfb54791b10d17c5e2604c716c8e939bed221435", + "version" : "1.0.76" } }, { diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 45e2fd5d50..b980c6dd65 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -1200,12 +1200,7 @@ class AudioConverterMock: AudioConverterProtocol { } } class AudioPlayerMock: AudioPlayerProtocol { - var actions: AnyPublisher { - get { return underlyingActions } - set(value) { underlyingActions = value } - } - var underlyingActions: AnyPublisher! - var mediaSource: MediaSourceProxy? + var sourceURL: URL? var duration: TimeInterval { get { return underlyingDuration } set(value) { underlyingDuration = value } @@ -1216,24 +1211,29 @@ class AudioPlayerMock: AudioPlayerProtocol { set(value) { underlyingCurrentTime = value } } var underlyingCurrentTime: TimeInterval! - var url: URL? + var playbackURL: URL? var state: MediaPlayerState { get { return underlyingState } set(value) { underlyingState = value } } var underlyingState: MediaPlayerState! + var actions: AnyPublisher { + get { return underlyingActions } + set(value) { underlyingActions = value } + } + var underlyingActions: AnyPublisher! //MARK: - load - var loadMediaSourceUsingAutoplayUnderlyingCallsCount = 0 - var loadMediaSourceUsingAutoplayCallsCount: Int { + var loadSourceURLPlaybackURLAutoplayUnderlyingCallsCount = 0 + var loadSourceURLPlaybackURLAutoplayCallsCount: Int { get { if Thread.isMainThread { - return loadMediaSourceUsingAutoplayUnderlyingCallsCount + return loadSourceURLPlaybackURLAutoplayUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = loadMediaSourceUsingAutoplayUnderlyingCallsCount + returnValue = loadSourceURLPlaybackURLAutoplayUnderlyingCallsCount } return returnValue! @@ -1241,28 +1241,28 @@ class AudioPlayerMock: AudioPlayerProtocol { } set { if Thread.isMainThread { - loadMediaSourceUsingAutoplayUnderlyingCallsCount = newValue + loadSourceURLPlaybackURLAutoplayUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - loadMediaSourceUsingAutoplayUnderlyingCallsCount = newValue + loadSourceURLPlaybackURLAutoplayUnderlyingCallsCount = newValue } } } } - var loadMediaSourceUsingAutoplayCalled: Bool { - return loadMediaSourceUsingAutoplayCallsCount > 0 + var loadSourceURLPlaybackURLAutoplayCalled: Bool { + return loadSourceURLPlaybackURLAutoplayCallsCount > 0 } - var loadMediaSourceUsingAutoplayReceivedArguments: (mediaSource: MediaSourceProxy, url: URL, autoplay: Bool)? - var loadMediaSourceUsingAutoplayReceivedInvocations: [(mediaSource: MediaSourceProxy, url: URL, autoplay: Bool)] = [] - var loadMediaSourceUsingAutoplayClosure: ((MediaSourceProxy, URL, Bool) -> Void)? + var loadSourceURLPlaybackURLAutoplayReceivedArguments: (sourceURL: URL, playbackURL: URL, autoplay: Bool)? + var loadSourceURLPlaybackURLAutoplayReceivedInvocations: [(sourceURL: URL, playbackURL: URL, autoplay: Bool)] = [] + var loadSourceURLPlaybackURLAutoplayClosure: ((URL, URL, Bool) -> Void)? - func load(mediaSource: MediaSourceProxy, using url: URL, autoplay: Bool) { - loadMediaSourceUsingAutoplayCallsCount += 1 - loadMediaSourceUsingAutoplayReceivedArguments = (mediaSource: mediaSource, url: url, autoplay: autoplay) + func load(sourceURL: URL, playbackURL: URL, autoplay: Bool) { + loadSourceURLPlaybackURLAutoplayCallsCount += 1 + loadSourceURLPlaybackURLAutoplayReceivedArguments = (sourceURL: sourceURL, playbackURL: playbackURL, autoplay: autoplay) DispatchQueue.main.async { - self.loadMediaSourceUsingAutoplayReceivedInvocations.append((mediaSource: mediaSource, url: url, autoplay: autoplay)) + self.loadSourceURLPlaybackURLAutoplayReceivedInvocations.append((sourceURL: sourceURL, playbackURL: playbackURL, autoplay: autoplay)) } - loadMediaSourceUsingAutoplayClosure?(mediaSource, url, autoplay) + loadSourceURLPlaybackURLAutoplayClosure?(sourceURL, playbackURL, autoplay) } //MARK: - reset @@ -9812,320 +9812,13 @@ class MediaLoaderMock: MediaLoaderProtocol { } } } -class MediaPlayerMock: MediaPlayerProtocol { - var mediaSource: MediaSourceProxy? - var duration: TimeInterval { - get { return underlyingDuration } - set(value) { underlyingDuration = value } - } - var underlyingDuration: TimeInterval! - var currentTime: TimeInterval { - get { return underlyingCurrentTime } - set(value) { underlyingCurrentTime = value } - } - var underlyingCurrentTime: TimeInterval! - var url: URL? - var state: MediaPlayerState { - get { return underlyingState } - set(value) { underlyingState = value } - } - var underlyingState: MediaPlayerState! - - //MARK: - load - - var loadMediaSourceUsingAutoplayUnderlyingCallsCount = 0 - var loadMediaSourceUsingAutoplayCallsCount: Int { - get { - if Thread.isMainThread { - return loadMediaSourceUsingAutoplayUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = loadMediaSourceUsingAutoplayUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - loadMediaSourceUsingAutoplayUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - loadMediaSourceUsingAutoplayUnderlyingCallsCount = newValue - } - } - } - } - var loadMediaSourceUsingAutoplayCalled: Bool { - return loadMediaSourceUsingAutoplayCallsCount > 0 - } - var loadMediaSourceUsingAutoplayReceivedArguments: (mediaSource: MediaSourceProxy, url: URL, autoplay: Bool)? - var loadMediaSourceUsingAutoplayReceivedInvocations: [(mediaSource: MediaSourceProxy, url: URL, autoplay: Bool)] = [] - var loadMediaSourceUsingAutoplayClosure: ((MediaSourceProxy, URL, Bool) -> Void)? - - func load(mediaSource: MediaSourceProxy, using url: URL, autoplay: Bool) { - loadMediaSourceUsingAutoplayCallsCount += 1 - loadMediaSourceUsingAutoplayReceivedArguments = (mediaSource: mediaSource, url: url, autoplay: autoplay) - DispatchQueue.main.async { - self.loadMediaSourceUsingAutoplayReceivedInvocations.append((mediaSource: mediaSource, url: url, autoplay: autoplay)) - } - loadMediaSourceUsingAutoplayClosure?(mediaSource, url, autoplay) - } - //MARK: - reset - - var resetUnderlyingCallsCount = 0 - var resetCallsCount: Int { - get { - if Thread.isMainThread { - return resetUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = resetUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - resetUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - resetUnderlyingCallsCount = newValue - } - } - } - } - var resetCalled: Bool { - return resetCallsCount > 0 - } - var resetClosure: (() -> Void)? - - func reset() { - resetCallsCount += 1 - resetClosure?() - } - //MARK: - play - - var playUnderlyingCallsCount = 0 - var playCallsCount: Int { - get { - if Thread.isMainThread { - return playUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = playUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - playUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - playUnderlyingCallsCount = newValue - } - } - } - } - var playCalled: Bool { - return playCallsCount > 0 - } - var playClosure: (() -> Void)? - - func play() { - playCallsCount += 1 - playClosure?() - } - //MARK: - pause - - var pauseUnderlyingCallsCount = 0 - var pauseCallsCount: Int { - get { - if Thread.isMainThread { - return pauseUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = pauseUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - pauseUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - pauseUnderlyingCallsCount = newValue - } - } - } - } - var pauseCalled: Bool { - return pauseCallsCount > 0 - } - var pauseClosure: (() -> Void)? - - func pause() { - pauseCallsCount += 1 - pauseClosure?() - } - //MARK: - stop - - var stopUnderlyingCallsCount = 0 - var stopCallsCount: Int { - get { - if Thread.isMainThread { - return stopUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = stopUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - stopUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - stopUnderlyingCallsCount = newValue - } - } - } - } - var stopCalled: Bool { - return stopCallsCount > 0 - } - var stopClosure: (() -> Void)? - - func stop() { - stopCallsCount += 1 - stopClosure?() - } - //MARK: - seek - - var seekToUnderlyingCallsCount = 0 - var seekToCallsCount: Int { - get { - if Thread.isMainThread { - return seekToUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = seekToUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - seekToUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - seekToUnderlyingCallsCount = newValue - } - } - } - } - var seekToCalled: Bool { - return seekToCallsCount > 0 - } - var seekToReceivedProgress: Double? - var seekToReceivedInvocations: [Double] = [] - var seekToClosure: ((Double) async -> Void)? - - func seek(to progress: Double) async { - seekToCallsCount += 1 - seekToReceivedProgress = progress - DispatchQueue.main.async { - self.seekToReceivedInvocations.append(progress) - } - await seekToClosure?(progress) - } -} class MediaPlayerProviderMock: MediaPlayerProviderProtocol { - - //MARK: - player - - var playerForUnderlyingCallsCount = 0 - var playerForCallsCount: Int { - get { - if Thread.isMainThread { - return playerForUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = playerForUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - playerForUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - playerForUnderlyingCallsCount = newValue - } - } - } - } - var playerForCalled: Bool { - return playerForCallsCount > 0 - } - var playerForReceivedMediaSource: MediaSourceProxy? - var playerForReceivedInvocations: [MediaSourceProxy] = [] - - var playerForUnderlyingReturnValue: Result! - var playerForReturnValue: Result! { - get { - if Thread.isMainThread { - return playerForUnderlyingReturnValue - } else { - var returnValue: Result? = nil - DispatchQueue.main.sync { - returnValue = playerForUnderlyingReturnValue - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - playerForUnderlyingReturnValue = newValue - } else { - DispatchQueue.main.sync { - playerForUnderlyingReturnValue = newValue - } - } - } + var player: AudioPlayerProtocol { + get { return underlyingPlayer } + set(value) { underlyingPlayer = value } } - var playerForClosure: ((MediaSourceProxy) -> Result)? + var underlyingPlayer: AudioPlayerProtocol! - func player(for mediaSource: MediaSourceProxy) -> Result { - playerForCallsCount += 1 - playerForReceivedMediaSource = mediaSource - DispatchQueue.main.async { - self.playerForReceivedInvocations.append(mediaSource) - } - if let playerForClosure = playerForClosure { - return playerForClosure(mediaSource) - } else { - return playerForReturnValue - } - } //MARK: - playerState var playerStateForUnderlyingCallsCount = 0 diff --git a/ElementX/Sources/Mocks/MediaProviderMock.swift b/ElementX/Sources/Mocks/MediaProviderMock.swift index eb1929eff4..c2ae134960 100644 --- a/ElementX/Sources/Mocks/MediaProviderMock.swift +++ b/ElementX/Sources/Mocks/MediaProviderMock.swift @@ -18,7 +18,8 @@ extension MediaProviderMock { return nil } - if mediaSource?.url == .picturesDirectory { + // 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 } diff --git a/ElementX/Sources/Mocks/RoomMemberProxyMock.swift b/ElementX/Sources/Mocks/RoomMemberProxyMock.swift index 2074c014b1..8c81c727e1 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: URL.picturesDirectory, + avatarURL: .mockMXCAvatar, membership: .join)) } static var mockMeAdmin: RoomMemberProxyMock { RoomMemberProxyMock(with: .init(userID: "@me:matrix.org", displayName: "Me", - avatarURL: URL.picturesDirectory, + avatarURL: .mockMXCAvatar, 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: URL.picturesDirectory, + avatarURL: .mockMXCAvatar, membership: .join)) } diff --git a/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift b/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift index ed88e9efe2..7c71582868 100644 --- a/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift +++ b/ElementX/Sources/Mocks/RoomSummaryProviderMock.swift @@ -91,7 +91,7 @@ extension Array where Element == RoomSummary { joinRequestType: nil, name: "Foundation and Empire", isDirect: false, - avatarURL: URL.picturesDirectory, + avatarURL: .mockMXCAvatar, heroes: [], lastMessage: AttributedString("How do you see the Emperor then? You think he keeps office hours?"), lastMessageFormattedTimestamp: "2:56 PM", @@ -226,7 +226,7 @@ extension Array where Element == RoomSummary { joinRequestType: .invite(inviter: RoomMemberProxyMock.mockCharlie), name: "First room", isDirect: false, - avatarURL: URL.picturesDirectory, + avatarURL: .mockMXCAvatar, heroes: [], lastMessage: nil, lastMessageFormattedTimestamp: nil, diff --git a/ElementX/Sources/Other/Extensions/URL.swift b/ElementX/Sources/Other/Extensions/URL.swift index fc26b266b5..0c026ef129 100644 --- a/ElementX/Sources/Other/Extensions/URL.swift +++ b/ElementX/Sources/Other/Extensions/URL.swift @@ -100,4 +100,12 @@ extension URL: @retroactive ExpressibleByStringLiteral { } return nil } + + // MARK: Mocks + + static var mockMXCAudio: URL { "mxc://matrix.org/1234567890FiLe" } + 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" } } diff --git a/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift b/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift index f78421bf94..1f8afbe19f 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift @@ -190,7 +190,7 @@ struct AvatarHeaderView_Previews: PreviewProvider, TestablePreview { name: "Test Room", avatar: .room(id: "@test:matrix.org", name: "Test Room", - avatarURL: .picturesDirectory), + avatarURL: .mockMXCAvatar), canonicalAlias: "#test:matrix.org", isEncrypted: true, isPublic: true), diff --git a/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift b/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift index f4b3d2bee1..6601cc5cac 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift @@ -97,7 +97,7 @@ struct RoomAvatarImage_Previews: PreviewProvider, TestablePreview { RoomAvatarImage(avatar: .room(id: "!2:server.com", name: "Room", - avatarURL: .picturesDirectory), + avatarURL: .mockMXCAvatar), avatarSize: .room(on: .home), mediaProvider: MediaProviderMock(configuration: .init())) @@ -109,7 +109,7 @@ struct RoomAvatarImage_Previews: PreviewProvider, TestablePreview { RoomAvatarImage(avatar: .heroes([.init(userID: "@user:server.com", displayName: "User", - avatarURL: .picturesDirectory)]), + avatarURL: .mockMXCAvatar)]), avatarSize: .room(on: .home), mediaProvider: MediaProviderMock(configuration: .init())) diff --git a/ElementX/Sources/Other/SwiftUI/Views/RoomHeaderView.swift b/ElementX/Sources/Other/SwiftUI/Views/RoomHeaderView.swift index c7291c4412..ff25c03dad 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/RoomHeaderView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/RoomHeaderView.swift @@ -41,7 +41,7 @@ struct RoomHeaderView_Previews: PreviewProvider, TestablePreview { RoomHeaderView(roomName: "Some Room name", roomAvatar: .room(id: "1", name: "Some Room Name", - avatarURL: URL.picturesDirectory), + avatarURL: .mockMXCAvatar), mediaProvider: MediaProviderMock(configuration: .init())) .previewLayout(.sizeThatFits) .padding() diff --git a/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift b/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift index 354e1cef80..e16b0485dd 100644 --- a/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift +++ b/ElementX/Sources/Screens/GlobalSearchScreen/View/GlobalSearchScreenCell.swift @@ -46,7 +46,7 @@ struct GlobalSearchScreenListRow_Previews: PreviewProvider, TestablePreview { description: "The best place in the whole wide world", avatar: .room(id: "123", name: "Tech central", - avatarURL: .picturesDirectory)), + avatarURL: .mockMXCAvatar)), context: viewModel.context) } } diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift index 4eb7606ff9..2f9f9f4ef0 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInviteCell.swift @@ -145,7 +145,7 @@ struct HomeScreenInviteCell_Previews: PreviewProvider, TestablePreview { HomeScreenInviteCell(room: .roomInvite(), context: viewModel().context) - HomeScreenInviteCell(room: .roomInvite(alias: "#footest:somewhere.org", avatarURL: .picturesDirectory), + HomeScreenInviteCell(room: .roomInvite(alias: "#footest:somewhere.org", avatarURL: .mockMXCAvatar), context: viewModel().context) HomeScreenInviteCell(room: .roomInvite(alias: "#footest:somewhere.org"), diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift index 0f0f64717e..2a79f62e18 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenKnockedCell.swift @@ -119,7 +119,7 @@ struct HomeScreenKnockedCell_Previews: PreviewProvider, TestablePreview { HomeScreenKnockedCell(room: .roomKnocked(), context: viewModel().context) - HomeScreenKnockedCell(room: .roomKnocked(alias: "#footest:somewhere.org", avatarURL: .picturesDirectory), + HomeScreenKnockedCell(room: .roomKnocked(alias: "#footest:somewhere.org", avatarURL: .mockMXCAvatar), context: viewModel().context) HomeScreenKnockedCell(room: .roomKnocked(alias: "#footest:somewhere.org"), diff --git a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift index f47e63c632..2c3bff5240 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift @@ -237,11 +237,11 @@ struct JoinRoomScreen_Previews: PreviewProvider, TestablePreview { switch mode { case .knocked: clientProxy.roomForIdentifierClosure = { _ in - .knocked(KnockedRoomProxyMock(.init(avatarURL: URL.homeDirectory))) + .knocked(KnockedRoomProxyMock(.init(avatarURL: .mockMXCAvatar))) } case .invited: clientProxy.roomForIdentifierClosure = { _ in - .invited(InvitedRoomProxyMock(.init(avatarURL: URL.homeDirectory))) + .invited(InvitedRoomProxyMock(.init(avatarURL: .mockMXCAvatar))) } default: break @@ -251,7 +251,7 @@ struct JoinRoomScreen_Previews: PreviewProvider, TestablePreview { canonicalAlias: "#3🌞problem:matrix.org", // swiftlint:disable:next line_length 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: URL.homeDirectory, + avatarURL: .mockMXCAvatar, memberCount: UInt(100), isHistoryWorldReadable: false, isJoined: membership.isJoined, diff --git a/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectorySearchScreen.swift b/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectorySearchScreen.swift index 95a67e0305..81f9605e29 100644 --- a/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectorySearchScreen.swift +++ b/ElementX/Sources/Screens/RoomDirectorySearchScreen/View/RoomDirectorySearchScreen.swift @@ -84,7 +84,7 @@ struct RoomDirectorySearchScreen_Previews: PreviewProvider, TestablePreview { topic: nil, avatar: .room(id: "test_2", name: "Test 2", - avatarURL: .documentsDirectory), + avatarURL: .mockMXCAvatar), canBeJoined: false)] let roomDirectorySearchProxy = RoomDirectorySearchProxyMock(configuration: .init(results: results)) diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift index efd25c1706..7eb4efa2a5 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift @@ -88,13 +88,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: .picturesDirectory, membership: .join)) + .init(with: .init(userID: "@avatar:matrix.org", displayName: "Avatar", avatarURL: .mockMXCAvatar, 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: .picturesDirectory, membership: .ban)) + .init(with: .init(userID: "@badavatar:matrix.org", avatarURL: .mockMXCAvatar, membership: .ban)) ] static let viewModel = RoomMembersListScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Some room", diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/CompletionSuggestionView.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/CompletionSuggestionView.swift index 29b5ff4cc9..2599f522d1 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: URL.documentsDirectory, range: .init()))]) { _ in } + .user(item: MentionSuggestionItem(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: .mockMXCAvatar, 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 aa6c14db2f..dc87b4c31d 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: URL.documentsDirectory, range: .init()))] + .user(item: MentionSuggestionItem(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: .mockMXCAvatar, 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 eea817a9e6..d8643ac603 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MentionSuggestionItemView.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MentionSuggestionItemView.swift @@ -38,7 +38,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: URL.documentsDirectory, range: .init())) + MentionSuggestionItemView(mediaProvider: mockMediaProvider, item: .init(id: "test", displayName: "Test", avatarURL: .mockMXCAvatar, range: .init())) MentionSuggestionItemView(mediaProvider: mockMediaProvider, item: .init(id: "test2", displayName: nil, avatarURL: nil, range: .init())) } } diff --git a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift index 18e6ef0ee8..c7d004df1e 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift @@ -408,10 +408,7 @@ class TimelineInteractionHandler { return } - guard case .success(let mediaPlayer) = mediaPlayerProvider.player(for: source), let audioPlayer = mediaPlayer as? AudioPlayerProtocol else { - MXLog.error("Cannot play a voice message without an audio player") - return - } + let audioPlayer = mediaPlayerProvider.player // Stop any recording in progress if voiceMessageRecorder.isRecording { @@ -430,7 +427,7 @@ class TimelineInteractionHandler { // Detach all other states await mediaPlayerProvider.detachAllStates(except: audioPlayerState) - guard audioPlayer.mediaSource == source, audioPlayer.state != .error else { + guard audioPlayer.sourceURL == source.url, audioPlayer.state != .error else { // Load content do { MXLog.info("Loading voice message audio content from source for itemID \(itemID)") @@ -438,7 +435,7 @@ class TimelineInteractionHandler { // Make sure that the player is still attached, as it may have been detached while waiting for the voice message to be loaded. if audioPlayerState.isAttached { - audioPlayer.load(mediaSource: source, using: url, autoplay: true) + audioPlayer.load(sourceURL: source.url, playbackURL: url, autoplay: true) } } catch { MXLog.error("Failed to load voice message: \(error)") diff --git a/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptCell.swift b/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptCell.swift index e1328e605f..53ae91850f 100644 --- a/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptCell.swift +++ b/ElementX/Sources/Screens/Timeline/View/ReadReceipts/ReadReceiptCell.swift @@ -66,7 +66,7 @@ struct ReadReceiptCell_Previews: PreviewProvider, TestablePreview { ReadReceiptCell(readReceipt: .init(userID: "@test:matrix.org", formattedTimestamp: "10:00"), memberState: .init(displayName: "Test", - avatarURL: URL.documentsDirectory), + avatarURL: .mockMXCAvatar), mediaProvider: MediaProviderMock(configuration: .init())) .previewDisplayName("With Image") ReadReceiptCell(readReceipt: .init(userID: "@test:matrix.org", diff --git a/ElementX/Sources/Services/Audio/Player/AudioPlayer.swift b/ElementX/Sources/Services/Audio/Player/AudioPlayer.swift index 79a1a3a5a9..d7cd59c57d 100644 --- a/ElementX/Sources/Services/Audio/Player/AudioPlayer.swift +++ b/ElementX/Sources/Services/Audio/Player/AudioPlayer.swift @@ -22,7 +22,7 @@ private enum InternalAudioPlayerState { } class AudioPlayer: NSObject, AudioPlayerProtocol { - var mediaSource: MediaSourceProxy? + var sourceURL: URL? private var playerItem: AVPlayerItem? private var internalAudioPlayer: AVQueuePlayer? @@ -46,7 +46,7 @@ class AudioPlayer: NSObject, AudioPlayerProtocol { private let releaseAudioSessionTimeoutInterval = 5.0 - private(set) var url: URL? + private(set) var playbackURL: URL? private var deinitInProgress = false @@ -86,13 +86,13 @@ class AudioPlayer: NSObject, AudioPlayerProtocol { unloadContent() } - func load(mediaSource: MediaSourceProxy, using url: URL, autoplay: Bool) { + func load(sourceURL: URL, playbackURL: URL, autoplay: Bool) { unloadContent() setInternalState(.loading) - self.mediaSource = mediaSource - self.url = url + self.sourceURL = sourceURL + self.playbackURL = playbackURL self.autoplay = autoplay - playerItem = AVPlayerItem(url: url) + playerItem = AVPlayerItem(url: playbackURL) internalAudioPlayer = AVQueuePlayer(playerItem: playerItem) addObservers() } @@ -162,8 +162,8 @@ class AudioPlayer: NSObject, AudioPlayerProtocol { } private func unloadContent() { - mediaSource = nil - url = nil + sourceURL = nil + playbackURL = nil internalAudioPlayer?.replaceCurrentItem(with: nil) internalAudioPlayer = nil playerItem = nil diff --git a/ElementX/Sources/Services/Audio/Player/AudioPlayerProtocol.swift b/ElementX/Sources/Services/Audio/Player/AudioPlayerProtocol.swift index 7addac3f3a..257713cc76 100644 --- a/ElementX/Sources/Services/Audio/Player/AudioPlayerProtocol.swift +++ b/ElementX/Sources/Services/Audio/Player/AudioPlayerProtocol.swift @@ -12,6 +12,17 @@ enum AudioPlayerError: Error { case genericError } +// There used to be a MediaPlayerProtocol that AudioPlayerProtocol inherited from. +// This should be called something else but we already have an AudioPlayerState, +// AudioPlayerPlaybackState and InternalAudioPlayerState so who knows what to call this. +enum MediaPlayerState { + case loading + case playing + case paused + case stopped + case error +} + enum AudioPlayerAction { case didStartLoading case didFinishLoading @@ -22,8 +33,21 @@ enum AudioPlayerAction { case didFailWithError(error: Error) } -protocol AudioPlayerProtocol: MediaPlayerProtocol { +protocol AudioPlayerProtocol: AnyObject { + var sourceURL: URL? { get } + var duration: TimeInterval { get } + var currentTime: TimeInterval { get } + var playbackURL: URL? { get } + var state: MediaPlayerState { get } + var actions: AnyPublisher { get } + + func load(sourceURL: URL, playbackURL: URL, autoplay: Bool) + func reset() + func play() + func pause() + func stop() + func seek(to progress: Double) async } // sourcery: AutoMockable diff --git a/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift b/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift index b0ab2abc31..2b468e28de 100644 --- a/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift +++ b/ElementX/Sources/Services/Audio/Player/AudioPlayerState.swift @@ -134,7 +134,7 @@ class AudioPlayerState: ObservableObject, Identifiable { MXLog.info("updating duration: \(duration) -> \(audioPlayerDuration)") duration = audioPlayerDuration } - fileURL = audioPlayer?.url + fileURL = audioPlayer?.playbackURL playbackState = .readyToPlay case .didStartPlaying: if let audioPlayer { diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index 0feae1793e..d13b363093 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -68,7 +68,7 @@ struct RoomPreviewDetails { let topic: String? let avatarURL: URL? let memberCount: UInt - let isHistoryWorldReadable: Bool + let isHistoryWorldReadable: Bool? let isJoined: Bool let isInvited: Bool let isPublic: Bool diff --git a/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift b/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift index abfb3b2fee..50023b5626 100644 --- a/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift +++ b/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift @@ -24,7 +24,10 @@ struct MediaSourceProxy: Hashable { } init(url: URL, mimeType: String?) { - underlyingSource = mediaSourceFromUrl(url: url.absoluteString) + guard let mediaSource = try? MediaSource.fromUrl(url: url.absoluteString) else { + fatalError("Unable to create MediaSource from URL: \(url.absoluteString)") + } + underlyingSource = mediaSource self.url = URL(string: underlyingSource.url()) self.mimeType = mimeType } diff --git a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProtocol.swift b/ElementX/Sources/Services/MediaPlayer/MediaPlayerProtocol.swift deleted file mode 100644 index e955061139..0000000000 --- a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProtocol.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright 2023, 2024 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only -// Please see LICENSE in the repository root for full details. -// - -import Foundation - -enum MediaPlayerState { - case loading - case playing - case paused - case stopped - case error -} - -protocol MediaPlayerProtocol: AnyObject { - var mediaSource: MediaSourceProxy? { get } - var duration: TimeInterval { get } - var currentTime: TimeInterval { get } - var url: URL? { get } - var state: MediaPlayerState { get } - - func load(mediaSource: MediaSourceProxy, using url: URL, autoplay: Bool) - func reset() - func play() - func pause() - func stop() - func seek(to progress: Double) async -} - -// sourcery: AutoMockable -extension MediaPlayerProtocol { } diff --git a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProvider.swift b/ElementX/Sources/Services/MediaPlayer/MediaPlayerProvider.swift index 894269cc56..e6399259e2 100644 --- a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProvider.swift +++ b/ElementX/Sources/Services/MediaPlayer/MediaPlayerProvider.swift @@ -11,24 +11,12 @@ class MediaPlayerProvider: MediaPlayerProviderProtocol { private lazy var audioPlayer = AudioPlayer() private var audioPlayerStates: [String: AudioPlayerState] = [:] + var player: AudioPlayerProtocol { audioPlayer } + deinit { audioPlayerStates = [:] } - func player(for mediaSource: MediaSourceProxy) -> Result { - guard let mimeType = mediaSource.mimeType else { - MXLog.error("Unknown mime type") - return .failure(.unsupportedMediaType) - } - - if mimeType.starts(with: "audio/") { - return .success(audioPlayer) - } else { - MXLog.error("Unsupported media type: \(mediaSource.mimeType ?? "unknown")") - return .failure(.unsupportedMediaType) - } - } - // MARK: - AudioPlayer func playerState(for id: AudioPlayerStateIdentifier) -> AudioPlayerState? { diff --git a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProviderProtocol.swift b/ElementX/Sources/Services/MediaPlayer/MediaPlayerProviderProtocol.swift index c1cb2b74ee..479e3796af 100644 --- a/ElementX/Sources/Services/MediaPlayer/MediaPlayerProviderProtocol.swift +++ b/ElementX/Sources/Services/MediaPlayer/MediaPlayerProviderProtocol.swift @@ -13,7 +13,7 @@ enum MediaPlayerProviderError: Error { @MainActor protocol MediaPlayerProviderProtocol { - func player(for mediaSource: MediaSourceProxy) -> Result + var player: AudioPlayerProtocol { get } func playerState(for id: AudioPlayerStateIdentifier) -> AudioPlayerState? func register(audioPlayerState: AudioPlayerState) diff --git a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift index 11177b93bf..776a6c5522 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift @@ -243,7 +243,7 @@ struct VideoInfoProxy: Hashable { } static var mockVideo: VideoInfoProxy { - .init(source: .init(url: .picturesDirectory, mimeType: nil), + .init(source: .init(url: .mockMXCVideo, mimeType: nil), duration: 100, size: .init(width: 1920, height: 1080), aspectRatio: 1.78, @@ -292,14 +292,14 @@ struct ImageInfoProxy: Hashable { } static var mockImage: ImageInfoProxy { - .init(source: .init(url: .picturesDirectory, mimeType: "image/png"), + .init(source: .init(url: .mockMXCImage, mimeType: "image/png"), size: .init(width: 100, height: 100), aspectRatio: 1, mimeType: "image/png") } static var mockThumbnail: ImageInfoProxy { - .init(source: .init(url: .picturesDirectory, mimeType: nil), + .init(source: .init(url: .mockMXCImage, mimeType: nil), size: nil, aspectRatio: nil, mimeType: nil) diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift index e907aed2c0..55f5f8769b 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift @@ -101,13 +101,12 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol { await previewAudioPlayerState.attachAudioPlayer(audioPlayer) } - if audioPlayer.url == url { + if audioPlayer.playbackURL == url { audioPlayer.play() return .success(()) } - let pendingMediaSource = MediaSourceProxy(url: url, mimeType: mp4accMimeType) - audioPlayer.load(mediaSource: pendingMediaSource, using: url, autoplay: true) + audioPlayer.load(sourceURL: url, playbackURL: url, autoplay: true) return .success(()) } @@ -242,10 +241,7 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol { previewAudioPlayerState = await AudioPlayerState(id: .recorderPreview, title: L10n.commonVoiceMessage, duration: recordingDuration, waveform: EstimatedWaveform(data: [])) // Build the preview audio player - let mediaSource = MediaSourceProxy(url: url, mimeType: mp4accMimeType) - guard case .success(let mediaPlayer) = await mediaPlayerProvider.player(for: mediaSource), let audioPlayer = mediaPlayer as? AudioPlayerProtocol else { - return .failure(.previewNotAvailable) - } + let audioPlayer = await mediaPlayerProvider.player previewAudioPlayer = audioPlayer return .success(()) diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index 73c4910754..56669b93f3 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -253,7 +253,7 @@ class MockScreen: Identifiable { let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), @@ -272,7 +272,7 @@ class MockScreen: Identifiable { let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.default let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), @@ -291,7 +291,7 @@ class MockScreen: Identifiable { let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.smallChunkWithReadReceipts let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), @@ -313,7 +313,7 @@ class MockScreen: Identifiable { timelineController.backPaginationResponses = [RoomTimelineItemFixtures.singleMessageChunk] timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage] let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "Small timeline", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "Small timeline", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), @@ -335,7 +335,7 @@ class MockScreen: Identifiable { timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk] let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "Small timeline, paginating", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "Small timeline, paginating", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), @@ -357,7 +357,7 @@ class MockScreen: Identifiable { timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk] let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "Large timeline", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "Large timeline", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), @@ -380,7 +380,7 @@ class MockScreen: Identifiable { timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk] timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage] let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "Large timeline", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "Large timeline", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), @@ -402,7 +402,7 @@ class MockScreen: Identifiable { timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage] let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "Large timeline", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "Large timeline", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), @@ -423,7 +423,7 @@ class MockScreen: Identifiable { let timelineController = MockRoomTimelineController() timelineController.timelineItems = RoomTimelineItemFixtures.permalinkChunk let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "Timeline highlight", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "Timeline highlight", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), @@ -458,7 +458,7 @@ class MockScreen: Identifiable { timelineController.timelineItems = RoomTimelineItemFixtures.disclosedPolls timelineController.incomingItems = [] let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), @@ -480,7 +480,7 @@ class MockScreen: Identifiable { timelineController.timelineItems = RoomTimelineItemFixtures.undisclosedPolls timelineController.incomingItems = [] let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), @@ -502,7 +502,7 @@ class MockScreen: Identifiable { timelineController.timelineItems = RoomTimelineItemFixtures.outgoingPolls timelineController.incomingItems = [] let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), - roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: URL.picturesDirectory)), + roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)), timelineController: timelineController, mediaProvider: MediaProviderMock(configuration: .init()), mediaPlayerProvider: MediaPlayerProviderMock(), 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 da48f52364..3b5c200b5d 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:4dcc4ffc59ec9fc2f68bdce87a7f3d7bff27b1a2f7113df0669d1170e7a68045 -size 88606 +oid sha256:f6e63d693948eb3139609c45c2511a6db5213ba6d312082deba2dcca31bb836d +size 92248 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 da48f52364..3b5c200b5d 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:4dcc4ffc59ec9fc2f68bdce87a7f3d7bff27b1a2f7113df0669d1170e7a68045 -size 88606 +oid sha256:f6e63d693948eb3139609c45c2511a6db5213ba6d312082deba2dcca31bb836d +size 92248 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 31587cb5a6..2ad9f0eab3 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:aceb415158105cb684244cc5d468ac24915aa4a2c1e0f03e4b95915dea604f44 -size 46009 +oid sha256:141cf3859c4b421be24e2409abc2d6bb4b53ff3c9878811cdbb6b67c901251a7 +size 49837 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 31587cb5a6..2ad9f0eab3 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:aceb415158105cb684244cc5d468ac24915aa4a2c1e0f03e4b95915dea604f44 -size 46009 +oid sha256:141cf3859c4b421be24e2409abc2d6bb4b53ff3c9878811cdbb6b67c901251a7 +size 49837 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 e594e1dd0b..fce9df4b14 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:1b8ef13343f827c0dc3e9aaf74ce28f8a3e96bb0f4b9aa457e6a9ff40b3ad632 -size 98059 +oid sha256:ad795840c41305dbe8028cfea18b8fe25d3be2ab9524bc3322ed77726df25bcb +size 101810 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 0deed32f47..1b2a6cd0d3 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:516b16553d506445d965c708a5f56e5b9c53b23488809a2513a56c2368a2d633 -size 98477 +oid sha256:70452fc6801a7a7778992bc40ef49c929744d76f0285e2f1aec33c09a5ae3242 +size 102228 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 b4ce7760f4..322efcd586 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:b4bc7dbfbb1c7c58641f7d19bcb648e792220c19919b9001b09bdc8ccda0c86f -size 53599 +oid sha256:26b773b1dd1468c8298fc18062e9cc8749698536c19ca643acb1551f9293fb91 +size 57194 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 0c9096622a..1e2990cb14 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:fd4bca95fba0ed2e11a1212c1ac3d1a638815274c370a1bdb4a3dd825c89de6d -size 54013 +oid sha256:6a952ed17097a7d8d6b16d3a330e1eaf3fdea80dac026618d456b561ff10c39a +size 57608 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 f190faed8f..f9236284a9 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:d5b3a8bd64746aad774b15fc3e3500bbab4144d64ed4f8714f9b2527c70a494c -size 1990774 +oid sha256:8927edf5a98a3beae9d1dd2a61985b5402b72ab5688a2960a8c65b726b28e7a8 +size 2016923 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 a140b1c4b7..3218c7edd5 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:b6be25a2a046c3d1088ae6f87e4e1e0033062225c624095d679f1083ffe538b6 -size 1945746 +oid sha256:c9390f013722ba23d3b9ade888bc484e7b276e223f135d6641371d60da690397 +size 1971897 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 80328b815e..477eae3b2c 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:46447c25230d95f04d122924d938f6f4b5eacd633140e586c3c276322f8e8b75 -size 1791354 +oid sha256:2347df221ddac84740cf5436620bb07bf3e7f24aea85e6dceec11f8d374a66d0 +size 1817511 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 be7b7aed9e..c7919792e2 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:e0070dcdfe989211600c14fdb7b96af79cfb2b50ae8c3d560f7fe738b368be48 -size 1982637 +oid sha256:630995e1d62ff737c63bda878adec6756c0baa5a0136fb898f9cbf07ef52aa43 +size 1987392 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 3691161625..d793b5ec09 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:41f91af2b20ff571cdf281d4dedaf1f6749a8fdaf33508a1b70511ef6e477af4 -size 1995837 +oid sha256:177f9b216f7716c511037ad044d08c499bc1d33b576d46dbda7d6c67bb513f1e +size 2022040 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 daf9980781..ae566af5c2 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:daf1b08dbe20c63aa66d1c16e3bc41fdc92a54ad4f143ccfcd9ca8382964a0fe -size 1946727 +oid sha256:a13076406c868e7b86d89782752c1fe70776151623c18d6fe47e59671120e0d7 +size 1972878 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 e0acdc11eb..2b13d28459 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:08e0296e33a657e0c42f95cb2e4963cb8f32c3a37979262cd76bc4c3ac3a7132 -size 1799819 +oid sha256:69ad1bad58cd73c5626fdf52923f6a0955221f5673b4485c131048d64b215c84 +size 1825976 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 1a6c7a7702..2a844d9813 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:8283d5d60db3b91caa096216e4dbb1d5e5342375080c81e5814acbb01b41c8c9 -size 2000079 +oid sha256:a81a307b980a5e1d950c98d2fe2981d0cf138da722d76007dd2f61693d85c208 +size 2004686 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 30981c1a0a..8eb621c81f 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:616a8a5fe92ef87797d9a69bd5d7581e685edad21b002bf079d1a02fdb782987 -size 827638 +oid sha256:329b0b5fd32c1e395f969a006d2b56d399292abdee46d6e15df89bf3a8005d89 +size 851720 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 4e9483a8df..f22223291a 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:6d7390ef83a9fb7e8887aff95c03282d4fbcf3826cf3e254d523373a2c434df0 -size 798961 +oid sha256:9f6a60932fcba3f2bcd0127af134fd7005cc74a3ba02bfa1717466c35e92ad8c +size 823057 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 ce2bdf2f6b..eecc7badea 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:3f9518a386e4c12c9e1527eb5f841fb0ca56fc8658529b58d6d459376caca39b -size 705027 +oid sha256:438018482d1792510fd3d07df8f9ba72ca7ddf3f1e69d7ab0b0adcdbe7a8b0f8 +size 729066 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 8db4a97964..3f5ee33021 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:19d3b48e373ed4e263c9cb0f6e5a3566a9c6612f19da8468be420eca0a10cd92 -size 819795 +oid sha256:72ccc0e3a37d2f8728fc59240b0a11099594e8576a4d89b2ad462ba422a2d38f +size 824019 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 1de1b350e5..422ad1cbd5 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:6ecca9bbfa7a1d245a96fc27aacfb5d60931ba1437639ebd8e9ff1756bd705c6 -size 835366 +oid sha256:2fb7e4c00fd1d30189f80d8abcf05dd3048039ce61a387f98691bfb618c9218e +size 859617 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 42fb8407bb..0920fc6c93 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:450d28a2af4b81f2db2e8a1fb28405d029439cabf5f48688b448391dd7e43b05 -size 800675 +oid sha256:bd08e040f1aff5e3ca2b50965a2bb368557134e8e3bc5bd6e390a1b4a328ae67 +size 824771 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 dfd17d6251..70405c8970 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:858759589a323ce04e894f398c230c0454f64a3c3148b183f9ecdbeb29955b89 -size 714177 +oid sha256:03f9fedddcc22df3d14c21cb5314cdd8fdf17592032f57bb762b7c1fe1bbf5ca +size 738216 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 8407998f15..a1596ce245 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:eb3a1c2ac88a74a4f9c402a46a8512abc2596937b92c3d17fa30a7cdf10ce22a -size 835796 +oid sha256:d9482f0f3428f1826ef0e5d7e83d65aa895fc88c8db8a756c8c93c2767300f99 +size 840024 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 eaa1387802..1b3feed28c 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:189a2f7d717020e1fdc38c758446fe00ecc6279fc29295df48fee6b11e2c0e45 -size 72244 +oid sha256:d00776a5033ba2bf44c909bd5c41a422ba3f8675bab60cee885788440f38a34a +size 76078 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 eaa1387802..1b3feed28c 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:189a2f7d717020e1fdc38c758446fe00ecc6279fc29295df48fee6b11e2c0e45 -size 72244 +oid sha256:d00776a5033ba2bf44c909bd5c41a422ba3f8675bab60cee885788440f38a34a +size 76078 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 9b2ae835eb..de20826930 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:a707341b7229847083f074c637678863b24e8bab3da2be830313c33236e1006d -size 31580 +oid sha256:87252ee182a5c1c0c8827b9fbb4679fcac0ad6829d92702f37a94d42ff069e91 +size 35403 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 9b2ae835eb..de20826930 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:a707341b7229847083f074c637678863b24e8bab3da2be830313c33236e1006d -size 31580 +oid sha256:87252ee182a5c1c0c8827b9fbb4679fcac0ad6829d92702f37a94d42ff069e91 +size 35403 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 984cf823e5..9dfa406a12 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:290f71a4d1e5bab703e3a4483acdbd3605ff9df65c18bbfdc7cca3297e516584 -size 76118 +oid sha256:7b6f71e4c5caef9d16e44bb90c0e2051db32467c190479271e9e9f50f249bad4 +size 79950 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 984cf823e5..9dfa406a12 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:290f71a4d1e5bab703e3a4483acdbd3605ff9df65c18bbfdc7cca3297e516584 -size 76118 +oid sha256:7b6f71e4c5caef9d16e44bb90c0e2051db32467c190479271e9e9f50f249bad4 +size 79950 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 e3caddf9a0..485685cc39 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:da24b677846f3088c15a2dc4a6d3de517bf499ce62bc0ad58586912179019286 -size 35184 +oid sha256:951bde2a3cc7a130218d8123e8d91469efdd14f66ff251154f0b803d9e378ffb +size 39094 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 e3caddf9a0..485685cc39 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:da24b677846f3088c15a2dc4a6d3de517bf499ce62bc0ad58586912179019286 -size 35184 +oid sha256:951bde2a3cc7a130218d8123e8d91469efdd14f66ff251154f0b803d9e378ffb +size 39094 diff --git a/UnitTests/Sources/ComposerToolbarViewModelTests.swift b/UnitTests/Sources/ComposerToolbarViewModelTests.swift index f1a1123282..fbecde99de 100644 --- a/UnitTests/Sources/ComposerToolbarViewModelTests.swift +++ b/UnitTests/Sources/ComposerToolbarViewModelTests.swift @@ -91,7 +91,7 @@ class ComposerToolbarViewModelTests: XCTestCase { func testSuggestions() { 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: URL.documentsDirectory, range: .init()))] + .user(item: MentionSuggestionItem(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: .mockMXCAvatar, range: .init()))] let mockCompletionSuggestionService = CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions)) viewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel, completionSuggestionService: mockCompletionSuggestionService, diff --git a/UnitTests/Sources/MediaPlayerProviderTests.swift b/UnitTests/Sources/MediaPlayerProviderTests.swift index 92ef5997d5..d4837d4728 100644 --- a/UnitTests/Sources/MediaPlayerProviderTests.swift +++ b/UnitTests/Sources/MediaPlayerProviderTests.swift @@ -15,50 +15,13 @@ class MediaPlayerProviderTests: XCTestCase { private var mediaPlayerProvider: MediaPlayerProvider! private let oggMimeType = "audio/ogg" - private let someURL = URL("/some/url") - private let someOtherURL = URL("/some/other/url") + private let someURL = URL.mockMXCAudio + private let someOtherURL = URL.mockMXCFile override func setUp() async throws { mediaPlayerProvider = MediaPlayerProvider() } - func testPlayerForWrongMediaType() async throws { - let mediaSourceWithoutMimeType = MediaSourceProxy(url: someURL, mimeType: nil) - switch mediaPlayerProvider.player(for: mediaSourceWithoutMimeType) { - case .failure(.unsupportedMediaType): - // Ok - break - default: - XCTFail("An error is expected") - } - - let mediaSourceVideo = MediaSourceProxy(url: someURL, mimeType: "video/mp4") - switch mediaPlayerProvider.player(for: mediaSourceVideo) { - case .failure(.unsupportedMediaType): - // Ok - break - default: - XCTFail("An error is expected") - } - } - - func testPlayerFor() async throws { - let mediaSource = MediaSourceProxy(url: someURL, mimeType: oggMimeType) - guard case .success(let playerA) = mediaPlayerProvider.player(for: mediaSource) else { - XCTFail("A valid player is expected") - return - } - - // calling it again with another mediasource must returns the same player - let otherMediaSource = MediaSourceProxy(url: someOtherURL, mimeType: oggMimeType) - guard case .success(let playerB) = mediaPlayerProvider.player(for: otherMediaSource) else { - XCTFail("A valid player is expected") - return - } - - XCTAssert(playerA === playerB) - } - func testPlayerStates() async throws { let audioPlayerStateId = AudioPlayerStateIdentifier.timelineItemIdentifier(.randomEvent) // By default, there should be no player state diff --git a/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift b/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift index 09d024d381..2e2b6e7d87 100644 --- a/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift +++ b/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift @@ -15,7 +15,7 @@ final class MediaLoaderTests: XCTestCase { mediaLoadingClient.getMediaContentMediaSourceReturnValue = Data() let mediaLoader = MediaLoader(client: mediaLoadingClient) - let mediaSource = MediaSourceProxy(url: URL.documentsDirectory, mimeType: nil) + let mediaSource = MediaSourceProxy(url: .mockMXCFile, mimeType: nil) do { for _ in 1...10 { @@ -33,7 +33,7 @@ final class MediaLoaderTests: XCTestCase { mediaLoadingClient.getMediaThumbnailMediaSourceWidthHeightReturnValue = Data() let mediaLoader = MediaLoader(client: mediaLoadingClient) - let mediaSource = MediaSourceProxy(url: URL.documentsDirectory, mimeType: nil) + let mediaSource = MediaSourceProxy(url: .mockMXCImage, mimeType: nil) do { for _ in 1...10 { diff --git a/UnitTests/Sources/MediaProvider/MediaProviderTests.swift b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift index 98712ba6c9..9e1dc87bd4 100644 --- a/UnitTests/Sources/MediaProvider/MediaProviderTests.swift +++ b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift @@ -36,7 +36,7 @@ final class MediaProviderTests: XCTestCase { return } - let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg")) + let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg")) let connectivitySubject = CurrentValueSubject(.unreachable) @@ -59,7 +59,7 @@ final class MediaProviderTests: XCTestCase { } func testLoadingRetriedOnReconnectionCancelsAfterSecondFailure() async throws { - let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg")) + let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg")) let connectivitySubject = CurrentValueSubject(.reachable) @@ -79,7 +79,7 @@ final class MediaProviderTests: XCTestCase { func test_whenImageFromSourceWithSourceNotNilAndImageCacheContainsImage_ImageIsReturned() throws { let avatarSize = Avatars.Size.room(on: .timeline) - let url = URL.picturesDirectory + let url = URL.mockMXCImage let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() imageCache.retrievedImagesInMemory[key] = imageForKey @@ -89,14 +89,14 @@ final class MediaProviderTests: XCTestCase { } func test_whenImageFromSourceWithSourceNotNilAndImageNotCached_nilReturned() throws { - let image = mediaProvider.imageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), + let image = mediaProvider.imageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), size: Avatars.Size.room(on: .timeline).scaledSize) XCTAssertNil(image) } func test_whenLoadImageFromSourceAndImageCacheContainsImage_successIsReturned() async throws { let avatarSize = Avatars.Size.room(on: .timeline) - let url = URL.picturesDirectory + let url = URL.mockMXCImage let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() imageCache.retrievedImagesInMemory[key] = imageForKey @@ -107,7 +107,7 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageSucceeds_successIsReturned() async throws { let avatarSize = Avatars.Size.room(on: .timeline) - let url = URL.picturesDirectory + let url = URL.mockMXCImage let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() imageCache.retrievedImages[key] = imageForKey @@ -122,7 +122,7 @@ final class MediaProviderTests: XCTestCase { mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = expectedImage.pngData() - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), size: avatarSize.scaledSize) switch result { case .success(let image): @@ -134,7 +134,7 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFails_imageIsStored() async throws { let avatarSize = Avatars.Size.room(on: .timeline) - let url = URL.picturesDirectory + let url = URL.mockMXCImage let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let expectedImage = try loadTestImage() @@ -151,7 +151,7 @@ final class MediaProviderTests: XCTestCase { mediaLoader.loadMediaContentForSourceReturnValue = expectedImage.pngData() - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), size: nil) switch result { case .success(let image): @@ -164,7 +164,7 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndLoadImageThumbnailFails_errorIsThrown() async throws { mediaLoader.loadMediaThumbnailForSourceWidthHeightThrowableError = MediaProviderTestsError.error - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), size: Avatars.Size.room(on: .timeline).scaledSize) switch result { case .success: @@ -177,7 +177,7 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndNoAvatarSizeAndLoadImageContentFails_errorIsThrown() async throws { mediaLoader.loadMediaContentForSourceThrowableError = MediaProviderTestsError.error - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), size: nil) switch result { case .success: @@ -190,7 +190,7 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndImageThumbnailIsLoadedWithCorruptedData_errorIsThrown() async throws { mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = Data() - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: URL.picturesDirectory, mimeType: "image/jpeg"), + let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), size: Avatars.Size.room(on: .timeline).scaledSize) switch result { case .success: diff --git a/UnitTests/Sources/RoomDetailsEditScreenViewModelTests.swift b/UnitTests/Sources/RoomDetailsEditScreenViewModelTests.swift index 2088df6e3e..4befd2efbc 100644 --- a/UnitTests/Sources/RoomDetailsEditScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomDetailsEditScreenViewModelTests.swift @@ -58,7 +58,7 @@ class RoomDetailsEditScreenViewModelTests: XCTestCase { } func testAvatarDidChange() { - setupViewModel(roomProxyConfiguration: .init(name: "Some room", avatarURL: .picturesDirectory, members: [.mockMeAdmin])) + setupViewModel(roomProxyConfiguration: .init(name: "Some room", avatarURL: .mockMXCAvatar, members: [.mockMeAdmin])) context.send(viewAction: .removeImage) XCTAssertTrue(context.viewState.avatarDidChange) XCTAssertTrue(context.viewState.canSave) @@ -100,7 +100,7 @@ class RoomDetailsEditScreenViewModelTests: XCTestCase { } func testDeleteAvatar() { - setupViewModel(roomProxyConfiguration: .init(name: "Some room", avatarURL: .picturesDirectory, members: [.mockMeAdmin])) + setupViewModel(roomProxyConfiguration: .init(name: "Some room", avatarURL: .mockMXCAvatar, members: [.mockMeAdmin])) XCTAssertNotNil(context.viewState.avatarURL) context.send(viewAction: .removeImage) XCTAssertNil(context.viewState.avatarURL) diff --git a/UnitTests/Sources/RoomScreenViewModelTests.swift b/UnitTests/Sources/RoomScreenViewModelTests.swift index 773c9af2c7..306abca905 100644 --- a/UnitTests/Sources/RoomScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomScreenViewModelTests.swift @@ -184,13 +184,13 @@ class RoomScreenViewModelTests: XCTestCase { try await deferred.fulfill() configuration.name = "NewName" - configuration.avatarURL = .documentsDirectory + configuration.avatarURL = .mockMXCAvatar configuration.hasOngoingCall = true roomProxyMock.canUserJoinCallUserIDReturnValue = .success(true) deferred = deferFulfillment(viewModel.context.$viewState) { viewState in viewState.roomTitle == "NewName" && - viewState.roomAvatar == .room(id: "TestID", name: "NewName", avatarURL: .documentsDirectory) && + viewState.roomAvatar == .room(id: "TestID", name: "NewName", avatarURL: .mockMXCAvatar) && viewState.canJoinCall && viewState.hasOngoingCall } diff --git a/UnitTests/Sources/UserProfileScreenViewModelTests.swift b/UnitTests/Sources/UserProfileScreenViewModelTests.swift index f040de8c28..6706966438 100644 --- a/UnitTests/Sources/UserProfileScreenViewModelTests.swift +++ b/UnitTests/Sources/UserProfileScreenViewModelTests.swift @@ -15,7 +15,7 @@ class UserProfileScreenViewModelTests: XCTestCase { var context: UserProfileScreenViewModelType.Context { viewModel.context } func testInitialState() async throws { - let profile = UserProfileProxy(userID: "@alice:matrix.org", displayName: "Alice", avatarURL: .picturesDirectory) + let profile = UserProfileProxy(userID: "@alice:matrix.org", displayName: "Alice", avatarURL: .mockMXCAvatar) let clientProxy = ClientProxyMock(.init()) clientProxy.profileForReturnValue = .success(profile) @@ -35,7 +35,7 @@ class UserProfileScreenViewModelTests: XCTestCase { } func testInitialStateAccountOwner() async throws { - let profile = UserProfileProxy(userID: RoomMemberProxyMock.mockMe.userID, displayName: "Me", avatarURL: .picturesDirectory) + let profile = UserProfileProxy(userID: RoomMemberProxyMock.mockMe.userID, displayName: "Me", avatarURL: .mockMXCAvatar) let clientProxy = ClientProxyMock(.init()) clientProxy.profileForReturnValue = .success(profile) diff --git a/UnitTests/Sources/VoiceMessageCacheTests.swift b/UnitTests/Sources/VoiceMessageCacheTests.swift index 12f8681486..7520867766 100644 --- a/UnitTests/Sources/VoiceMessageCacheTests.swift +++ b/UnitTests/Sources/VoiceMessageCacheTests.swift @@ -16,7 +16,7 @@ class VoiceMessageCacheTests: XCTestCase { private var mediaSource: MediaSourceProxy! private var fileManager: FileManager! - private let someURL = URL("/some/url") + private let someURL = URL.mockMXCAudio private let testFilename = "test-file" private let mpeg4aacFileExtension = "m4a" private let testTemporaryDirectory = URL.temporaryDirectory.appendingPathComponent("test-voice-messsage-cache") diff --git a/UnitTests/Sources/VoiceMessageMediaManagerTests.swift b/UnitTests/Sources/VoiceMessageMediaManagerTests.swift index 7a85f15dc4..2aeecf0624 100644 --- a/UnitTests/Sources/VoiceMessageMediaManagerTests.swift +++ b/UnitTests/Sources/VoiceMessageMediaManagerTests.swift @@ -16,7 +16,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { private var voiceMessageCache: VoiceMessageCacheMock! private var mediaProvider: MediaProviderMock! - private let someURL = URL("/some/url") + private let someURL = URL.mockMXCAudio private let audioOGGMimeType = "audio/ogg" override func setUp() async throws { diff --git a/UnitTests/Sources/VoiceMessageRecorderTests.swift b/UnitTests/Sources/VoiceMessageRecorderTests.swift index bba8e525fb..a3c675c88f 100644 --- a/UnitTests/Sources/VoiceMessageRecorderTests.swift +++ b/UnitTests/Sources/VoiceMessageRecorderTests.swift @@ -43,9 +43,7 @@ class VoiceMessageRecorderTests: XCTestCase { audioPlayer.state = .stopped mediaPlayerProvider = MediaPlayerProviderMock() - mediaPlayerProvider.playerForClosure = { _ in - .success(self.audioPlayer) - } + mediaPlayerProvider.player = audioPlayer audioConverter = AudioConverterMock() voiceMessageCache = VoiceMessageCacheMock() voiceMessageCache.urlForRecording = FileManager.default.temporaryDirectory.appendingPathComponent("test-voice-message").appendingPathExtension("m4a") @@ -121,11 +119,10 @@ class VoiceMessageRecorderTests: XCTestCase { return } XCTAssertEqual(voiceMessageRecorder.previewAudioPlayerState?.isAttached, true) - XCTAssert(audioPlayer.loadMediaSourceUsingAutoplayCalled) - XCTAssertEqual(audioPlayer.loadMediaSourceUsingAutoplayReceivedArguments?.url, recordingURL) - XCTAssertEqual(audioPlayer.loadMediaSourceUsingAutoplayReceivedArguments?.mediaSource.mimeType, "audio/m4a") - XCTAssertEqual(audioPlayer.loadMediaSourceUsingAutoplayReceivedArguments?.mediaSource.url, recordingURL) - XCTAssertEqual(audioPlayer.loadMediaSourceUsingAutoplayReceivedArguments?.autoplay, true) + XCTAssert(audioPlayer.loadSourceURLPlaybackURLAutoplayCalled) + XCTAssertEqual(audioPlayer.loadSourceURLPlaybackURLAutoplayReceivedArguments?.sourceURL, recordingURL) + XCTAssertEqual(audioPlayer.loadSourceURLPlaybackURLAutoplayReceivedArguments?.playbackURL, recordingURL) + XCTAssertEqual(audioPlayer.loadSourceURLPlaybackURLAutoplayReceivedArguments?.autoplay, true) XCTAssertFalse(audioPlayer.playCalled) } @@ -141,7 +138,7 @@ class VoiceMessageRecorderTests: XCTestCase { func testResumePlayback() async throws { try await setRecordingComplete() - audioPlayer.url = recordingURL + audioPlayer.playbackURL = recordingURL guard case .success = await voiceMessageRecorder.startPlayback() else { XCTFail("Playback should start") @@ -149,7 +146,7 @@ class VoiceMessageRecorderTests: XCTestCase { } XCTAssertEqual(voiceMessageRecorder.previewAudioPlayerState?.isAttached, true) // The media must not have been reloaded - XCTAssertFalse(audioPlayer.loadMediaSourceUsingAutoplayCalled) + XCTAssertFalse(audioPlayer.loadSourceURLPlaybackURLAutoplayCalled) XCTAssertTrue(audioPlayer.playCalled) } diff --git a/project.yml b/project.yml index ea2d55d7c3..df794b7e46 100644 --- a/project.yml +++ b/project.yml @@ -61,7 +61,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.75 + exactVersion: 1.0.76 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From c598b6325db7c6ce3dc341aebdef99dfff4f0dc1 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:44:34 +0000 Subject: [PATCH 61/74] Fix a bug on iOS 17 where you couldn't long press on a message. (#3567) --- .../Timeline/View/Style/TimelineItemBubbledStylerView.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift index 037f7f1829..fcfd2160d8 100644 --- a/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift +++ b/ElementX/Sources/Screens/Timeline/View/Style/TimelineItemBubbledStylerView.swift @@ -124,6 +124,12 @@ struct TimelineItemBubbledStylerView: View { var messageBubbleWithActions: some View { messageBubble + .onTapGesture { + // We need a tap gesture before the long press gesture below, otherwise something + // on iOS 17 hijacks the long press and you can't bring up the context menu. This + // is no longer an issue on iOS 18. Note: it's fine for this to be empty, we handle + // specific taps within the timeline views themselves. + } .longPressWithFeedback { context.send(viewAction: .displayTimelineItemMenu(itemID: timelineItem.id)) } From 000073c7a0f22e1532a6fc7394a8e372ac46b8e5 Mon Sep 17 00:00:00 2001 From: Element CI Date: Thu, 28 Nov 2024 07:03:12 -0800 Subject: [PATCH 62/74] Prepare next release --- CHANGES.md | 47 ++++++++++++++++++++++++++++++ ElementX.xcodeproj/project.pbxproj | 4 +-- project.yml | 2 +- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5399deba5e..3fe9a833a3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,50 @@ +## Changes in 1.9.7 (2024-11-28) + +### What's Changed + +✨ Features +* Support adding a caption to media uploads. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3531 +* Show both defaults and frequent emojis in the timeline item menu, make the list scrollable by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3534 +* Enable inline replies for push notifications. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3542 + +🙌 Improvements +* using `roomPreview` API for invited rooms by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3530 +* Add support for sharing URLs and text. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3546 +* Add support for adding/editing/removing media captions. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3547 +* Update how file captions are rendered by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3554 + +🐛 Bugfixes +* Handle NSItemProvider public.image data types. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3541 +* Fix the media upload preview screen on macOS. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3543 +* Delay handling inline notification replies until the user session is established by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3544 +* Put the share extension Info.plist updates in the xcodegen yaml 🤦‍♂️ by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3549 +* Fix the presentation of QuickLook when viewing logs on macOS. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3556 +* Stop delaying ElementCall until the next sync loop and only notify other participants when presumed to already be up to date. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3559 +* Add back missing send button when media captions are disabled. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3561 +* Fix a bug on iOS 17 where you couldn't long press on a message. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3567 + +🗣 Translations +* Translations update by @RiotRobot in https://github.com/element-hq/element-x-ios/pull/3552 + +🧱 Build +* Link the MatrixRustSDK dynamically and only embed it in the main target by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3539 + +🚧 In development 🚧 +* Knock Requests List Screen by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3533 +* Knock Requests banner display logic by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3550 +* Knock Requests navigation flows by @Velin92 in https://github.com/element-hq/element-x-ios/pull/3555 + +Others +* Fix UI tests, update compound to roll back snapshot testing and avoid the requirement for Swift Testing. by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3540 +* Update the SDK. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3545 +* Move timeline item tap gestures to the items themselves instead of the bubbled styler by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3553 +* Bump the RustSDK to v1.0.75 by @stefanceriu in https://github.com/element-hq/element-x-ios/pull/3557 +* Move the media caption composer (and Add Caption action) behind a feature flag for now. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3560 +* Update the SDK. by @pixlwave in https://github.com/element-hq/element-x-ios/pull/3565 + + +**Full Changelog**: https://github.com/element-hq/element-x-ios/compare/1.9.6...1.9.7 + ## Changes in 1.9.6 (2024-11-19) ### What's Changed diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 555db7e68a..954e7e75c3 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -7800,7 +7800,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 17.6; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; MACOSX_DEPLOYMENT_TARGET = 14.6; - MARKETING_VERSION = 1.9.7; + MARKETING_VERSION = 1.9.8; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCTION_APP_NAME = Element; @@ -7877,7 +7877,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 17.6; KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"; MACOSX_DEPLOYMENT_TARGET = 14.6; - MARKETING_VERSION = 1.9.7; + MARKETING_VERSION = 1.9.8; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; diff --git a/project.yml b/project.yml index df794b7e46..510e3277e1 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.7 + MARKETING_VERSION: 1.9.8 CURRENT_PROJECT_VERSION: 1 SUPPORTS_MACCATALYST: false From d48fb644683627e130f636bddb5ca35ead9ee775 Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Thu, 28 Nov 2024 18:02:07 +0100 Subject: [PATCH 63/74] Small Knock adjustments (#3568) * small adjustments * autocorrection disabled --- ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift | 2 +- .../Sources/Screens/CreateRoom/View/CreateRoomScreen.swift | 4 ++-- .../Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift index 31e40fd5d6..8f9a5d8dc5 100644 --- a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift +++ b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift @@ -92,7 +92,7 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol case .removeImage: actionsSubject.send(.removeImage) case .updateAliasLocalPart(let aliasLocalPart): - state.aliasLocalPart = aliasLocalPart + state.aliasLocalPart = aliasLocalPart.lowercased() // If this has been called this means that the user wants a custom address not necessarily reflecting the name // So we disable the two from syncing. syncNameAndAlias = false diff --git a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift index ff7fae7d93..22f8dbd78b 100644 --- a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift +++ b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift @@ -195,8 +195,8 @@ struct CreateRoomScreen: View { .foregroundStyle(.compound.textSecondary) TextField("", text: aliasBinding) - .autocapitalization(.none) - .textCase(.lowercase) + .textInputAutocapitalization(.never) + .autocorrectionDisabled() .tint(.compound.iconAccentTertiary) .font(.compound.bodyLG) .foregroundStyle(.compound.textPrimary) diff --git a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift index 2c3bff5240..40c3d65e3b 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift @@ -110,7 +110,7 @@ struct JoinRoomScreen: View { HStack(spacing: 0) { TextField("", text: $context.knockMessage, axis: .vertical) .onChange(of: context.knockMessage) { _, newValue in - context.knockMessage = String(newValue.prefix(1000)) + context.knockMessage = String(newValue.prefix(500)) } .lineLimit(4, reservesSpace: true) .font(.compound.bodyMD) From 4869dcfe9768275dc8aa4ce532c05a527bf8ef3d Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Thu, 28 Nov 2024 17:30:07 +0000 Subject: [PATCH 64/74] Wait until the sync has stopped before marking the task as complete. (#3564) --- .../Sources/Application/AppCoordinator.swift | 29 ++++++++------- .../Mocks/Generated/GeneratedMocks.swift | 35 +++++++++++++++++++ .../Sources/Services/Client/ClientProxy.swift | 2 +- .../Services/Client/ClientProxyProtocol.swift | 1 + 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 111a913405..74f446003f 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -882,12 +882,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg // MARK: - Application State - private func stopSync(isBackgroundTask: Bool) { + private func stopSync(isBackgroundTask: Bool, completion: (() -> Void)? = nil) { if isBackgroundTask, UIApplication.shared.applicationState == .active { // Attempt to stop the background task sync loop cleanly, only if the app not already running return } - userSession?.clientProxy.stopSync() + userSession?.clientProxy.stopSync(completion: completion) clientProxyObserver = nil } @@ -968,9 +968,11 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg backgroundTask = appMediator.beginBackgroundTask { [weak self] in guard let self else { return } - stopSync(isBackgroundTask: true) - - if let backgroundTask { + MXLog.info("Background task is about to expire.") + stopSync(isBackgroundTask: true) { [weak self] in + guard let self, let backgroundTask else { return } + + MXLog.info("Ending background task.") appMediator.endBackgroundTask(backgroundTask) self.backgroundTask = nil } @@ -1026,10 +1028,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg scheduleBackgroundAppRefresh() task.expirationHandler = { [weak self] in - self?.stopSync(isBackgroundTask: true) + MXLog.info("Background app refresh task is about to expire.") - MXLog.info("Background app refresh task expired") - task.setTaskCompleted(success: true) + self?.stopSync(isBackgroundTask: true) { + MXLog.info("Marking Background app refresh task as complete.") + task.setTaskCompleted(success: true) + } } guard let userSession else { @@ -1047,13 +1051,14 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg .sink(receiveValue: { [weak self] _ in guard let self else { return } MXLog.info("Background app refresh finished") + backgroundRefreshSyncObserver?.cancel() // Make sure we stop the sync loop, otherwise the ongoing request is immediately // handled the next time the app refreshes, which can trigger timeout failures. - stopSync(isBackgroundTask: true) - backgroundRefreshSyncObserver?.cancel() - - task.setTaskCompleted(success: true) + stopSync(isBackgroundTask: true) { + MXLog.info("Marking Background app refresh task as complete.") + task.setTaskCompleted(success: true) + } }) } } diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index b980c6dd65..ef2b2f793a 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -2346,6 +2346,41 @@ class ClientProxyMock: ClientProxyProtocol { stopSyncCallsCount += 1 stopSyncClosure?() } + //MARK: - stopSync + + var stopSyncCompletionUnderlyingCallsCount = 0 + var stopSyncCompletionCallsCount: Int { + get { + if Thread.isMainThread { + return stopSyncCompletionUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = stopSyncCompletionUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + stopSyncCompletionUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + stopSyncCompletionUnderlyingCallsCount = newValue + } + } + } + } + var stopSyncCompletionCalled: Bool { + return stopSyncCompletionCallsCount > 0 + } + var stopSyncCompletionClosure: (((() -> Void)?) -> Void)? + + func stopSync(completion: (() -> Void)?) { + stopSyncCompletionCallsCount += 1 + stopSyncCompletionClosure?(completion) + } //MARK: - accountURL var accountURLActionUnderlyingCallsCount = 0 diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 61c0aa4888..41d264eda0 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -305,7 +305,7 @@ class ClientProxy: ClientProxyProtocol { stopSync(completion: nil) } - private func stopSync(completion: (() -> Void)?) { + func stopSync(completion: (() -> Void)?) { MXLog.info("Stopping sync") if restartTask != nil { diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index d13b363093..ac06415980 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -123,6 +123,7 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { func startSync() func stopSync() + func stopSync(completion: (() -> Void)?) // Hopefully this will become async once we get SE-0371. func accountURL(action: AccountManagementAction) async -> URL? From fdbacbc22dba0b961b746ed5ae2a9c2e90b9df2e Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Thu, 28 Nov 2024 17:30:26 +0000 Subject: [PATCH 65/74] Add the unit test media files as development assets. (#3569) Move UnitTests/Resources/Media into a top-level DevelopmentAssets directory. --- .gitattributes | 2 +- .../Media/landscape_test_image.jpg | 0 .../Media/landscape_test_video.mov | 0 .../Media/portrait_test_image.jpg | 0 .../Media/portrait_test_video.mp4 | 0 .../Media/test_animated_image.gif | 0 .../Media/test_apple_image.heic | 0 .../Media/test_audio.mp3 | 0 .../Media/test_image.png | 0 .../Media/test_pdf.pdf | Bin .../Media/test_rotated_image.jpg | 0 .../Media/test_voice_message.m4a | 0 ElementX.xcodeproj/project.pbxproj | 144 ++++++++++-------- ElementX/SupportingFiles/target.yml | 2 + UnitTests/SupportingFiles/target.yml | 2 +- 15 files changed, 88 insertions(+), 62 deletions(-) rename {UnitTests/Resources => DevelopmentAssets}/Media/landscape_test_image.jpg (100%) rename {UnitTests/Resources => DevelopmentAssets}/Media/landscape_test_video.mov (100%) rename {UnitTests/Resources => DevelopmentAssets}/Media/portrait_test_image.jpg (100%) rename {UnitTests/Resources => DevelopmentAssets}/Media/portrait_test_video.mp4 (100%) rename {UnitTests/Resources => DevelopmentAssets}/Media/test_animated_image.gif (100%) rename {UnitTests/Resources => DevelopmentAssets}/Media/test_apple_image.heic (100%) rename {UnitTests/Resources => DevelopmentAssets}/Media/test_audio.mp3 (100%) rename {UnitTests/Resources => DevelopmentAssets}/Media/test_image.png (100%) rename {UnitTests/Resources => DevelopmentAssets}/Media/test_pdf.pdf (100%) rename {UnitTests/Resources => DevelopmentAssets}/Media/test_rotated_image.jpg (100%) rename {UnitTests/Resources => DevelopmentAssets}/Media/test_voice_message.m4a (100%) diff --git a/.gitattributes b/.gitattributes index a1202033e2..ca32692480 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,4 @@ UITests/Sources/__Snapshots__/** filter=lfs diff=lfs merge=lfs -text -UnitTests/Resources/** filter=lfs diff=lfs merge=lfs -text +DevelopmentAssets/Media/** filter=lfs diff=lfs merge=lfs -text UnitTests/__Snapshots__/** filter=lfs diff=lfs merge=lfs -text PreviewTests/Sources/__Snapshots__/** filter=lfs diff=lfs merge=lfs -text \ No newline at end of file diff --git a/UnitTests/Resources/Media/landscape_test_image.jpg b/DevelopmentAssets/Media/landscape_test_image.jpg similarity index 100% rename from UnitTests/Resources/Media/landscape_test_image.jpg rename to DevelopmentAssets/Media/landscape_test_image.jpg diff --git a/UnitTests/Resources/Media/landscape_test_video.mov b/DevelopmentAssets/Media/landscape_test_video.mov similarity index 100% rename from UnitTests/Resources/Media/landscape_test_video.mov rename to DevelopmentAssets/Media/landscape_test_video.mov diff --git a/UnitTests/Resources/Media/portrait_test_image.jpg b/DevelopmentAssets/Media/portrait_test_image.jpg similarity index 100% rename from UnitTests/Resources/Media/portrait_test_image.jpg rename to DevelopmentAssets/Media/portrait_test_image.jpg diff --git a/UnitTests/Resources/Media/portrait_test_video.mp4 b/DevelopmentAssets/Media/portrait_test_video.mp4 similarity index 100% rename from UnitTests/Resources/Media/portrait_test_video.mp4 rename to DevelopmentAssets/Media/portrait_test_video.mp4 diff --git a/UnitTests/Resources/Media/test_animated_image.gif b/DevelopmentAssets/Media/test_animated_image.gif similarity index 100% rename from UnitTests/Resources/Media/test_animated_image.gif rename to DevelopmentAssets/Media/test_animated_image.gif diff --git a/UnitTests/Resources/Media/test_apple_image.heic b/DevelopmentAssets/Media/test_apple_image.heic similarity index 100% rename from UnitTests/Resources/Media/test_apple_image.heic rename to DevelopmentAssets/Media/test_apple_image.heic diff --git a/UnitTests/Resources/Media/test_audio.mp3 b/DevelopmentAssets/Media/test_audio.mp3 similarity index 100% rename from UnitTests/Resources/Media/test_audio.mp3 rename to DevelopmentAssets/Media/test_audio.mp3 diff --git a/UnitTests/Resources/Media/test_image.png b/DevelopmentAssets/Media/test_image.png similarity index 100% rename from UnitTests/Resources/Media/test_image.png rename to DevelopmentAssets/Media/test_image.png diff --git a/UnitTests/Resources/Media/test_pdf.pdf b/DevelopmentAssets/Media/test_pdf.pdf similarity index 100% rename from UnitTests/Resources/Media/test_pdf.pdf rename to DevelopmentAssets/Media/test_pdf.pdf diff --git a/UnitTests/Resources/Media/test_rotated_image.jpg b/DevelopmentAssets/Media/test_rotated_image.jpg similarity index 100% rename from UnitTests/Resources/Media/test_rotated_image.jpg rename to DevelopmentAssets/Media/test_rotated_image.jpg diff --git a/UnitTests/Resources/Media/test_voice_message.m4a b/DevelopmentAssets/Media/test_voice_message.m4a similarity index 100% rename from UnitTests/Resources/Media/test_voice_message.m4a rename to DevelopmentAssets/Media/test_voice_message.m4a diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 954e7e75c3..b40ed15747 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ /* Begin PBXBuildFile section */ 0033481EE363E4914295F188 /* LocalizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C070FD43DC6BF4E50217965A /* LocalizationTests.swift */; }; 00C3023B6DF55024D8876B76 /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 3D8BEEFCA07BEA43F4F4BF77 /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 01373C1AC4839604C4FDA404 /* test_apple_image.heic in Resources */ = {isa = PBXBuildFile; fileRef = BB576F4118C35E6B5124FA22 /* test_apple_image.heic */; }; 01681E8B20AD6F0D237F2DC1 /* IdentityConfirmedScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C6624240FFD32B7F0834229 /* IdentityConfirmedScreenViewModel.swift */; }; 0180C44B997EDA8D21F883AC /* RoomNotificationSettingsCustomSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B746EFA112532A7B701FB914 /* RoomNotificationSettingsCustomSectionView.swift */; }; 01B63F1A04A276B39AC17014 /* CallInviteRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9A3D3CFA199FA7897364547 /* CallInviteRoomTimelineItem.swift */; }; @@ -102,12 +103,14 @@ 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 */; }; 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 */; }; 13CBC470FB619A6393A21908 /* RoomNotificationSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8296D6FB451E25CEC0767BBA /* RoomNotificationSettingsScreenCoordinator.swift */; }; 14343C2F9AD2BFEA92CA28FF /* MapTilerStyleBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7AE92E7BFF71797BDE1D261 /* MapTilerStyleBuilder.swift */; }; 1471A080552631358D152C18 /* AudioPlayerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BDB3E65A79779EDA5D33D8A /* AudioPlayerState.swift */; }; + 147597951DB07123A87AA1D1 /* landscape_test_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 96CE9D6642DD487D8CC90C9C /* landscape_test_image.jpg */; }; 149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */; }; 14E99D27628B1A6F0CB46FEA /* SeparatorRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */; }; 151D2477F75782C8702F2873 /* PollInteractionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC528B3764E3CF7FCFEF40E7 /* PollInteractionHandler.swift */; }; @@ -126,6 +129,7 @@ 1795EA6A6C4942CAE0459DF0 /* SecureBackupKeyBackupScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82B612853BFB68373249777B /* SecureBackupKeyBackupScreenViewModel.swift */; }; 17BC15DA08A52587466698C5 /* RoomMessageEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */; }; 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 */; }; @@ -142,6 +146,7 @@ 1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */; }; 1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */; }; 1B2F9F368619FFF8C63C87CC /* BugReportScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EECE8B331CD169790EF284F /* BugReportScreenViewModelTests.swift */; }; + 1B5B30839656AE2F957C6B1E /* test_pdf.pdf in Resources */ = {isa = PBXBuildFile; fileRef = BE98688578F8B0541D853695 /* test_pdf.pdf */; }; 1B88BB631F7FC45A213BB554 /* TimelineItemSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */; }; 1B8E30B35BF8F541C1318F19 /* SecureBackupScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40316EFFEAC7B206EE9A55AE /* SecureBackupScreenViewModelTests.swift */; }; 1BA04D05EBC6646958B1BE60 /* PlaceholderScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF34A2FD6797535C95AC918D /* PlaceholderScreenCoordinator.swift */; }; @@ -163,7 +168,6 @@ 211B5F524E851178EE549417 /* CurrentValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */; }; 21813AF91CFC6F3E3896DB53 /* AppLockSetupBiometricsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10F130DF775CE6BC51A4E392 /* AppLockSetupBiometricsScreenModels.swift */; }; 21AFEFB8CEFE56A3811A1F5B /* VoiceMessageCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 283974987DA7EC61D2AB57D9 /* VoiceMessageCacheTests.swift */; }; - 21BF2B7CEDFE3CA67C5355AD /* test_image.png in Resources */ = {isa = PBXBuildFile; fileRef = C733D11B421CFE3A657EF230 /* test_image.png */; }; 21F29351EDD7B2A5534EE862 /* SecureBackupKeyBackupScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD558A898847C179E4B7A237 /* SecureBackupKeyBackupScreen.swift */; }; 22882C710BC99EC34A5024A0 /* UITestsScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */; }; 22C5483D01EEB290B8339817 /* HomeScreenInviteCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FC33C3F6BF597E095CE9FA /* HomeScreenInviteCell.swift */; }; @@ -206,6 +210,7 @@ 29EE1791E0AFA1ABB7F23D2F /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 3853B78FB8531B83936C5DA6 /* SwiftState */; }; 2A864BB12A8501B47805D828 /* AuthenticationFlowCoordinatorUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 295E28C3B9EAADF519BF2F44 /* AuthenticationFlowCoordinatorUITests.swift */; }; 2AAB2A77F1762A2648078A30 /* InteractiveQuickLook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */; }; + 2AB9D4146C8748CF1D007B67 /* test_pdf.pdf in Resources */ = {isa = PBXBuildFile; fileRef = BE98688578F8B0541D853695 /* test_pdf.pdf */; }; 2ABF11717C64054CEF2819A3 /* RoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */; }; 2AED12987603157C32C2114D /* TimelineBubbleLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */; }; 2B97BCE72D86645F1485C976 /* RoomDirectorySearchMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 894EE8F5B399A165BA2A6634 /* RoomDirectorySearchMock.swift */; }; @@ -240,7 +245,6 @@ 3113065AABBC14CEAE6843FA /* UserSessionFlowCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8774CF614849664B5B3C2A1 /* UserSessionFlowCoordinatorStateMachine.swift */; }; 3116693C5EB476E028990416 /* XCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74611A4182DCF5F4D42696EC /* XCTestCase.swift */; }; 3118D9ABFD4BE5A3492FF88A /* ElementCallConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC437C491EA6996513B1CEAB /* ElementCallConfiguration.swift */; }; - 31A27DD23C8637A0EBA76AFB /* test_rotated_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 7229371D48BE92239D852C1B /* test_rotated_image.jpg */; }; 32B7891D937377A59606EDFC /* UserFlowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8599815136EFF5B73F38 /* UserFlowTests.swift */; }; 339BC18777912E1989F2F17D /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584A61D9C459FAFEF038A7C0 /* Section.swift */; }; 33CAC1226DFB8B5D8447D286 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; }; @@ -249,7 +253,6 @@ 34357B287357BC0B9715DD51 /* UserAgentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */; }; 34433A509DFEC93579B3B35B /* AdvancedSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C18CC37B97E77838609CFFE7 /* AdvancedSettingsScreen.swift */; }; 3467FEE8210D301FF1B77001 /* UserIndicatorControllerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7893780A1FD6E3F38B3E9049 /* UserIndicatorControllerMock.swift */; }; - 3471204F2CC05D4821C35F23 /* landscape_test_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 7A5D2323D7B6BF4913EB7EED /* landscape_test_image.jpg */; }; 34C752A73717C691582DC6C7 /* UnsupportedRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */; }; 34F1261CEF6D6A00D559B520 /* SettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CFD5EB0B0EEA4549FB49784 /* SettingsScreen.swift */; }; 352C439BE0F75E101EF11FB1 /* RoomScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2886615BEBAE33A0AA4D5F8 /* RoomScreenModels.swift */; }; @@ -296,7 +299,6 @@ 3DA57CA0D609A6B37CA1DC2F /* BugReportService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DC38E64A5ED3FDB201029A /* BugReportService.swift */; }; 3DAD62988F072607441CB7A5 /* PollFormScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */; }; 3DAF325D8AE461F7CDB282BD /* StartChatScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6861FE915C7B5466E6962BBA /* StartChatScreen.swift */; }; - 3E23BB48F91485D893D0A429 /* test_animated_image.gif in Resources */ = {isa = PBXBuildFile; fileRef = 9C2BCB402FEB0FA1A54BEF4B /* test_animated_image.gif */; }; 3E7B65C2C97748D5D65AAA8B /* NotificationPermissionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB2FC2AA9A07EE792DF65CF /* NotificationPermissionsScreenModels.swift */; }; 3EC5A41F9FB7DD63A4DC6144 /* RoomChangeRolesScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B14B1DE3E2D5D26732C49036 /* RoomChangeRolesScreenViewModel.swift */; }; 3EC698F80DDEEFA273857841 /* ArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 893777A4997BBDB68079D4F5 /* ArrayTests.swift */; }; @@ -316,6 +318,7 @@ 4219391CD2351E410554B3E8 /* AggregratedReaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B858A61F2A570DFB8DE570A7 /* AggregratedReaction.swift */; }; 422E8D182CA688D4565CD1E1 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B21E611DADDEF00307E7AC /* String.swift */; }; 4295E5F850897710A51AE114 /* GeoURI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190EC7285D3CFEF0D3011BCF /* GeoURI.swift */; }; + 42995EA68E194B19DAD6AEEF /* test_rotated_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 723B055A57857BFF0F18D9CB /* test_rotated_image.jpg */; }; 42A5A42ACF063EEE6B1980D2 /* ReportContentScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81B17B1F29448D1B9049B11C /* ReportContentScreenViewModel.swift */; }; 42B084FDE621FBEE433AF444 /* LegalInformationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4176C3E20C772DE8D182863C /* LegalInformationScreen.swift */; }; 42F1C8731166633E35A6D7E6 /* RoomEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0A307A44F952CD73E63AE31 /* RoomEventStringBuilder.swift */; }; @@ -433,6 +436,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 */; }; + 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 */; }; 5D52925FEB1B780C65B0529F /* PinnedEventsTimelineScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA4F6D7000EDCD187E0989E7 /* PinnedEventsTimelineScreen.swift */; }; @@ -507,8 +511,8 @@ 6AD722DD92E465E56D2885AB /* BugReportScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA919F521E9F0EE3638AFC85 /* BugReportScreen.swift */; }; 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 */; }; 6BAD956B909A6E29F6CC6E7C /* ButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */; }; - 6BB6944443C421C722ED1E7D /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */; }; 6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */; }; 6C98153D60FF9B648C166C27 /* TimelineItemMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */; }; 6CD61FAF03E8986523C2ABB8 /* StartChatScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3005886F00029F058DB62BE /* StartChatScreenCoordinator.swift */; }; @@ -592,6 +596,7 @@ 7BD2123144A32F082CECC108 /* AudioRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2EAFFD44F81F86012D6EC27 /* AudioRoomTimelineView.swift */; }; 7BF368A78E6D9AFD222F25AF /* SecureBackupScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE094FCB6387D268C436161 /* SecureBackupScreenViewModel.swift */; }; 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 */; }; 7C6376192F578E0BA801BFEC /* AnalyticsSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */; }; 7CD16990BA843BE9ED639129 /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DFE4453AB0B34C203447162 /* ImageRoomTimelineItem.swift */; }; @@ -600,6 +605,7 @@ 7D58B4F46CAA9A7C3E4C6A30 /* UserDetailsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88410BD213FDF9B28E8B671F /* UserDetailsEditScreen.swift */; }; 7D6DC832DE7A3DE874E2E9BC /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = BB111AE9D390233CDD2C7FD5 /* MatrixRustSDK */; }; 7E2BB42805C59DB57E95610F /* PillView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7773CBFDBD458E0B7E270507 /* PillView.swift */; }; + 7E43FBB918AAC136034F2758 /* test_image.png in Resources */ = {isa = PBXBuildFile; fileRef = 810133CF215075C285FC6F3A /* test_image.png */; }; 7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */; }; 7ECF12D5DCD69F67BD3E3842 /* RoomTimelineControllerFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */; }; 7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; }; @@ -629,7 +635,6 @@ 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 */; }; - 858276B19C7C0AD4CA98EA78 /* portrait_test_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = AF042B0FB2EE88977C91E330 /* portrait_test_image.jpg */; }; 8587A53DE8EF94FD796DC375 /* RoomAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEF5FE93A06F563B477F024A /* RoomAvatarImage.swift */; }; 859E2CA2EDF343BD24DE52EB /* RoomDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */; }; 85F89F3F320F4FADCFFFE68B /* ServerSelectionScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3059CFA00C67D8787273B20 /* ServerSelectionScreenViewModel.swift */; }; @@ -647,7 +652,6 @@ 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 */; }; - 87CEDB8A0696F0D5AE2ABB28 /* test_audio.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = D5E26C54362206BBDD096D83 /* test_audio.mp3 */; }; 8810A2A30A68252EBB54EE05 /* HomeScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BC7CA1BC1041E93077BBA1 /* HomeScreenModels.swift */; }; 88356DE7F2AD243AB10C7B7A /* Signposter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */; }; 887AC93C523AEFB640EA5EC8 /* TextBasedRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E33FD32BBC44D703C7AE4F9 /* TextBasedRoomTimelineItem.swift */; }; @@ -688,6 +692,7 @@ 8E7A902CA16E24928F83646C /* ElementCallServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E321E840DCC63790049984F4 /* ElementCallServiceMock.swift */; }; 8ED8AF57A06F5EE9978ED23F /* AuthenticationStartScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FB89DC7F9A4A91020037001 /* AuthenticationStartScreenViewModelTests.swift */; }; 8F2FAA98457750D9D664136F /* Mapbox in Frameworks */ = {isa = PBXBuildFile; productRef = C1BF15833233CD3BDB7E2B1D /* Mapbox */; }; + 8F3AD08F2E706AA60F1A1D4D /* portrait_test_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = BC51BF90469412ABDE658CDD /* portrait_test_image.jpg */; }; 904F06C9C1AEF884C2077542 /* RoomDirectorySearchScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */; }; 90733645AE76FB33DAD28C2B /* URLSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE40D4A5DD857AC16EED945A /* URLSession.swift */; }; 90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; }; @@ -758,7 +763,6 @@ 9E838A62918E47BC72D6640D /* UserIndicatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AB54B4F94686CCF0289B72F /* UserIndicatorPresenter.swift */; }; 9EBDC79CAC9B63A0D626E333 /* LegalInformationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EB2CAA266B921D128C35710 /* LegalInformationScreenCoordinator.swift */; }; 9EE71509E6E7519A2B2388B3 /* KnockRequestsListScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD9C9A31D9AB3B6D8128E69 /* KnockRequestsListScreenModels.swift */; }; - 9EF9773DBE3F6497A25CE236 /* test_apple_image.heic in Resources */ = {isa = PBXBuildFile; fileRef = F6B676B4866F5B383DE819B2 /* test_apple_image.heic */; }; 9F11B9F347F9E2D236799FB3 /* ElementCallServiceConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 406C90AF8C3E98DF5D4E5430 /* ElementCallServiceConstants.swift */; }; 9F11E743EA01482E78A438B0 /* GlobalSearchScreenCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DB19219E6CC4D002E15D48 /* GlobalSearchScreenCell.swift */; }; 9F19096BFA629C0AC282B1E4 /* CreateRoomScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CEB4634C0DD7779C4AB504 /* CreateRoomScreenUITests.swift */; }; @@ -773,6 +777,7 @@ A0D7E5BD0298A97DCBDCE40B /* Emojibase in Frameworks */ = {isa = PBXBuildFile; productRef = C05729B1684C331F5FFE9232 /* Emojibase */; }; A10D6CCDE2010C09EEA1A593 /* HomeScreenRoomList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7661EFFCAA307A97D71132A /* HomeScreenRoomList.swift */; }; A14A9419105A1CD42F0511C4 /* UserIndicatorModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43005941B3A2C9671E23C85 /* UserIndicatorModalView.swift */; }; + A1672EF491FE6F3BBF7878BE /* test_apple_image.heic in Resources */ = {isa = PBXBuildFile; fileRef = BB576F4118C35E6B5124FA22 /* test_apple_image.heic */; }; A17FAD2EBC53E17B5FD384DB /* InviteUsersScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22730A30C50AC2E3D5BA8642 /* InviteUsersScreenViewModelProtocol.swift */; }; A1BA8D6BABAFA9BAAEAA3FFD /* NotificationSettingsProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDD775CFD72DD2D3C8A8390 /* NotificationSettingsProxyProtocol.swift */; }; A1DF0E1E526A981ED6D5DF44 /* UserIndicatorControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2429224EB0EEA34D35CE9249 /* UserIndicatorControllerTests.swift */; }; @@ -848,6 +853,7 @@ B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */; }; B188D0907A4D38AAAF6FEFA8 /* AppLockSetupFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DBB08A95EFA668F2CF27211 /* AppLockSetupFlowCoordinator.swift */; }; B1B255CE0E4306DD6E09D936 /* EncryptionResetPasswordScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54A5E6F398C269AD52C9AE21 /* EncryptionResetPasswordScreenModels.swift */; }; + B20484642B41C2D76238BAAA /* test_animated_image.gif in Resources */ = {isa = PBXBuildFile; fileRef = 53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */; }; B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */; }; B245583C63F8F90357B87FAE /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = A2AE110B053B55E38F8D10C7 /* KZFileWatchers */; }; B272E5D1DE8BDA87A6B7A696 /* RoomTimelineProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */; }; @@ -874,6 +880,7 @@ B79E8AB83EBBDCD476D0362F /* PollFormScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D622EC7898469BB1D0881CDD /* PollFormScreen.swift */; }; B7C9E07F4F9CCC8DD7156A20 /* CallScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28146817C61423CACCF942F5 /* CallScreenModels.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 */; }; B89990DD875B0B603D4D4332 /* NotificationItemProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B927CF5EF7FCCDA5EDC474B /* NotificationItemProxyProtocol.swift */; }; B8EC8A544162B0A41B9AB339 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC3F82523D6F48B926D6AF68 /* AppSettings.swift */; }; @@ -939,6 +946,7 @@ C7774720A4B2E34693E3227C /* RoomNotificationSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8896CDD20CA2D87EA3B848A1 /* RoomNotificationSettingsScreen.swift */; }; C7ABEBECDC513F7887DACF66 /* ProgressMaskModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68010886142843705E342645 /* ProgressMaskModifier.swift */; }; C7B07EBA0F12B5912DA9BB97 /* UserIdentitySDKMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8DE9D0D480D087D0F676B52 /* UserIdentitySDKMock.swift */; }; + C7F20DBF873CC72FB482E326 /* test_rotated_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 723B055A57857BFF0F18D9CB /* test_rotated_image.jpg */; }; C80E06ED97CE52704A46C148 /* ClientBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1C33355FFB0F0953C35036 /* ClientBuilder.swift */; }; C85C7A201E4CFDA477ACEBEB /* AppLockSetupSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8610C1D21565C950BCA6A454 /* AppLockSetupSettingsScreenViewModelProtocol.swift */; }; C8A9C595038AFA2D707AC8C1 /* NotificationPermissionsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E69F67D2A70ABD08CA6D54 /* NotificationPermissionsScreenViewModelProtocol.swift */; }; @@ -961,7 +969,6 @@ CB6BCBF28E4B76EA08C2926D /* StateRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B16048D30F0438731C41F775 /* StateRoomTimelineItem.swift */; }; CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */; }; CBA9EDF305036039166E76FF /* StartChatScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2AEC1AB349A341FE13DEC1 /* StartChatScreenUITests.swift */; }; - CBB4F39A1309F7281AE7AA8E /* test_voice_message.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */; }; CBD2ABE4C1A47ECD99E1488E /* NotificationSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 421FA93BCC2840E66E4F306F /* NotificationSettingsScreenViewModelProtocol.swift */; }; CC0D088F505F33A20DC5590F /* RoomStateEventStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */; }; CC1C948F67A5510A340FD7F0 /* SessionDirectoriesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0825EAFD47332DD459DE893F /* SessionDirectoriesTests.swift */; }; @@ -988,7 +995,6 @@ D12F440F7973F1489F61389D /* NotificationSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */; }; D181AC8FF236B7F91C0A8C28 /* MapTiler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23AA3F4B285570805CB0CCDD /* MapTiler.swift */; }; D19A748E95E2FAB2940570F0 /* CallScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4103AB4340F2974D690A12A /* CallScreen.swift */; }; - D1EEF0CB0F5D9C15E224E670 /* landscape_test_video.mov in Resources */ = {isa = PBXBuildFile; fileRef = 9A2AC7BE17C05CF7D2A22338 /* landscape_test_video.mov */; }; D2048FD56760BDABA3DB5FC2 /* AppLockServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */; }; D22345698F6548C1EE960940 /* IdentityConfirmedScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */; }; D26093BB80B69092B0E9AC7C /* PinnedItemsIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E66763BD54A3A1D9C6E6F2F1 /* PinnedItemsIndicatorView.swift */; }; @@ -1018,6 +1024,7 @@ D8459AAD6969B1431ECBE990 /* UnsupportedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9E535B3388755B65C34CD10 /* UnsupportedRoomTimelineView.swift */; }; D8CFA0EE46376F9FF04EEE45 /* TextRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4853C923A1AF43711D025EAF /* TextRoomTimelineView.swift */; }; D8F1462EA00AFC939FF9ACCA /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 203D1ACC20287F8986C959D3 /* target.yml */; }; + D97C782FE0005995C36FA04A /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = E5E7D4EE7CA295E5039FDA21 /* portrait_test_video.mp4 */; }; D98B5EE8C4F5A2CE84687AE8 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; }; D9F80CE61BF8FF627FDB0543 /* LoadableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352359663A0E52BA20761EE /* LoadableImage.swift */; }; DA7E867F5EAFF8E20B2EE3B6 /* SecureBackupScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3D16709ADD4F4BCC710B1E /* SecureBackupScreenModels.swift */; }; @@ -1036,6 +1043,7 @@ DEDBD3E9CFCC9F20CAC79881 /* JoinRoomScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 136F80A613B55BDD071DCEA5 /* JoinRoomScreenModels.swift */; }; DF004A5B2EABBD0574D06A04 /* SplashScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 854BCEAF2A832176FAACD2CB /* SplashScreenCoordinator.swift */; }; DF05F9C9D3D977EB77E13692 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 385D4C28F9DC5CF53BD9ECDB /* DeviceKit */; }; + DF40CDBEFE1D02B5F9C4ACB1 /* test_image.png in Resources */ = {isa = PBXBuildFile; fileRef = 810133CF215075C285FC6F3A /* test_image.png */; }; DF504B10A4918F971A57BEF2 /* PostHogAnalyticsClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1715E3D7F53C0748AA50C91C /* PostHogAnalyticsClient.swift */; }; DF8F1211F2B0B56F0FCCA5C2 /* CertificateValidatorHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3865AD7B7249C939D7C69C33 /* CertificateValidatorHook.swift */; }; DFCA89C4EC2A5332ED6B441F /* DataProtectionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4959CECEC984B3995616F427 /* DataProtectionManager.swift */; }; @@ -1074,7 +1082,6 @@ E67418DACEDBC29E988E6ACD /* message.caf in Resources */ = {isa = PBXBuildFile; fileRef = ED482057AE39D5C6D9C5F3D8 /* message.caf */; }; E6FA87F773424B27614B23E9 /* TimelineItemAccessibilityModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA7E93C2E148B96EF6A8500 /* TimelineItemAccessibilityModifier.swift */; }; E75CE800B3E64D0F7F8E228D /* TemplateScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C08E9043618AE5B0BF7B07E1 /* TemplateScreenViewModelTests.swift */; }; - E77469C5CD7F7F58C0AC9752 /* test_pdf.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 3FFDA99C98BE05F43A92343B /* test_pdf.pdf */; }; E77FE06B165A38BF1735509F /* SecureBackupScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF73F49E6B6683F7E2D26F0 /* SecureBackupScreenCoordinator.swift */; }; E78D429F18071545BF661A52 /* RoomDetailsEditScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */; }; E794AB6ABE1FF5AF0573FEA1 /* BlurHashEncode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */; }; @@ -1131,6 +1138,7 @@ F118DD449066E594F63C697D /* RoomMemberProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B5E17028C02DFA7DDA3931 /* RoomMemberProxyProtocol.swift */; }; F12F6BED7B6D7EE4BEE55039 /* PlainMentionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AE78FA0011E07920AE83135 /* PlainMentionBuilder.swift */; }; F18CA61A58C77C84F551B8E7 /* GeneratedMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57916A1578D8043BB0795441 /* GeneratedMocks.swift */; }; + F252C0EA49088801F4CA6006 /* landscape_test_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 96CE9D6642DD487D8CC90C9C /* landscape_test_image.jpg */; }; F253AAB4C8F06208173C9C4A /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; F255083E18CDBFDF7E640FB1 /* Avatars.swift in Sources */ = {isa = PBXBuildFile; fileRef = C142248014E08E885E323E56 /* Avatars.swift */; }; F2D5C0E1351DA7BD16867629 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD4823EAB4B4E8BAB4F6B8C /* TimelineStyle.swift */; }; @@ -1141,8 +1149,10 @@ F3F38062C6CA21CF403C5C90 /* AudioConverterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2757B1BE23DF8AA239937243 /* AudioConverterProtocol.swift */; }; F3F9D61C53C348043D3D6F51 /* EncryptionResetScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 811E8BF34E931D51552C9C13 /* EncryptionResetScreen.swift */; }; F40B097470D3110DFDB1FAAA /* LegalInformationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */; }; + F4582042AA4225CC1E4B8A1E /* landscape_test_video.mov in Resources */ = {isa = PBXBuildFile; fileRef = 78BBDF7A05CF53B5CDC13682 /* landscape_test_video.mov */; }; F4996C82A4B3A5FF0C8EDD03 /* RoomListFilterModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E06AAD6D9D3F5833E7A5A2F9 /* RoomListFilterModels.swift */; }; F4C005F006FC3657B9F0A31D /* BugReportHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25586C0ADB814FEE9897DCAA /* BugReportHook.swift */; }; + F4D5A2A8304ED61621BF02D4 /* test_audio.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */; }; F519DE17A3A0F760307B2E6D /* InviteUsersScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D155E09BF961BBA8F85263 /* InviteUsersScreenViewModel.swift */; }; F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E60332509665C00179ACF6 /* MessageForwardingScreenViewModel.swift */; }; F5D2270B5021D521C0D22E11 /* FlowCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.swift */; }; @@ -1185,6 +1195,7 @@ 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 */; }; + 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 */; }; FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF1593DD87F974F8509BB619 /* ElementAnimations.swift */; }; @@ -1284,7 +1295,6 @@ 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; 0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = ""; }; - 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = ""; }; 044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = ""; }; @@ -1569,7 +1579,6 @@ 3E9E0929CEFA356090BE5FB8 /* RoomMembersListScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModelTests.swift; sourceTree = ""; }; 3EF1AC723C2609C7705569CA /* MediaLoaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaLoaderTests.swift; sourceTree = ""; }; 3F54FA7C5CB7B342EF9B9B2F /* NoticeRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineView.swift; sourceTree = ""; }; - 3FFDA99C98BE05F43A92343B /* test_pdf.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = test_pdf.pdf; sourceTree = ""; }; 40076C770A5FB83325252973 /* VoiceMessageMediaManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageMediaManager.swift; sourceTree = ""; }; 40316EFFEAC7B206EE9A55AE /* SecureBackupScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenViewModelTests.swift; sourceTree = ""; }; 406C90AF8C3E98DF5D4E5430 /* ElementCallServiceConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallServiceConstants.swift; sourceTree = ""; }; @@ -1670,6 +1679,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 = ""; }; + 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 = ""; }; 5484457C81B325660901B161 /* AppLockSetupSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupSettingsScreen.swift; sourceTree = ""; }; @@ -1745,6 +1755,7 @@ 667DD3A9D932D7D9EB380CAA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sk; path = sk.lproj/Localizable.stringsdict; sourceTree = ""; }; 669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadingPreprocessor.swift; sourceTree = ""; }; 66AFD800AF033D8B0D11191A /* UserPropertiesExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPropertiesExt.swift; sourceTree = ""; }; + 66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = test_audio.mp3; sourceTree = ""; }; 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = ""; }; 66F91544AC136BF6477BDAB8 /* TimelineDeliveryStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineDeliveryStatusView.swift; sourceTree = ""; }; 671C338B7259DC5774816885 /* AuthenticationServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceTests.swift; sourceTree = ""; }; @@ -1789,7 +1800,7 @@ 71BC7CA1BC1041E93077BBA1 /* HomeScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenModels.swift; sourceTree = ""; }; 71D52BAA5BADB06E5E8C295D /* Assets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Assets.swift; sourceTree = ""; }; 71E2E5103702D13361D09100 /* UserProfileScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileScreenViewModelTests.swift; sourceTree = ""; }; - 7229371D48BE92239D852C1B /* test_rotated_image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = test_rotated_image.jpg; sourceTree = ""; }; + 723B055A57857BFF0F18D9CB /* test_rotated_image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = test_rotated_image.jpg; sourceTree = ""; }; 72614BFF35B8394C6E13F55A /* TimelineItemStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemStatusView.swift; sourceTree = ""; }; 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilderProtocol.swift; sourceTree = ""; }; 7310D8DFE01AF45F0689C3AA /* Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Publisher.swift; sourceTree = ""; }; @@ -1812,10 +1823,10 @@ 78910787F967CBC6042A101E /* StartChatScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenViewModelProtocol.swift; sourceTree = ""; }; 78913D6E120D46138E97C107 /* NavigationSplitCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSplitCoordinatorTests.swift; sourceTree = ""; }; 7893780A1FD6E3F38B3E9049 /* UserIndicatorControllerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerMock.swift; sourceTree = ""; }; + 78BBDF7A05CF53B5CDC13682 /* landscape_test_video.mov */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; path = landscape_test_video.mov; sourceTree = ""; }; 796CBD0C56FA0D3AEDAB255B /* SessionVerificationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenCoordinator.swift; sourceTree = ""; }; 79FAC366FF299BCC555D756E /* ElementWellKnown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementWellKnown.swift; sourceTree = ""; }; 7A03E073077D92AA19C43DCF /* IdentityConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenCoordinator.swift; sourceTree = ""; }; - 7A5D2323D7B6BF4913EB7EED /* landscape_test_image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = landscape_test_image.jpg; sourceTree = ""; }; 7AAD8C633AA57948B34EDCF7 /* RoomChangeRolesScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModelProtocol.swift; sourceTree = ""; }; 7AC0CD1CAFD3F8B057F9AEA5 /* ClientBuilderHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientBuilderHook.swift; sourceTree = ""; }; 7AE094FCB6387D268C436161 /* SecureBackupScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenViewModel.swift; sourceTree = ""; }; @@ -1845,6 +1856,7 @@ 7FDF541AE914059942B575B4 /* IdentityConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenModels.swift; sourceTree = ""; }; 8063E65441E771200108C558 /* ReadReceiptsSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadReceiptsSummaryView.swift; sourceTree = ""; }; 80E815FF3CC5E5A355E3A25E /* RoomMessageEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageEventStringBuilder.swift; sourceTree = ""; }; + 810133CF215075C285FC6F3A /* test_image.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = test_image.png; sourceTree = ""; }; 8112846C9D9D3817689CBAF8 /* TimelineTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableViewController.swift; sourceTree = ""; }; 811E8BF34E931D51552C9C13 /* EncryptionResetScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreen.swift; sourceTree = ""; }; 8140010A796DB2C7977B6643 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = ""; }; @@ -1948,6 +1960,7 @@ 95BAC0F6C9644336E9567EE6 /* NSRegularExpresion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSRegularExpresion.swift; sourceTree = ""; }; 969694F67E844FCA51F7E051 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/InfoPlist.strings; sourceTree = ""; }; 96C4762F8D6112E43117DB2F /* CustomStringConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomStringConvertible.swift; sourceTree = ""; }; + 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 = ""; }; 9780389F8A53E4D26E23DD03 /* LoginScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1963,7 +1976,6 @@ 9A028783CFFF861C5E44FFB1 /* BadgeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeLabel.swift; sourceTree = ""; }; 9A1C33355FFB0F0953C35036 /* ClientBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientBuilder.swift; sourceTree = ""; }; 9A22A05E472533ED3C5A31B3 /* NavigationModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationModule.swift; sourceTree = ""; }; - 9A2AC7BE17C05CF7D2A22338 /* landscape_test_video.mov */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; path = landscape_test_video.mov; sourceTree = ""; }; 9A68BCE6438873D2661D93D0 /* BugReportServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportServiceProtocol.swift; sourceTree = ""; }; 9AA3AF94A06D319BB37E52DA /* TimelineItemFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemFactoryTests.swift; sourceTree = ""; }; 9B06663F7858E45882E63471 /* StaticLocationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLocationScreen.swift; sourceTree = ""; }; @@ -1971,7 +1983,6 @@ 9B663BE498BB39EADC24025D /* SettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenModels.swift; sourceTree = ""; }; 9B67DF223EEB8DCAF178A1D4 /* AnalyticsPromptScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenCoordinator.swift; sourceTree = ""; }; 9B7D8D3638864B7482E148CC /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = ""; }; - 9C2BCB402FEB0FA1A54BEF4B /* test_animated_image.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = test_animated_image.gif; sourceTree = ""; }; 9C3ACC093F88FD9888518561 /* AuthenticationStartScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModel.swift; sourceTree = ""; }; 9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestMeasurementParser.swift; sourceTree = ""; }; 9C5E81214D27A6B898FC397D /* ElementX.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ElementX.entitlements; sourceTree = ""; }; @@ -2061,7 +2072,6 @@ AE5DDBEBBA17973ED4638823 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Localizable.stringsdict; 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 = ""; }; - AF042B0FB2EE88977C91E330 /* portrait_test_image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = portrait_test_image.jpg; sourceTree = ""; }; AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilderTests.swift; sourceTree = ""; }; AF848B41DAF1066F3054D4A1 /* SessionVerificationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenModels.swift; sourceTree = ""; }; AF8548D48512127CCC17C520 /* PollRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollRoomTimelineView.swift; sourceTree = ""; }; @@ -2119,15 +2129,18 @@ BA40B98B098B6F0371B750B3 /* TemplateScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenModels.swift; sourceTree = ""; }; BA919F521E9F0EE3638AFC85 /* BugReportScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreen.swift; sourceTree = ""; }; BB284643AF7AB131E307DCE0 /* AudioSessionProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioSessionProtocol.swift; sourceTree = ""; }; + BB576F4118C35E6B5124FA22 /* test_apple_image.heic */ = {isa = PBXFileReference; path = test_apple_image.heic; sourceTree = ""; }; BB5B00A014307CE37B2812CD /* TimelineViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineViewModelProtocol.swift; sourceTree = ""; }; BB8BC4C791D0E88CFCF4E5DF /* ServerSelectionScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenCoordinator.swift; sourceTree = ""; }; BBEC57C204D77908E355EF42 /* AudioRecorderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecorderProtocol.swift; sourceTree = ""; }; + BC51BF90469412ABDE658CDD /* portrait_test_image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = portrait_test_image.jpg; sourceTree = ""; }; BC8AA23D4F37CC26564F63C5 /* LayoutMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutMocks.swift; sourceTree = ""; }; BCDA016D05107DED3B9495CB /* TimelineItemDebugView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemDebugView.swift; sourceTree = ""; }; BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNNotificationContent.swift; sourceTree = ""; }; BE4C76F31A382B8E4DD07583 /* EncryptionResetUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetUITests.swift; sourceTree = ""; }; BE78CAD0B964C66FD06EF83E /* DeactivateAccountScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreenModels.swift; sourceTree = ""; }; BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemReplyDetails.swift; sourceTree = ""; }; + BE98688578F8B0541D853695 /* test_pdf.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = test_pdf.pdf; sourceTree = ""; }; BE9BBB18FB27F09032AD8769 /* NotificationPermissionsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenViewModel.swift; sourceTree = ""; }; BEA38B9851CFCC4D67F5587D /* EmojiPickerScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenCoordinator.swift; sourceTree = ""; }; BEBA759D1347CFFB3D84ED1F /* UserSessionStoreProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionStoreProtocol.swift; sourceTree = ""; }; @@ -2177,7 +2190,6 @@ C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderAvatarImage.swift; sourceTree = ""; }; 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 = ""; }; - C733D11B421CFE3A657EF230 /* test_image.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = test_image.png; sourceTree = ""; }; C75EF87651B00A176AB08E97 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.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 = ""; }; @@ -2242,7 +2254,6 @@ D53FCCE44F96E0BC411A6CF0 /* TimelineSenderAvatarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineSenderAvatarView.swift; sourceTree = ""; }; D54E12B98252F6C527E31FEE /* MediaUploadPreviewScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelProtocol.swift; sourceTree = ""; }; D5B4932E4EFBC8FAC10972CD /* UserProfileScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileScreenCoordinator.swift; sourceTree = ""; }; - D5E26C54362206BBDD096D83 /* test_audio.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = test_audio.mp3; sourceTree = ""; }; D5EA0312A6262484AA393AC9 /* CompletionSuggestionServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionServiceTests.swift; sourceTree = ""; }; D622EC7898469BB1D0881CDD /* PollFormScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreen.swift; sourceTree = ""; }; D653265D006E708E4E51AD64 /* HomeScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenCoordinator.swift; sourceTree = ""; }; @@ -2268,6 +2279,7 @@ DC0AEA686E425F86F6BA0404 /* UNNotification+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNNotification+Creator.swift"; sourceTree = ""; }; DC10CCC8D68B863E20660DBC /* MessageForwardingScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenViewModelProtocol.swift; sourceTree = ""; }; DC528B3764E3CF7FCFEF40E7 /* PollInteractionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollInteractionHandler.swift; sourceTree = ""; }; + 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 = ""; }; DD97F9661ABF08CE002054A2 /* AppLockServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceTests.swift; sourceTree = ""; }; @@ -2304,6 +2316,7 @@ E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashDecode.swift; sourceTree = ""; }; E53BFB7E4F329621C844E8C3 /* AnalyticsPromptScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreen.swift; sourceTree = ""; }; E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsProxyProtocol.swift; sourceTree = ""; }; + E5E7D4EE7CA295E5039FDA21 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerProtocol.swift; sourceTree = ""; }; E5F2B6443D1ED8602F328539 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = ""; }; E60757AFE04391B43EA568B8 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -2368,7 +2381,6 @@ F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = ""; }; - F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = ""; }; F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = ""; }; F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = ""; }; @@ -2386,7 +2398,6 @@ F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineBubbleLayout.swift; sourceTree = ""; }; F5E23D8EE6CBACF32F1EC874 /* MediaPlayerProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProviderProtocol.swift; sourceTree = ""; }; F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModel.swift; sourceTree = ""; }; - F6B676B4866F5B383DE819B2 /* test_apple_image.heic */ = {isa = PBXFileReference; path = test_apple_image.heic; sourceTree = ""; }; F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = ""; }; F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockUITests.swift; sourceTree = ""; }; F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderMock.swift; sourceTree = ""; }; @@ -3331,6 +3342,7 @@ C0FAC17D4DD7D3A502822550 /* UITests */, 8A9C09B6A392465E03B8D1B1 /* IntegrationTests */, 823ED0EC3F1B6CF47D284011 /* Tools */, + A8002CB4F20B6282850A614C /* DevelopmentAssets */, B04B538A859CD012755DC19C /* NSE */, 1803CD2B96BF06009334BB61 /* PreviewTests */, D0111119CDF3E28E6D7768E8 /* ShareExtension */, @@ -4794,7 +4806,6 @@ A4852B57D55D71EEBFCD931D /* UnitTests */ = { isa = PBXGroup; children = ( - E600AACDF87CDBCE32683236 /* Resources */, 73CD9796729EB702B4DFA88C /* Sources */, 24FD174C31912A5FACFEAFB5 /* SupportingFiles */, ); @@ -4847,6 +4858,14 @@ path = View; sourceTree = ""; }; + A8002CB4F20B6282850A614C /* DevelopmentAssets */ = { + isa = PBXGroup; + children = ( + DDAF2AD15C368A2809857B6A /* Media */, + ); + path = DevelopmentAssets; + sourceTree = ""; + }; AAFDD509929A0CCF8BCE51EB /* Authentication */ = { isa = PBXGroup; children = ( @@ -4876,24 +4895,6 @@ path = View; sourceTree = ""; }; - ACF39CFC617601C942702CDC /* Media */ = { - isa = PBXGroup; - children = ( - 7A5D2323D7B6BF4913EB7EED /* landscape_test_image.jpg */, - 9A2AC7BE17C05CF7D2A22338 /* landscape_test_video.mov */, - AF042B0FB2EE88977C91E330 /* portrait_test_image.jpg */, - F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */, - 9C2BCB402FEB0FA1A54BEF4B /* test_animated_image.gif */, - F6B676B4866F5B383DE819B2 /* test_apple_image.heic */, - D5E26C54362206BBDD096D83 /* test_audio.mp3 */, - C733D11B421CFE3A657EF230 /* test_image.png */, - 3FFDA99C98BE05F43A92343B /* test_pdf.pdf */, - 7229371D48BE92239D852C1B /* test_rotated_image.jpg */, - 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */, - ); - path = Media; - sourceTree = ""; - }; AD5FCF9340D670C526AD17E4 /* UI */ = { isa = PBXGroup; children = ( @@ -5366,6 +5367,24 @@ path = View; sourceTree = ""; }; + DDAF2AD15C368A2809857B6A /* Media */ = { + isa = PBXGroup; + children = ( + 96CE9D6642DD487D8CC90C9C /* landscape_test_image.jpg */, + 78BBDF7A05CF53B5CDC13682 /* landscape_test_video.mov */, + BC51BF90469412ABDE658CDD /* portrait_test_image.jpg */, + E5E7D4EE7CA295E5039FDA21 /* portrait_test_video.mp4 */, + 53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */, + BB576F4118C35E6B5124FA22 /* test_apple_image.heic */, + 66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */, + 810133CF215075C285FC6F3A /* test_image.png */, + BE98688578F8B0541D853695 /* test_pdf.pdf */, + 723B055A57857BFF0F18D9CB /* test_rotated_image.jpg */, + DCA2D836BD10303F37FAAEED /* test_voice_message.m4a */, + ); + path = Media; + sourceTree = ""; + }; DDC32FD8B94AA19C4FC062AD /* View */ = { isa = PBXGroup; children = ( @@ -5474,14 +5493,6 @@ path = SDK; sourceTree = ""; }; - E600AACDF87CDBCE32683236 /* Resources */ = { - isa = PBXGroup; - children = ( - ACF39CFC617601C942702CDC /* Media */, - ); - path = Resources; - sourceTree = ""; - }; E68740F873AB18A5C26844EA /* Sources */ = { isa = PBXGroup; children = ( @@ -6114,8 +6125,19 @@ 5FCD8AFA364206EE32B909A3 /* Settings.bundle in Resources */, CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */, 2797C9D9BA642370F1C85D78 /* Untranslated.stringsdict 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 */, DFF7D6A6C26DDD40D00AE579 /* target.yml in Resources */, + 18978C9438206828C1D5AF2A /* test_animated_image.gif in Resources */, + 01373C1AC4839604C4FDA404 /* test_apple_image.heic in Resources */, + 6B61F5B27412ED4BC2F9769C /* test_audio.mp3 in Resources */, + DF40CDBEFE1D02B5F9C4ACB1 /* test_image.png in Resources */, + 2AB9D4146C8748CF1D007B67 /* test_pdf.pdf in Resources */, + C7F20DBF873CC72FB482E326 /* test_rotated_image.jpg in Resources */, + 7C164A642E8932B5F9004550 /* test_voice_message.m4a in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6148,18 +6170,18 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3471204F2CC05D4821C35F23 /* landscape_test_image.jpg in Resources */, - D1EEF0CB0F5D9C15E224E670 /* landscape_test_video.mov in Resources */, - 858276B19C7C0AD4CA98EA78 /* portrait_test_image.jpg in Resources */, - 6BB6944443C421C722ED1E7D /* portrait_test_video.mp4 in Resources */, + F252C0EA49088801F4CA6006 /* landscape_test_image.jpg in Resources */, + F4582042AA4225CC1E4B8A1E /* landscape_test_video.mov in Resources */, + 8F3AD08F2E706AA60F1A1D4D /* portrait_test_image.jpg in Resources */, + D97C782FE0005995C36FA04A /* portrait_test_video.mp4 in Resources */, 35E975CFDA60E05362A7CF79 /* target.yml in Resources */, - 3E23BB48F91485D893D0A429 /* test_animated_image.gif in Resources */, - 9EF9773DBE3F6497A25CE236 /* test_apple_image.heic in Resources */, - 87CEDB8A0696F0D5AE2ABB28 /* test_audio.mp3 in Resources */, - 21BF2B7CEDFE3CA67C5355AD /* test_image.png in Resources */, - E77469C5CD7F7F58C0AC9752 /* test_pdf.pdf in Resources */, - 31A27DD23C8637A0EBA76AFB /* test_rotated_image.jpg in Resources */, - CBB4F39A1309F7281AE7AA8E /* test_voice_message.m4a in Resources */, + B20484642B41C2D76238BAAA /* test_animated_image.gif in Resources */, + A1672EF491FE6F3BBF7878BE /* test_apple_image.heic in Resources */, + F4D5A2A8304ED61621BF02D4 /* test_audio.mp3 in Resources */, + 7E43FBB918AAC136034F2758 /* test_image.png in Resources */, + 1B5B30839656AE2F957C6B1E /* test_pdf.pdf in Resources */, + 42995EA68E194B19DAD6AEEF /* test_rotated_image.jpg in Resources */, + B855AF29D7D8FC8DAAA73D4A /* test_voice_message.m4a in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -7655,6 +7677,7 @@ CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CURRENT_PROJECT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + DEVELOPMENT_ASSET_PATHS = DevelopmentAssets/Media; DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)"; INFOPLIST_FILE = ElementX/SupportingFiles/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -7683,6 +7706,7 @@ CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CURRENT_PROJECT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + DEVELOPMENT_ASSET_PATHS = DevelopmentAssets/Media; DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)"; INFOPLIST_FILE = ElementX/SupportingFiles/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml index 6d21c2ffd7..bb92ccae3d 100644 --- a/ElementX/SupportingFiles/target.yml +++ b/ElementX/SupportingFiles/target.yml @@ -124,6 +124,7 @@ targets: SWIFT_OBJC_BRIDGING_HEADER: ElementX/SupportingFiles/ElementX-Bridging-Header.h SWIFT_OBJC_INTERFACE_HEADER_NAME: GeneratedInterface-Swift.h PILLS_UT_TYPE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER).pills + DEVELOPMENT_ASSET_PATHS: DevelopmentAssets/Media OTHER_SWIFT_FLAGS: - "-DIS_MAIN_APP" @@ -227,3 +228,4 @@ targets: - path: ../Resources - path: ../SupportingFiles - path: ../../Tools/Scripts/Templates/SimpleScreenExample/ElementX + - path: ../../DevelopmentAssets/Media diff --git a/UnitTests/SupportingFiles/target.yml b/UnitTests/SupportingFiles/target.yml index 957f321bf1..553041fe9c 100644 --- a/UnitTests/SupportingFiles/target.yml +++ b/UnitTests/SupportingFiles/target.yml @@ -48,4 +48,4 @@ targets: - path: ../SupportingFiles - path: ../../ElementX/Sources/Other/InfoPlistReader.swift - path: ../../Tools/Scripts/Templates/SimpleScreenExample/Tests/Unit - - path: ../Resources + - path: ../../DevelopmentAssets From c8627cfd641f8794cac6b4f387ec95a601d43915 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Fri, 29 Nov 2024 12:26:59 +0000 Subject: [PATCH 66/74] Add support for copying a caption. (#3563) * Add timeline item action for copying a media caption. * Fix the action colours when long pressing a timeline item. Nice side effect: Reasonable sized buttons when button shapes are enabled. * Re-arrange the Timeline Item Menu. * Add timeline item menu snapshots for media items. --- .../en.lproj/Localizable.strings | 3 + ElementX/Sources/Generated/Strings.swift | 6 + .../SwiftUI/Layout/MenuSheetLabelStyle.swift | 32 ++++- .../View/RoomAttachmentPicker.swift | 6 - .../Timeline/TimelineInteractionHandler.swift | 15 +-- .../ItemMenu/TimelineItemMacContextMenu.swift | 2 +- .../View/ItemMenu/TimelineItemMenu.swift | 87 +++++++++---- .../ItemMenu/TimelineItemMenuAction.swift | 24 ++-- .../TimelineItemMenuActionProvider.swift | 100 +++++++++------ .../Fixtures/RoomTimelineItemFixtures.swift | 121 ++++++++++++++---- ...ventBasedMessageTimelineItemProtocol.swift | 16 ++- .../EventBasedTimelineItemProtocol.swift | 10 ++ ...melineItemMenu-iPad-en-GB.Authenticity.png | 4 +- ...elineItemMenu-iPad-en-GB.Button-shapes.png | 4 +- ...neItemMenu-iPad-en-GB.Identity-Changed.png | 4 +- ...ItemMenu-iPad-en-GB.Media-with-Caption.png | 3 + ...test_timelineItemMenu-iPad-en-GB.Media.png | 3 + ...est_timelineItemMenu-iPad-en-GB.Normal.png | 4 +- ...emMenu-iPad-en-GB.Own-Unsigned-Devices.png | 4 +- ...imelineItemMenu-iPad-en-GB.Unencrypted.png | 4 +- ...ineItemMenu-iPad-en-GB.Unknown-failure.png | 4 +- ...neItemMenu-iPad-en-GB.Unsigned-Devices.png | 4 +- ...t_timelineItemMenu-iPad-en-GB.Unsigned.png | 4 +- ...elineItemMenu-iPad-pseudo.Authenticity.png | 4 +- ...lineItemMenu-iPad-pseudo.Button-shapes.png | 4 +- ...eItemMenu-iPad-pseudo.Identity-Changed.png | 4 +- ...temMenu-iPad-pseudo.Media-with-Caption.png | 3 + ...est_timelineItemMenu-iPad-pseudo.Media.png | 3 + ...st_timelineItemMenu-iPad-pseudo.Normal.png | 4 +- ...mMenu-iPad-pseudo.Own-Unsigned-Devices.png | 4 +- ...melineItemMenu-iPad-pseudo.Unencrypted.png | 4 +- ...neItemMenu-iPad-pseudo.Unknown-failure.png | 4 +- ...eItemMenu-iPad-pseudo.Unsigned-Devices.png | 4 +- ..._timelineItemMenu-iPad-pseudo.Unsigned.png | 4 +- ...eItemMenu-iPhone-16-en-GB.Authenticity.png | 4 +- ...ItemMenu-iPhone-16-en-GB.Button-shapes.png | 4 +- ...mMenu-iPhone-16-en-GB.Identity-Changed.png | 4 +- ...enu-iPhone-16-en-GB.Media-with-Caption.png | 3 + ...timelineItemMenu-iPhone-16-en-GB.Media.png | 3 + ...imelineItemMenu-iPhone-16-en-GB.Normal.png | 4 +- ...u-iPhone-16-en-GB.Own-Unsigned-Devices.png | 4 +- ...neItemMenu-iPhone-16-en-GB.Unencrypted.png | 4 +- ...emMenu-iPhone-16-en-GB.Unknown-failure.png | 4 +- ...mMenu-iPhone-16-en-GB.Unsigned-Devices.png | 4 +- ...elineItemMenu-iPhone-16-en-GB.Unsigned.png | 4 +- ...ItemMenu-iPhone-16-pseudo.Authenticity.png | 4 +- ...temMenu-iPhone-16-pseudo.Button-shapes.png | 4 +- ...Menu-iPhone-16-pseudo.Identity-Changed.png | 4 +- ...nu-iPhone-16-pseudo.Media-with-Caption.png | 3 + ...imelineItemMenu-iPhone-16-pseudo.Media.png | 3 + ...melineItemMenu-iPhone-16-pseudo.Normal.png | 4 +- ...-iPhone-16-pseudo.Own-Unsigned-Devices.png | 4 +- ...eItemMenu-iPhone-16-pseudo.Unencrypted.png | 4 +- ...mMenu-iPhone-16-pseudo.Unknown-failure.png | 4 +- ...Menu-iPhone-16-pseudo.Unsigned-Devices.png | 4 +- ...lineItemMenu-iPhone-16-pseudo.Unsigned.png | 4 +- 56 files changed, 396 insertions(+), 194 deletions(-) create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media-with-Caption.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media-with-Caption.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media-with-Caption.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media-with-Caption.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media.png diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 85fac299a8..f81ac7c6dc 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Confirm password"; "action_continue" = "Continue"; "action_copy" = "Copy"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Copy link"; "action_copy_link_to_message" = "Copy link to message"; +"action_copy_text" = "Copy text"; "action_create" = "Create"; "action_create_a_room" = "Create a room"; "action_deactivate" = "Deactivate"; @@ -84,6 +86,7 @@ "action_reject" = "Reject"; "action_remove" = "Remove"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Reply"; "action_reply_in_thread" = "Reply in thread"; "action_report_bug" = "Report bug"; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index db23287898..36ae30edda 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -104,10 +104,14 @@ internal enum L10n { internal static var actionContinue: String { return L10n.tr("Localizable", "action_continue") } /// Copy internal static var actionCopy: String { return L10n.tr("Localizable", "action_copy") } + /// Copy caption + internal static var actionCopyCaption: String { return L10n.tr("Localizable", "action_copy_caption") } /// Copy link internal static var actionCopyLink: String { return L10n.tr("Localizable", "action_copy_link") } /// Copy link to message internal static var actionCopyLinkToMessage: String { return L10n.tr("Localizable", "action_copy_link_to_message") } + /// Copy text + internal static var actionCopyText: String { return L10n.tr("Localizable", "action_copy_text") } /// Create internal static var actionCreate: String { return L10n.tr("Localizable", "action_create") } /// Create a room @@ -204,6 +208,8 @@ internal enum L10n { internal static var actionRemove: String { return L10n.tr("Localizable", "action_remove") } /// Remove caption internal static var actionRemoveCaption: String { return L10n.tr("Localizable", "action_remove_caption") } + /// Remove message + internal static var actionRemoveMessage: String { return L10n.tr("Localizable", "action_remove_message") } /// Reply internal static var actionReply: String { return L10n.tr("Localizable", "action_reply") } /// Reply in thread diff --git a/ElementX/Sources/Other/SwiftUI/Layout/MenuSheetLabelStyle.swift b/ElementX/Sources/Other/SwiftUI/Layout/MenuSheetLabelStyle.swift index 0ea17f68e4..12f701be93 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/MenuSheetLabelStyle.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/MenuSheetLabelStyle.swift @@ -7,14 +7,34 @@ import SwiftUI -extension LabelStyle where Self == MenuSheetLabelStyle { - /// A label style for labels that are within a menu that is being presented as a sheet. - static var menuSheet: Self { MenuSheetLabelStyle() } +extension ButtonStyle where Self == MenuSheetButtonStyle { + /// A button style for buttons that are within a menu that is being presented as a sheet. + static var menuSheet: Self { MenuSheetButtonStyle() } } -/// The style used for labels that are part of a menu that's presented as -/// a sheet as `TimelineItemMenu` and `RoomAttachmentPicker`. -struct MenuSheetLabelStyle: LabelStyle { +/// The style used for buttons that are part of a menu that's presented as +/// a sheet such as `TimelineItemMenu`. +struct MenuSheetButtonStyle: ButtonStyle { + @Environment(\.accessibilityShowButtonShapes) private var accessibilityShowButtonShapes + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .labelStyle(MenuSheetLabelStyle()) + .foregroundStyle(configuration.role == .destructive ? .compound.textCriticalPrimary : .compound.textActionPrimary) + .contentShape(.rect) + .opacity(configuration.isPressed ? 0.3 : 1) + .background { + if accessibilityShowButtonShapes { + RoundedRectangle(cornerRadius: 12) + .fill(Color(uiColor: .secondarySystemFill)) + .opacity(configuration.isPressed ? 0.8 : 1) + .padding(4) + } + } + } +} + +private struct MenuSheetLabelStyle: LabelStyle { var spacing: CGFloat = 16 func makeBody(configuration: Configuration) -> some View { diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift index 0732bd15f8..b789445a71 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift @@ -32,7 +32,6 @@ struct RoomAttachmentPicker: View { context.send(viewAction: .enableTextFormatting) } label: { Label(L10n.screenRoomAttachmentTextFormatting, icon: \.textFormatting) - .labelStyle(.menuSheet) } .accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerTextFormatting) @@ -40,7 +39,6 @@ struct RoomAttachmentPicker: View { context.send(viewAction: .attach(.poll)) } label: { Label(L10n.screenRoomAttachmentSourcePoll, icon: \.polls) - .labelStyle(.menuSheet) } .accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerPoll) @@ -48,7 +46,6 @@ struct RoomAttachmentPicker: View { context.send(viewAction: .attach(.location)) } label: { Label(L10n.screenRoomAttachmentSourceLocation, icon: \.locationPin) - .labelStyle(.menuSheet) } .accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerLocation) @@ -56,7 +53,6 @@ struct RoomAttachmentPicker: View { context.send(viewAction: .attach(.file)) } label: { Label(L10n.screenRoomAttachmentSourceFiles, icon: \.attachment) - .labelStyle(.menuSheet) } .accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerDocuments) @@ -64,7 +60,6 @@ struct RoomAttachmentPicker: View { context.send(viewAction: .attach(.photoLibrary)) } label: { Label(L10n.screenRoomAttachmentSourceGallery, icon: \.image) - .labelStyle(.menuSheet) } .accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerPhotoLibrary) @@ -72,7 +67,6 @@ struct RoomAttachmentPicker: View { context.send(viewAction: .attach(.camera)) } label: { Label(L10n.screenRoomAttachmentSourceCamera, icon: \.takePhoto) - .labelStyle(.menuSheet) } .accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerCamera) } diff --git a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift index c7d004df1e..2e610569ca 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineInteractionHandler.swift @@ -102,7 +102,13 @@ class TimelineInteractionHandler { case .copy: guard let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol else { return } UIPasteboard.general.string = messageTimelineItem.body - case .edit: + case .copyCaption: + guard let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol, + let caption = messageTimelineItem.mediaCaption else { + return + } + UIPasteboard.general.string = caption + case .edit, .addCaption, .editCaption, .editPoll: switch timelineItem { case let messageTimelineItem as EventBasedMessageTimelineItemProtocol: processEditMessageEvent(messageTimelineItem) @@ -115,13 +121,6 @@ class TimelineInteractionHandler { default: MXLog.error("Cannot edit item with id: \(timelineItem.id)") } - case .addCaption, .editCaption: - switch timelineItem { - case let messageTimelineItem as EventBasedMessageTimelineItemProtocol: - processEditMessageEvent(messageTimelineItem) - default: - MXLog.error("Cannot add/edit caption on item with id: \(timelineItem.id)") - } case .removeCaption: guard case let .event(_, eventOrTransactionID) = timelineItem.id else { MXLog.error("Failed removing caption, missing event ID") diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMacContextMenu.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMacContextMenu.swift index f97ae80116..8cb4264d49 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMacContextMenu.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMacContextMenu.swift @@ -51,7 +51,7 @@ struct TimelineItemMacContextMenu: View { } Section { - ForEach(menuActions.debugActions) { action in + ForEach(menuActions.secondaryActions) { action in Button(role: action.isDestructive ? .destructive : nil) { send(action) } label: { diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift index 43e7144ac7..e7448035cb 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenu.swift @@ -47,7 +47,7 @@ struct TimelineItemMenu: View { .background(Color.compound.bgSubtlePrimary) } - viewsForActions(actions.debugActions) + viewsForActions(actions.secondaryActions) } } } @@ -179,8 +179,8 @@ struct TimelineItemMenu: View { send(action) } label: { action.label - .labelStyle(.menuSheet) } + .buttonStyle(.menuSheet) } } @@ -261,21 +261,28 @@ private extension View { // MARK: - Previews struct TimelineItemMenu_Previews: PreviewProvider, TestablePreview { + enum ItemType { case incomingText, outgoingMedia, outgoingMediaWithCaption } + static let viewModel = TimelineViewModel.mock - static let (item, actions) = makeItem() - static let (backupItem, _) = makeItem(authenticity: .notGuaranteed(color: .gray)) - static let (unsignedItem, _) = makeItem(authenticity: .unsignedDevice(color: .red)) - static let (unencryptedItem, _) = makeItem(authenticity: .sentInClear(color: .red)) - static let (unknownFailureItem, _) = makeItem(deliveryStatus: .sendingFailed(.unknown)) - static let (identityChangedItem, _) = makeItem(deliveryStatus: .sendingFailed(.verifiedUser(.changedIdentity(users: [ + static let (item, actions) = makeActions() + static let (backupItem, _) = makeActions(authenticity: .notGuaranteed(color: .gray)) + static let (unsignedItem, _) = makeActions(authenticity: .unsignedDevice(color: .red)) + static let (unencryptedItem, _) = makeActions(authenticity: .sentInClear(color: .red)) + static let (unknownFailureItem, _) = makeActions(deliveryStatus: .sendingFailed(.unknown)) + static let (identityChangedItem, _) = makeActions(deliveryStatus: .sendingFailed(.verifiedUser(.changedIdentity(users: [ "@alice:matrix.org" ])))) - static let (unsignedDevicesItem, _) = makeItem(deliveryStatus: .sendingFailed(.verifiedUser(.hasUnsignedDevice(devices: [ + static let (unsignedDevicesItem, _) = makeActions(deliveryStatus: .sendingFailed(.verifiedUser(.hasUnsignedDevice(devices: [ "@alice:matrix.org": ["DEVICE1", "DEVICE2"] ])))) - static let (ownUnsignedDevicesItem, _) = makeItem(deliveryStatus: .sendingFailed(.verifiedUser(.hasUnsignedDevice(devices: [ + static let (ownUnsignedDevicesItem, _) = makeActions(deliveryStatus: .sendingFailed(.verifiedUser(.hasUnsignedDevice(devices: [ RoomMemberProxyMock.mockMe.userID: ["DEVICE1"] ])))) + + // Media + + static let (mediaItem, mediaItemActions) = makeActions(itemType: .outgoingMedia) + static let (mediaItemWithCaption, mediaItemWithCaptionActions) = makeActions(itemType: .outgoingMediaWithCaption) static var previews: some View { TimelineItemMenu(item: item, actions: actions) @@ -314,26 +321,56 @@ struct TimelineItemMenu_Previews: PreviewProvider, TestablePreview { TimelineItemMenu(item: identityChangedItem, actions: actions) .environmentObject(viewModel.context) .previewDisplayName("Identity Changed") + + // Media + + TimelineItemMenu(item: mediaItem, actions: mediaItemActions) + .environmentObject(viewModel.context) + .previewDisplayName("Media") + + TimelineItemMenu(item: mediaItemWithCaption, actions: mediaItemWithCaptionActions) + .environmentObject(viewModel.context) + .previewDisplayName("Media with Caption") } - static func makeItem(authenticity: EncryptionAuthenticity? = nil, - deliveryStatus: TimelineItemDeliveryStatus? = nil) -> (TextRoomTimelineItem, TimelineItemMenuActions)! { - guard var item = RoomTimelineItemFixtures.singleMessageChunk.first as? TextRoomTimelineItem, - let actions = TimelineItemMenuActions(isReactable: true, - actions: [.copy, .edit, .reply(isThread: false), .pin, .redact], - debugActions: [.viewSource], - emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) else { - return nil - } + static func makeActions(itemType: ItemType = .incomingText, + authenticity: EncryptionAuthenticity? = nil, + deliveryStatus: TimelineItemDeliveryStatus? = nil) -> (EventBasedTimelineItemProtocol, TimelineItemMenuActions)! { + guard var item = makeItem(itemType: itemType) else { return nil } + let provider = TimelineItemMenuActionProvider(timelineItem: item, + canCurrentUserRedactSelf: true, + canCurrentUserRedactOthers: false, + canCurrentUserPin: true, + pinnedEventIDs: [], + isDM: true, + isViewSourceEnabled: true, + isCreateMediaCaptionsEnabled: true, + isPinnedEventsTimeline: false, + emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) + guard let actions = provider.makeActions() else { return nil } - if let authenticity { - item.properties.encryptionAuthenticity = authenticity - } - - if let deliveryStatus { - item.properties.deliveryStatus = deliveryStatus + if var textItem = item as? TextRoomTimelineItem { + if let authenticity { + textItem.properties.encryptionAuthenticity = authenticity + } + + if let deliveryStatus { + textItem.properties.deliveryStatus = deliveryStatus + } + item = textItem } return (item, actions) } + + static func makeItem(itemType: ItemType) -> EventBasedTimelineItemProtocol? { + switch itemType { + case .incomingText: + RoomTimelineItemFixtures.singleMessageChunk.first as? EventBasedTimelineItemProtocol + case .outgoingMedia: + RoomTimelineItemFixtures.mediaChunk[1] as? EventBasedTimelineItemProtocol + case .outgoingMediaWithCaption: + RoomTimelineItemFixtures.mediaChunk[5] as? EventBasedTimelineItemProtocol + } + } } diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift index 38f8246225..3a0e88b792 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuAction.swift @@ -13,18 +13,18 @@ import SwiftUI struct TimelineItemMenuActions { let reactions: [TimelineItemMenuReaction] let actions: [TimelineItemMenuAction] - let debugActions: [TimelineItemMenuAction] + let secondaryActions: [TimelineItemMenuAction] init?(isReactable: Bool, actions: [TimelineItemMenuAction], - debugActions: [TimelineItemMenuAction], + secondaryActions: [TimelineItemMenuAction], emojiProvider: EmojiProviderProtocol) { - if !isReactable, actions.isEmpty, debugActions.isEmpty { + if !isReactable, actions.isEmpty, secondaryActions.isEmpty { return nil } self.actions = actions - self.debugActions = debugActions + self.secondaryActions = secondaryActions var frequentlyUsed: OrderedSet = [ .init(key: "👍️", symbol: .handThumbsup), @@ -56,10 +56,12 @@ struct TimelineItemMenuReaction: Hashable { enum TimelineItemMenuAction: Identifiable, Hashable { case copy + case copyCaption case edit case addCaption case editCaption case removeCaption + case editPoll case copyPermalink case redact case reply(isThread: Bool) @@ -79,7 +81,7 @@ enum TimelineItemMenuAction: Identifiable, Hashable { /// Whether the item should cancel a reply/edit occurring in the composer. var switchToDefaultComposer: Bool { switch self { - case .reply, .edit, .addCaption, .editCaption: + case .reply, .edit, .addCaption, .editCaption, .editPoll: return false default: return true @@ -89,7 +91,7 @@ enum TimelineItemMenuAction: Identifiable, Hashable { /// Whether the action should be shown for an item that failed to send. var canAppearInFailedEcho: Bool { switch self { - case .copy, .edit, .redact, .viewSource: + case .copy, .edit, .redact, .viewSource, .editPoll: return true default: return false @@ -130,7 +132,9 @@ enum TimelineItemMenuAction: Identifiable, Hashable { var label: some View { switch self { case .copy: - Label(L10n.actionCopy, icon: \.copy) + Label(L10n.actionCopyText, icon: \.copy) + case .copyCaption: + Label(L10n.actionCopyCaption, icon: \.copy) case .edit: Label(L10n.actionEdit, icon: \.edit) case .addCaption: @@ -138,7 +142,9 @@ enum TimelineItemMenuAction: Identifiable, Hashable { case .editCaption: Label(L10n.actionEditCaption, icon: \.edit) case .removeCaption: - Label(L10n.actionRemoveCaption, icon: \.delete) + Label(L10n.actionRemoveCaption, icon: \.close) + case .editPoll: + Label(L10n.actionEditPoll, icon: \.edit) case .copyPermalink: Label(L10n.actionCopyLinkToMessage, icon: \.link) case .reply(let isThread): @@ -146,7 +152,7 @@ enum TimelineItemMenuAction: Identifiable, Hashable { case .forward: Label(L10n.actionForward, icon: \.forward) case .redact: - Label(L10n.actionRemove, icon: \.delete) + Label(L10n.actionRemoveMessage, icon: \.delete) case .viewSource: Label(L10n.actionViewSource, icon: \.code) case .retryDecryption: diff --git a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift index cad18009e4..4d624fb3f7 100644 --- a/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift +++ b/ElementX/Sources/Screens/Timeline/View/ItemMenu/TimelineItemMenuActionProvider.swift @@ -32,26 +32,12 @@ struct TimelineItemMenuActionProvider { return nil } - var debugActions: [TimelineItemMenuAction] = [] - if isViewSourceEnabled { - debugActions.append(.viewSource) - } - if let encryptedItem = timelineItem as? EncryptedRoomTimelineItem { - switch encryptedItem.encryptionType { - case .megolmV1AesSha2(let sessionID, _): - debugActions.append(.retryDecryption(sessionID: sessionID)) - default: - break - } - - return .init(isReactable: false, - actions: [.copyPermalink], - debugActions: debugActions, - emojiProvider: emojiProvider) + return makeEncryptedItemActions(encryptedItem) } var actions: [TimelineItemMenuAction] = [] + var secondaryActions: [TimelineItemMenuAction] = [] if item.canBeRepliedTo { if let messageItem = item as? EventBasedMessageTimelineItemProtocol { @@ -64,59 +50,95 @@ struct TimelineItemMenuActionProvider { if item.isForwardable { 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 let messageItem = item as? EventBasedMessageTimelineItemProtocol, messageItem.supportsMediaCaption { - if messageItem.hasMediaCaption { - actions.append(contentsOf: [.editCaption, .removeCaption]) + if item.supportsMediaCaption { + if item.hasMediaCaption { + actions.append(.editCaption) } else if isCreateMediaCaptionsEnabled { actions.append(.addCaption) } + } else if item is PollRoomTimelineItem { + actions.append(.editPoll) } else if !(item is VoiceMessageRoomTimelineItem) { actions.append(.edit) } } - - if canCurrentUserPin, let eventID = item.id.eventID { - actions.append(pinnedEventIDs.contains(eventID) ? .unpin : .pin) - } if item.isCopyable { actions.append(.copy) + } else if item.hasMediaCaption { + actions.append(.copyCaption) } - if item.isRemoteMessage { - actions.append(.copyPermalink) + if 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 canRedactItem(item) { - actions.append(.redact) + if isViewSourceEnabled { + actions.append(.viewSource) } - + if !item.isOutgoing { - actions.append(.report) + secondaryActions.append(.report) } - - if item.hasFailedToSend { - actions = actions.filter(\.canAppearInFailedEcho) - } - - if item.isRedacted { - actions = actions.filter(\.canAppearInRedacted) + + if canRedactItem(item) { + secondaryActions.append(.redact) } if isPinnedEventsTimeline { actions.insert(.viewInRoomTimeline, at: 0) actions = actions.filter(\.canAppearInPinnedEventsTimeline) + secondaryActions = secondaryActions.filter(\.canAppearInPinnedEventsTimeline) + } + + if item.hasFailedToSend { + actions = actions.filter(\.canAppearInFailedEcho) + secondaryActions = secondaryActions.filter(\.canAppearInFailedEcho) + } + + if item.isRedacted { + actions = actions.filter(\.canAppearInRedacted) + secondaryActions = secondaryActions.filter(\.canAppearInRedacted) } return .init(isReactable: isPinnedEventsTimeline ? false : item.isReactable, actions: actions, - debugActions: debugActions, + 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, emojiProvider: emojiProvider) } diff --git a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift index da67a49fcc..716849af32 100644 --- a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift +++ b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift @@ -250,28 +250,16 @@ enum RoomTimelineItemFixtures { static var mediaChunk: [RoomTimelineItemProtocol] { [ - VideoRoomTimelineItem(id: .randomEvent, - timestamp: "10:47 am", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: ""), - content: .init(filename: "video.mp4", - videoInfo: .mockVideo, - thumbnailInfo: .mockThumbnail, - blurhash: "KtI~70X5V?yss9oyrYs:t6")), - ImageRoomTimelineItem(id: .randomEvent, - timestamp: "10:47 am", - isOutgoing: false, - isEditable: false, - canBeRepliedTo: true, - isThreaded: false, - sender: .init(id: ""), - content: .init(filename: "image.jpg", - imageInfo: .mockImage, - thumbnailInfo: nil, - blurhash: "KpE4oyayR5|GbHb];3j@of")) + AudioRoomTimelineItem(isOutgoing: false, caption: "Listen to this!"), + AudioRoomTimelineItem(isOutgoing: true), + FileRoomTimelineItem(isOutgoing: false), + FileRoomTimelineItem(isOutgoing: true, caption: "Please check this ASAP!"), + ImageRoomTimelineItem(isOutgoing: false), + ImageRoomTimelineItem(isOutgoing: true, caption: "Isn't this pretty!"), + VideoRoomTimelineItem(isOutgoing: false, caption: "Woah, it was incredible!"), + VideoRoomTimelineItem(isOutgoing: true), + VoiceMessageRoomTimelineItem(isOutgoing: false), + VoiceMessageRoomTimelineItem(isOutgoing: true) ] } } @@ -294,3 +282,92 @@ private extension TextRoomTimelineItem { return newSelf } } + +private extension AudioRoomTimelineItem { + init(isOutgoing: Bool, caption: String? = nil) { + self.init(id: .randomEvent, + timestamp: "10:47 am", + isOutgoing: isOutgoing, + isEditable: isOutgoing, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: isOutgoing ? "@alice:matrix.org" : "@bob:matrix.org"), + content: .init(filename: "audio.mp3", + caption: caption, + duration: 60, + waveform: nil, + source: .init(url: .mockMXCAudio, mimeType: nil), + fileSize: nil, + contentType: .mp3)) + } +} + +private extension FileRoomTimelineItem { + init(isOutgoing: Bool, caption: String? = nil) { + self.init(id: .randomEvent, + timestamp: "10:47 am", + isOutgoing: isOutgoing, + isEditable: isOutgoing, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: isOutgoing ? "@alice:matrix.org" : "@bob:matrix.org"), + content: .init(filename: "file.pdf", + caption: caption, + source: .init(url: .mockMXCFile, mimeType: nil), + fileSize: nil, + thumbnailSource: nil, + contentType: .pdf)) + } +} + +private extension ImageRoomTimelineItem { + init(isOutgoing: Bool, caption: String? = nil) { + self.init(id: .randomEvent, + timestamp: "10:47 am", + isOutgoing: isOutgoing, + isEditable: isOutgoing, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: isOutgoing ? "@alice:matrix.org" : "@bob:matrix.org"), + content: .init(filename: "image.jpg", + caption: caption, + imageInfo: .mockImage, + thumbnailInfo: nil, + blurhash: "KpE4oyayR5|GbHb];3j@of")) + } +} + +private extension VideoRoomTimelineItem { + init(isOutgoing: Bool, caption: String? = nil) { + self.init(id: .randomEvent, + timestamp: "10:47 am", + isOutgoing: isOutgoing, + isEditable: isOutgoing, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: isOutgoing ? "@alice:matrix.org" : "@bob:matrix.org"), + content: .init(filename: "video.mp4", + caption: caption, + videoInfo: .mockVideo, + thumbnailInfo: .mockThumbnail, + blurhash: "KtI~70X5V?yss9oyrYs:t6")) + } +} + +private extension VoiceMessageRoomTimelineItem { + init(isOutgoing: Bool) { + self.init(id: .randomEvent, + timestamp: "10:47 am", + isOutgoing: isOutgoing, + isEditable: isOutgoing, + canBeRepliedTo: true, + isThreaded: false, + sender: .init(id: isOutgoing ? "@alice:matrix.org" : "@bob:matrix.org"), + content: .init(filename: "message.ogg", + duration: 10, + waveform: .mockWaveform, + source: .init(url: .mockMXCAudio, mimeType: nil), + fileSize: nil, + contentType: .audio)) + } +} diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift index a0832abf5c..7340377662 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedMessageTimelineItemProtocol.swift @@ -35,18 +35,22 @@ extension EventBasedMessageTimelineItemProtocol { } } - var hasMediaCaption: Bool { + var mediaCaption: String? { switch contentType { case .audio(let content): - content.caption != nil + content.caption case .file(let content): - content.caption != nil + content.caption case .image(let content): - content.caption != nil + content.caption case .video(let content): - content.caption != nil + content.caption case .emote, .notice, .text, .location, .voice: - false + nil } } + + var hasMediaCaption: Bool { + mediaCaption != nil + } } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift index aa99847b79..0150401ff9 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/EventBasedTimelineItemProtocol.swift @@ -99,4 +99,14 @@ extension EventBasedTimelineItemProtocol { return true } } + + var supportsMediaCaption: Bool { + guard let messageBasedItem = self as? EventBasedMessageTimelineItemProtocol else { return false } + return messageBasedItem.supportsMediaCaption + } + + var hasMediaCaption: Bool { + guard let messageBasedItem = self as? EventBasedMessageTimelineItemProtocol else { return false } + return messageBasedItem.hasMediaCaption + } } 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 5614e91256..c93414d20c 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:bcc6fdf7c3f7e40f9beedb8f9779fa74b3c8d7020112398059783ff2820fa4ed -size 135575 +oid sha256:42992a72deec6d6cc0a3268f4619db58fb44ba869b6cca0c9937ee70a0effd7e +size 147883 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 e6e1c3129a..d3a797f89f 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:3e337818f2c9ecd0e7abfe35868857394f3b1129e798354266035b65ed9fe9ee -size 142532 +oid sha256:a0868feab75e9ac054da551d7ebcc17d7cb8e2cfb3c4ab540f5d05753a273aea +size 154967 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 db49f13798..c4a29de515 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:a7ba26595547bdab86bc57097fcccb0062b73c9afcccc5ee2d9481c24a5ee954 -size 134046 +oid sha256:a57163af2dbcb6af527279ee9959aaf4ac5830424b14deede615891b8da411c4 +size 146496 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 new file mode 100644 index 0000000000..d0b6409961 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media-with-Caption.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8dfdb1408f464b7570b1c587e03dec72be0cc02ad28af2475c7f13eabfecfdea +size 143529 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 new file mode 100644 index 0000000000..b34a3b3ca5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-en-GB.Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8bad202aa9c390b47af7d1e35f3e65c731a3f3ae659c943c7f1ae63581590ec +size 133449 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 6dc2b5e65b..839ae5df7d 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:7f1d6997b3ca132dbf486145371ccc38418ee1ccfbb05ebd670f73f621008c48 -size 124084 +oid sha256:ccec869066425d2bcb107a1dae131d0a87bd2f1c8b345edd8fe77edfe3f779a1 +size 136131 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 e1bddfabb3..5cf9b34abd 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:fbf1b0ba7b26a5bf3040ceffbfcca15cf38445fe4db7a39b81b16826517c6762 -size 134605 +oid sha256:e4448552425a8dde78ee792f3915d76721d548d38daa3b59854e56d692b15286 +size 147056 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 214c0a0e7d..5df36e3645 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:bdcb99ed272db7ee82b09574da7e791ee371b35107ca8104a72acd71e99b1156 -size 129013 +oid sha256:b9845682cd8bc72244d05d872a5212735890703a5e65400667986f1d158a991d +size 141448 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 6dc2b5e65b..839ae5df7d 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:7f1d6997b3ca132dbf486145371ccc38418ee1ccfbb05ebd670f73f621008c48 -size 124084 +oid sha256:ccec869066425d2bcb107a1dae131d0a87bd2f1c8b345edd8fe77edfe3f779a1 +size 136131 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 a8350dec89..5c5b13d3ca 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:83ec69d4b69f3a33422b0a472665c65855a365b4f676888edb9eb054ebaf77d4 -size 133818 +oid sha256:b2d5f335b38cdde8f4e5e8c40e7c2c95bee523d353d880e026c7c012c0f86284 +size 146268 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 af16a6b6e3..98d7bb1f03 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:e173a969f56bdfad935308070f5dc1958eaf7781fbcf18e01c81b95799ce3ae1 -size 132960 +oid sha256:5bcb1cf3a950c99e05559cb2cf2162e5b96cbccdebbe42e3b09efa2256a5c53c +size 145195 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 73cb694b0b..fa99fad4f2 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:c5a5a1d65cd3f0c569f2ca1fb80258e8179870acade4a1d68b3e9e67a52d8d29 -size 142541 +oid sha256:75219b465e5332f12fada6b5c507c9ee6c62c409b06167824310cb7dfbb068f7 +size 156450 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 871bdb3e53..50382b6028 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:9fbc2bf481aeecb17f3be814b3bcf7147f2d8d757eb82a15b2a0db10a5ec8f40 -size 144452 +oid sha256:e950f852539eccca04f68060e56787413f90a6c2481df251e8ab315cf5b659d1 +size 158242 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 da7e6a2e88..90a3935d12 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:1eac1d2d29c71d9c332f26b311b50c7ef601896a6941a1f617d200e23bb88731 -size 141641 +oid sha256:065d14de719ede0234e865a45119a2731da20e7982249db240180db9b7dafe71 +size 155522 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 new file mode 100644 index 0000000000..8cbff9be9e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media-with-Caption.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c33873265e2e90314f656d95668da81ab86e7461fea51bfbff083eaea512b52 +size 148202 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media.png new file mode 100644 index 0000000000..e8f58be7fa --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPad-pseudo.Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:001894f533a0619f577647f55a790769d50f5200d4664d027a6b4337e7c8fc25 +size 136972 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 fbbe196d73..883b6c33ac 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:39c0cc82049d6e4c12416c457a087d99b52169ab266da1beaa22888aa933bca5 -size 125934 +oid sha256:a9bd0e980e02351fdcc69c1e2e71c6c579ee9223b671aedbb8b906d82f0a6da6 +size 139535 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 01df243b16..ad09b6c549 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:eac68c72456505eaafd6c94948857aaa2d54accc4990c3dd3cd1cb31023c89bf -size 140645 +oid sha256:e28d69132bf0d7c6e2380916185df3e5bc0bcf858eda4418cbf561e19b0cfa91 +size 154495 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 65f5a2de07..60922e7054 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:150daec2df86269a675887b754f64e067dcdb856dff9d1c8a36e746495745ab8 -size 133199 +oid sha256:b0451dcad4c79972172c171622e32af923db17278bb59d8858ed538ef2e5acb8 +size 146847 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 fbbe196d73..883b6c33ac 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:39c0cc82049d6e4c12416c457a087d99b52169ab266da1beaa22888aa933bca5 -size 125934 +oid sha256:a9bd0e980e02351fdcc69c1e2e71c6c579ee9223b671aedbb8b906d82f0a6da6 +size 139535 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 ebe3d9742a..5db052a2f9 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:a1d61ad248aa93c90b680e51cdf4a30d8cfd9568a062b03b559d6f9d57fffddf -size 140013 +oid sha256:dc893c5f8cfe7a247818288ec6e551ff9ee4c02971cde61d6bb5502f7af139d5 +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 49a10d7bdf..2042c2f77e 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:2c30cb638c2eecebb63ca66a5f0107bb85225aa786cbf32ecbca9974b42cd383 -size 139069 +oid sha256:1d8fb938c99c65f5884636f8806bf3fe9a5de5b6877cf0a2899529df29e30679 +size 152908 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 b3d2bd4605..e2a88dcb56 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:dd17e2229ac0f1c09ef301589f24de7f879364dbc468460d6e387b2393d6b584 -size 88452 +oid sha256:914c77c473286e62ff5fabd0d62ce7bd0a71c0755a8d2e99ceabb102bdd7f7f0 +size 99760 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 c5cf3ce854..3ef2032d0d 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:2e9f207e4656524273989488b2e8f1d9ee2901d500a76b89dbbf01e831a146c7 -size 91341 +oid sha256:6224e94342cbe0303473eb91f16f97e85e67e43ab74be0d6b68868e3a428d1ea +size 103095 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 acee9f6830..8b21398133 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:46f40c81c046bb1593d0ac0d1b396558e75ab4d9a85ce9f460610c623835711a -size 87463 +oid sha256:db0cc945ae881ff0979376ebe01eda05899100557c0778164a0b43f54f8ae6c5 +size 98124 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 new file mode 100644 index 0000000000..494a4efc7e --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media-with-Caption.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:10701f9bcc6d6906d8b1063b145fd754c0af3928e5d5664cb35b1aa4d79aa999 +size 95921 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 new file mode 100644 index 0000000000..50924d695d --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-en-GB.Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01dd4d77411e87302bb5b4b152de7e5eb761c7f4b367a84f36a31fc5e141fa9d +size 87399 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 afc3971093..8010c1fc28 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:b1a6d6103056a883e4fa9344b65766867ef28355f359c428c6f8fc7b8a5b1dd4 -size 78383 +oid sha256:841d4f5f4f5a4e3eac938f2fcd4b0bb94561eebd6179c91cb84816f3ae7df8b8 +size 89445 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 3589187676..26ee5627dd 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:12b9450065c9aa924ac7b833d2c98a8ea011ea3ec470438869f08591590a5576 -size 88346 +oid sha256:6383d2c6351a4833a6ce83a71c6c57c2297d3a8b19c2a818211e21ce61cb7c96 +size 99003 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 fa0bdd2c33..ee8f8bda2f 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:05ae1dfcf89ec7c5329c570e29b876935d261470a6fc074d961452f75e4ab4e3 -size 81155 +oid sha256:b3068613a53a7634432c201ee51c5bd5e066d93a524019ee7f0b7c6b7199842b +size 92207 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 afc3971093..8010c1fc28 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:b1a6d6103056a883e4fa9344b65766867ef28355f359c428c6f8fc7b8a5b1dd4 -size 78383 +oid sha256:841d4f5f4f5a4e3eac938f2fcd4b0bb94561eebd6179c91cb84816f3ae7df8b8 +size 89445 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 b9a00d5ed0..2eb2514307 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:100ebc998da4d0625307771a9fda2dc78becccf2fe0e58cb514967cc26b77e46 -size 86917 +oid sha256:a0dac8094cdadc60b5bf9fb5057b910a51d34598ca207acedac4af329ebe61b3 +size 97569 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 eeb51c7cfa..d84a6afc5e 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:5d2451f6dfdb5d0342c13d9bba95f035610649f5e0c6c026b6b5c02a3f5ea792 -size 84457 +oid sha256:f008b5f6b5015caa5102ee2e3368072b89dc8d369b43d229776b2c4d3a7ec119 +size 95442 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 114f53c75e..87fda90f0a 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:a7e0833f33a5372ac34cb1ffc904b3113c292ddfac1798f2ec49263f72487b8b -size 104147 +oid sha256:2214c2b47d33f7e71ebe4b113d8c57461977d0e5558b4851e54be67bfc613bc1 +size 120917 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 7e06a52bec..964cce30dc 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:9dd681b7005cad7f3172e46704ce15f35348741ab4f61c25c7e25dbc976dd47f -size 96872 +oid sha256:c0ca91f7036a9b588ae5cfaa98df46fad4a0c546a815646bcc93b60f5cc04b96 +size 114129 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 1f8ad9ff39..50d2b28ef6 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:66a515af35f86cc79842515e6f200a8ac9e66393bafa3d08dd73c94b55a0e273 -size 102463 +oid sha256:224c0a2a1a180bb0f769690986615b42670eaeba5da36c136a194a9b649392a4 +size 119359 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 new file mode 100644 index 0000000000..e3bf6ea23a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media-with-Caption.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ff91b2679413fe8a068f82306eeaa78de5db89edacc910443fd03a9200ac42c +size 111302 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 new file mode 100644 index 0000000000..b87398e005 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineItemMenu-iPhone-16-pseudo.Media.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f083235302db13e888d8c1fdd9cf6746acba7c6b25e6066f225514b78963bc7 +size 99585 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 cbf97d5941..31e7b33399 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:f9f354421510618dc4c3ebdd4ed3f6aeb274236bd4d680948127a21737882a35 -size 83970 +oid sha256:28feeb86b0c09df9a9bc37b3523adbd9145c24372ba3f0d1e46e3b7811d56339 +size 100926 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 4d6d50c68f..23c68ebfd9 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:20be265e58a5ce19848a1d9c9221587656efbeb1eefa982bf598021ed91b1976 -size 104759 +oid sha256:68ba46257a66431778c6fd648be80e65bd724f451cc4bbd05a92c8dd6eca3ab3 +size 121585 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 d2ca600aa9..28e552dc35 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:bbcb5ce6d51e66aa74d7ebb6cdaf574a80613cf5cbc2a52285f2db5758a260c8 -size 88609 +oid sha256:4a3212f9f5ccb198f4bb9770ea232b700cf635a0a3d37ecb7b8297c0496c12f4 +size 105456 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 cbf97d5941..31e7b33399 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:f9f354421510618dc4c3ebdd4ed3f6aeb274236bd4d680948127a21737882a35 -size 83970 +oid sha256:28feeb86b0c09df9a9bc37b3523adbd9145c24372ba3f0d1e46e3b7811d56339 +size 100926 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 37099ec4fb..eb0e274347 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:cb4cba6c55ed6d5a399729817e3bbcf0109e940022009ec2b994d744a0e26b9e -size 100765 +oid sha256:9e084c9628684fe7b383b72a2f5906e47f9d65ba2de12a374b728ece3be37c68 +size 117656 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 5f247f2022..80225d3ad1 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:e808c53766810d2cef79e239295f55b151a151cb42a7d7fd24f83ef889964ae1 -size 95987 +oid sha256:ec4a30d3db9d84514c116964209d741a6179b11c0992b0e92e9e98a8d5e050eb +size 112532 From 49a94e0bdb365248df0326cbe6a2b66222a93356 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Fri, 29 Nov 2024 12:42:27 +0000 Subject: [PATCH 67/74] Handle media source validation more gracefully. (#3571) * Handle media source validation more gracefully. * Fix unit tests. --- .../Other/SwiftUI/Views/LoadableImage.swift | 40 ++++++++-------- .../RoomDetailsScreenViewModel.swift | 3 +- .../RoomMemberDetailsScreenViewModel.swift | 3 +- .../UserProfileScreenViewModel.swift | 3 +- .../Media/Provider/MediaSourceProxy.swift | 7 +-- .../Proxy/NotificationItemProxy.swift | 4 +- .../RoomTimelineController.swift | 4 +- .../Services/Timeline/TimelineItemProxy.swift | 42 ++++++++++------- .../RoomTimelineItemFactory.swift | 11 ++--- .../MediaProvider/MediaLoaderTests.swift | 8 ++-- .../MediaProvider/MediaProviderTests.swift | 46 +++++++++---------- .../Sources/VoiceMessageCacheTests.swift | 2 +- .../VoiceMessageMediaManagerTests.swift | 12 ++--- 13 files changed, 95 insertions(+), 90 deletions(-) diff --git a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift index c8702156d3..c34420f7ca 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift @@ -21,7 +21,7 @@ enum LoadableImageMediaType: Equatable { } struct LoadableImage: View { - private let mediaSource: MediaSourceProxy + private let mediaSource: MediaSourceProxy? private let mediaType: LoadableImageMediaType private let blurhash: String? private let size: CGSize? @@ -60,27 +60,31 @@ struct LoadableImage: View { mediaProvider: MediaProviderProtocol?, transformer: @escaping (AnyView) -> TransformerView = { $0 }, placeholder: @escaping () -> PlaceholderView) { - self.init(mediaSource: MediaSourceProxy(url: url, mimeType: nil), - mediaType: mediaType, - blurhash: blurhash, - size: size, - mediaProvider: mediaProvider, - transformer: transformer, - placeholder: placeholder) + mediaSource = try? MediaSourceProxy(url: url, mimeType: nil) + self.mediaType = mediaType + self.blurhash = blurhash + self.size = size + self.mediaProvider = mediaProvider + self.transformer = transformer + self.placeholder = placeholder } var body: some View { - LoadableImageContent(mediaSource: mediaSource, - mediaType: mediaType, - blurhash: blurhash, - size: size, - mediaProvider: mediaProvider, - transformer: transformer, - placeholder: placeholder) - .id(stableMediaIdentifier) + if let mediaSource { + LoadableImageContent(mediaSource: mediaSource, + mediaType: mediaType, + blurhash: blurhash, + size: size, + mediaProvider: mediaProvider, + transformer: transformer, + placeholder: placeholder) + .id(stableMediaIdentifier) + } else { + placeholder() + } } - private var stableMediaIdentifier: String { + private var stableMediaIdentifier: String? { switch mediaType { case .timelineItem(let uniqueID): // Consider media for the same item to be the same view @@ -88,7 +92,7 @@ struct LoadableImage: View { default: // Binds the lifecycle of the LoadableImage to the associated URL. // This fixes the problem of the cache returning old values after a change in the URL. - mediaSource.url.absoluteString + mediaSource?.url.absoluteString } } } diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift index 34a8d8a271..a7a8cbd856 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift @@ -363,7 +363,8 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr } // We don't actually know the mime type here, assume it's an image. - if case let .success(file) = await mediaProvider.loadFileFromSource(.init(url: url, mimeType: "image/jpeg")) { + if let mediaSource = try? MediaSourceProxy(url: url, mimeType: "image/jpeg"), + case let .success(file) = await mediaProvider.loadFileFromSource(mediaSource) { state.bindings.mediaPreviewItem = MediaPreviewItem(file: file, title: roomProxy.infoPublisher.value.displayName) } } diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift index 178183a853..ac550181f6 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift @@ -165,7 +165,8 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro defer { userIndicatorController.retractIndicatorWithId(loadingIndicatorIdentifier) } // We don't actually know the mime type here, assume it's an image. - if case let .success(file) = await mediaProvider.loadFileFromSource(.init(url: url, mimeType: "image/jpeg")) { + if let mediaSource = try? MediaSourceProxy(url: url, mimeType: "image/jpeg"), + case let .success(file) = await mediaProvider.loadFileFromSource(mediaSource) { state.bindings.mediaPreviewItem = MediaPreviewItem(file: file, title: roomMemberProxy.displayName) } } diff --git a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift index 01a0f10337..bbf1f2eff7 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift @@ -104,7 +104,8 @@ class UserProfileScreenViewModel: UserProfileScreenViewModelType, UserProfileScr defer { hideLoadingIndicator() } // We don't actually know the mime type here, assume it's an image. - if case let .success(file) = await mediaProvider.loadFileFromSource(.init(url: url, mimeType: "image/jpeg")) { + if let mediaSource = try? MediaSourceProxy(url: url, mimeType: "image/jpeg"), + case let .success(file) = await mediaProvider.loadFileFromSource(mediaSource) { state.bindings.mediaPreviewItem = MediaPreviewItem(file: file, title: userProfile.displayName) } } diff --git a/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift b/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift index 50023b5626..2f1a85a826 100644 --- a/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift +++ b/ElementX/Sources/Services/Media/Provider/MediaSourceProxy.swift @@ -23,11 +23,8 @@ struct MediaSourceProxy: Hashable { self.mimeType = mimeType } - init(url: URL, mimeType: String?) { - guard let mediaSource = try? MediaSource.fromUrl(url: url.absoluteString) else { - fatalError("Unable to create MediaSource from URL: \(url.absoluteString)") - } - underlyingSource = mediaSource + init(url: URL, mimeType: String?) throws { + underlyingSource = try MediaSource.fromUrl(url: url.absoluteString) self.url = URL(string: underlyingSource.url()) self.mimeType = mimeType } diff --git a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift index 40cbf1e8a9..ab181df3d3 100644 --- a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift +++ b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift @@ -55,7 +55,7 @@ struct NotificationItemProxy: NotificationItemProxyProtocol { var senderAvatarMediaSource: MediaSourceProxy? { if let senderAvatarURLString = notificationItem.senderInfo.avatarUrl, let senderAvatarURL = URL(string: senderAvatarURLString) { - return MediaSourceProxy(url: senderAvatarURL, mimeType: nil) + return try? MediaSourceProxy(url: senderAvatarURL, mimeType: nil) } return nil } @@ -63,7 +63,7 @@ struct NotificationItemProxy: NotificationItemProxyProtocol { var roomAvatarMediaSource: MediaSourceProxy? { if let roomAvatarURLString = notificationItem.roomInfo.avatarUrl, let roomAvatarURL = URL(string: roomAvatarURLString) { - return MediaSourceProxy(url: roomAvatarURL, mimeType: nil) + return try? MediaSourceProxy(url: roomAvatarURL, mimeType: nil) } return nil } diff --git a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift index a9abcd63ff..bdf6a5a6e1 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/RoomTimelineController.swift @@ -195,9 +195,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol { } } - if let avatarURL { - let mediaSource = MediaSourceProxy(url: avatarURL, mimeType: nil) - + if let avatarURL, let mediaSource = try? MediaSourceProxy(url: avatarURL, mimeType: nil) { if case let .success(avatarData) = await mediaProvider.loadThumbnailForSource(source: mediaSource, size: .init(width: 100, height: 100)) { sendMessageIntent.setImage(INImage(imageData: avatarData), forParameterNamed: \.speakableGroupName) } else { diff --git a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift index 776a6c5522..bd024e4967 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift @@ -243,11 +243,15 @@ struct VideoInfoProxy: Hashable { } static var mockVideo: VideoInfoProxy { - .init(source: .init(url: .mockMXCVideo, mimeType: nil), - duration: 100, - size: .init(width: 1920, height: 1080), - aspectRatio: 1.78, - mimeType: nil) + guard let mediaSource = try? MediaSourceProxy(url: .mockMXCVideo, mimeType: nil) else { + fatalError("Invalid mock media source URL") + } + + return .init(source: mediaSource, + duration: 100, + size: .init(width: 1920, height: 1080), + aspectRatio: 1.78, + mimeType: nil) } } @@ -269,10 +273,6 @@ struct ImageInfoProxy: Hashable { self.init(source: .init(source: source, mimeType: mimeType), width: width, height: height, mimeType: mimeType) } - init(url: URL, width: UInt64?, height: UInt64?, mimeType: String?) { - self.init(source: .init(url: url, mimeType: mimeType), width: width, height: height, mimeType: mimeType) - } - init(source: MediaSourceProxy, width: UInt64?, height: UInt64?, mimeType: String?) { self.source = source @@ -292,17 +292,25 @@ struct ImageInfoProxy: Hashable { } static var mockImage: ImageInfoProxy { - .init(source: .init(url: .mockMXCImage, mimeType: "image/png"), - size: .init(width: 100, height: 100), - aspectRatio: 1, - mimeType: "image/png") + guard let mediaSource = try? MediaSourceProxy(url: .mockMXCImage, mimeType: "image/png") else { + fatalError("Invalid mock media source URL") + } + + return .init(source: mediaSource, + size: .init(width: 100, height: 100), + aspectRatio: 1, + mimeType: "image/png") } static var mockThumbnail: ImageInfoProxy { - .init(source: .init(url: .mockMXCImage, mimeType: nil), - size: nil, - aspectRatio: nil, - mimeType: nil) + guard let mediaSource = try? MediaSourceProxy(url: .mockMXCImage, mimeType: "image/png") else { + fatalError("Invalid mock media source URL") + } + + return .init(source: mediaSource, + size: nil, + aspectRatio: nil, + mimeType: nil) } } diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index 0843b042f2..e1a3fd6c52 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -33,12 +33,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { case .redactedMessage: return buildRedactedTimelineItem(eventItemProxy, isOutgoing) case .sticker(let body, let imageInfo, let mediaSource): - guard let url = URL(string: mediaSource.url()) else { - MXLog.error("Invalid sticker url string: \(mediaSource.url())") - return buildUnsupportedTimelineItem(eventItemProxy, "m.sticker", "Invalid Sticker URL", isOutgoing) - } - - return buildStickerTimelineItem(eventItemProxy, body, imageInfo, url, isOutgoing) + return buildStickerTimelineItem(eventItemProxy, body, imageInfo, mediaSource, isOutgoing) case .failedToParseMessageLike(let eventType, let error): return buildUnsupportedTimelineItem(eventItemProxy, eventType, error, isOutgoing) case .failedToParseState(let eventType, _, let error): @@ -119,9 +114,9 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { private func buildStickerTimelineItem(_ eventItemProxy: EventTimelineItemProxy, _ body: String, _ info: MatrixRustSDK.ImageInfo, - _ imageURL: URL, + _ mediaSource: MediaSource, _ isOutgoing: Bool) -> RoomTimelineItemProtocol { - let imageInfo = ImageInfoProxy(url: imageURL, width: info.width, height: info.height, mimeType: info.mimetype) + let imageInfo = ImageInfoProxy(source: mediaSource, width: info.width, height: info.height, mimeType: info.mimetype) return StickerRoomTimelineItem(id: eventItemProxy.id, body: body, diff --git a/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift b/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift index 2e2b6e7d87..bca846f2b6 100644 --- a/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift +++ b/UnitTests/Sources/MediaProvider/MediaLoaderTests.swift @@ -10,12 +10,12 @@ import MatrixRustSDK import XCTest final class MediaLoaderTests: XCTestCase { - func testMediaRequestCoalescing() async { + func testMediaRequestCoalescing() async throws { let mediaLoadingClient = ClientSDKMock() mediaLoadingClient.getMediaContentMediaSourceReturnValue = Data() let mediaLoader = MediaLoader(client: mediaLoadingClient) - let mediaSource = MediaSourceProxy(url: .mockMXCFile, mimeType: nil) + let mediaSource = try MediaSourceProxy(url: .mockMXCFile, mimeType: nil) do { for _ in 1...10 { @@ -28,12 +28,12 @@ final class MediaLoaderTests: XCTestCase { } } - func testMediaThumbnailRequestCoalescing() async { + func testMediaThumbnailRequestCoalescing() async throws { let mediaLoadingClient = ClientSDKMock() mediaLoadingClient.getMediaThumbnailMediaSourceWidthHeightReturnValue = Data() let mediaLoader = MediaLoader(client: mediaLoadingClient) - let mediaSource = MediaSourceProxy(url: .mockMXCImage, mimeType: nil) + let mediaSource = try MediaSourceProxy(url: .mockMXCImage, mimeType: nil) do { for _ in 1...10 { diff --git a/UnitTests/Sources/MediaProvider/MediaProviderTests.swift b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift index 9e1dc87bd4..a012afe776 100644 --- a/UnitTests/Sources/MediaProvider/MediaProviderTests.swift +++ b/UnitTests/Sources/MediaProvider/MediaProviderTests.swift @@ -36,7 +36,7 @@ final class MediaProviderTests: XCTestCase { return } - let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg")) + let loadTask = try mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg")) let connectivitySubject = CurrentValueSubject(.unreachable) @@ -59,7 +59,7 @@ final class MediaProviderTests: XCTestCase { } func testLoadingRetriedOnReconnectionCancelsAfterSecondFailure() async throws { - let loadTask = mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg")) + let loadTask = try mediaProvider.loadImageRetryingOnReconnection(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg")) let connectivitySubject = CurrentValueSubject(.reachable) @@ -73,7 +73,7 @@ final class MediaProviderTests: XCTestCase { } func test_whenImageFromSourceWithSourceNil_nilReturned() throws { - let image = mediaProvider.imageFromSource(nil, size: Avatars.Size.room(on: .timeline).scaledSize) + let image = try mediaProvider.imageFromSource(nil, size: Avatars.Size.room(on: .timeline).scaledSize) XCTAssertNil(image) } @@ -83,14 +83,14 @@ final class MediaProviderTests: XCTestCase { let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() imageCache.retrievedImagesInMemory[key] = imageForKey - let image = mediaProvider.imageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), - size: avatarSize.scaledSize) + let image = try mediaProvider.imageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), + size: avatarSize.scaledSize) XCTAssertEqual(image, imageForKey) } func test_whenImageFromSourceWithSourceNotNilAndImageNotCached_nilReturned() throws { - let image = mediaProvider.imageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: Avatars.Size.room(on: .timeline).scaledSize) + let image = try mediaProvider.imageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: Avatars.Size.room(on: .timeline).scaledSize) XCTAssertNil(image) } @@ -100,8 +100,8 @@ final class MediaProviderTests: XCTestCase { let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() imageCache.retrievedImagesInMemory[key] = imageForKey - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), - size: avatarSize.scaledSize) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), + size: avatarSize.scaledSize) XCTAssertEqual(Result.success(imageForKey), result) } @@ -111,8 +111,8 @@ final class MediaProviderTests: XCTestCase { let key = "\(url.absoluteString){\(avatarSize.scaledValue),\(avatarSize.scaledValue)}" let imageForKey = UIImage() imageCache.retrievedImages[key] = imageForKey - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), - size: avatarSize.scaledSize) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), + size: avatarSize.scaledSize) XCTAssertEqual(Result.success(imageForKey), result) } @@ -122,8 +122,8 @@ final class MediaProviderTests: XCTestCase { mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = expectedImage.pngData() - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: avatarSize.scaledSize) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: avatarSize.scaledSize) switch result { case .success(let image): XCTAssertEqual(image.pngData(), expectedImage.pngData()) @@ -140,8 +140,8 @@ final class MediaProviderTests: XCTestCase { mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = expectedImage.pngData() - _ = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), - size: avatarSize.scaledSize) + _ = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: url, mimeType: "image/jpeg"), + size: avatarSize.scaledSize) let storedImage = try XCTUnwrap(imageCache.storedImages[key]) XCTAssertEqual(expectedImage.pngData(), storedImage.pngData()) } @@ -151,8 +151,8 @@ final class MediaProviderTests: XCTestCase { mediaLoader.loadMediaContentForSourceReturnValue = expectedImage.pngData() - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: nil) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: nil) switch result { case .success(let image): XCTAssertEqual(image.pngData(), expectedImage.pngData()) @@ -164,8 +164,8 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndLoadImageThumbnailFails_errorIsThrown() async throws { mediaLoader.loadMediaThumbnailForSourceWidthHeightThrowableError = MediaProviderTestsError.error - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: Avatars.Size.room(on: .timeline).scaledSize) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: Avatars.Size.room(on: .timeline).scaledSize) switch result { case .success: XCTFail("Should fail") @@ -177,8 +177,8 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndNoAvatarSizeAndLoadImageContentFails_errorIsThrown() async throws { mediaLoader.loadMediaContentForSourceThrowableError = MediaProviderTestsError.error - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: nil) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: nil) switch result { case .success: XCTFail("Should fail") @@ -190,8 +190,8 @@ final class MediaProviderTests: XCTestCase { func test_whenLoadImageFromSourceAndImageNotCachedAndRetrieveImageFailsAndImageThumbnailIsLoadedWithCorruptedData_errorIsThrown() async throws { mediaLoader.loadMediaThumbnailForSourceWidthHeightReturnValue = Data() - let result = await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), - size: Avatars.Size.room(on: .timeline).scaledSize) + let result = try await mediaProvider.loadImageFromSource(MediaSourceProxy(url: .mockMXCImage, mimeType: "image/jpeg"), + size: Avatars.Size.room(on: .timeline).scaledSize) switch result { case .success: XCTFail("Should fail") diff --git a/UnitTests/Sources/VoiceMessageCacheTests.swift b/UnitTests/Sources/VoiceMessageCacheTests.swift index 7520867766..d5cb77a7f7 100644 --- a/UnitTests/Sources/VoiceMessageCacheTests.swift +++ b/UnitTests/Sources/VoiceMessageCacheTests.swift @@ -26,7 +26,7 @@ class VoiceMessageCacheTests: XCTestCase { voiceMessageCache.clearCache() fileManager = FileManager.default - mediaSource = MediaSourceProxy(url: someURL, mimeType: "audio/ogg") + mediaSource = try MediaSourceProxy(url: someURL, mimeType: "audio/ogg") // Create the temporary directory we will use try fileManager.createDirectory(at: testTemporaryDirectory, withIntermediateDirectories: true) diff --git a/UnitTests/Sources/VoiceMessageMediaManagerTests.swift b/UnitTests/Sources/VoiceMessageMediaManagerTests.swift index 2aeecf0624..b9dba42870 100644 --- a/UnitTests/Sources/VoiceMessageMediaManagerTests.swift +++ b/UnitTests/Sources/VoiceMessageMediaManagerTests.swift @@ -28,7 +28,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { func testLoadVoiceMessageFromSourceUnsupportedMedia() async throws { // Only "audio/ogg" file are supported - let unsupportedMediaSource = MediaSourceProxy(url: someURL, mimeType: "audio/wav") + let unsupportedMediaSource = try MediaSourceProxy(url: someURL, mimeType: "audio/wav") do { _ = try await voiceMessageMediaManager.loadVoiceMessageFromSource(unsupportedMediaSource, body: nil) XCTFail("A `VoiceMessageMediaManagerError.unsupportedMimeTye` error is expected") @@ -49,7 +49,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { let cachedConvertedFileURL = URL("/some/url/cached_converted_file.m4a") voiceMessageCache.fileURLForReturnValue = nil - let mediaSource = MediaSourceProxy(url: someURL, mimeType: "audio/ogg; codecs=opus") + let mediaSource = try MediaSourceProxy(url: someURL, mimeType: "audio/ogg; codecs=opus") mediaProvider.loadFileFromSourceFilenameReturnValue = .success(MediaFileHandleProxy.unmanaged(url: loadedFile)) voiceMessageCache.cacheMediaSourceUsingMoveReturnValue = .success(cachedConvertedFileURL) @@ -67,7 +67,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { func testLoadVoiceMessageFromSourceAlreadyCached() async throws { // Check if the file is already present in cache voiceMessageCache.fileURLForReturnValue = URL("/converted_file/url") - let mediaSource = MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) + let mediaSource = try MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) let url = try await voiceMessageMediaManager.loadVoiceMessageFromSource(mediaSource, body: nil) XCTAssertEqual(url, URL("/converted_file/url")) // The file must have be search in the cache @@ -81,7 +81,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { // An error must be reported if the file cannot be retrieved do { voiceMessageCache.fileURLForReturnValue = nil - let mediaSource = MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) + let mediaSource = try MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) _ = try await voiceMessageMediaManager.loadVoiceMessageFromSource(mediaSource, body: nil) XCTFail("A `MediaProviderError.failedRetrievingFile` error is expected") } catch { @@ -102,7 +102,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { // Check if the file is not already present in cache voiceMessageCache.fileURLForReturnValue = nil - let mediaSource = MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) + let mediaSource = try MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) mediaProvider.loadFileFromSourceFilenameReturnValue = .success(MediaFileHandleProxy.unmanaged(url: loadedFile)) let audioConverter = AudioConverterMock() voiceMessageCache.cacheMediaSourceUsingMoveReturnValue = .success(cachedConvertedFileURL) @@ -145,7 +145,7 @@ class VoiceMessageMediaManagerTests: XCTestCase { voiceMessageCache: voiceMessageCache, audioConverter: audioConverter) - let mediaSource = MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) + let mediaSource = try MediaSourceProxy(url: someURL, mimeType: audioOGGMimeType) for _ in 0..<10 { let url = try await voiceMessageMediaManager.loadVoiceMessageFromSource(mediaSource, body: nil) XCTAssertEqual(url, cachedConvertedFileURL) From 671e6754125f6b627a4c92889e69a6c2eee5cd4b Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 29 Nov 2024 13:11:14 +0000 Subject: [PATCH 68/74] Fix a compile error. --- .../Timeline/Fixtures/RoomTimelineItemFixtures.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift index 716849af32..da1aef5116 100644 --- a/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift +++ b/ElementX/Sources/Services/Timeline/Fixtures/RoomTimelineItemFixtures.swift @@ -296,7 +296,7 @@ private extension AudioRoomTimelineItem { caption: caption, duration: 60, waveform: nil, - source: .init(url: .mockMXCAudio, mimeType: nil), + source: try? .init(url: .mockMXCAudio, mimeType: nil), fileSize: nil, contentType: .mp3)) } @@ -313,7 +313,7 @@ private extension FileRoomTimelineItem { sender: .init(id: isOutgoing ? "@alice:matrix.org" : "@bob:matrix.org"), content: .init(filename: "file.pdf", caption: caption, - source: .init(url: .mockMXCFile, mimeType: nil), + source: try? .init(url: .mockMXCFile, mimeType: nil), fileSize: nil, thumbnailSource: nil, contentType: .pdf)) @@ -366,7 +366,7 @@ private extension VoiceMessageRoomTimelineItem { content: .init(filename: "message.ogg", duration: 10, waveform: .mockWaveform, - source: .init(url: .mockMXCAudio, mimeType: nil), + source: try? .init(url: .mockMXCAudio, mimeType: nil), fileSize: nil, contentType: .audio)) } From 8d6909982d4f274ed4d07dd147679a062aef5bc1 Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Fri, 29 Nov 2024 16:44:15 +0100 Subject: [PATCH 69/74] Move pinned messages button in details --- .../View/RoomDetailsScreen.swift | 17 +++++++++-------- ...est_roomDetailsScreen-iPad-en-GB.DM-Room.png | 4 ++-- ...oomDetailsScreen-iPad-en-GB.Generic-Room.png | 4 ++-- ...roomDetailsScreen-iPad-en-GB.Simple-Room.png | 4 ++-- ...st_roomDetailsScreen-iPad-pseudo.DM-Room.png | 4 ++-- ...omDetailsScreen-iPad-pseudo.Generic-Room.png | 4 ++-- ...oomDetailsScreen-iPad-pseudo.Simple-Room.png | 4 ++-- ...oomDetailsScreen-iPhone-16-en-GB.DM-Room.png | 4 ++-- ...tailsScreen-iPhone-16-en-GB.Generic-Room.png | 4 ++-- ...etailsScreen-iPhone-16-en-GB.Simple-Room.png | 4 ++-- ...omDetailsScreen-iPhone-16-pseudo.DM-Room.png | 4 ++-- ...ailsScreen-iPhone-16-pseudo.Generic-Room.png | 4 ++-- ...tailsScreen-iPhone-16-pseudo.Simple-Room.png | 4 ++-- 13 files changed, 33 insertions(+), 32 deletions(-) diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift index 042ba4e614..6a8613d167 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -160,6 +160,15 @@ struct RoomDetailsScreen: View { }) .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: { + context.send(viewAction: .processTapPinnedEvents) + })) + .disabled(context.viewState.pinnedEventsActionState.isLoading) + if context.viewState.canSeeKnockingRequests { ListRow(label: .default(title: L10n.screenRoomDetailsRequestsToJoinTitle, icon: \.askToJoin), @@ -198,14 +207,6 @@ struct RoomDetailsScreen: View { context.send(viewAction: .toggleFavourite(isFavourite: newValue)) } - 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: { - context.send(viewAction: .processTapPinnedEvents) - })) - .disabled(context.viewState.pinnedEventsActionState.isLoading) - if context.viewState.canEditRolesOrPermissions, context.viewState.dmRecipient == nil { ListRow(label: .default(title: L10n.screenRoomDetailsRolesAndPermissions, icon: \.admin), 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 1e4ca1fcee..6e0f797d4d 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:426e4bce963193df6ce6be11ccd1a9ba1a22fa064aae84ebe96ecb92a164b507 -size 196225 +oid sha256:ccbc97e0c7c93037173dd2096568f862c2fbea2ab088fed7a50c2fca57f082b7 +size 196689 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 24ee96c2ae..a633075f0d 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:12f8dddc315ccc8ea2d4158254be65769f9d5bcc58bdd7613e4223ae22a36f70 -size 174040 +oid sha256:69c8d1611151cd7356e8595eb8c320cea39469b162f8608a513d19b842b9fc14 +size 174237 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 d298dc2299..76a13ede2e 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:d7198ec0f5b671f2909415c3d87a499584d4afd6268507b37a7176bb261169fa -size 149752 +oid sha256:0f149aa6746040c30b0d07e75ea2594f2e98befd365421cd466031152835ee40 +size 149948 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 a9328a97ca..9c08304fed 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:1e5c945f464ebacef94fe9d71da03678b2148f5658c31fcb79d500967ac5ba0a -size 200975 +oid sha256:cd1ea55f817dc1d283dc713cf400e73e43455b9d71bb8283b9c126488e852f23 +size 201104 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 b5fc7cce45..10972ab92f 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:b9130f74c15d8f53f70ab3c6389ee97496f05996f4529864dd84a0854fb99371 -size 179894 +oid sha256:98b2d3b1922ed3fdb9ae9f23f0801d4c6cc1c47eb22118a1c673028e3c3064b1 +size 180087 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 73465f586e..b601720ab5 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:bca314935dec069cbc120122a131b512655f861cf8c9e5daa2ae5f1a8766d30f -size 160283 +oid sha256:1fadb3e09d55ba1c9e0ba4082eea366422642c76ae731cad3172c522c57734d5 +size 160375 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 518a4f1e8f..d58a4e5fb6 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:9128fc4e3140862b04941fb298b5b352b732556902862f52f78e3c06c1acc00e -size 139620 +oid sha256:e3f3c59007c7154f7121a3a5b3a6a05fd5e389c7ac9f922d4c93ef5084090b55 +size 139781 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 c15e2c0b92..c986f93ed7 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:cda8e8481480985513bbba1a25a8621aafef7699d2f1f9297769ea20dc571e32 -size 111920 +oid sha256:84e62d4e5808da5e807e076179538e6cb42dafae0c1c1aabf3732dbc4bb7c8a0 +size 112044 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 cd3b1ba072..c4d851f7eb 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:e8d59ded6b52bbdc156eaf01a8a26ed960e64c7d87f2d05c4b7923c4d8cf651d -size 96987 +oid sha256:f86bc2dd442d2a0c9ab5179a19dff28a24716b188d3267d8c64aecea6856a328 +size 97074 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 4a7da07112..a1f4a62f6a 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:3d7488c400a906d44d246e1f8e2705f127aa254f3f1639c46e6206b072a9fab2 -size 152011 +oid sha256:ac29c1a44d4f8805ee35dc66cade4ba3c5dca673fd95079dd5e5b8346e350314 +size 152666 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 88c796aecc..846f2565a2 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:0bf2e3e38fee10e28c1fa5415e7b97bd07a1c1cddc52d3cfd446fa9fdabb20bf -size 128305 +oid sha256:a3937e498c27177646dae584d63ba4ee8eae44098956bab21d7869305ff32639 +size 124185 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 6fa8cf6278..f521e5bba8 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:8e69bbc84760736834b39a253232206e0f98942a9de5bb909b36ea80ffdee4d7 -size 110395 +oid sha256:be13972396c7ed858d62628c251234f033af3f1e585118c092f039b94eaf133b +size 111276 From 34f1c61fe2424aa804e84380c6ee99fb6e01e557 Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Fri, 29 Nov 2024 16:23:20 +0000 Subject: [PATCH 70/74] Add a warning to the media caption composer. (#3574) We can now remove the feature flag. --- .../en.lproj/Localizable.strings | 5 +- .../Sources/Application/AppSettings.swift | 4 + .../RoomFlowCoordinator.swift | 2 +- ElementX/Sources/Generated/Strings.swift | 2 + .../MediaUploadPreviewScreenCoordinator.swift | 4 +- .../MediaUploadPreviewScreenModels.swift | 4 +- .../MediaUploadPreviewScreenViewModel.swift | 4 +- .../View/MediaUploadPreviewScreen.swift | 94 ++++++++++++++----- ..._mediaUploadPreviewScreen-iPad-en-GB.1.png | 4 +- ...eviewScreen-iPad-en-GB.Caption-warning.png | 3 + ...mediaUploadPreviewScreen-iPad-pseudo.1.png | 4 +- ...viewScreen-iPad-pseudo.Caption-warning.png | 3 + ...aUploadPreviewScreen-iPhone-16-en-GB.1.png | 4 +- ...Screen-iPhone-16-en-GB.Caption-warning.png | 3 + ...UploadPreviewScreen-iPhone-16-pseudo.1.png | 4 +- ...creen-iPhone-16-pseudo.Caption-warning.png | 3 + ...diaUploadPreviewScreenViewModelTests.swift | 2 +- 17 files changed, 106 insertions(+), 43 deletions(-) create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.Caption-warning.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.Caption-warning.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.Caption-warning.png create mode 100644 PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.Caption-warning.png diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index f81ac7c6dc..050bd10328 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -387,6 +387,9 @@ "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_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."; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -584,8 +587,6 @@ "screen_login_title" = "Welcome back!"; "screen_login_title_with_homeserver" = "Sign in to %1$@"; "screen_media_picker_error_failed_selection" = "Failed selecting media, please try again."; -"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."; "screen_migration_message" = "This is a one time process, thanks for waiting."; "screen_migration_title" = "Setting up your account."; "screen_notification_optin_subtitle" = "You can change your settings later."; diff --git a/ElementX/Sources/Application/AppSettings.swift b/ElementX/Sources/Application/AppSettings.swift index eff6e295a1..8da94ab933 100644 --- a/ElementX/Sources/Application/AppSettings.swift +++ b/ElementX/Sources/Application/AppSettings.swift @@ -240,6 +240,10 @@ final class AppSettings { @UserPreference(key: UserDefaultsKeys.optimizeMediaUploads, defaultValue: true, storageType: .userDefaults(store)) var optimizeMediaUploads + + /// Whether or not to show a warning on the media caption composer so the user knows + /// that captions might not be visible to users who are using other Matrix clients. + let shouldShowMediaCaptionWarning = true // MARK: - Element Call diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index 3a58bdfac1..fddb7fea16 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -997,7 +997,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: appSettings), title: url.lastPathComponent, url: url, - createMediaCaptionsEnabled: appSettings.createMediaCaptionsEnabled) + shouldShowCaptionWarning: appSettings.shouldShowMediaCaptionWarning) let mediaUploadPreviewScreenCoordinator = MediaUploadPreviewScreenCoordinator(parameters: parameters) diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 36ae30edda..4e3258eccd 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -1358,6 +1358,8 @@ internal enum L10n { } /// 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. + internal static var screenMediaUploadPreviewCaptionWarning: String { return L10n.tr("Localizable", "screen_media_upload_preview_caption_warning") } /// Failed processing media to upload, please try again. internal static var screenMediaUploadPreviewErrorFailedProcessing: String { return L10n.tr("Localizable", "screen_media_upload_preview_error_failed_processing") } /// Failed uploading media, please try again. diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift index 78bf651045..4d2610314b 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenCoordinator.swift @@ -14,7 +14,7 @@ struct MediaUploadPreviewScreenCoordinatorParameters { let mediaUploadingPreprocessor: MediaUploadingPreprocessor let title: String? let url: URL - let createMediaCaptionsEnabled: Bool + let shouldShowCaptionWarning: Bool } enum MediaUploadPreviewScreenCoordinatorAction { @@ -36,7 +36,7 @@ final class MediaUploadPreviewScreenCoordinator: CoordinatorProtocol { mediaUploadingPreprocessor: parameters.mediaUploadingPreprocessor, title: parameters.title, url: parameters.url, - createMediaCaptionsEnabled: parameters.createMediaCaptionsEnabled) + shouldShowCaptionWarning: parameters.shouldShowCaptionWarning) } func start() { diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift index ecd05d345b..b3568c35c4 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift @@ -14,7 +14,7 @@ enum MediaUploadPreviewScreenViewModelAction { struct MediaUploadPreviewScreenViewState: BindableState { let url: URL let title: String? - let showMediaCaptionComposer: Bool + let shouldShowCaptionWarning: Bool var shouldDisableInteraction = false var bindings = MediaUploadPreviewScreenBindings() @@ -23,6 +23,8 @@ struct MediaUploadPreviewScreenViewState: BindableState { struct MediaUploadPreviewScreenBindings: BindableState { var caption = NSAttributedString() var presendCallback: (() -> Void)? + + var isPresentingMediaCaptionWarning = false } enum MediaUploadPreviewScreenViewAction { diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift index e4d8decd4f..f76a025c85 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift @@ -33,13 +33,13 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, mediaUploadingPreprocessor: MediaUploadingPreprocessor, title: String?, url: URL, - createMediaCaptionsEnabled: Bool) { + shouldShowCaptionWarning: Bool) { self.userIndicatorController = userIndicatorController self.roomProxy = roomProxy self.mediaUploadingPreprocessor = mediaUploadingPreprocessor self.url = url - super.init(initialViewState: MediaUploadPreviewScreenViewState(url: url, title: title, showMediaCaptionComposer: createMediaCaptionsEnabled)) + super.init(initialViewState: MediaUploadPreviewScreenViewState(url: url, title: title, shouldShowCaptionWarning: shouldShowCaptionWarning)) } override func process(viewAction: MediaUploadPreviewScreenViewAction) { diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift index 2b4e722abd..17ba7c9be4 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift @@ -14,26 +14,27 @@ struct MediaUploadPreviewScreen: View { @ObservedObject var context: MediaUploadPreviewScreenViewModel.Context - var title: String { ProcessInfo.processInfo.isiOSAppOnMac ? context.viewState.title ?? "" : "" } - var colorSchemeOverride: ColorScheme { ProcessInfo.processInfo.isiOSAppOnMac ? colorScheme : .dark } + @State private var captionWarningFrame: CGRect = .zero + + private var title: String { ProcessInfo.processInfo.isiOSAppOnMac ? context.viewState.title ?? "" : "" } + private var colorSchemeOverride: ColorScheme { ProcessInfo.processInfo.isiOSAppOnMac ? colorScheme : .dark } var body: some View { mainContent .id(context.viewState.url) .ignoresSafeArea(edges: [.horizontal]) .safeAreaInset(edge: .bottom, spacing: 0) { - if context.viewState.showMediaCaptionComposer { - composer - .padding(.horizontal, 12) - .padding(.vertical, 16) - .background() // Don't use compound so we match the QLPreviewController. - } + composer + .padding(.horizontal, 12) + .padding(.vertical, 16) + .background() // Don't use compound so we match the QLPreviewController. } .navigationTitle(title) .navigationBarTitleDisplayMode(.inline) .toolbar { toolbar } .disabled(context.viewState.shouldDisableInteraction) .interactiveDismissDisabled() + .presentationBackground(.background) // Fix a bug introduced by the caption warning. .preferredColorScheme(colorSchemeOverride) } @@ -52,13 +53,19 @@ struct MediaUploadPreviewScreen: View { private var composer: some View { HStack(spacing: 12) { - MessageComposerTextField(placeholder: L10n.richTextEditorComposerCaptionPlaceholder, - text: $context.caption, - presendCallback: $context.presendCallback, - maxHeight: ComposerConstant.maxHeight, - keyHandler: { _ in }, - pasteHandler: { _ in }) - .messageComposerStyle() + HStack(spacing: 6) { + MessageComposerTextField(placeholder: L10n.richTextEditorComposerCaptionPlaceholder, + text: $context.caption, + presendCallback: $context.presendCallback, + maxHeight: ComposerConstant.maxHeight, + keyHandler: { _ in }, + pasteHandler: { _ in }) + + if context.viewState.shouldShowCaptionWarning { + captionWarningButton + } + } + .messageComposerStyle() SendButton { context.send(viewAction: .send) @@ -66,6 +73,47 @@ struct MediaUploadPreviewScreen: View { } } + private var captionWarningButton: some View { + Button { + context.isPresentingMediaCaptionWarning = true + } label: { + CompoundIcon(\.infoSolid, size: .xSmall, relativeTo: .compound.bodyLG) + } + .tint(.compound.iconCriticalPrimary) + .popover(isPresented: $context.isPresentingMediaCaptionWarning, arrowEdge: .bottom) { + captionWarningContent + .presentationDetents([.height(captionWarningFrame.height)]) + .presentationDragIndicator(.visible) + .padding(.top, 19) // For the drag indicator + .presentationBackground(.compound.bgCanvasDefault) + .preferredColorScheme(colorSchemeOverride) + } + } + + var captionWarningContent: some View { + VStack(spacing: 0) { + VStack(spacing: 16) { + BigIcon(icon: \.infoSolid, style: .alertSolid) + + Text(L10n.screenMediaUploadPreviewCaptionWarning) + .font(.compound.bodyMD) + .foregroundStyle(.compound.textPrimary) + .multilineTextAlignment(.center) + .fixedSize(horizontal: false, vertical: true) + } + .padding(24) + .padding(.bottom, 8) + + Button(L10n.actionOk) { + context.isPresentingMediaCaptionWarning = false + } + .buttonStyle(.compound(.secondary)) + .padding(.horizontal, 16) + .padding(.bottom, 16) + } + .readFrame($captionWarningFrame) + } + @ToolbarContentBuilder private var toolbar: some ToolbarContent { ToolbarItem(placement: .cancellationAction) { @@ -76,16 +124,6 @@ struct MediaUploadPreviewScreen: View { // follow the dark colour scheme on devices running with dark mode disabled. .tint(.compound.textActionPrimary) } - - if !context.viewState.showMediaCaptionComposer { - ToolbarItem(placement: .confirmationAction) { - Button { context.send(viewAction: .send) } label: { - Text(L10n.actionSend) - } - // Same fix as above (this button is temporary anyway). - .tint(.compound.textActionPrimary) - } - } } } @@ -169,10 +207,14 @@ struct MediaUploadPreviewScreen_Previews: PreviewProvider, TestablePreview { mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings), title: "App Icon.png", url: snapshotURL, - createMediaCaptionsEnabled: true) + shouldShowCaptionWarning: true) static var previews: some View { NavigationStack { MediaUploadPreviewScreen(context: viewModel.context) } + + MediaUploadPreviewScreen(context: viewModel.context) + .captionWarningContent + .previewDisplayName("Caption warning") } } 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 a218dc80e7..d9424a3003 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:885fb08cfe301dd996fa6f1b276afa7a74f6534d692ab313ec7d64bfcb970981 -size 91980 +oid sha256:79c2656c58dde4df7af57a9ce1561d33c83772a8f15e88ea57fe80f8c14b61b5 +size 92652 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.Caption-warning.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.Caption-warning.png new file mode 100644 index 0000000000..3881a9edb5 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.Caption-warning.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4443b88f50798db3ddf789a3a1daf69b45158e799801e51e0a6604840af9b811 +size 84527 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 687ed48841..377fe1b2b7 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:ab99e9ac3233f55705f96cc0c8f1480351f0765b7b36d1e90e3262758b2ede9a -size 93223 +oid sha256:f53cf59f991c8958e8ae06759f05cf41b39ec6d1b402fcc6123edbd54e863409 +size 93837 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.Caption-warning.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.Caption-warning.png new file mode 100644 index 0000000000..de24f7d437 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.Caption-warning.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:babfab486bcb62122404c32f1268e3f6ce486c7ac1942de40e3fd754260c2e9a +size 89371 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 748902c2b8..b77d39bca7 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:3cd02932f70d0c1336b295d94ca31694f569fea56b36b8cc29c448284406e8dd -size 50622 +oid sha256:1212f7afafd62561d7a90852e077667a042d4e86bd9b572904e0c89146e8d8b9 +size 51188 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.Caption-warning.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.Caption-warning.png new file mode 100644 index 0000000000..1b0c003376 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.Caption-warning.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:74e2863ec160d47570f9d8c512d5dc4c6afa50ce0f2fb6cd7520a4bfb287f4dc +size 43826 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 960476010a..3bf2bb188f 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:26109f9334be8c7452fd98c15158bea787df6b87f560f8ee6b6aea46dc6a1647 -size 51627 +oid sha256:f6ac82c8457a7771ae7c30049ea4250f434285e4ae15ad52eefc935bd38e37eb +size 51942 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.Caption-warning.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.Caption-warning.png new file mode 100644 index 0000000000..8d73d82d75 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.Caption-warning.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1ea4d6009691a8079ae6d788dda3d9ea3c28d45451ad31278dbe8dfc399e2f7 +size 54743 diff --git a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift index 9a47185aea..7fe56df9de 100644 --- a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift +++ b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift @@ -126,7 +126,7 @@ class MediaUploadPreviewScreenViewModelTests: XCTestCase { mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings), title: "Some File", url: url, - createMediaCaptionsEnabled: true) + shouldShowCaptionWarning: true) } private func verifyCaption(_ caption: String?, expectedCaption: String?) -> Result { From b8085356fb90177d3e0425a11de5cb3cdf64b4fd Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Mon, 2 Dec 2024 10:21:08 +0000 Subject: [PATCH 71/74] Translations update (#3576) * Translations update * fix a test --------- Co-authored-by: pixlwave <6060466+pixlwave@users.noreply.github.com> Co-authored-by: Mauro Romito --- .../be.lproj/Localizable.strings | 19 +- .../bg.lproj/Localizable.strings | 19 +- .../cs.lproj/Localizable.strings | 17 +- .../de.lproj/Localizable.strings | 239 +++++++++--------- .../de.lproj/Localizable.stringsdict | 4 +- .../el.lproj/Localizable.strings | 17 +- .../en.lproj/Localizable.strings | 2 +- .../es.lproj/Localizable.strings | 19 +- .../et.lproj/Localizable.strings | 19 +- .../fa.lproj/Localizable.strings | 19 +- .../fi.lproj/Localizable.strings | 17 +- .../fr.lproj/Localizable.strings | 51 ++-- .../fr.lproj/Localizable.stringsdict | 4 +- .../hu.lproj/Localizable.strings | 19 +- .../id.lproj/Localizable.strings | 17 +- .../it.lproj/Localizable.strings | 19 +- .../ka.lproj/Localizable.strings | 19 +- .../nl.lproj/Localizable.strings | 19 +- .../pl.lproj/Localizable.strings | 25 +- .../pt-BR.lproj/Localizable.strings | 19 +- .../pt.lproj/Localizable.strings | 17 +- .../ro.lproj/Localizable.strings | 19 +- .../ru.lproj/Localizable.strings | 17 +- .../sk.lproj/Localizable.strings | 17 +- .../sv.lproj/Localizable.strings | 19 +- .../uk.lproj/Localizable.strings | 17 +- .../uz.lproj/Localizable.strings | 19 +- .../zh-Hans.lproj/Localizable.strings | 19 +- .../zh-Hant-TW.lproj/Localizable.strings | 19 +- ElementX/Sources/Generated/Strings.swift | 2 +- ...n-GB.Create-Public-Room-existing-alias.png | 4 +- 31 files changed, 545 insertions(+), 207 deletions(-) diff --git a/ElementX/Resources/Localizations/be.lproj/Localizable.strings b/ElementX/Resources/Localizations/be.lproj/Localizable.strings index c554a8ba59..4fa69ce0df 100644 --- a/ElementX/Resources/Localizations/be.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/be.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Пацвердзіць пароль"; "action_continue" = "Працягнуць"; "action_copy" = "Капіраваць"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Скапіраваць спасылку"; "action_copy_link_to_message" = "Скапіраваць спасылку на паведамленне"; +"action_copy_text" = "Copy text"; "action_create" = "Стварыць"; "action_create_a_room" = "Стварыце пакой"; "action_deactivate" = "Дэактываваць"; @@ -84,6 +86,7 @@ "action_reject" = "Адхіліць"; "action_remove" = "Выдаліць"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Адказаць"; "action_reply_in_thread" = "Адказаць у гутаркі"; "action_report_bug" = "Паведаміць пра памылку"; @@ -359,7 +362,7 @@ "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" = "Папрасіце далучыцца"; "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_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"; @@ -370,11 +373,23 @@ "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_media_upload_preview_error_failed_processing" = "Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз."; +"screen_media_upload_preview_error_failed_sending" = "Не атрымалася загрузіць медыяфайлы, паспрабуйце яшчэ раз."; "screen_pinned_timeline_empty_state_description" = "Націсніце на паведамленне і абярыце «%1$@ », каб уключыць сюды."; "screen_pinned_timeline_empty_state_headline" = "Замацуеце важныя паведамленні, каб іх можна было лёгка знайсці"; "screen_reset_encryption_password_error" = "Адбылася невядомая памылка. Калі ласка, праверце правільнасць пароля вашага ўліковага запісу і паўтарыце спробу."; @@ -572,8 +587,6 @@ "screen_login_title" = "Сардэчна запрашаем!"; "screen_login_title_with_homeserver" = "Увайсці ў %1$@"; "screen_media_picker_error_failed_selection" = "Не ўдалося выбраць носьбіт, паўтарыце спробу."; -"screen_media_upload_preview_error_failed_processing" = "Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз."; -"screen_media_upload_preview_error_failed_sending" = "Не атрымалася загрузіць медыяфайлы, паспрабуйце яшчэ раз."; "screen_migration_message" = "Гэта аднаразовы працэс, дзякуем за чаканне."; "screen_migration_title" = "Налада ўліковага запісу."; "screen_notification_optin_subtitle" = "Вы можаце змяніць налады пазней."; diff --git a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings index de474f50d2..df5429a5e1 100644 --- a/ElementX/Resources/Localizations/bg.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/bg.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Confirm password"; "action_continue" = "Продължаване"; "action_copy" = "Копиране"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Копиране на връзката"; "action_copy_link_to_message" = "Копиране на връзката към съобщението"; +"action_copy_text" = "Copy text"; "action_create" = "Създаване"; "action_create_a_room" = "Създаване на стая"; "action_deactivate" = "Deactivate"; @@ -84,6 +86,7 @@ "action_reject" = "Reject"; "action_remove" = "Премахване"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Отговор"; "action_reply_in_thread" = "Отговор в нишка"; "action_report_bug" = "Report bug"; @@ -359,7 +362,7 @@ "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_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"; @@ -370,11 +373,23 @@ "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_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."; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -572,8 +587,6 @@ "screen_login_title" = "Добре дошли отново!"; "screen_login_title_with_homeserver" = "Влизане в %1$@"; "screen_media_picker_error_failed_selection" = "Failed selecting media, please try again."; -"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."; "screen_migration_message" = "This is a one time process, thanks for waiting."; "screen_migration_title" = "Setting up your account."; "screen_notification_optin_subtitle" = "Можете да промените настройките си по-късно."; diff --git a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings index df250261a6..1a5f11e52f 100644 --- a/ElementX/Resources/Localizations/cs.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/cs.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Potvrdit heslo"; "action_continue" = "Pokračovat"; "action_copy" = "Kopírovat"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Kopírovat odkaz"; "action_copy_link_to_message" = "Kopírovat odkaz na zprávu"; +"action_copy_text" = "Copy text"; "action_create" = "Vytvořit"; "action_create_a_room" = "Vytvořit místnost"; "action_deactivate" = "Deaktivovat"; @@ -84,6 +86,7 @@ "action_reject" = "Odmítnout"; "action_remove" = "Odstranit"; "action_remove_caption" = "Odstranit titulek"; +"action_remove_message" = "Remove message"; "action_reply" = "Odpovědět"; "action_reply_in_thread" = "Odpovědět ve vlákně"; "action_report_bug" = "Nahlásit chybu"; @@ -370,11 +373,23 @@ "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_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_decline_and_ban_action_title" = "Odmítnout a vykázat"; "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_title" = "Žádosti o vstup"; +"screen_media_upload_preview_caption_warning" = "Captions might not be visible to people using older apps."; +"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."; "screen_pinned_timeline_empty_state_headline" = "Připněte důležité zprávy, aby je bylo možné snadno najít"; "screen_reset_encryption_password_error" = "Došlo k neznámé chybě. Zkontrolujte, zda je heslo k účtu správné a zkuste to znovu."; @@ -572,8 +587,6 @@ "screen_login_title" = "Vítejte zpět!"; "screen_login_title_with_homeserver" = "Přihlaste se k %1$@"; "screen_media_picker_error_failed_selection" = "Výběr média se nezdařil, zkuste to prosím znovu."; -"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_migration_message" = "Jedná se o jednorázový proces, prosíme o strpení."; "screen_migration_title" = "Nastavení vašeho účtu"; "screen_notification_optin_subtitle" = "Nastavení můžete později změnit."; diff --git a/ElementX/Resources/Localizations/de.lproj/Localizable.strings b/ElementX/Resources/Localizations/de.lproj/Localizable.strings index 96f128ed64..8e410678d5 100644 --- a/ElementX/Resources/Localizations/de.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/de.lproj/Localizable.strings @@ -22,7 +22,7 @@ "a11y_voice_message_record" = "Sprachnachricht aufnehmen."; "a11y_voice_message_stop_recording" = "Aufnahme beenden"; "action_accept" = "Akzeptieren"; -"action_add_caption" = "Add caption"; +"action_add_caption" = "Bildunterschrift hinzufügen"; "action_add_to_timeline" = "Zum Nachrichtenverlauf hinzufügen"; "action_back" = "Zurück"; "action_call" = "Anruf"; @@ -33,22 +33,24 @@ "action_close" = "Schließen"; "action_complete_verification" = "Verifizierung abschließen"; "action_confirm" = "Bestätigen"; -"action_confirm_password" = "Confirm password"; +"action_confirm_password" = "Passwort bestätigen"; "action_continue" = "Weiter"; "action_copy" = "Kopieren"; +"action_copy_caption" = "Bildunterschrift kopieren"; "action_copy_link" = "Link kopieren"; "action_copy_link_to_message" = "Link zur Nachricht kopieren"; +"action_copy_text" = "Text kopieren"; "action_create" = "Erstellen"; "action_create_a_room" = "Raum erstellen"; -"action_deactivate" = "Deactivate"; -"action_deactivate_account" = "Deactivate account"; +"action_deactivate" = "Deaktivieren"; +"action_deactivate_account" = "Benutzerkonto deaktivieren"; "action_decline" = "Ablehnen"; "action_delete_poll" = "Umfrage löschen"; "action_disable" = "Deaktivieren"; "action_discard" = "Verwerfen"; "action_done" = "Erledigt"; "action_edit" = "Bearbeiten"; -"action_edit_caption" = "Edit caption"; +"action_edit_caption" = "Bildunterschrift bearbeiten"; "action_edit_poll" = "Umfrage bearbeiten"; "action_enable" = "Aktivieren"; "action_end_poll" = "Umfrage beenden"; @@ -56,7 +58,7 @@ "action_forgot_password" = "Passwort vergessen?"; "action_forward" = "Weiterleiten"; "action_go_back" = "Zurück"; -"action_ignore" = "Ignore"; +"action_ignore" = "Ignorieren"; "action_invite" = "Einladen"; "action_invite_friends" = "Personen einladen"; "action_invite_friends_to_app" = "Zu %1$@ einladen"; @@ -83,7 +85,8 @@ "action_react" = "Reagieren"; "action_reject" = "Ablehnen"; "action_remove" = "Entfernen"; -"action_remove_caption" = "Remove caption"; +"action_remove_caption" = "Bildunterschrift entfernen"; +"action_remove_message" = "Nachricht löschen"; "action_reply" = "Antworten"; "action_reply_in_thread" = "Im Thread antworten"; "action_report_bug" = "Fehler melden"; @@ -98,7 +101,7 @@ "action_send_message" = "Nachricht senden"; "action_share" = "Teilen"; "action_share_link" = "Link teilen"; -"action_show" = "Show"; +"action_show" = "Zeige"; "action_sign_in_again" = "Erneut anmelden"; "action_signout" = "Abmelden"; "action_signout_anyway" = "Trotzdem abmelden"; @@ -122,7 +125,7 @@ "banner_set_up_recovery_title" = "Wiederherstellung einrichten"; "common_about" = "Über"; "common_acceptable_use_policy" = "Nutzungsrichtlinie"; -"common_adding_caption" = "Adding caption"; +"common_adding_caption" = "Hinzufügen einer Bildunterschrift"; "common_advanced_settings" = "Erweiterte Einstellungen"; "common_analytics" = "Analysedaten"; "common_appearance" = "Erscheinungsbild"; @@ -137,13 +140,13 @@ "common_dark" = "Dunkel"; "common_decryption_error" = "Dekodierungsfehler"; "common_developer_options" = "Entwickleroptionen"; -"common_device_id" = "Device ID"; +"common_device_id" = "Geräte-ID"; "common_direct_chat" = "Direktnachricht"; "common_edited_suffix" = "(bearbeitet)"; "common_editing" = "Bearbeitung"; -"common_editing_caption" = "Editing caption"; +"common_editing_caption" = "Bearbeitung der Bildunterschrift"; "common_emote" = "* %1$@ %2$@"; -"common_encryption" = "Encryption"; +"common_encryption" = "Verschlüsselung"; "common_encryption_enabled" = "Verschlüsselung aktiviert"; "common_enter_your_pin" = "PIN eingeben"; "common_error" = "Fehler"; @@ -154,7 +157,7 @@ "common_favourited" = "Favorit"; "common_file" = "Datei"; "common_forward_message" = "Nachricht weiterleiten"; -"common_frequently_used" = "Frequently used"; +"common_frequently_used" = "Häufig verwendet"; "common_gif" = "GIF"; "common_image" = "Bild"; "common_in_reply_to" = "Als Antwort auf %1$@"; @@ -230,34 +233,34 @@ "common_unable_to_invite_title" = "Einladung(en) konnte(n) nicht gesendet werden"; "common_unlock" = "Entsperren"; "common_unmute" = "Stummschaltung aufheben"; -"common_unsupported_call" = "Unsupported call"; +"common_unsupported_call" = "Anruf nicht unterstützt"; "common_unsupported_event" = "Nicht unterstütztes Ereignis"; "common_username" = "Benutzername"; "common_verification_cancelled" = "Verifizierung abgebrochen"; "common_verification_complete" = "Verifizierung abgeschlossen"; -"common_verification_failed" = "Verification failed"; -"common_verified" = "Verified"; +"common_verification_failed" = "Verifizierung fehlgeschlagen"; +"common_verified" = "Verifiziert"; "common_verify_device" = "Gerät verifizieren"; -"common_verify_identity" = "Verify identity"; +"common_verify_identity" = "Identität überprüfen"; "common_video" = "Video"; "common_voice_message" = "Sprachnachricht"; "common_waiting" = "Warten…"; "common_waiting_for_decryption_key" = "Warte auf diese Nachricht"; -"common.copied_to_clipboard" = "Copied to clipboard"; +"common.copied_to_clipboard" = "In die Zwischenablage kopiert"; "common.do_not_show_this_again" = "Nicht mehr anzeigen"; "common.open_source_licenses" = "Open-Source-Lizenzen"; "common.pinned" = "Fixiert"; "common.send_to" = "Senden an"; -"common.you" = "You"; -"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" = "Dein Chat-Backup ist derzeit nicht synchronisiert. Du musst deinen Wiederherstellungsschlüssel bestätigen, um Zugriff auf dein Chat-Backup zu erhalten."; -"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" = "Wiederherstellungsschlüssel bestätigen."; +"common.you" = "Sie"; +"common_unable_to_decrypt_insecure_device" = "Von einem ungesicherten Gerät gesendet"; +"common_unable_to_decrypt_verification_violation" = "Die verifizierte Identität des Senders hat sich geändert"; +"confirm_recovery_key_banner_message" = "Bestätigen Sie die Validität Ihres Wiederherstellungsschlüssels, um weiterhin auf Ihren Schlüsselspeicher und den Nachrichtenverlauf zugreifen zu können."; +"confirm_recovery_key_banner_primary_button_title" = "Geben Sie Ihren Wiederherstellungsschlüssel ein"; +"confirm_recovery_key_banner_secondary_button_title" = "Haben Sie Ihren Wiederherstellungsschlüssel vergessen?"; +"confirm_recovery_key_banner_title" = "Ihr Schlüsselspeicher ist nicht synchronisiert"; "crash_detection_dialog_content" = "%1$@ ist bei der letzten Nutzung abgestürzt. Möchtest du einen Absturzbericht mit uns teilen?"; -"crypto_identity_change_pin_violation" = "%1$@'s identity appears to have changed. %2$@"; -"crypto_identity_change_pin_violation_new" = "%1$@’s %2$@ identity appears to have changed. %3$@"; +"crypto_identity_change_pin_violation" = "%1$@'s Identität has sich offenbar geändert. %2$@"; +"crypto_identity_change_pin_violation_new" = "%1$@'s %2$@ Identität hat sich offenbar geändert. %3$@"; "crypto_identity_change_pin_violation_new_user_id" = "(%1$@)"; "dialog_permission_camera" = "Damit die Anwendung die Kamera verwenden kann, erteile bitte die Erlaubnis in den Systemeinstellungen."; "dialog_permission_generic" = "Bitte erteile die Erlaubnis in den Systemeinstellungen."; @@ -312,12 +315,12 @@ "notification_incoming_call" = "Eingehender Anruf"; "notification_inline_reply_failed" = "** Fehler beim Senden - bitte Raum öffnen"; "notification_invite_body" = "Du wurdest zu einem Chat eingeladen"; -"notification_invite_body_with_sender" = "%1$@ invited you to chat"; +"notification_invite_body_with_sender" = "%1$@ hat dich zum Chatten eingeladen"; "notification_mentioned_you_body" = "Hat Dich erwähnt: %1$@"; "notification_new_messages" = "Neue Nachrichten"; "notification_reaction_body" = "Reagiert mit %1$@"; "notification_room_invite_body" = "Du wurdest eingeladen, den Raum zu betreten"; -"notification_room_invite_body_with_sender" = "%1$@ invited you to join the room"; +"notification_room_invite_body_with_sender" = "%1$@ hat dich eingeladen, dem Chatroom beizutreten"; "notification_sender_me" = "Ich"; "notification_sender_mention_reply" = "%1$@ hat Dich erwähnt oder geantwortet"; "notification_test_push_notification_content" = "Du siehst dir die Benachrichtigung an! Klicke hier!"; @@ -349,32 +352,44 @@ "rich_text_editor_unindent" = "Ohne Einrückung"; "rich_text_editor_url_placeholder" = "Link"; "rich_text_editor_a11y_add_attachment" = "Anhang hinzufügen"; -"rich_text_editor_composer_caption_placeholder" = "Optional caption…"; +"rich_text_editor_composer_caption_placeholder" = "Optionale Bildunterschrift..."; "screen_advanced_settings_element_call_base_url" = "Benutzerdefinierte Element-Aufruf-Basis-URL"; "screen_advanced_settings_element_call_base_url_description" = "Lege eine eigene Basis-URL für Element Call fest."; "screen_advanced_settings_element_call_base_url_validation_error" = "Ungültige URL, bitte stelle sicher, dass du das Protokoll (http/https) und die richtige Adresse angibst."; -"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_button_title" = "Accept all"; -"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_create_room_room_access_section_anyone_option_description" = "Jeder kann diesem Chatroom beitreten"; +"screen_create_room_room_access_section_anyone_option_title" = "Jemand"; +"screen_create_room_room_access_section_header" = "Chatroom Zugang"; +"screen_create_room_room_access_section_knocking_option_description" = "Jeder kann darum bitten, dem Chatroom beizutreten, aber ein Administrator oder ein Moderator muss die Anfrage akzeptieren."; +"screen_create_room_room_access_section_knocking_option_title" = "Beitritt beantragen"; +"screen_create_room_room_address_invalid_symbols_error_description" = "Einige Zeichen sind nicht erlaubt. Es werden nur Buchstaben, Ziffern und die folgenden Symbole unterstützt: ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _"; +"screen_create_room_room_address_not_available_error_description" = "Diese Chatroomadresse existiert bereits. Bitte versuchen Sie, das Adressenfeld des Chatrooms zu bearbeiten oder den Namen des Chatrooms zu ändern"; +"screen_create_room_room_address_section_footer" = "Damit dieser Chatroom im öffentlichen Chatroomverzeichnis sichtbar ist, benötigen Sie eine Chatroomadresse."; +"screen_create_room_room_address_section_title" = "Chatroom Adresse"; +"screen_create_room_room_visibility_section_title" = " Sichtbarkeit des Chatrooms"; +"screen_join_room_cancel_knock_action" = "Anfrage abbrechen"; +"screen_join_room_cancel_knock_alert_confirmation" = "Ja, abbrechen"; +"screen_join_room_cancel_knock_alert_description" = "Möchten Sie Ihre Beitrittsanfrage für diesen Chatroom wirklich stornieren?"; +"screen_join_room_cancel_knock_alert_title" = "Beitrittsanfrage stornieren"; +"screen_join_room_knock_message_description" = "Nachricht (optional)"; +"screen_join_room_knock_sent_description" = "Falls Ihre Anfrage, dem Raum beizutreten, akzeptiert wird, werden Sie eine Einladung erhalten."; +"screen_join_room_knock_sent_title" = "Beitrittsanfrage geschickt"; +"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Ja, akzeptiere alle"; +"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_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_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_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_title" = "Beitrittsanfragen"; +"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."; "screen_pinned_timeline_empty_state_description" = "Drücke auf eine Nachricht und wähle “%1$@”, um sie hier einzufügen."; "screen_pinned_timeline_empty_state_headline" = "Fixiere wichtige Nachrichten, so dass sie leicht gefunden werden können"; "screen_reset_encryption_password_error" = "Es ist ein unbekannter Fehler aufgetreten. Bitte überprüfe das Passwort deines Kontos und versuche es erneut."; @@ -384,23 +399,23 @@ "screen_resolve_send_failure_unsigned_device_primary_button_title" = "Nachricht trotzdem senden"; "screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ verwendet wenigstens ein nicht verifiziertes Gerät. Du kannst die Nachricht trotzdem verschicken, oder vorerst abbrechen und später erneut versuchen, nachdem %2$@ alle Geräte verifiziert hat."; "screen_resolve_send_failure_unsigned_device_title" = "Deine Nachricht wurde nicht gesendet, weil %1$@ nicht alle Geräte verifiziert hat"; -"screen_resolve_send_failure_you_unsigned_device_subtitle" = "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices."; -"screen_resolve_send_failure_you_unsigned_device_title" = "Your message was not sent because you have not verified one or more of your devices"; +"screen_resolve_send_failure_you_unsigned_device_subtitle" = "Mindestens eines Ihrer Geräte ist nicht verifiziert worden. Sie können die Nachricht trotzdem senden, oder den Vorgang zunächst abbrechen und es später erneut versuchen, nachdem Sie alle Ihrer Geräte verifiziert haben."; +"screen_resolve_send_failure_you_unsigned_device_title" = "Ihre Nachricht wurde nicht geschickt, da Sie eines oder mehrere Ihrer Geräte nicht verifiziert haben."; "screen_room_mentions_at_room_subtitle" = "Alle Mitglieder benachrichtigen"; -"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; +"screen_room_multiple_knock_requests_view_all_button_title" = "Alles ansehen"; "screen_room_pinned_banner_indicator" = "%1$@ von %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ fixierte Nachrichten"; "screen_room_pinned_banner_loading_description" = "Nachricht wird geladen…"; "screen_room_pinned_banner_view_all_button_title" = "Alle anzeigen"; -"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" = "Akzeptieren"; +"screen_room_single_knock_request_title" = "%1$@ möchte diesem Chatroom beitreten"; +"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" = "Requests to join"; -"screen_roomlist_knock_event_sent_description" = "Request to join sent"; +"screen_room_details_requests_to_join_title" = "Beitrittsanfragen"; +"screen_roomlist_knock_event_sent_description" = "Beitrittsanfrage gesendet"; "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" = "Message not sent because you have not verified one or more of your devices."; +"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."; "screen_account_provider_form_hint" = "Homeserver-Adresse"; "screen_account_provider_form_notice" = "Gib einen Suchbegriff oder eine Domainadresse ein."; "screen_account_provider_form_subtitle" = "Suche nach einem Unternehmen, einer Community oder einem privaten Server."; @@ -409,8 +424,8 @@ "screen_account_provider_signup_title" = "Du bist dabei, ein Konto bei %@ zu erstellen"; "screen_advanced_settings_developer_mode" = "Entwickler-Modus"; "screen_advanced_settings_developer_mode_description" = "Aktivieren, um Zugriff auf Features und Funktionen für Entwickler zu aktivieren."; -"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" = "Laden Sie Fotos und Videos schneller hoch und reduzieren Sie die Datennutzung"; +"screen_advanced_settings_media_compression_title" = "Optimieren Sie die Medienqualität"; "screen_advanced_settings_rich_text_editor_description" = "Deaktiviere den Rich-Text-Editor, um Markdown manuell einzugeben."; "screen_advanced_settings_send_read_receipts" = "Lesebestätigungen"; "screen_advanced_settings_send_read_receipts_description" = "Wenn diese Option deaktiviert ist, werden Ihre Lesebestätigungen an niemanden gesendet. Du erhältst weiterhin Lesebestätigungen von anderen Benutzern."; @@ -477,14 +492,14 @@ "screen_change_server_title" = "Wähle deinen Server aus"; "screen_chat_backup_key_backup_action_disable" = "Backup deaktivieren"; "screen_chat_backup_key_backup_action_enable" = "Backup aktivieren"; -"screen_chat_backup_key_backup_description" = "Das Backup stellt sicher, dass du deinen Nachrichtenverlauf nicht verlierst. %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" = "Speichern Sie Ihre verschlüsselte Identität und Ihre codierten Nachrichtenschlüssel auf dem Server. Auf diese Weise können Sie Ihren Nachrichtenverlauf auf allen neuen Geräten einsehen. %1$@."; +"screen_chat_backup_key_backup_title" = "Schlüsselspeicher"; +"screen_chat_backup_key_storage_disabled_error" = "Der Schlüsselspeicher muss aktiviert sein, um Datenwiederherstellung zu ermöglichen."; +"screen_chat_backup_key_storage_toggle_description" = "Schlüssel von diesem Gerät hochladen"; +"screen_chat_backup_key_storage_toggle_title" = "Schlüsselspeicherung zulassen"; "screen_chat_backup_recovery_action_change" = "Wiederherstellungsschlüssel ändern"; -"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" = "Dein Chat-Backup ist derzeit nicht synchronisiert."; +"screen_chat_backup_recovery_action_change_description" = "Stellen Sie Ihre verschlüsselte Identität und Ihren Nachrichtenverlauf mit einem Wiederherstellungsschlüssel wieder her, falls Sie den Zugang zu allen Ihren Geräten verloren haben."; +"screen_chat_backup_recovery_action_confirm_description" = "Dein Schlüssel ist derzeit nicht synchronisiert."; "screen_chat_backup_recovery_action_setup_description" = "Erhalte Zugriff auf deine verschlüsselten Nachrichten, wenn du alle deine Geräte verlierst oder von %1$@ überall abgemeldet bist."; "screen_create_account_title" = "Konto erstellen"; "screen_create_new_recovery_key_list_item_1" = "Öffne %1$@ auf einem Desktop-Gerät"; @@ -504,22 +519,22 @@ "screen_create_poll_title" = "Umfrage erstellen"; "screen_create_room_action_create_room" = "Neuer Raum"; "screen_create_room_error_creating_room" = "Beim Erstellen des Chats ist ein Fehler aufgetreten"; -"screen_create_room_private_option_description" = "Die Nachrichten in diesem Chat sind verschlüsselt. Die Verschlüsselung kann nicht nachträglich deaktiviert werden."; -"screen_create_room_private_option_title" = "Privater Raum (nur auf Einladung)"; -"screen_create_room_public_option_description" = "Die Nachrichten sind nicht verschlüsselt und können von jedem gelesen werden. Die Verschlüsselung kann zu einem späteren Zeitpunkt aktiviert werden."; -"screen_create_room_public_option_title" = "Öffentlicher Raum (für alle)"; +"screen_create_room_private_option_description" = "Nur eingeladene Personen haben Zutritt zu diesem Chatroom. Alle Nachrichten sind durchgehend verschlüsselt."; +"screen_create_room_private_option_title" = "Privater Chatroom"; +"screen_create_room_public_option_description" = "Jeder kann diesen Chatroom finden.\nSie können dies aber jederzeit in den Chatroomeinstellungen ändern."; +"screen_create_room_public_option_title" = "Öffentlicher Chatroom"; "screen_create_room_topic_label" = "Thema (optional)"; -"screen_deactivate_account_confirmation_dialog_content" = "Please confirm that you want to deactivate your account. This action cannot be undone."; -"screen_deactivate_account_delete_all_messages" = "Delete all my messages"; -"screen_deactivate_account_delete_all_messages_notice" = "Warning: Future users may see incomplete conversations."; -"screen_deactivate_account_description" = "Deactivating your account is %1$@, it will:"; -"screen_deactivate_account_description_bold_part" = "irreversible"; -"screen_deactivate_account_list_item_1" = "%1$@ your account (you can't log back in, and your ID can't be reused)."; -"screen_deactivate_account_list_item_1_bold_part" = "Permanently disable"; -"screen_deactivate_account_list_item_2" = "Remove you from all chat rooms."; -"screen_deactivate_account_list_item_3" = "Delete your account information from our identity server."; -"screen_deactivate_account_list_item_4" = "Your messages will still be visible to registered users but won’t be available to new or unregistered users if you choose to delete them."; -"screen_deactivate_account_title" = "Deactivate account"; +"screen_deactivate_account_confirmation_dialog_content" = "Bitte bestätigen Sie, dass Sie Ihr Benutzerkonto deaktivieren möchten. Diese Aktion kann nicht rückgängig gemacht werden."; +"screen_deactivate_account_delete_all_messages" = "Lösche alle meine Nachrichten"; +"screen_deactivate_account_delete_all_messages_notice" = "Warnung: Benutzern werden möglicherweise unvollständige Konversationen angezeigt."; +"screen_deactivate_account_description" = "Wenn Sie Ihr Konto deaktivieren%1$@, wird es:"; +"screen_deactivate_account_description_bold_part" = "irreversibel"; +"screen_deactivate_account_list_item_1" = "%1$@ Ihr Konto (Sie können sich nicht erneut anmelden und Ihre ID kann nicht wiederverwendet werden)."; +"screen_deactivate_account_list_item_1_bold_part" = "Dauerhaft deaktivieren"; +"screen_deactivate_account_list_item_2" = "Sie werden aus allen Chatrooms entfernt."; +"screen_deactivate_account_list_item_3" = "Löschen Sie Ihre Kontoinformationen von unserem Identitätsserver."; +"screen_deactivate_account_list_item_4" = "Gelöschte Nachrichten werden für bereits registrierte Benutzer weiterhin sichtbar sein, wenn sie auch neuen oder nicht registrierten Benutzern nicht mehr zur Verfügung stehen."; +"screen_deactivate_account_title" = "Benutzerkonto deaktivieren"; "screen_edit_poll_delete_confirmation" = "Bist du dir sicher, dass du diese Umfrage löschen möchtest?"; "screen_edit_profile_display_name" = "Anzeigename"; "screen_edit_profile_display_name_placeholder" = "Dein Anzeigename"; @@ -531,9 +546,9 @@ "screen_encryption_reset_bullet_1" = "Deine Kontodaten, Kontakte, Einstellungen und die Liste der Chats bleiben erhalten"; "screen_encryption_reset_bullet_2" = "Du verlierst alle deine bisherigen Nachrichten sofern sie nicht auf einem anderen Gerät vorliegen"; "screen_encryption_reset_bullet_3" = "Du musst alle deine bestehenden Geräte und Kontakte erneut verifizieren."; -"screen_encryption_reset_footer" = "Only reset your identity if you don’t have access to another signed-in device and you’ve lost your recovery key."; -"screen_encryption_reset_title" = "Can't confirm? You’ll need to reset your identity."; -"screen_identity_confirmation_cannot_confirm" = "Can't confirm?"; +"screen_encryption_reset_footer" = "Setzen Sie Ihre Identität nur dann zurück, wenn Sie keinen Zugriff auf ein anderes Ihrer angemeldeten Geräte und auch Ihren Wiederherstellungsschlüssel verloren haben."; +"screen_encryption_reset_title" = "Sie können es nicht bestätigen? Dann müssen Sie Ihre Identität zurücksetzen."; +"screen_identity_confirmation_cannot_confirm" = "Sie können es nicht bestätigen?"; "screen_identity_confirmation_create_new_recovery_key" = "Erstelle einen neuen Wiederherstellungsschlüssel"; "screen_identity_confirmation_subtitle" = "Verifiziere dieses Gerät, um sicheres Messaging einzurichten."; "screen_identity_confirmation_title" = "Bestätige, dass du es bist"; @@ -572,8 +587,6 @@ "screen_login_title" = "Willkommen zurück!"; "screen_login_title_with_homeserver" = "Anmelden bei %1$@"; "screen_media_picker_error_failed_selection" = "Medienauswahl fehlgeschlagen, bitte versuche es erneut."; -"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."; "screen_migration_message" = "Dies ist ein einmaliger Vorgang, danke fürs Warten."; "screen_migration_title" = "Dein Konto wird eingerichtet."; "screen_notification_optin_subtitle" = "Du kannst deine Einstellungen später ändern."; @@ -640,7 +653,7 @@ "screen_qr_code_login_initial_state_item_3" = "Wähle %1$@"; "screen_qr_code_login_initial_state_item_3_action" = "\"Neues Gerät verknüpfen\""; "screen_qr_code_login_initial_state_item_4" = "Scanne den QR-Code mit diesem Gerät"; -"screen_qr_code_login_initial_state_subtitle" = "Only available if your account provider supports it."; +"screen_qr_code_login_initial_state_subtitle" = "Nur verfügbar für den Fall dass Ihr Kontoanbieter dies unterstützt."; "screen_qr_code_login_initial_state_title" = "Öffne %1$@ auf einem anderen Gerät, um den QR-Code zu erhalten"; "screen_qr_code_login_invalid_scan_state_description" = "Verwende den QR-Code, der auf dem anderen Gerät angezeigt wird."; "screen_qr_code_login_invalid_scan_state_subtitle" = "Falscher QR-Code"; @@ -659,7 +672,7 @@ "screen_recovery_key_change_title" = "Wiederherstellungsschlüssel ändern?"; "screen_recovery_key_confirm_create_new_recovery_key" = "Neuen Wiederherstellungsschlüssel erstellen"; "screen_recovery_key_confirm_description" = "Sorge dafür, dass niemand diesen Bildschirm sehen kann!"; -"screen_recovery_key_confirm_error_content" = "Bitte versuche es noch einmal, um den Zugriff auf dein Chat-Backup zu bestätigen."; +"screen_recovery_key_confirm_error_content" = "Bitte versuchen Sie erneut, den Zugriff auf Ihren Schlüsselspeicher zu bestätigen."; "screen_recovery_key_confirm_error_title" = "Falscher Wiederherstellungsschlüssel"; "screen_recovery_key_confirm_key_description" = "Dies funktioniert auch mit einem Sicherheitsschlüssel oder Sicherheitsphrase."; "screen_recovery_key_confirm_key_placeholder" = "Eingeben..."; @@ -668,14 +681,14 @@ "screen_recovery_key_copied_to_clipboard" = "Wiederherstellungsschlüssel kopiert"; "screen_recovery_key_generating_key" = "Generieren…"; "screen_recovery_key_save_action" = "Wiederherstellungsschlüssel speichern"; -"screen_recovery_key_save_description" = "Notiere dir deinen Wiederherstellungsschlüssel an einem sicheren Ort oder speichere ihn in einem Passwort-Manager."; +"screen_recovery_key_save_description" = "Schreiben Sie Ihren Wiederherstellungsschlüssel in eine verschlüsselte Datei, oder in einem Passwort-Manager oder in einem Safe. "; "screen_recovery_key_save_key_description" = "Tippe, um den Wiederherstellungsschlüssel zu kopieren"; "screen_recovery_key_save_title" = "Speichere deinen Wiederherstellungsschlüssel"; "screen_recovery_key_setup_confirmation_description" = "Nach diesem Schritt kannst du nicht mehr auf deinen neuen Wiederherstellungsschlüssel zugreifen."; "screen_recovery_key_setup_confirmation_title" = "Hast du deinen Wiederherstellungsschlüssel gespeichert?"; "screen_recovery_key_setup_description" = "Dein Chat-Backup ist durch einen Wiederherstellungsschlüssel geschützt. Wenn du nach der Einrichtung einen neuen Wiederherstellungsschlüssel brauchst, kannst du ihn über die Option \"Wiederherstellungsschlüssel ändern\" neu erstellen."; "screen_recovery_key_setup_generate_key" = "Wiederherstellungsschlüssel erstellen"; -"screen_recovery_key_setup_generate_key_description" = "Stelle sicher, dass du deinen Wiederherstellungsschlüssel an einem sicheren Ort aufbewahren kannst"; +"screen_recovery_key_setup_generate_key_description" = "Geben Sie dies an niemanden weiter!"; "screen_recovery_key_setup_success" = "Einrichtung der Wiederherstellung erfolgreich"; "screen_recovery_key_setup_title" = "Wiederherstellung einrichten"; "screen_report_content_block_user_hint" = "Prüfe, ob du alle aktuellen und zukünftigen Nachrichten dieses Benutzers ausblenden möchtest"; @@ -749,8 +762,8 @@ "screen_room_member_details_unblock_alert_action" = "Blockierung aufheben"; "screen_room_member_details_unblock_alert_description" = "Der Nutzer kann dir wieder Nachrichten senden & alle Nachrichten des Nutzers werden wieder angezeigt."; "screen_room_member_details_unblock_user" = "Blockierung aufheben"; -"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" = "Verwenden Sie die Web-App, um diesen Benutzer zu verifizieren."; +"screen_room_member_details_verify_button_title" = "Überprüfen Sie %1$@"; "screen_room_member_list_ban_member_confirmation_action" = "Sperren"; "screen_room_member_list_ban_member_confirmation_description" = "Sie können dem Raum nicht mehr beitreten, selbst wenn sie eingeladen werden."; "screen_room_member_list_ban_member_confirmation_title" = "Bist du sicher, dass du dieses Mitglied sperren möchtest?"; @@ -804,7 +817,7 @@ "screen_room_timeline_add_reaction" = "Emoji hinzufügen"; "screen_room_timeline_beginning_of_room" = "Dies ist der Anfang von %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Dies ist der Anfang dieses Gesprächs."; -"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; +"screen_room_timeline_legacy_call" = "Anruftyp wird nicht unterstützt. Fragen Sie nach, ob der Anrufer die neue Element X-App verwenden kann."; "screen_room_timeline_less_reactions" = "Weniger anzeigen"; "screen_room_timeline_message_copied" = "Nachricht wurde kopiert"; "screen_room_timeline_no_permission_to_post" = "Du bist nicht berechtigt, in diesem Raum zu schreiben"; @@ -848,7 +861,7 @@ "screen_session_verification_compare_numbers_title" = "Vergleiche die Zahlen"; "screen_session_verification_complete_subtitle" = "Deine neue Session ist nun verifiziert. Sie hat Zugriff auf deine verschlüsselten Nachrichten und wird von anderen Benutzern als vertrauenswürdig eingestuft."; "screen_session_verification_enter_recovery_key" = "Wiederherstellungsschlüssel eingeben"; -"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" = "Entweder ist bei der Anfrage ein Timeout aufgetreten, oder die Anfrage wurde abgelehnt, oder es gab eine Nichtübereinstimmung bei der Überprüfung."; "screen_session_verification_open_existing_session_subtitle" = "Beweise deine Identität, um auf deinen verschlüsselten Nachrichtenverlauf zuzugreifen."; "screen_session_verification_open_existing_session_title" = "Öffne eine bestehende Session"; "screen_session_verification_positive_button_canceled" = "Verifizierung wiederholen"; @@ -856,19 +869,19 @@ "screen_session_verification_positive_button_verifying_ongoing" = "Warten auf eine Übereinstimmung"; "screen_session_verification_ready_subtitle" = "Vergleiche eine spezielle Reihe von Emojis."; "screen_session_verification_request_accepted_subtitle" = "Vergleiche die einzelnen Emojis und stelle sicher, dass sie in der gleichen Reihenfolge erscheinen."; -"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" = "Angemeldet"; +"screen_session_verification_request_failure_title" = "Überprüfung fehlgeschlagen"; +"screen_session_verification_request_footer" = "Fahren Sie nur fort, falls Sie für diese Überprüfung verantwortlich sind.."; +"screen_session_verification_request_subtitle" = "Verifizieren Sie das andere Gerät, um die Sicherheit Ihres Nachrichtenverlaufs zu gewährleisten."; +"screen_session_verification_request_success_subtitle" = "Jetzt können Sie gesichert Nachrichten auf Ihrem anderen Gerät lesen oder senden."; +"screen_session_verification_request_success_title" = "Gerät verifiziert"; +"screen_session_verification_request_title" = "Verifizierung angefordert"; "screen_session_verification_they_dont_match" = "Sie stimmen nicht überein"; "screen_session_verification_they_match" = "Sie stimmen überein"; -"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" = "Stellen Sie sicher, dass die App auf dem anderen Gerät geöffnet ist, bevor Sie die Überprüfung auf diesem Gerät aus starten."; +"screen_session_verification_use_another_device_title" = "Öffnen Sie die App auf einem anderen verifizierten Gerät"; +"screen_session_verification_waiting_another_device_subtitle" = "Sie sollten ein Popup-Fenster auf dem anderen Gerät sehen. Starten Sie die Überprüfung von dort aus."; +"screen_session_verification_waiting_another_device_title" = "Starten Sie die Überprüfung auf dem anderen Gerät"; "screen_session_verification_waiting_to_accept_subtitle" = "Akzeptiere die Anfrage, um den Verifizierungsprozess in deiner anderen Session zu starten, um fortzufahren."; "screen_session_verification_waiting_to_accept_title" = "Warten auf die Annahme der Anfrage"; "screen_share_location_title" = "Standort teilen"; @@ -933,7 +946,7 @@ "state_event_room_invite_you" = "%1$@ hat dich eingeladen"; "state_event_room_join" = "%1$@ hat den Raum betreten"; "state_event_room_join_by_you" = "Du hast den Raum betreten"; -"state_event_room_knock" = "%1$@ hat angefragt beizutreten"; +"state_event_room_knock" = "%1$@ beantragt den Beitritt"; "state_event_room_knock_accepted" = "%1$@ hat %2$@ den Beitritt erlaubt"; "state_event_room_knock_accepted_by_you" = "Du hast %1$@ den Beitritt erlaubt."; "state_event_room_knock_by_you" = "Du hast angefragt beizutreten"; @@ -1054,8 +1067,8 @@ "screen_login_subtitle" = "Matrix ist ein offenes Netzwerk für eine sichere, dezentrale Kommunikation."; "screen_notification_settings_mentions_section_title" = "Erwähnungen"; "screen_qr_code_login_invalid_scan_state_retry_button" = "Erneut versuchen"; -"screen_recovery_key_change_generate_key_description" = "Stelle sicher, dass du deinen Wiederherstellungsschlüssel an einem sicheren Ort aufbewahren kannst"; -"screen_recovery_key_confirm_title" = "Enter your recovery key"; +"screen_recovery_key_change_generate_key_description" = "Geben Sie dies an niemanden weiter!"; +"screen_recovery_key_confirm_title" = "Geben Sie Ihren Wiederherstellungsschlüssel ein"; "screen_report_content_block_user" = "Benutzer blockieren"; "screen_reset_encryption_password_placeholder" = "Eingeben..."; "screen_room_attachment_source_camera_photo" = "Foto aufnehmen"; @@ -1081,7 +1094,7 @@ "screen_room_timeline_reactions_show_less" = "Weniger anzeigen"; "screen_roomlist_filter_people" = "Personen"; "screen_server_confirmation_change_server" = "Kontoanbieter wechseln"; -"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" = "Entweder ist bei der Anfrage ein Timeout aufgetreten, oder die Anfrage wurde abgelehnt, oder es gab eine Nichtübereinstimmung bei der Überprüfung."; "screen_signout_confirmation_dialog_submit" = "Abmelden"; "screen_signout_confirmation_dialog_title" = "Abmelden"; "screen_signout_key_backup_offline_title" = "Deine Schlüssel werden noch gesichert"; diff --git a/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict index b31e5f4185..6ce7634c6b 100644 --- a/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/de.lproj/Localizable.stringsdict @@ -237,9 +237,9 @@ NSStringFormatValueTypeKey d one - %1$@ +%2$d other want to join this room + %1$@+ %2$d andere wollen diesem Chatroom beitreten other - %1$@ +%2$d others want to join this room + %1$@+ %2$d andere wollen diesem Chatroom beitreten screen_room_timeline_state_changes diff --git a/ElementX/Resources/Localizations/el.lproj/Localizable.strings b/ElementX/Resources/Localizations/el.lproj/Localizable.strings index 9d2a10296c..4c56b70a3c 100644 --- a/ElementX/Resources/Localizations/el.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/el.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Επιβεβαίωση κωδικού πρόσβασης"; "action_continue" = "Συνέχεια"; "action_copy" = "Αντιγραφή"; +"action_copy_caption" = "Αντιγραφή λεζάντας"; "action_copy_link" = "Αντιγραφή συνδέσμου"; "action_copy_link_to_message" = "Αντιγραφή συνδέσμου στο μήνυμα"; +"action_copy_text" = "Αντιγραφή κειμένου"; "action_create" = "Δημιουργία"; "action_create_a_room" = "Δημιούργησε ένα δωμάτιο"; "action_deactivate" = "Απενεργοποίηση"; @@ -84,6 +86,7 @@ "action_reject" = "Απόρριψη"; "action_remove" = "Αφαίρεση"; "action_remove_caption" = "Αφαίρεση λεζάντας"; +"action_remove_message" = "Αφαίρεση μηνύματος"; "action_reply" = "Απάντηση"; "action_reply_in_thread" = "Απάντηση στο θέμα"; "action_report_bug" = "Αναφορά σφάλματος"; @@ -370,11 +373,23 @@ "screen_join_room_knock_message_description" = "Μήνυμα (προαιρετικό)"; "screen_join_room_knock_sent_description" = "Θα λάβεις πρόσκληση για συμμετοχή στο δωμάτιο εάν το αίτημά σου γίνει αποδεκτό."; "screen_join_room_knock_sent_title" = "Το αίτημα συμμετοχής στάλθηκε"; +"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Ναι, αποδοχή όλων"; +"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_ban_alert_confirm_button_title" = "Ναι, απόρριψη και αποκλεισμός"; +"screen_knock_requests_list_ban_alert_description" = "Σίγουρα θες να απορρίψειε και να αποκλείσεις τον χρήστη %1$@; Αυτός ο χρήστης δεν θα μπορεί να ζητήσει πρόσβαση για να συμμετάσχει ξανά σε αυτό το δωμάτιο."; +"screen_knock_requests_list_ban_alert_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_empty_state_description" = "Όταν κάποιος θα ζητήσει να συμμετάσχει στο δωμάτιο, θα μπορείς να δεις το αίτημά του εδώ."; "screen_knock_requests_list_empty_state_title" = "Δεν υπάρχει εκκρεμές αίτημα συμμετοχής"; "screen_knock_requests_list_title" = "Αιτήματα συμμετοχής"; +"screen_media_upload_preview_caption_warning" = "Οι λεζάντες ενδέχεται να μην είναι ορατές σε άτομα που χρησιμοποιούν παλαιότερες εφαρμογές."; +"screen_media_upload_preview_error_failed_processing" = "Αποτυχία μεταφόρτωσης μέσου, δοκίμασε ξανά."; +"screen_media_upload_preview_error_failed_sending" = "Αποτυχία μεταφόρτωσης πολυμέσων, δοκίμασε ξανά."; "screen_pinned_timeline_empty_state_description" = "Πάτα σε ένα μήνυμα και επέλεξε «%1$@» για να συμπεριληφθεί εδώ."; "screen_pinned_timeline_empty_state_headline" = "Καρφίτσωσε σημαντικά μηνύματα, ώστε να μπορούν να εντοπιστούν εύκολα"; "screen_reset_encryption_password_error" = "Συνέβη ένα άγνωστο σφάλμα. Έλεγξε ότι ο κωδικός πρόσβασης του λογαριασμού σου είναι σωστός και δοκίμασε ξανά."; @@ -572,8 +587,6 @@ "screen_login_title" = "Καλωσόρισες ξανά!"; "screen_login_title_with_homeserver" = "Συνδέσου στο %1$@"; "screen_media_picker_error_failed_selection" = "Αποτυχία επιλογής πολυμέσου, δοκίμασε ξανά."; -"screen_media_upload_preview_error_failed_processing" = "Αποτυχία μεταφόρτωσης μέσου, δοκίμασε ξανά."; -"screen_media_upload_preview_error_failed_sending" = "Αποτυχία μεταφόρτωσης πολυμέσων, δοκίμασε ξανά."; "screen_migration_message" = "Αυτή είναι μια εφάπαξ διαδικασία, ευχαριστώ που περίμενες."; "screen_migration_title" = "Ρύθμιση του λογαριασμού σου."; "screen_notification_optin_subtitle" = "Μπορείς να αλλάξεις τις ρυθμίσεις σου αργότερα."; diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 050bd10328..18d852607c 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -362,7 +362,7 @@ "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_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"; diff --git a/ElementX/Resources/Localizations/es.lproj/Localizable.strings b/ElementX/Resources/Localizations/es.lproj/Localizable.strings index 71aa00537b..1ac660bde8 100644 --- a/ElementX/Resources/Localizations/es.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/es.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Confirm password"; "action_continue" = "Continuar"; "action_copy" = "Copiar"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Copiar enlace"; "action_copy_link_to_message" = "Copiar enlace al mensaje"; +"action_copy_text" = "Copy text"; "action_create" = "Crear"; "action_create_a_room" = "Crear una sala"; "action_deactivate" = "Deactivate"; @@ -84,6 +86,7 @@ "action_reject" = "Reject"; "action_remove" = "Eliminar"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Responder"; "action_reply_in_thread" = "Responder en el hilo"; "action_report_bug" = "Informar de un error"; @@ -359,7 +362,7 @@ "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_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"; @@ -370,11 +373,23 @@ "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_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."; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -572,8 +587,6 @@ "screen_login_title" = "¡Hola de nuevo!"; "screen_login_title_with_homeserver" = "Iniciar sesión en %1$@"; "screen_media_picker_error_failed_selection" = "Error al seleccionar archivos multimedia, por favor inténtalo de nuevo."; -"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."; "screen_migration_message" = "Este proceso solo se hace una vez, gracias por esperar."; "screen_migration_title" = "Configura tu cuenta"; "screen_notification_optin_subtitle" = "Puedes cambiar la configuración más tarde."; diff --git a/ElementX/Resources/Localizations/et.lproj/Localizable.strings b/ElementX/Resources/Localizations/et.lproj/Localizable.strings index 3b206cc39e..ea7f3cd3f9 100644 --- a/ElementX/Resources/Localizations/et.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/et.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Kinnita otsust oma salasõnaga"; "action_continue" = "Jätka"; "action_copy" = "Kopeeri"; +"action_copy_caption" = "Kopeeri selgitus"; "action_copy_link" = "Kopeeri link"; "action_copy_link_to_message" = "Kopeeri sõnumi link"; +"action_copy_text" = "Kopeeri tekst"; "action_create" = "Loo"; "action_create_a_room" = "Loo jututuba"; "action_deactivate" = "Eemalda konto"; @@ -84,6 +86,7 @@ "action_reject" = "Keeldu"; "action_remove" = "Eemalda"; "action_remove_caption" = "Eemalda selgitus"; +"action_remove_message" = "Eemalda sõnum"; "action_reply" = "Vasta"; "action_reply_in_thread" = "Vasta jutulõngas"; "action_report_bug" = "Teata veast"; @@ -349,7 +352,7 @@ "rich_text_editor_unindent" = "Eemalda taandrida"; "rich_text_editor_url_placeholder" = "Link"; "rich_text_editor_a11y_add_attachment" = "Lisa manus"; -"rich_text_editor_composer_caption_placeholder" = "Pealkiri, kui soovid lisada…"; +"rich_text_editor_composer_caption_placeholder" = "Selgitus või nimi, kui soovid lisada…"; "screen_advanced_settings_element_call_base_url" = "Element Calli kohandatud teenuseaadress"; "screen_advanced_settings_element_call_base_url_description" = "Seadista kohandatud teenuseaadress Element Calli jaoks."; "screen_advanced_settings_element_call_base_url_validation_error" = "Vigane url. Palun vaata, et url algaks protokolliga (http/https) ning aadress ise oleks ka õige."; @@ -370,11 +373,23 @@ "screen_join_room_knock_message_description" = "Selgitus (kui soovid lisada)"; "screen_join_room_knock_sent_description" = "Kui sinu liitumispalvega ollakse nõus, siis saad kutse jututoaga liitumiseks."; "screen_join_room_knock_sent_title" = "Liitumispalve on saadetud"; +"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Jah, võta kõik vastu"; +"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_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_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_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_title" = "Liitumispalved"; +"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."; "screen_pinned_timeline_empty_state_description" = "Siia lisamiseks vajuta sõnumil ja vali „%1$@“."; "screen_pinned_timeline_empty_state_headline" = "Et olulisi sõnumeid oleks lihtsam leida, tõsta nad esile"; "screen_reset_encryption_password_error" = "Tekkis teadmata viga. Palun kontrolli, kas sinu kasutajakonto salasõna on õige ja proovi uuesti."; @@ -572,8 +587,6 @@ "screen_login_title" = "Tere tulemast tagasi!"; "screen_login_title_with_homeserver" = "Logi sisse serverisse %1$@"; "screen_media_picker_error_failed_selection" = "Meediafaili valimine ei õnnestunud. Palun proovi uuesti."; -"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."; "screen_migration_message" = "Tänud, et ootad - seda toimingut on vaja teha vaid üks kord."; "screen_migration_title" = "Seadistame sinu kasutajakontot."; "screen_notification_optin_subtitle" = "Sa võid seadistusi hiljem alati muuta."; diff --git a/ElementX/Resources/Localizations/fa.lproj/Localizable.strings b/ElementX/Resources/Localizations/fa.lproj/Localizable.strings index 9b81467001..03821d049a 100644 --- a/ElementX/Resources/Localizations/fa.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fa.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "تأیید گذرواژه"; "action_continue" = "ادامه"; "action_copy" = "رونوشت"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "رونوشت از پیوند"; "action_copy_link_to_message" = "رونوشت از پیوند پیام"; +"action_copy_text" = "Copy text"; "action_create" = "ایجاد"; "action_create_a_room" = "ایجاد اتاق"; "action_deactivate" = "غیرفعّال"; @@ -84,6 +86,7 @@ "action_reject" = "رد کردن"; "action_remove" = "برداشتن"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "پاسخ"; "action_reply_in_thread" = "پاسخ در رشته"; "action_report_bug" = "گزارش اشکال"; @@ -359,7 +362,7 @@ "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_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"; @@ -370,11 +373,23 @@ "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_media_upload_preview_error_failed_processing" = "پردازش رسانه برای بارگذاری شکست خورد. لطفاً دوباره تلاش کنید."; +"screen_media_upload_preview_error_failed_sending" = "بارگذاری رسانه شکست خورد. لطفاً دوباره تلاش کنید."; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -572,8 +587,6 @@ "screen_login_title" = "خوش برگشتید!"; "screen_login_title_with_homeserver" = "ورود به %1$@"; "screen_media_picker_error_failed_selection" = "گزینش رسانه شکست خورد. لطفاً دوباره تلاش کنید."; -"screen_media_upload_preview_error_failed_processing" = "پردازش رسانه برای بارگذاری شکست خورد. لطفاً دوباره تلاش کنید."; -"screen_media_upload_preview_error_failed_sending" = "بارگذاری رسانه شکست خورد. لطفاً دوباره تلاش کنید."; "screen_migration_message" = "فرایندی یک باره است. ممنون از شکیباییتان."; "screen_migration_title" = "برپایی حسابتان."; "screen_notification_optin_subtitle" = "می‌توانید بعداً تنظیماتتان را تغییر دهید."; diff --git a/ElementX/Resources/Localizations/fi.lproj/Localizable.strings b/ElementX/Resources/Localizations/fi.lproj/Localizable.strings index 8ec1f1dbe8..3c44d7e5ae 100644 --- a/ElementX/Resources/Localizations/fi.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fi.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Vahvista salasana"; "action_continue" = "Jatka"; "action_copy" = "Kopioi"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Kopioi linkki"; "action_copy_link_to_message" = "Kopioi linkki viestiin"; +"action_copy_text" = "Copy text"; "action_create" = "Luo"; "action_create_a_room" = "Luo huone"; "action_deactivate" = "Deaktivoi"; @@ -84,6 +86,7 @@ "action_reject" = "Hylkää"; "action_remove" = "Poista"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Vastaa"; "action_reply_in_thread" = "Vastaa ketjuun"; "action_report_bug" = "Ilmoita virheestä"; @@ -370,11 +373,23 @@ "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_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."; "screen_pinned_timeline_empty_state_headline" = "Kiinnitä tärkeät viestit, jotta ne löytyvät helposti."; "screen_reset_encryption_password_error" = "Tapahtui tuntematon virhe. Tarkista, että tilisi salasana on oikein ja yritä uudelleen."; @@ -572,8 +587,6 @@ "screen_login_title" = "Tervetuloa takaisin!"; "screen_login_title_with_homeserver" = "Kirjaudu sisään %1$@ -palvelimelle"; "screen_media_picker_error_failed_selection" = "Median valinta epäonnistui, yritä uudelleen."; -"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_migration_message" = "Tämä on kertaluonteinen prosessi, kiitos odottamisesta."; "screen_migration_title" = "Tiliä määritetään."; "screen_notification_optin_subtitle" = "Voit muuttaa asetuksia myöhemmin."; diff --git a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings index fa725fba8d..02ba04bf50 100644 --- a/ElementX/Resources/Localizations/fr.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/fr.lproj/Localizable.strings @@ -22,7 +22,7 @@ "a11y_voice_message_record" = "Enregistrer un message vocal."; "a11y_voice_message_stop_recording" = "Arrêter l'enregistrement"; "action_accept" = "Accepter"; -"action_add_caption" = "Add caption"; +"action_add_caption" = "Ajouter une légende"; "action_add_to_timeline" = "Ajouter à la discussion"; "action_back" = "Retour"; "action_call" = "Appel"; @@ -36,8 +36,10 @@ "action_confirm_password" = "Confirmez le mot de passe"; "action_continue" = "Continuer"; "action_copy" = "Copier"; +"action_copy_caption" = "Copier la légende"; "action_copy_link" = "Copier le lien"; "action_copy_link_to_message" = "Copier le lien vers le message"; +"action_copy_text" = "Copier le texte"; "action_create" = "Créer"; "action_create_a_room" = "Créer un salon"; "action_deactivate" = "Désactiver"; @@ -48,7 +50,7 @@ "action_discard" = "Annuler"; "action_done" = "Terminé"; "action_edit" = "Modifier"; -"action_edit_caption" = "Edit caption"; +"action_edit_caption" = "Modifier la légende"; "action_edit_poll" = "Modifier le sondage"; "action_enable" = "Activer"; "action_end_poll" = "Terminer le sondage"; @@ -83,7 +85,8 @@ "action_react" = "Réagissez"; "action_reject" = "Rejeter"; "action_remove" = "Supprimer"; -"action_remove_caption" = "Remove caption"; +"action_remove_caption" = "Supprimer la légende"; +"action_remove_message" = "Supprimer le message"; "action_reply" = "Répondre"; "action_reply_in_thread" = "Répondre dans le fil de discussion"; "action_report_bug" = "Signaler un problème"; @@ -122,7 +125,7 @@ "banner_set_up_recovery_title" = "Configurer la récupération"; "common_about" = "À propos"; "common_acceptable_use_policy" = "Politique d’utilisation acceptable"; -"common_adding_caption" = "Adding caption"; +"common_adding_caption" = "Ajout d'une légende"; "common_advanced_settings" = "Paramètres avancés"; "common_analytics" = "Statistiques d’utilisation"; "common_appearance" = "Apparence"; @@ -141,7 +144,7 @@ "common_direct_chat" = "Discussion à deux"; "common_edited_suffix" = "(modifié)"; "common_editing" = "Édition"; -"common_editing_caption" = "Editing caption"; +"common_editing_caption" = "Modification de la légende"; "common_emote" = "* %1$@ %2$@"; "common_encryption" = "Chiffrement"; "common_encryption_enabled" = "Chiffrement activé"; @@ -230,7 +233,7 @@ "common_unable_to_invite_title" = "Impossible d’envoyer une ou plusieurs invitations"; "common_unlock" = "Déverrouillage"; "common_unmute" = "Retirer la sourdine"; -"common_unsupported_call" = "Unsupported call"; +"common_unsupported_call" = "Appel non pris en charge"; "common_unsupported_event" = "Événement non pris en charge"; "common_username" = "Nom d’utilisateur"; "common_verification_cancelled" = "Vérification annulée"; @@ -370,11 +373,23 @@ "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_button_title" = "Accept all"; -"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_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_title" = "Tout accepter"; +"screen_knock_requests_list_accept_all_button_title" = "Tout accepter"; +"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_title" = "Refuser et interdire l'accès"; +"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_title" = "Refuser l'accès"; +"screen_knock_requests_list_decline_and_ban_action_title" = "Refuser et bannir"; +"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_title" = "Demandes en attente"; +"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."; "screen_pinned_timeline_empty_state_description" = "Cliquez (clic long) sur un message et choisissez « %1$@ » pour qu‘il apparaisse ici."; "screen_pinned_timeline_empty_state_headline" = "Épinglez les messages importants pour leur donner plus de visibilité"; "screen_reset_encryption_password_error" = "Une erreur s'est produite. Vérifiez que le mot de passe de votre compte est correct et réessayez."; @@ -387,16 +402,16 @@ "screen_resolve_send_failure_you_unsigned_device_subtitle" = "Un ou plusieurs de vos appareils ne sont pas vérifiés. Vous pouvez quand même envoyer le message, ou vous pouvez annuler et réessayer plus tard après avoir vérifié tous vos appareils."; "screen_resolve_send_failure_you_unsigned_device_title" = "Votre message n'a pas été envoyé car vous n'avez pas vérifié tous vos appareils"; "screen_room_mentions_at_room_subtitle" = "Notifier tout le salon"; -"screen_room_multiple_knock_requests_view_all_button_title" = "View all"; +"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_view_all_button_title" = "Voir tout"; -"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" = "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" = "Requests to join"; +"screen_room_details_requests_to_join_title" = "Demandes en attente"; "screen_roomlist_knock_event_sent_description" = "Demande d'adhésion envoyée"; "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."; @@ -572,8 +587,6 @@ "screen_login_title" = "Content de vous revoir !"; "screen_login_title_with_homeserver" = "Connectez-vous à %1$@"; "screen_media_picker_error_failed_selection" = "Échec de la sélection du média, veuillez réessayer."; -"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."; "screen_migration_message" = "Il s’agit d’une opération ponctuelle, merci d’attendre quelques instants."; "screen_migration_title" = "Configuration de votre compte."; "screen_notification_optin_subtitle" = "Vous pourrez modifier vos paramètres ultérieurement."; @@ -804,7 +817,7 @@ "screen_room_timeline_add_reaction" = "Ajouter un émoji"; "screen_room_timeline_beginning_of_room" = "Ceci est le début de %1$@."; "screen_room_timeline_beginning_of_room_no_name" = "Ceci est le début de cette conversation."; -"screen_room_timeline_legacy_call" = "Unsupported call. Ask if the caller can use the new Element X app."; +"screen_room_timeline_legacy_call" = "Appel non pris en charge. Demandez à l'appelant s'il peut utiliser la nouvelle application Element X pour vous appeler."; "screen_room_timeline_less_reactions" = "Afficher moins"; "screen_room_timeline_message_copied" = "Message copié"; "screen_room_timeline_no_permission_to_post" = "Vous n’êtes pas autorisé à publier dans ce salon"; diff --git a/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict b/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict index c8a0ebe57e..e12dce7a4d 100644 --- a/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict +++ b/ElementX/Resources/Localizations/fr.lproj/Localizable.stringsdict @@ -237,9 +237,9 @@ NSStringFormatValueTypeKey d one - %1$@ +%2$d other want to join this room + %1$@ et %2$d autre personne souhaitent rejoindre ce salon other - %1$@ +%2$d others want to join this room + %1$@ et %2$d autres personnes souhaitent rejoindre ce salon screen_room_timeline_state_changes diff --git a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings index 870977da2d..f6f5b11a1f 100644 --- a/ElementX/Resources/Localizations/hu.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/hu.lproj/Localizable.strings @@ -36,8 +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_link" = "Hivatkozás másolása"; "action_copy_link_to_message" = "Üzenetre mutató hivatkozás másolása"; +"action_copy_text" = "Copy text"; "action_create" = "Létrehozás"; "action_create_a_room" = "Szoba létrehozása"; "action_deactivate" = "Deaktiválás"; @@ -84,6 +86,7 @@ "action_reject" = "Elutasítás"; "action_remove" = "Eltávolítás"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Válasz"; "action_reply_in_thread" = "Válasz az üzenetszálban"; "action_report_bug" = "Hiba jelentése"; @@ -359,7 +362,7 @@ "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_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" = "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"; @@ -370,11 +373,23 @@ "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_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."; "screen_pinned_timeline_empty_state_headline" = "Tűzze ki a fontos üzeneteket, hogy könnyen felfedezhetők legyenek"; "screen_reset_encryption_password_error" = "Ismeretlen hiba történt. Ellenőrizze, hogy a fiókja jelszava helyes-e, és próbálja meg újra."; @@ -572,8 +587,6 @@ "screen_login_title" = "Örülünk, hogy visszatért!"; "screen_login_title_with_homeserver" = "Bejelentkezés ide: %1$@"; "screen_media_picker_error_failed_selection" = "Nem sikerült kiválasztani a médiát, próbálja újra."; -"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_migration_message" = "Ez egy egyszeri folyamat, köszönjük a türelmét."; "screen_migration_title" = "A fiók beállítása."; "screen_notification_optin_subtitle" = "A beállításokat később is módosíthatja."; diff --git a/ElementX/Resources/Localizations/id.lproj/Localizable.strings b/ElementX/Resources/Localizations/id.lproj/Localizable.strings index 1128e3f4a6..7f654be975 100644 --- a/ElementX/Resources/Localizations/id.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/id.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Konfirmasi kata sandi"; "action_continue" = "Lanjutkan"; "action_copy" = "Salin"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Salin tautan"; "action_copy_link_to_message" = "Salin tautan ke pesan"; +"action_copy_text" = "Copy text"; "action_create" = "Buat"; "action_create_a_room" = "Buat ruangan"; "action_deactivate" = "Nonaktifkan"; @@ -84,6 +86,7 @@ "action_reject" = "Tolak"; "action_remove" = "Hapus"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Balas"; "action_reply_in_thread" = "Balas dalam utas"; "action_report_bug" = "Laporkan kutu"; @@ -370,11 +373,23 @@ "screen_join_room_knock_message_description" = "Pesan (opsional)"; "screen_join_room_knock_sent_description" = "Anda akan menerima undangan untuk bergabung dengan ruangan jika permintaan Anda diterima."; "screen_join_room_knock_sent_title" = "Permintaan untuk bergabung dikirim"; +"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_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."; "screen_pinned_timeline_empty_state_description" = "Tekan pesan dan pilih “%1$@” untuk disertakan di sini."; "screen_pinned_timeline_empty_state_headline" = "Sematkan pesan penting agar mudah ditemukan"; "screen_reset_encryption_password_error" = "Terjadi kesalahan yang tidak diketahui. Harap periksa apakah kata sandi akun Anda sudah benar dan coba lagi."; @@ -572,8 +587,6 @@ "screen_login_title" = "Selamat datang kembali!"; "screen_login_title_with_homeserver" = "Masuk ke %1$@"; "screen_media_picker_error_failed_selection" = "Gagal memilih media, silakan coba lagi."; -"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."; "screen_migration_message" = "Ini adalah proses satu kali, terima kasih telah menunggu."; "screen_migration_title" = "Menyiapkan akun Anda."; "screen_notification_optin_subtitle" = "Anda dapat mengubah pengaturan Anda nanti."; diff --git a/ElementX/Resources/Localizations/it.lproj/Localizable.strings b/ElementX/Resources/Localizations/it.lproj/Localizable.strings index 6cf966b9da..33309394d1 100644 --- a/ElementX/Resources/Localizations/it.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/it.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Conferma password"; "action_continue" = "Continua"; "action_copy" = "Copia"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Copia collegamento"; "action_copy_link_to_message" = "Copia collegamento al messaggio"; +"action_copy_text" = "Copy text"; "action_create" = "Crea"; "action_create_a_room" = "Crea una stanza"; "action_deactivate" = "Disattiva"; @@ -84,6 +86,7 @@ "action_reject" = "Rifiuta"; "action_remove" = "Rimuovi"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Rispondi"; "action_reply_in_thread" = "Rispondi nella discussione"; "action_report_bug" = "Segnala un problema"; @@ -359,7 +362,7 @@ "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_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"; @@ -370,11 +373,23 @@ "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_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."; "screen_pinned_timeline_empty_state_headline" = "Fissa i messaggi importanti così che possano essere trovati facilmente"; "screen_reset_encryption_password_error" = "Si è verificato un errore sconosciuto. Controlla che la password del tuo account sia corretta e riprova."; @@ -572,8 +587,6 @@ "screen_login_title" = "Bentornato!"; "screen_login_title_with_homeserver" = "Accedi a %1$@"; "screen_media_picker_error_failed_selection" = "Selezione del file multimediale fallita, riprova."; -"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_migration_message" = "Si tratta di una procedura che si effettua una sola volta, grazie per l'attesa."; "screen_migration_title" = "Configurazione del tuo account."; "screen_notification_optin_subtitle" = "Potrai modificare le tue impostazioni in seguito."; diff --git a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings index 76743f9003..bfd0efcef3 100644 --- a/ElementX/Resources/Localizations/ka.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ka.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Confirm password"; "action_continue" = "გაგრძელება"; "action_copy" = "კოპირება"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "ბმულის კოპირება"; "action_copy_link_to_message" = "დააკოპირეთ შეტყობინების ბმული"; +"action_copy_text" = "Copy text"; "action_create" = "შექმნა"; "action_create_a_room" = "ოთახის შექმნა"; "action_deactivate" = "Deactivate"; @@ -84,6 +86,7 @@ "action_reject" = "Reject"; "action_remove" = "წაშლა"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "პასუხი"; "action_reply_in_thread" = "პასუხი თემაში"; "action_report_bug" = "ხარვეზის შეტყობინება"; @@ -359,7 +362,7 @@ "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_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"; @@ -370,11 +373,23 @@ "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_media_upload_preview_error_failed_processing" = "მედიის ატვირთვა ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა."; +"screen_media_upload_preview_error_failed_sending" = "მედიის ატვირთვა ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა."; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -572,8 +587,6 @@ "screen_login_title" = "კეთილი იყოს თქვენი მობრძანება!"; "screen_login_title_with_homeserver" = "შესვლა %1$@-ში"; "screen_media_picker_error_failed_selection" = "მედიის შერჩევა ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა."; -"screen_media_upload_preview_error_failed_processing" = "მედიის ატვირთვა ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა."; -"screen_media_upload_preview_error_failed_sending" = "მედიის ატვირთვა ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა."; "screen_migration_message" = "ეს არის ერთჯერადი პროცესი, მადლობა ლოდინისთვის."; "screen_migration_title" = "თქვენი ანგარიშის კონფიგურაცია"; "screen_notification_optin_subtitle" = "თქვენ შეგიძლიათ შეცვალოთ თქვენი პარამეტრები მოგვიანებით."; diff --git a/ElementX/Resources/Localizations/nl.lproj/Localizable.strings b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings index db6deefbd5..4c633456bb 100644 --- a/ElementX/Resources/Localizations/nl.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/nl.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Bevestig wachtwoord"; "action_continue" = "Voortzetten"; "action_copy" = "Kopiëren"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Kopieer link"; "action_copy_link_to_message" = "Kopieer link naar bericht"; +"action_copy_text" = "Copy text"; "action_create" = "Aanmaken"; "action_create_a_room" = "Creëer een kamer"; "action_deactivate" = "Sluiten"; @@ -84,6 +86,7 @@ "action_reject" = "Weiger"; "action_remove" = "Verwijderen"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Antwoorden"; "action_reply_in_thread" = "Antwoord in subchat"; "action_report_bug" = "Probleem melden"; @@ -359,7 +362,7 @@ "screen_create_room_room_access_section_knocking_option_description" = "Iedereen kan vragen om toe te treden tot de kamer, maar een beheerder of moderator moet het verzoek accepteren"; "screen_create_room_room_access_section_knocking_option_title" = "Vraag om toe te treden"; "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_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"; @@ -370,11 +373,23 @@ "screen_join_room_knock_message_description" = "Bericht (optioneel)"; "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" = "Verzoek om toe te treden verzonden"; +"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_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."; "screen_pinned_timeline_empty_state_description" = "Druk op een bericht en kies „%1$@” om het hier toe te voegen."; "screen_pinned_timeline_empty_state_headline" = "Zet belangrijke berichten vast zodat ze gemakkelijk te vinden zijn"; "screen_reset_encryption_password_error" = "Er is een onbekende fout opgetreden. Controleer of het wachtwoord van je account juist is en probeer het opnieuw."; @@ -572,8 +587,6 @@ "screen_login_title" = "Welkom terug!"; "screen_login_title_with_homeserver" = "Inloggen bij %1$@"; "screen_media_picker_error_failed_selection" = "Het selecteren van media is mislukt. Probeer het opnieuw."; -"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."; "screen_migration_message" = "Dit is een eenmalig proces, bedankt voor het wachten."; "screen_migration_title" = "Je account instellen."; "screen_notification_optin_subtitle" = "Je kunt je instellingen later wijzigen."; diff --git a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings index b6a0b10941..37b1f45f85 100644 --- a/ElementX/Resources/Localizations/pl.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pl.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Potwierdź hasło"; "action_continue" = "Kontynuuj"; "action_copy" = "Kopiuj"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Kopiuj link"; "action_copy_link_to_message" = "Kopiuj link do wiadomości"; +"action_copy_text" = "Copy text"; "action_create" = "Utwórz"; "action_create_a_room" = "Utwórz pokój"; "action_deactivate" = "Dezaktywuj"; @@ -84,6 +86,7 @@ "action_reject" = "Odrzuć"; "action_remove" = "Usuń"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Odpowiedz"; "action_reply_in_thread" = "Odpowiedz w wątku"; "action_report_bug" = "Zgłoś błąd"; @@ -359,7 +362,7 @@ "screen_create_room_room_access_section_knocking_option_description" = "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić prośbę"; "screen_create_room_room_access_section_knocking_option_title" = "Poproś o dołączenie"; "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_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" = "Aby ten pokój był widoczny w katalogu pomieszczeń publicznych, będziesz potrzebował adres pokoju."; "screen_create_room_room_address_section_title" = "Adres pokoju"; "screen_create_room_room_visibility_section_title" = "Widoczność pomieszczenia"; @@ -370,11 +373,23 @@ "screen_join_room_knock_message_description" = "Wiadomość (opcjonalne)"; "screen_join_room_knock_sent_description" = "Otrzymasz zaproszenie dołączenia do pokoju, jeśli prośba zostanie zaakceptowana."; "screen_join_room_knock_sent_title" = "Wysłano prośbę o dołączenie"; +"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_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."; "screen_pinned_timeline_empty_state_description" = "Naciśnij wiadomość i wybierz “%1$@”, aby dołączyć tutaj."; "screen_pinned_timeline_empty_state_headline" = "Przypinaj ważne wiadomości, aby można było je łatwo znaleźć"; "screen_reset_encryption_password_error" = "Wystąpił nieznany błąd. Sprawdź, czy hasło jest poprawne i spróbuj ponownie."; @@ -572,8 +587,6 @@ "screen_login_title" = "Witaj ponownie!"; "screen_login_title_with_homeserver" = "Zaloguj się do %1$@"; "screen_media_picker_error_failed_selection" = "Nie udało się wybrać multimediów. Spróbuj ponownie."; -"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."; "screen_migration_message" = "Jest to jednorazowy proces, dziękujemy za czekanie."; "screen_migration_title" = "Konfigurowanie Twojego konta."; "screen_notification_optin_subtitle" = "Możesz zmienić ustawienia później."; @@ -848,7 +861,7 @@ "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ą."; "screen_session_verification_enter_recovery_key" = "Wprowadź klucz przywracania"; -"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" = "Albo upłynął limit czasu żądania, albo żądanie zostało odrzucone, albo wystąpił błąd weryfikacji."; "screen_session_verification_open_existing_session_subtitle" = "Udowodnij, że to ty, aby uzyskać dostęp do historii zaszyfrowanych wiadomości."; "screen_session_verification_open_existing_session_title" = "Otwórz istniejącą sesję"; "screen_session_verification_positive_button_canceled" = "Ponów weryfikację"; @@ -860,7 +873,7 @@ "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ę."; "screen_session_verification_request_subtitle" = "Zweryfikuj drugie urządzenie, aby zabezpieczyć historię wiadomości."; -"screen_session_verification_request_success_subtitle" = "Now you can read or send messages securely on your other device."; +"screen_session_verification_request_success_subtitle" = "Już możesz bezpiecznie czytać lub wysyłać wiadomości na drugim urządzeniu."; "screen_session_verification_request_success_title" = "Urządzenie zweryfikowane"; "screen_session_verification_request_title" = "Zażądano weryfikacji"; "screen_session_verification_they_dont_match" = "Nie pasują do siebie"; @@ -1081,7 +1094,7 @@ "screen_room_timeline_reactions_show_less" = "Pokaż mniej"; "screen_roomlist_filter_people" = "Osoby"; "screen_server_confirmation_change_server" = "Zmień dostawcę konta"; -"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" = "Albo upłynął limit czasu żądania, albo żądanie zostało odrzucone, albo wystąpił błąd weryfikacji."; "screen_signout_confirmation_dialog_submit" = "Wyloguj"; "screen_signout_confirmation_dialog_title" = "Wyloguj"; "screen_signout_key_backup_offline_title" = "Twoje klucze są nadal archiwizowane"; diff --git a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings index 508dabe58e..ea5cd6ded4 100644 --- a/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt-BR.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Confirm password"; "action_continue" = "Continuar"; "action_copy" = "Copiar"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Copiar link"; "action_copy_link_to_message" = "Copiar link para a mensagem"; +"action_copy_text" = "Copy text"; "action_create" = "Criar"; "action_create_a_room" = "Criar uma sala"; "action_deactivate" = "Deactivate"; @@ -84,6 +86,7 @@ "action_reject" = "Recusar"; "action_remove" = "Remover"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Responder"; "action_reply_in_thread" = "Responder no tópico"; "action_report_bug" = "Reportar erro"; @@ -359,7 +362,7 @@ "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_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"; @@ -370,11 +373,23 @@ "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_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."; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -572,8 +587,6 @@ "screen_login_title" = "Bem-vindo de volta!"; "screen_login_title_with_homeserver" = "Iniciar sessão em %1$@"; "screen_media_picker_error_failed_selection" = "Falha ao selecionar a mídia, tente novamente."; -"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."; "screen_migration_message" = "Este é um processo único, obrigado por esperar."; "screen_migration_title" = "Configurando sua conta."; "screen_notification_optin_subtitle" = "Você pode alterar suas configurações mais tarde."; diff --git a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings index b6c1abf085..e0453d96d1 100644 --- a/ElementX/Resources/Localizations/pt.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/pt.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Confirmar palavra-passe"; "action_continue" = "Continuar"; "action_copy" = "Copiar"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Copiar ligação"; "action_copy_link_to_message" = "Copiar ligação da mensagem"; +"action_copy_text" = "Copy text"; "action_create" = "Criar"; "action_create_a_room" = "Criar uma sala"; "action_deactivate" = "Desativar"; @@ -84,6 +86,7 @@ "action_reject" = "Rejeitar"; "action_remove" = "Remover"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Responder"; "action_reply_in_thread" = "Responder ao tópico"; "action_report_bug" = "Comunicar problema"; @@ -370,11 +373,23 @@ "screen_join_room_knock_message_description" = "Mensagem (opcional)"; "screen_join_room_knock_sent_description" = "Irá receber um convite para participar na sala se seu pedido for aceite."; "screen_join_room_knock_sent_title" = "Pedido de adesão enviado"; +"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_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."; "screen_pinned_timeline_empty_state_description" = "Pressione uma mensagem e escolha \"%1$@\" para incluir aqui."; "screen_pinned_timeline_empty_state_headline" = "Fixa mensagens importantes para que possam ser facilmente descobertas"; "screen_reset_encryption_password_error" = "Um erro desconhecido aconteceu. Verifique se a senha da sua conta está correta e tente novamente."; @@ -572,8 +587,6 @@ "screen_login_title" = "Bem-vindo(a) de volta!"; "screen_login_title_with_homeserver" = "Iniciar sessão em %1$@"; "screen_media_picker_error_failed_selection" = "Falha ao selecionar multimédia, por favor tente novamente."; -"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."; "screen_migration_message" = "Este processo só acontece uma única vez, obrigado por esperares."; "screen_migration_title" = "A configurar a tua conta…"; "screen_notification_optin_subtitle" = "Podes alterar as tuas definições mais tarde."; diff --git a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings index 7aef2d3cc6..dbbeb1b50a 100644 --- a/ElementX/Resources/Localizations/ro.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ro.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Confirm password"; "action_continue" = "Continuați"; "action_copy" = "Copiați"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Copiați linkul"; "action_copy_link_to_message" = "Copiați linkul către mesaj"; +"action_copy_text" = "Copy text"; "action_create" = "Creați"; "action_create_a_room" = "Creați o cameră"; "action_deactivate" = "Deactivate"; @@ -84,6 +86,7 @@ "action_reject" = "Respinge"; "action_remove" = "Ștergeți"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Răspundeți"; "action_reply_in_thread" = "Răspundeți în fir"; "action_report_bug" = "Raportați o eroare"; @@ -359,7 +362,7 @@ "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_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"; @@ -370,11 +373,23 @@ "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_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."; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -572,8 +587,6 @@ "screen_login_title" = "Bine ați revenit!"; "screen_login_title_with_homeserver" = "Conectați-vă la %1$@"; "screen_media_picker_error_failed_selection" = "Selectarea fișierelor media a eșuat, încercați din nou."; -"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."; "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ă"; "screen_notification_optin_subtitle" = "Puteți modifica setările mai târziu."; diff --git a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings index 55c700e373..1e29541697 100644 --- a/ElementX/Resources/Localizations/ru.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/ru.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Подтвердите пароль"; "action_continue" = "Продолжить"; "action_copy" = "Копировать"; +"action_copy_caption" = "Скопировать подпись"; "action_copy_link" = "Скопировать ссылку"; "action_copy_link_to_message" = "Скопировать ссылку в сообщение"; +"action_copy_text" = "Копировать текст"; "action_create" = "Создать"; "action_create_a_room" = "Создать комнату"; "action_deactivate" = "Отключить"; @@ -84,6 +86,7 @@ "action_reject" = "Отклонить"; "action_remove" = "Удалить"; "action_remove_caption" = "Удалить подпись"; +"action_remove_message" = "Удалить сообщение"; "action_reply" = "Ответить"; "action_reply_in_thread" = "Ответить в теме"; "action_report_bug" = "Сообщить об ошибке"; @@ -370,11 +373,23 @@ "screen_join_room_knock_message_description" = "Сообщение (опционально)"; "screen_join_room_knock_sent_description" = "Вы получите приглашение присоединиться к комнате, как только ваш запрос будет принят."; "screen_join_room_knock_sent_title" = "Запрос на присоединение отправлен"; +"screen_knock_requests_list_accept_all_alert_confirm_button_title" = "Да, принять все"; +"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_ban_alert_confirm_button_title" = "Да, отклонить и запретить"; +"screen_knock_requests_list_ban_alert_description" = "Вы уверен, что хочешь отклонить и запретить %1$@? Этот пользователь больше не сможет запросить доступ к этой комнате."; +"screen_knock_requests_list_ban_alert_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_empty_state_description" = "Вы сможете увидеть запрос, когда кто-то попросит присоединиться к комнате."; "screen_knock_requests_list_empty_state_title" = "Нет ожидающих запросов на присоединение"; "screen_knock_requests_list_title" = "Запросы на присоединение"; +"screen_media_upload_preview_caption_warning" = "Подпись может быть не видна пользователям старых приложений."; +"screen_media_upload_preview_error_failed_processing" = "Не удалось обработать медиафайл для загрузки, попробуйте еще раз."; +"screen_media_upload_preview_error_failed_sending" = "Не удалось загрузить медиафайлы, попробуйте еще раз."; "screen_pinned_timeline_empty_state_description" = "Нажмите на сообщение и выберите “%1$@”, чтобы добавить его сюда."; "screen_pinned_timeline_empty_state_headline" = "Закрепите важные сообщения, чтобы их можно было легко найти"; "screen_reset_encryption_password_error" = "Произошла неизвестная ошибка. Проверьте правильность пароля учетной записи и повторите попытку."; @@ -572,8 +587,6 @@ "screen_login_title" = "Рады видеть вас снова!"; "screen_login_title_with_homeserver" = "Войти в %1$@"; "screen_media_picker_error_failed_selection" = "Не удалось выбрать носитель, попробуйте еще раз."; -"screen_media_upload_preview_error_failed_processing" = "Не удалось обработать медиафайл для загрузки, попробуйте еще раз."; -"screen_media_upload_preview_error_failed_sending" = "Не удалось загрузить медиафайлы, попробуйте еще раз."; "screen_migration_message" = "Это одноразовый процесс, спасибо, что подождали."; "screen_migration_title" = "Настройка учетной записи."; "screen_notification_optin_subtitle" = "Вы можете изменить настройки позже."; diff --git a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings index 5157db2c85..367a13aa32 100644 --- a/ElementX/Resources/Localizations/sk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sk.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Potvrdiť heslo"; "action_continue" = "Pokračovať"; "action_copy" = "Kopírovať"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Kopírovať odkaz"; "action_copy_link_to_message" = "Kopírovať odkaz do správy"; +"action_copy_text" = "Copy text"; "action_create" = "Vytvoriť"; "action_create_a_room" = "Vytvoriť miestnosť"; "action_deactivate" = "Deaktivovať"; @@ -84,6 +86,7 @@ "action_reject" = "Odmietnuť"; "action_remove" = "Odstrániť"; "action_remove_caption" = "Odstrániť titulok"; +"action_remove_message" = "Remove message"; "action_reply" = "Odpovedať"; "action_reply_in_thread" = "Odpovedať vo vlákne"; "action_report_bug" = "Nahlásiť chybu"; @@ -370,11 +373,23 @@ "screen_join_room_knock_message_description" = "Správa (voliteľné)"; "screen_join_room_knock_sent_description" = "Ak bude vaša žiadosť prijatá, dostanete pozvánku na vstup do miestnosti."; "screen_join_room_knock_sent_title" = "Žiadosť o pripojenie bola odoslaná"; +"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" = "Prijať všetky"; +"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" = "Odmietnuť a zakázať"; "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_title" = "Žiadosti o pripojenie"; +"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."; "screen_pinned_timeline_empty_state_description" = "Stlačte správu a vyberte možnosť „%1$@“, ktorú chcete zahrnúť sem."; "screen_pinned_timeline_empty_state_headline" = "Pripnite dôležité správy, aby sa dali ľahko nájsť"; "screen_reset_encryption_password_error" = "Nastala neznáma chyba. Skontrolujte, či je heslo vášho účtu správne a skúste to znova."; @@ -572,8 +587,6 @@ "screen_login_title" = "Vitajte späť!"; "screen_login_title_with_homeserver" = "Prihlásiť sa do %1$@"; "screen_media_picker_error_failed_selection" = "Nepodarilo sa vybrať médium, skúste to prosím znova."; -"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."; "screen_migration_message" = "Ide o jednorazový proces, ďakujeme za trpezlivosť."; "screen_migration_title" = "Nastavenie vášho účtu."; "screen_notification_optin_subtitle" = "Svoje nastavenia môžete neskôr zmeniť."; diff --git a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings index befb12583a..12ccf743e0 100644 --- a/ElementX/Resources/Localizations/sv.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/sv.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Confirm password"; "action_continue" = "Fortsätt"; "action_copy" = "Kopiera"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Kopiera länk"; "action_copy_link_to_message" = "Kopiera länk till meddelande"; +"action_copy_text" = "Copy text"; "action_create" = "Skapa"; "action_create_a_room" = "Skapa ett rum"; "action_deactivate" = "Deactivate"; @@ -84,6 +86,7 @@ "action_reject" = "Avvisa"; "action_remove" = "Ta bort"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Svara"; "action_reply_in_thread" = "Svara i tråd"; "action_report_bug" = "Rapportera bugg"; @@ -359,7 +362,7 @@ "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_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"; @@ -370,11 +373,23 @@ "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_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."; "screen_pinned_timeline_empty_state_description" = "Tryck på ett meddelande och välj ”%1$@” för att inkludera det här."; "screen_pinned_timeline_empty_state_headline" = "Fäst viktiga meddelanden så att de lätt kan upptäckas"; "screen_reset_encryption_password_error" = "Ett okänt fel inträffade. Kontrollera att ditt kontolösenord är korrekt och försök igen."; @@ -572,8 +587,6 @@ "screen_login_title" = "Välkommen tillbaka!"; "screen_login_title_with_homeserver" = "Logga in på %1$@"; "screen_media_picker_error_failed_selection" = "Misslyckades att välja media, vänligen pröva igen."; -"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."; "screen_migration_message" = "Detta är en engångsprocess, tack för att du väntar."; "screen_migration_title" = "Konfigurerar ditt konto"; "screen_notification_optin_subtitle" = "Du kan ändra dina inställningar senare."; diff --git a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings index 4b49907eed..b2b8377d92 100644 --- a/ElementX/Resources/Localizations/uk.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/uk.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Підтвердіть пароль"; "action_continue" = "Продовжити"; "action_copy" = "Скопіювати"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Скопіювати посилання"; "action_copy_link_to_message" = "Скопіювати посилання на повідомлення"; +"action_copy_text" = "Copy text"; "action_create" = "Створити"; "action_create_a_room" = "Створити кімнату"; "action_deactivate" = "Деактивувати"; @@ -84,6 +86,7 @@ "action_reject" = "Відхилити"; "action_remove" = "Вилучити"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Відповісти"; "action_reply_in_thread" = "Відповісти в гілці"; "action_report_bug" = "Повідомити про помилку"; @@ -370,11 +373,23 @@ "screen_join_room_knock_message_description" = "Повідомлення (необов'язково)"; "screen_join_room_knock_sent_description" = "Ви отримаєте запрошення приєднатися до кімнати, якщо ваш запит буде прийнятий."; "screen_join_room_knock_sent_title" = "Запит на приєднання надіслано"; +"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_media_upload_preview_error_failed_processing" = "Не вдалося обробити медіафайл для завантаження, спробуйте ще раз."; +"screen_media_upload_preview_error_failed_sending" = "Не вдалося завантажити медіафайл, спробуйте ще раз."; "screen_pinned_timeline_empty_state_description" = "Натисніть на повідомлення і виберіть \"%1$@\", щоб додати його сюди."; "screen_pinned_timeline_empty_state_headline" = "Закріпіть важливі повідомлення, щоб їх можна було легко знайти"; "screen_reset_encryption_password_error" = "Сталася невідома помилка. Будь ласка, перевірте правильність пароля свого облікового запису та повторіть спробу."; @@ -572,8 +587,6 @@ "screen_login_title" = "З поверненням!"; "screen_login_title_with_homeserver" = "Увійти в %1$@"; "screen_media_picker_error_failed_selection" = "Не вдалося вибрати медіафайл, спробуйте ще раз."; -"screen_media_upload_preview_error_failed_processing" = "Не вдалося обробити медіафайл для завантаження, спробуйте ще раз."; -"screen_media_upload_preview_error_failed_sending" = "Не вдалося завантажити медіафайл, спробуйте ще раз."; "screen_migration_message" = "Це одноразовий процес, дякую за очікування."; "screen_migration_title" = "Налаштування облікового запису."; "screen_notification_optin_subtitle" = "Ви можете змінити свої налаштування пізніше."; diff --git a/ElementX/Resources/Localizations/uz.lproj/Localizable.strings b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings index 98edd1ed8d..858a6e471e 100644 --- a/ElementX/Resources/Localizations/uz.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/uz.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Confirm password"; "action_continue" = "Davom etish"; "action_copy" = "nusxa"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "Havolani nusxalash"; "action_copy_link_to_message" = "Havolani xabaraga nusxalash"; +"action_copy_text" = "Copy text"; "action_create" = "Yaratmoq"; "action_create_a_room" = "Xonani yaratish"; "action_deactivate" = "Deactivate"; @@ -84,6 +86,7 @@ "action_reject" = "Reject"; "action_remove" = "Ochirish"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "Javob bering"; "action_reply_in_thread" = "Mavzuda javob bering"; "action_report_bug" = "Xato haqida xabar berish"; @@ -359,7 +362,7 @@ "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_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"; @@ -370,11 +373,23 @@ "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_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."; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -572,8 +587,6 @@ "screen_login_title" = "Qaytib kelganingizdan xursandmiz!"; "screen_login_title_with_homeserver" = "Kirish%1$@"; "screen_media_picker_error_failed_selection" = "Media tanlash jarayonida xatolik yuz berdi, qayta urinib ko'ring"; -"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."; "screen_migration_message" = "Bu bir martalik jarayon, kutganingiz uchun rahmat."; "screen_migration_title" = "Hisobingiz sozlanmoqda."; "screen_notification_optin_subtitle" = "Sozlamalaringizni keyinroq o'zgartirishingiz mumkin."; diff --git a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings index 738a895efa..a4ae040a24 100644 --- a/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hans.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "确认密码"; "action_continue" = "继续"; "action_copy" = "复制"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "复制链接"; "action_copy_link_to_message" = "复制消息链接"; +"action_copy_text" = "Copy text"; "action_create" = "创建"; "action_create_a_room" = "创建聊天室"; "action_deactivate" = "停用"; @@ -84,6 +86,7 @@ "action_reject" = "拒绝"; "action_remove" = "移除"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "回复"; "action_reply_in_thread" = "在消息列中回复"; "action_report_bug" = "报告错误"; @@ -359,7 +362,7 @@ "screen_create_room_room_access_section_knocking_option_description" = "任何人都可以请求加入房间,但必须由管理员或审核人接受"; "screen_create_room_room_access_section_knocking_option_title" = "请求加入"; "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_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" = "要使该房间在公开房间目录中可见,您需要一个房间地址。"; "screen_create_room_room_address_section_title" = "房间地址"; "screen_create_room_room_visibility_section_title" = "房间可见性"; @@ -370,11 +373,23 @@ "screen_join_room_knock_message_description" = "消息(可选)"; "screen_join_room_knock_sent_description" = "如果您的请求被接受,您将收到加入房间的邀请。"; "screen_join_room_knock_sent_title" = "加入请求已发送"; +"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_media_upload_preview_error_failed_processing" = "处理要上传的媒体失败,请重试。"; +"screen_media_upload_preview_error_failed_sending" = "上传媒体失败,请重试。"; "screen_pinned_timeline_empty_state_description" = "按下消息并选择 “%1$@” 将其包含在此处。"; "screen_pinned_timeline_empty_state_headline" = "固定重要消息,以便轻松发现它们"; "screen_reset_encryption_password_error" = "发生未知错误。请检查您的帐户密码是否正确,然后重试。"; @@ -572,8 +587,6 @@ "screen_login_title" = "欢迎回来!"; "screen_login_title_with_homeserver" = "登录到 %1$@"; "screen_media_picker_error_failed_selection" = "选择媒体失败,请重试。"; -"screen_media_upload_preview_error_failed_processing" = "处理要上传的媒体失败,请重试。"; -"screen_media_upload_preview_error_failed_sending" = "上传媒体失败,请重试。"; "screen_migration_message" = "这是一个一次性的过程,感谢您的等待。"; "screen_migration_title" = "设置您的账户。"; "screen_notification_optin_subtitle" = "您可以稍后更改设置。"; diff --git a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings index a191abfb3b..543bf88bbb 100644 --- a/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/zh-Hant-TW.lproj/Localizable.strings @@ -36,8 +36,10 @@ "action_confirm_password" = "Confirm password"; "action_continue" = "繼續"; "action_copy" = "複製"; +"action_copy_caption" = "Copy caption"; "action_copy_link" = "複製連結"; "action_copy_link_to_message" = "複製訊息連結"; +"action_copy_text" = "Copy text"; "action_create" = "建立"; "action_create_a_room" = "建立聊天室"; "action_deactivate" = "Deactivate"; @@ -84,6 +86,7 @@ "action_reject" = "拒絕"; "action_remove" = "移除"; "action_remove_caption" = "Remove caption"; +"action_remove_message" = "Remove message"; "action_reply" = "回覆"; "action_reply_in_thread" = "在討論串中回覆"; "action_report_bug" = "回報程式錯誤"; @@ -359,7 +362,7 @@ "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_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"; @@ -370,11 +373,23 @@ "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_media_upload_preview_error_failed_processing" = "Failed processing media to upload, please try again."; +"screen_media_upload_preview_error_failed_sending" = "無法上傳媒體檔案,請稍後再試。"; "screen_pinned_timeline_empty_state_description" = "Press on a message and choose “%1$@” to include here."; "screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered"; "screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again."; @@ -572,8 +587,6 @@ "screen_login_title" = "歡迎回來!"; "screen_login_title_with_homeserver" = "登入 %1$@"; "screen_media_picker_error_failed_selection" = "Failed selecting media, please try again."; -"screen_media_upload_preview_error_failed_processing" = "Failed processing media to upload, please try again."; -"screen_media_upload_preview_error_failed_sending" = "無法上傳媒體檔案,請稍後再試。"; "screen_migration_message" = "這是一次性的程序,感謝您耐心等候。"; "screen_migration_title" = "正在設定您的帳號。"; "screen_notification_optin_subtitle" = "You can change your settings later."; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 4e3258eccd..26487abd95 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -1136,7 +1136,7 @@ internal enum L10n { internal static var screenCreateRoomRoomAccessSectionKnockingOptionTitle: String { return L10n.tr("Localizable", "screen_create_room_room_access_section_knocking_option_title") } /// Some characters are not allowed. Only letters, digits and the following symbols are supported ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _ internal static var screenCreateRoomRoomAddressInvalidSymbolsErrorDescription: String { return L10n.tr("Localizable", "screen_create_room_room_address_invalid_symbols_error_description") } - /// This room address already exists, please try editing the room address field or change the room name + /// This room address already exists. Please try editing the room address field or change the room name internal static var screenCreateRoomRoomAddressNotAvailableErrorDescription: String { return L10n.tr("Localizable", "screen_create_room_room_address_not_available_error_description") } /// In order for this room to be visible in the public room directory, you will need a room address. internal static var screenCreateRoomRoomAddressSectionFooter: String { return L10n.tr("Localizable", "screen_create_room_room_address_section_footer") } diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png index 36ad9e2928..85ac456ab7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_createRoom-iPad-en-GB.Create-Public-Room-existing-alias.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45b5411fcb1ccc302a743d6d09374ca862f0d53a2b38efcfe67a44d316384bf9 -size 202406 +oid sha256:771b306678c67daad0db700bb437ab4940f8fea812a91fa733d330e6ac11f927 +size 202567 From c7afde3801be81dedee63ba2b4ec5a517663c942 Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:28:50 +0100 Subject: [PATCH 72/74] Knock a room - added a char counter for the message (#3570) * added a char counter * moved code --- .../JoinRoomScreen/View/JoinRoomScreen.swift | 14 +++++++++++--- .../test_joinRoomScreen-iPad-en-GB.Knock.png | 4 ++-- .../test_joinRoomScreen-iPad-pseudo.Knock.png | 4 ++-- .../test_joinRoomScreen-iPhone-16-en-GB.Knock.png | 4 ++-- .../test_joinRoomScreen-iPhone-16-pseudo.Knock.png | 4 ++-- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift index 40c3d65e3b..3953ed96c6 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/View/JoinRoomScreen.swift @@ -9,6 +9,7 @@ import Compound import SwiftUI struct JoinRoomScreen: View { + private let maxKnockMessageLength = 500 @Environment(\.dynamicTypeSize) private var dynamicTypeSize @ObservedObject var context: JoinRoomScreenViewModel.Context @@ -103,6 +104,13 @@ struct JoinRoomScreen: View { } } } + + private var knockMessageFooterString: String { + guard !context.knockMessage.isEmpty else { + return L10n.screenJoinRoomKnockMessageDescription + } + return "\(context.knockMessage.count)/\(maxKnockMessageLength)" + } @ViewBuilder private var knockMessage: some View { @@ -110,7 +118,7 @@ struct JoinRoomScreen: View { HStack(spacing: 0) { TextField("", text: $context.knockMessage, axis: .vertical) .onChange(of: context.knockMessage) { _, newValue in - context.knockMessage = String(newValue.prefix(500)) + context.knockMessage = String(newValue.prefix(maxKnockMessageLength)) } .lineLimit(4, reservesSpace: true) .font(.compound.bodyMD) @@ -125,8 +133,8 @@ struct JoinRoomScreen: View { .stroke(.compound.borderInteractivePrimary) } - Text(L10n.screenJoinRoomKnockMessageDescription) - .font(.compound.bodyMD) + Text(knockMessageFooterString) + .font(.compound.bodySM) .foregroundStyle(.compound.textSecondary) } } 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 477eae3b2c..f900ee4495 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:2347df221ddac84740cf5436620bb07bf3e7f24aea85e6dceec11f8d374a66d0 -size 1817511 +oid sha256:659cf8286eb523208e2fca0ba19578ff4b33a0076dea962fc3f133a089f5bca9 +size 1816652 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 2b13d28459..b72d10f4f5 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:69ad1bad58cd73c5626fdf52923f6a0955221f5673b4485c131048d64b215c84 -size 1825976 +oid sha256:563f7440384e75819f985d659108c5e37bd8c5bca2ca79fbdb2c1ee0617ed17d +size 1824851 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 eecc7badea..4ea478dc6c 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:438018482d1792510fd3d07df8f9ba72ca7ddf3f1e69d7ab0b0adcdbe7a8b0f8 -size 729066 +oid sha256:6f3d9a81bc16d26c4048e4bd59fefe56159a10f2a0f32139ee84ecef7f4d001f +size 728704 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 70405c8970..f430d91d1d 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:03f9fedddcc22df3d14c21cb5314cdd8fdf17592032f57bb762b7c1fe1bbf5ca -size 738216 +oid sha256:6cbcee4066b91f8649d34a66b1b42dfd036541ed7eb7043bff6618089192ae1a +size 736832 From 4372048c619401cbce3014e555fa2fb3bef623d5 Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Tue, 3 Dec 2024 12:18:16 +0100 Subject: [PATCH 73/74] Update SDK 1.0.77 (#3578) * update SDK * added new cause case * added historical message --- ElementX.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- .../Sources/FlowCoordinators/UserSessionFlowCoordinator.swift | 2 ++ .../View/TimelineItemViews/EncryptedRoomTimelineView.swift | 1 + .../TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift | 1 + .../Timeline/TimelineItems/RoomTimelineItemFactory.swift | 3 +++ project.yml | 2 +- 7 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index b40ed15747..8bd039e09f 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -8215,7 +8215,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.76; + version = 1.0.77; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 00f2e1f4d9..6b6570ef8c 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "dfb54791b10d17c5e2604c716c8e939bed221435", - "version" : "1.0.76" + "revision" : "4e01a9482cfefae4f06c6f3a5a33d21a2bf73d84", + "version" : "1.0.77" } }, { diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index a057d2a741..d73e0b3467 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -393,6 +393,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { 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) } } .store(in: &cancellables) diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EncryptedRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EncryptedRoomTimelineView.swift index 4febbbdc3a..ff43aedda4 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EncryptedRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/EncryptedRoomTimelineView.swift @@ -18,6 +18,7 @@ struct EncryptedRoomTimelineView: View { case .unknown: return \.time case .sentBeforeWeJoined, + .historicalMessage, .verificationViolation, .insecureDevice: return \.block diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift index eaed672901..f6d5e7e0d5 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/Items/Other/EncryptedRoomTimelineItem.swift @@ -19,6 +19,7 @@ struct EncryptedRoomTimelineItem: EventBasedTimelineItemProtocol, Equatable { case verificationViolation case insecureDevice case unknown + case historicalMessage } let id: TimelineItemIdentifier diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index e1a3fd6c52..c26fc8d2b8 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -153,6 +153,9 @@ 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 .olmV1Curve25519AesSha2(let senderKey): encryptionType = .olmV1Curve25519AesSha2(senderKey: senderKey) diff --git a/project.yml b/project.yml index 510e3277e1..7660990072 100644 --- a/project.yml +++ b/project.yml @@ -61,7 +61,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.76 + exactVersion: 1.0.77 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From 4187155159d5d6d9c793377cbbd01417f60e673e Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Tue, 3 Dec 2024 11:28:21 +0000 Subject: [PATCH 74/74] Enable local echoes for media uploads for all builds. (#3579) * Enable local echoes for media uploads for all builds. * Update a string. --- .../en.lproj/Localizable.strings | 2 +- ElementX/Sources/Generated/Strings.swift | 2 +- .../Mocks/Generated/GeneratedMocks.swift | 200 +++++++++--------- .../MediaUploadPreviewScreenViewModel.swift | 22 +- .../Services/Timeline/TimelineProxy.swift | 44 ++-- .../Timeline/TimelineProxyProtocol.swift | 7 - .../VoiceMessage/VoiceMessageRecorder.swift | 3 +- ..._mediaUploadPreviewScreen-iPad-en-GB.1.png | 4 +- ...mediaUploadPreviewScreen-iPad-pseudo.1.png | 4 +- ...aUploadPreviewScreen-iPhone-16-en-GB.1.png | 4 +- ...UploadPreviewScreen-iPhone-16-pseudo.1.png | 4 +- ...diaUploadPreviewScreenViewModelTests.swift | 8 +- .../Sources/VoiceMessageRecorderTests.swift | 10 +- 13 files changed, 139 insertions(+), 175 deletions(-) diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 18d852607c..9abc9ec077 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -352,7 +352,7 @@ "rich_text_editor_unindent" = "Unindent"; "rich_text_editor_url_placeholder" = "Link"; "rich_text_editor_a11y_add_attachment" = "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."; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 26487abd95..cb7e231c6d 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -796,7 +796,7 @@ internal enum L10n { internal static var richTextEditorCloseFormattingOptions: String { return L10n.tr("Localizable", "rich_text_editor_close_formatting_options") } /// Toggle code block internal static var richTextEditorCodeBlock: String { return L10n.tr("Localizable", "rich_text_editor_code_block") } - /// Optional caption… + /// Add a caption internal static var richTextEditorComposerCaptionPlaceholder: String { return L10n.tr("Localizable", "rich_text_editor_composer_caption_placeholder") } /// Message… internal static var richTextEditorComposerPlaceholder: String { return L10n.tr("Localizable", "rich_text_editor_composer_placeholder") } diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index ef2b2f793a..576eff68fd 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -14114,15 +14114,15 @@ class TimelineProxyMock: TimelineProxyProtocol { } //MARK: - sendAudio - var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCallsCount: Int { + var sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingCallsCount = 0 + var sendAudioUrlAudioInfoCaptionRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount + return sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingCallsCount } return returnValue! @@ -14130,27 +14130,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingCallsCount = newValue } } } } - var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCalled: Bool { - return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCallsCount > 0 + var sendAudioUrlAudioInfoCaptionRequestHandleCalled: Bool { + return sendAudioUrlAudioInfoCaptionRequestHandleCallsCount > 0 } - var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { + var sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingReturnValue: Result! + var sendAudioUrlAudioInfoCaptionRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue + return sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingReturnValue } return returnValue! @@ -14158,35 +14158,35 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingReturnValue = newValue } } } } - var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure: ((URL, AudioInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendAudioUrlAudioInfoCaptionRequestHandleClosure: ((URL, AudioInfo, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendAudio(url: URL, audioInfo: AudioInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCallsCount += 1 - if let sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure = sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure { - return await sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure(url, audioInfo, caption, progressSubject, requestHandle) + func sendAudio(url: URL, audioInfo: AudioInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendAudioUrlAudioInfoCaptionRequestHandleCallsCount += 1 + if let sendAudioUrlAudioInfoCaptionRequestHandleClosure = sendAudioUrlAudioInfoCaptionRequestHandleClosure { + return await sendAudioUrlAudioInfoCaptionRequestHandleClosure(url, audioInfo, caption, requestHandle) } else { - return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleReturnValue + return sendAudioUrlAudioInfoCaptionRequestHandleReturnValue } } //MARK: - sendFile - var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCallsCount: Int { + var sendFileUrlFileInfoCaptionRequestHandleUnderlyingCallsCount = 0 + var sendFileUrlFileInfoCaptionRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount + return sendFileUrlFileInfoCaptionRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendFileUrlFileInfoCaptionRequestHandleUnderlyingCallsCount } return returnValue! @@ -14194,27 +14194,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendFileUrlFileInfoCaptionRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendFileUrlFileInfoCaptionRequestHandleUnderlyingCallsCount = newValue } } } } - var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCalled: Bool { - return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCallsCount > 0 + var sendFileUrlFileInfoCaptionRequestHandleCalled: Bool { + return sendFileUrlFileInfoCaptionRequestHandleCallsCount > 0 } - var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { + var sendFileUrlFileInfoCaptionRequestHandleUnderlyingReturnValue: Result! + var sendFileUrlFileInfoCaptionRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue + return sendFileUrlFileInfoCaptionRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendFileUrlFileInfoCaptionRequestHandleUnderlyingReturnValue } return returnValue! @@ -14222,35 +14222,35 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendFileUrlFileInfoCaptionRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendFileUrlFileInfoCaptionRequestHandleUnderlyingReturnValue = newValue } } } } - var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure: ((URL, FileInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendFileUrlFileInfoCaptionRequestHandleClosure: ((URL, FileInfo, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendFile(url: URL, fileInfo: FileInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCallsCount += 1 - if let sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure = sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure { - return await sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure(url, fileInfo, caption, progressSubject, requestHandle) + func sendFile(url: URL, fileInfo: FileInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendFileUrlFileInfoCaptionRequestHandleCallsCount += 1 + if let sendFileUrlFileInfoCaptionRequestHandleClosure = sendFileUrlFileInfoCaptionRequestHandleClosure { + return await sendFileUrlFileInfoCaptionRequestHandleClosure(url, fileInfo, caption, requestHandle) } else { - return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleReturnValue + return sendFileUrlFileInfoCaptionRequestHandleReturnValue } } //MARK: - sendImage - var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCallsCount: Int { + var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingCallsCount = 0 + var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount + return sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingCallsCount } return returnValue! @@ -14258,27 +14258,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingCallsCount = newValue } } } } - var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCalled: Bool { - return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCallsCount > 0 + var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleCalled: Bool { + return sendImageUrlThumbnailURLImageInfoCaptionRequestHandleCallsCount > 0 } - var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { + var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingReturnValue: Result! + var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue + return sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingReturnValue } return returnValue! @@ -14286,22 +14286,22 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingReturnValue = newValue } } } } - var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure: ((URL, URL, ImageInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleClosure: ((URL, URL, ImageInfo, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCallsCount += 1 - if let sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure = sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure { - return await sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure(url, thumbnailURL, imageInfo, caption, progressSubject, requestHandle) + func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendImageUrlThumbnailURLImageInfoCaptionRequestHandleCallsCount += 1 + if let sendImageUrlThumbnailURLImageInfoCaptionRequestHandleClosure = sendImageUrlThumbnailURLImageInfoCaptionRequestHandleClosure { + return await sendImageUrlThumbnailURLImageInfoCaptionRequestHandleClosure(url, thumbnailURL, imageInfo, caption, requestHandle) } else { - return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleReturnValue + return sendImageUrlThumbnailURLImageInfoCaptionRequestHandleReturnValue } } //MARK: - sendLocation @@ -14376,15 +14376,15 @@ class TimelineProxyMock: TimelineProxyProtocol { } //MARK: - sendVideo - var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCallsCount: Int { + var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingCallsCount = 0 + var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount + return sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingCallsCount } return returnValue! @@ -14392,27 +14392,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingCallsCount = newValue } } } } - var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCalled: Bool { - return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCallsCount > 0 + var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleCalled: Bool { + return sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleCallsCount > 0 } - var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { + var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingReturnValue: Result! + var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue + return sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingReturnValue } return returnValue! @@ -14420,35 +14420,35 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingReturnValue = newValue } } } } - var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure: ((URL, URL, VideoInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleClosure: ((URL, URL, VideoInfo, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCallsCount += 1 - if let sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure = sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure { - return await sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure(url, thumbnailURL, videoInfo, caption, progressSubject, requestHandle) + func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleCallsCount += 1 + if let sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleClosure = sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleClosure { + return await sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleClosure(url, thumbnailURL, videoInfo, caption, requestHandle) } else { - return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleReturnValue + return sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleReturnValue } } //MARK: - sendVoiceMessage - var sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleCallsCount: Int { + var sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingCallsCount = 0 + var sendVoiceMessageUrlAudioInfoWaveformRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleUnderlyingCallsCount + return sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingCallsCount } return returnValue! @@ -14456,27 +14456,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingCallsCount = newValue } } } } - var sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleCalled: Bool { - return sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleCallsCount > 0 + var sendVoiceMessageUrlAudioInfoWaveformRequestHandleCalled: Bool { + return sendVoiceMessageUrlAudioInfoWaveformRequestHandleCallsCount > 0 } - var sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleReturnValue: Result! { + var sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingReturnValue: Result! + var sendVoiceMessageUrlAudioInfoWaveformRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleUnderlyingReturnValue + return sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingReturnValue } return returnValue! @@ -14484,22 +14484,22 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingReturnValue = newValue } } } } - var sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleClosure: ((URL, AudioInfo, [UInt16], CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendVoiceMessageUrlAudioInfoWaveformRequestHandleClosure: ((URL, AudioInfo, [UInt16], @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendVoiceMessage(url: URL, audioInfo: AudioInfo, waveform: [UInt16], progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleCallsCount += 1 - if let sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleClosure = sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleClosure { - return await sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleClosure(url, audioInfo, waveform, progressSubject, requestHandle) + func sendVoiceMessage(url: URL, audioInfo: AudioInfo, waveform: [UInt16], requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendVoiceMessageUrlAudioInfoWaveformRequestHandleCallsCount += 1 + if let sendVoiceMessageUrlAudioInfoWaveformRequestHandleClosure = sendVoiceMessageUrlAudioInfoWaveformRequestHandleClosure { + return await sendVoiceMessageUrlAudioInfoWaveformRequestHandleClosure(url, audioInfo, waveform, requestHandle) } else { - return sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleReturnValue + return sendVoiceMessageUrlAudioInfoWaveformRequestHandleReturnValue } } //MARK: - sendReadReceipt diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift index f76a025c85..f3741f6e0b 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift @@ -49,13 +49,11 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, switch viewAction { case .send: Task { - let progressSubject = AppSettings.isDevelopmentBuild ? nil : CurrentValueSubject(0.0) - - startLoading(progressPublisher: progressSubject?.asCurrentValuePublisher()) + startLoading() switch await mediaUploadingPreprocessor.processMedia(at: url) { case .success(let mediaInfo): - switch await sendAttachment(mediaInfo: mediaInfo, caption: caption, progressSubject: progressSubject) { + switch await sendAttachment(mediaInfo: mediaInfo, caption: caption) { case .success: actionsSubject.send(.dismiss) case .failure(let error): @@ -79,7 +77,7 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, // MARK: - Private - private func sendAttachment(mediaInfo: MediaInfo, caption: String?, progressSubject: CurrentValueSubject?) async -> Result { + private func sendAttachment(mediaInfo: MediaInfo, caption: String?) async -> Result { let requestHandle: ((SendAttachmentJoinHandleProtocol) -> Void) = { [weak self] handle in self?.requestHandle = handle } @@ -90,42 +88,32 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, thumbnailURL: thumbnailURL, imageInfo: imageInfo, caption: caption, - progressSubject: progressSubject, requestHandle: requestHandle) case let .video(videoURL, thumbnailURL, videoInfo): return await roomProxy.timeline.sendVideo(url: videoURL, thumbnailURL: thumbnailURL, videoInfo: videoInfo, caption: caption, - progressSubject: progressSubject, requestHandle: requestHandle) case let .audio(audioURL, audioInfo): return await roomProxy.timeline.sendAudio(url: audioURL, audioInfo: audioInfo, caption: caption, - progressSubject: progressSubject, requestHandle: requestHandle) case let .file(fileURL, fileInfo): return await roomProxy.timeline.sendFile(url: fileURL, fileInfo: fileInfo, caption: caption, - progressSubject: progressSubject, requestHandle: requestHandle) } } private static let loadingIndicatorIdentifier = "\(MediaUploadPreviewScreenViewModel.self)-Loading" - private func startLoading(progressPublisher: CurrentValuePublisher?) { - let progress: UserIndicator.Progress = if let progressPublisher { - .published(progressPublisher) - } else { - .indeterminate - } - + private func startLoading() { userIndicatorController.submitIndicator( UserIndicator(id: Self.loadingIndicatorIdentifier, - type: .modal(progress: progress, interactiveDismissDisabled: false, allowsInteraction: true), + type: .modal(progress: .indeterminate, interactiveDismissDisabled: false, allowsInteraction: true), title: L10n.commonSending, persistent: true) ) diff --git a/ElementX/Sources/Services/Timeline/TimelineProxy.swift b/ElementX/Sources/Services/Timeline/TimelineProxy.swift index 0c2422de17..93238d41ea 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxy.swift @@ -224,18 +224,15 @@ final class TimelineProxy: TimelineProxyProtocol { func sendAudio(url: URL, audioInfo: AudioInfo, caption: String?, - progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending audio") let handle = timeline.sendAudio(url: url.path(percentEncoded: false), audioInfo: audioInfo, caption: caption, - formattedCaption: nil, - progressWatcher: UploadProgressListener { progress in - progressSubject?.send(progress) - }, - useSendQueue: AppSettings.isDevelopmentBuild) + formattedCaption: nil, // Rust will build this from the caption's markdown. + progressWatcher: nil, + useSendQueue: true) await requestHandle(handle) @@ -253,18 +250,15 @@ final class TimelineProxy: TimelineProxyProtocol { func sendFile(url: URL, fileInfo: FileInfo, caption: String?, - progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending file") let handle = timeline.sendFile(url: url.path(percentEncoded: false), fileInfo: fileInfo, caption: caption, - formattedCaption: nil, - progressWatcher: UploadProgressListener { progress in - progressSubject?.send(progress) - }, - useSendQueue: AppSettings.isDevelopmentBuild) + formattedCaption: nil, // Rust will build this from the caption's markdown. + progressWatcher: nil, + useSendQueue: true) await requestHandle(handle) @@ -279,12 +273,10 @@ final class TimelineProxy: TimelineProxyProtocol { return .success(()) } - // swiftlint:disable:next function_parameter_count func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, caption: String?, - progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending image") @@ -292,11 +284,9 @@ final class TimelineProxy: TimelineProxyProtocol { thumbnailUrl: thumbnailURL.path(percentEncoded: false), imageInfo: imageInfo, caption: caption, - formattedCaption: nil, - progressWatcher: UploadProgressListener { progress in - progressSubject?.send(progress) - }, - useSendQueue: AppSettings.isDevelopmentBuild) + formattedCaption: nil, // Rust will build this from the caption's markdown. + progressWatcher: nil, + useSendQueue: true) await requestHandle(handle) @@ -334,7 +324,6 @@ final class TimelineProxy: TimelineProxyProtocol { thumbnailURL: URL, videoInfo: VideoInfo, caption: String?, - progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending video") @@ -342,11 +331,9 @@ final class TimelineProxy: TimelineProxyProtocol { thumbnailUrl: thumbnailURL.path(percentEncoded: false), videoInfo: videoInfo, caption: caption, - formattedCaption: nil, - progressWatcher: UploadProgressListener { progress in - progressSubject?.send(progress) - }, - useSendQueue: AppSettings.isDevelopmentBuild) + formattedCaption: nil, // Rust will build this from the caption's markdown. + progressWatcher: nil, + useSendQueue: true) await requestHandle(handle) @@ -364,7 +351,6 @@ final class TimelineProxy: TimelineProxyProtocol { func sendVoiceMessage(url: URL, audioInfo: AudioInfo, waveform: [UInt16], - progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending voice message") @@ -373,10 +359,8 @@ final class TimelineProxy: TimelineProxyProtocol { waveform: waveform, caption: nil, formattedCaption: nil, - progressWatcher: UploadProgressListener { progress in - progressSubject?.send(progress) - }, - useSendQueue: AppSettings.isDevelopmentBuild) + progressWatcher: nil, + useSendQueue: true) await requestHandle(handle) diff --git a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift index 3bff76ecba..d1520cbbeb 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift @@ -52,21 +52,17 @@ protocol TimelineProxyProtocol { func sendAudio(url: URL, audioInfo: AudioInfo, caption: String?, - progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result func sendFile(url: URL, fileInfo: FileInfo, caption: String?, - progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result - // swiftlint:disable:next function_parameter_count func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, caption: String?, - progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result func sendLocation(body: String, @@ -75,18 +71,15 @@ protocol TimelineProxyProtocol { zoomLevel: UInt8?, assetType: AssetType?) async -> Result - // swiftlint:disable:next function_parameter_count func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, caption: String?, - progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result func sendVoiceMessage(url: URL, audioInfo: AudioInfo, waveform: [UInt16], - progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result func sendReadReceipt(for eventID: String, type: ReceiptType) async -> Result diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift index 55f5f8769b..cd9e14f329 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageRecorder.swift @@ -178,8 +178,7 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol { let result = await roomProxy.timeline.sendVoiceMessage(url: oggFile, audioInfo: audioInfo, - waveform: waveform, - progressSubject: nil) { _ in } + waveform: waveform) { _ in } if case .failure(let error) = result { MXLog.error("Failed to send the voice message. \(error)") 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 d9424a3003..480ef09fe2 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:79c2656c58dde4df7af57a9ce1561d33c83772a8f15e88ea57fe80f8c14b61b5 -size 92652 +oid sha256:742693f46cc68c183a0996ef9dd008feb93637ac548db45f202485dc3e8a6849 +size 92357 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 377fe1b2b7..1383459ef5 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:f53cf59f991c8958e8ae06759f05cf41b39ec6d1b402fcc6123edbd54e863409 -size 93837 +oid sha256:725f841b450a1246120002770a578df844c3674c3dd782fea8f284f451df408e +size 93411 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 b77d39bca7..9f1fb6b938 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:1212f7afafd62561d7a90852e077667a042d4e86bd9b572904e0c89146e8d8b9 -size 51188 +oid sha256:e2689c49be718d18370c01e0fbcf67a77c358a057a9d6a6d7627930072c22d2e +size 50886 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 3bf2bb188f..a178888568 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:f6ac82c8457a7771ae7c30049ea4250f434285e4ae15ad52eefc935bd38e37eb -size 51942 +oid sha256:2a0cfc0ced4f4ab9bf6944b82217e1ed46f54d2aa2d358d040aa8c67f4a24074 +size 51725 diff --git a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift index 7fe56df9de..81218b0311 100644 --- a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift +++ b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift @@ -106,16 +106,16 @@ class MediaUploadPreviewScreenViewModelTests: XCTestCase { private func setUpViewModel(url: URL, expectedCaption: String?) { timelineProxy = TimelineProxyMock(.init()) - timelineProxy.sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, caption, _, _ in + timelineProxy.sendAudioUrlAudioInfoCaptionRequestHandleClosure = { [weak self] _, _, caption, _ in self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) } - timelineProxy.sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, caption, _, _ in + timelineProxy.sendFileUrlFileInfoCaptionRequestHandleClosure = { [weak self] _, _, caption, _ in self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) } - timelineProxy.sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, _, caption, _, _ in + timelineProxy.sendImageUrlThumbnailURLImageInfoCaptionRequestHandleClosure = { [weak self] _, _, _, caption, _ in self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) } - timelineProxy.sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, _, caption, _, _ in + timelineProxy.sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleClosure = { [weak self] _, _, _, caption, _ in self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) } diff --git a/UnitTests/Sources/VoiceMessageRecorderTests.swift b/UnitTests/Sources/VoiceMessageRecorderTests.swift index a3c675c88f..57e45a1a2f 100644 --- a/UnitTests/Sources/VoiceMessageRecorderTests.swift +++ b/UnitTests/Sources/VoiceMessageRecorderTests.swift @@ -227,7 +227,7 @@ class VoiceMessageRecorderTests: XCTestCase { let timelineProxy = TimelineProxyMock() let roomProxy = JoinedRoomProxyMock() roomProxy.timeline = timelineProxy - timelineProxy.sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleReturnValue = .failure(.sdkError(SDKError.generic)) + timelineProxy.sendVoiceMessageUrlAudioInfoWaveformRequestHandleReturnValue = .failure(.sdkError(SDKError.generic)) guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else { XCTFail("An error is expected") return @@ -248,7 +248,7 @@ class VoiceMessageRecorderTests: XCTestCase { let timelineProxy = TimelineProxyMock() let roomProxy = JoinedRoomProxyMock() roomProxy.timeline = timelineProxy - timelineProxy.sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleReturnValue = .failure(.sdkError(SDKError.generic)) + timelineProxy.sendVoiceMessageUrlAudioInfoWaveformRequestHandleReturnValue = .failure(.sdkError(SDKError.generic)) guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else { XCTFail("An error is expected") return @@ -271,7 +271,7 @@ class VoiceMessageRecorderTests: XCTestCase { let timelineProxy = TimelineProxyMock() let roomProxy = JoinedRoomProxyMock() roomProxy.timeline = timelineProxy - timelineProxy.sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleReturnValue = .failure(.sdkError(SDKError.generic)) + timelineProxy.sendVoiceMessageUrlAudioInfoWaveformRequestHandleReturnValue = .failure(.sdkError(SDKError.generic)) guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else { XCTFail("An error is expected") return @@ -307,7 +307,7 @@ class VoiceMessageRecorderTests: XCTestCase { XCTAssertEqual(destination.pathExtension, "ogg") } - timelineProxy.sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleClosure = { url, audioInfo, waveform, _, _ in + timelineProxy.sendVoiceMessageUrlAudioInfoWaveformRequestHandleClosure = { url, audioInfo, waveform, _ in XCTAssertEqual(url, convertedFileURL) XCTAssertEqual(audioInfo.duration, self.audioRecorder.currentTime) XCTAssertEqual(audioInfo.size, convertedFileSize) @@ -323,7 +323,7 @@ class VoiceMessageRecorderTests: XCTestCase { } XCTAssert(audioConverter.convertToOpusOggSourceURLDestinationURLCalled) - XCTAssert(timelineProxy.sendVoiceMessageUrlAudioInfoWaveformProgressSubjectRequestHandleCalled) + XCTAssert(timelineProxy.sendVoiceMessageUrlAudioInfoWaveformRequestHandleCalled) // the converted file must have been deleted if let convertedFileURL {